# Band-2 Budget Invariant — E2E Anti-Canary Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: use /executing-plans (inline; scope is one test + doc-truth updates). Steps use checkbox (`- [ ]`) syntax.

**Goal:** Harden the band-2 no-false-clean budget invariant from unit-only to END-TO-END, and record the truthful status of the #1 open problem (cross-file Shape-B trigger).

**Architecture:** Approach A (pull every first-party CALLED import, budget-capped, `dropped` → degraded) is ALREADY SHIPPED in `orchestrator/resolver.py` (#36 — `CRITICAL` demoted to ordering-only hint) + `orchestrator/gate.py` (`collect_deps` called unconditionally, `--max-scope 60`, `dropped` → `build_emit_dict` `status='degraded'`). Empirically verified: the barrel cell pulls the keyword-free `buildSessionPayload` into scope (dry-run). The keyword-free-pull and dropped→degraded properties are unit-tested (`test_gate.py::test_bundle_and_oracle_set_reach_barrel_resolved_def`, `test_gate_emit.py::test_emit_dict_degrades_on_dropped_dep`). The ONE untested binding property: that `collect_deps` ACTUALLY drops when real fan-in exceeds `--max-scope`, AND that gate.py's emit surfaces `status='degraded'` E2E (the existing emit test passes a hand-built `dropped` dict — it never proves the resolver drops under real over-budget). This plan adds that E2E anti-canary.

**Tech Stack:** Python stdlib, pytest. No LLM (pure resolver/emit path).

---

## Wave Plan

| Wave | Tasks | Files touched | Safe to parallelize? |
|------|-------|---------------|----------------------|
| 1 | Task 1 | tests/test_gate_emit.py | single task |
| 2 | Task 2 | docs/validation/2026-06-17-band2-trigger-gap-shipped.md, CLAUDE.md | single task (docs, post-test) |

## File Structure

- `tests/test_gate_emit.py` (MODIFY) — add the E2E over-budget anti-canary (real fan-in > cap → real `dropped` → `status='degraded'`, dropped symbol listed in `coverage.unresolved`).
- `docs/validation/2026-06-17-band2-trigger-gap-shipped.md` (MODIFY) — append a RESOLVED note (the trigger gap is closed by #36; evidence = the barrel-cell dry-run + the two unit tests + this E2E anti-canary).
- `CLAUDE.md` (MODIFY) — flip the "#1 open problem" line: delivery shipped; the residual is the n≥3 recall RATE (corpus-scarcity-blocked), not the trigger.

---

### Task 1: E2E over-budget anti-canary

**Wave:** 1
**Blocks:** Task 2
**Blocked by:** —

**Files:**
- Modify: `tests/test_gate_emit.py`
- Test: `tests/test_gate_emit.py` (same file — it IS the test)

- [ ] **Step 1: Write the failing/locking test** — build a real workspace tree with fan-in > `max_scope`, run the REAL `resolver.collect_deps` with a tiny budget so it genuinely drops, then feed the real `(deps, dropped)` into `build_emit_dict` and assert degraded + the dropped symbol is surfaced. Append to `tests/test_gate_emit.py`:

```python
def test_over_budget_fanin_drops_real_and_emit_is_degraded(tmp_path):
    # BINDING budget invariant (no-false-clean, spec band2-resolver-generalization §"Budget invariant"):
    # a REAL over-budget fan-in must DROP imports in collect_deps AND surface status='degraded' E2E — never a
    # clean SILENT. Unlike test_emit_dict_degrades_on_dropped_dep (hand-built dropped dict), this proves the
    # resolver actually drops under real over-budget and the emit path carries it.
    import importlib.util
    def _load(n, p):
        s = importlib.util.spec_from_file_location(n, p); m = importlib.util.module_from_spec(s)
        s.loader.exec_module(m); return m
    resolver = _load("sg_resolver", os.path.join(ROOT, "orchestrator", "resolver.py"))
    gate = _load("sg_gate", os.path.join(ROOT, "orchestrator", "gate.py"))

    d = str(tmp_path)
    open(os.path.join(d, "pnpm-workspace.yaml"), "w").write("packages:\n  - 'apps/*'\n")
    app = os.path.join(d, "apps/api/src"); os.makedirs(app, exist_ok=True)
    open(os.path.join(d, "apps/api/package.json"), "w").write(
        json.dumps({"name": "@zync/api", "exports": {".": "./src/index.ts"}}))
    # 3 first-party helper defs + an importer that CALLS all 3 (keyword-free names — pull is shape-driven, not name)
    for i in range(3):
        open(os.path.join(app, f"helper{i}.ts"), "w").write(
            f"export function doThing{i}(a){{ return a }}\n")
    importer = os.path.join(app, "route.ts")
    open(importer, "w").write(
        "".join(f"import {{ doThing{i} }} from './helper{i}'\n" for i in range(3)) +
        "doThing0(1); doThing1(2); doThing2(3)\n")

    aliases = resolver.build_workspace_aliases(d)
    # budget = 2 < 3 first-party called imports -> the resolver MUST drop at least one
    deps, dropped = resolver.collect_deps(importer, aliases, 1, 2)
    assert len(deps) == 2, f"budget cap not enforced; deps={deps}"
    assert dropped, "over-budget fan-in MUST populate dropped (no silent skip)"
    dropped_syms = " ".join(dropped.values())
    assert "doThing" in dropped_syms, f"dropped reason must name the dropped import; got {dropped}"

    emit = gate.build_emit_dict(importer, "baseline", ["S1"], 3, [], [], dropped, False)
    assert emit["status"] == "degraded", f"dropped deps MUST degrade the emit (no-false-clean); got {emit}"
    assert any("max-scope" in u for u in emit["coverage"]["unresolved"]), \
        f"the dropped import must appear in coverage.unresolved; got {emit['coverage']}"
```

- [ ] **Step 2: Run it.**

Run: `python3 -m pytest tests/test_gate_emit.py::test_over_budget_fanin_drops_real_and_emit_is_degraded -v`
Expected: PASS (the invariant is shipped — this LOCKS it E2E). If it FAILS, a real no-false-clean regression exists in `collect_deps`/`build_emit_dict` — stop and fix the code, not the test.

- [ ] **Step 3: Run the full suite** — no regression.

Run: `python3 -m pytest -q`
Expected: all pass (prior count + 1).

- [ ] **Step 4: Commit.**

```bash
git add tests/test_gate_emit.py
git commit -m "test(band2): E2E over-budget anti-canary — real fan-in>cap drops + emit degraded (budget invariant)"
```

---

### Task 2: Record truthful status of the #1 open problem

**Wave:** 2
**Blocks:** —
**Blocked by:** Task 1

**Files:**
- Modify: `docs/validation/2026-06-17-band2-trigger-gap-shipped.md`
- Modify: `CLAUDE.md`

- [ ] **Step 1:** Append a RESOLVED section to `docs/validation/2026-06-17-band2-trigger-gap-shipped.md` stating: the trigger gap is CLOSED by resolver #36 (CRITICAL demoted to ordering-only; `collect_deps` pulls ALL first-party called imports). Evidence: barrel-cell dry-run pulls keyword-free `buildSessionPayload`; `test_gate.py::test_bundle_and_oracle_set_reach_barrel_resolved_def`; `test_gate_emit.py::test_emit_dict_degrades_on_dropped_dep` + the new E2E anti-canary. RESIDUAL (not the trigger): n≥3 Shape-B recall RATE across non-payments domains — corpus-scarcity-blocked (Shape-B n=1/85; synthesizing for recall is FORBIDDEN), so it stays an n=1 point estimate until real fix commits with the imported-insecure-default shape are harvested across auth/tenant domains.

- [ ] **Step 2:** Update the `## Measured state` line in `CLAUDE.md` that names cross-file Shape-B "the #1 open problem": flip it to "DELIVERY shipped (#36, resolver pulls all first-party called imports, budget invariant E2E-tested); the residual is the n≥3 recall RATE (corpus-blocked), NOT the trigger."

- [ ] **Step 3: Commit.**

```bash
git add CLAUDE.md docs/validation/2026-06-17-band2-trigger-gap-shipped.md
git commit -m "docs: band-2 trigger gap CLOSED (#36 delivery); residual = n>=3 recall RATE (corpus-blocked)"
```

## Self-Review

- **Spec coverage:** the approaches-spec validation gate has 3 binding items — (1) keyword-free pull [already tested, confirmed], (2) dropped→degraded budget invariant [unit-tested + now E2E in Task 1], (3) n≥3 recall RATE [corpus-blocked, honestly recorded in Task 2, NOT silently dropped]. Precision no-regression is unchanged (no resolver code touched). No new resolver/gate code — the build was already shipped; this plan validates + records.
- **Placeholder scan:** none — test code is complete and runnable.
- **Type consistency:** `collect_deps(target, aliases, max_hops, max_files)` and `build_emit_dict(target, detector_id, covers, k, groups, oracle_results, dropped, merge_degraded)` signatures match the source read this session.
- **Wave check:** Task 1 (test) blocks Task 2 (status doc cites the test). No file overlap. Correct ordering.
