# Band-2 trigger gap — reproduced in the shipped scaffold (2026-06-17)

audience: AI coding agents first. Measured log. Tags [MEASURED] vs [DESIGN]. Do not prettify.

## BLUF

The salvaged band-2 proactive resolver (`orchestrator/gate.py` `CRITICAL` regex) is **payments-gated and
dead beyond payments** — CONFIRMED by a zero-LLM static pilot against the shipped Shape-B corpus cell. The
canonical cross-file builder is never pulled into scope, so band-1 never sees it → silent miss. DETECTION is
not the problem (spike already measured 3/3 once the builder is in scope); the **resolver/trigger is the whole
game**. This is the #1 open problem (recall-spike §Redirect, advisor 2026-06-17).

## Result [MEASURED — static, no LLM] — `domains/security/corpus/S1-xfile-2fa-on-refresh/vuln.ts`

The `CRITICAL` trigger (`claim|lock|guard|settle|payout|refund|charge|transfer|release|mediat|authoriz|verif|
reserve|consume|debit|credit|ledger|escrow|hold|webhook|idempoten`) tested against the 18 symbols `vuln.ts`
imports:

```
trigger MATCHES (pulled into scope): NONE
buildSessionPayload matched?: False
=> canonical builder buildSessionPayload is NOT PULLED -> Shape-B silent miss confirmed in shipped project
```

`buildSessionPayload` (the C02-shape builder whose insecure default `enforce_2fa: args.enforce2fa ?? false` is
the canonical) contains no payments/auth-crypto keyword → the proactive band-2 pull never fires for it. The
escalation that the gate exists to perform does not happen on the founding shape outside payments.

## Why the keyword gate is the wrong fix (not a broader list) [DESIGN]

Broadening the regex (add `session|token|cookie|permission|role|tenant|2fa|…`) just moves the deadline to the
next domain — the recall-spike doc already names keyword-gating "dead beyond payments." A keyword list is the
hack this project's vocabulary/discovery principle rejects (convention discovery, no registry).

**Direction (for the next brainstorm→plan cycle, NOT yet built):** replace the name-match gate with a
**first-party-called-import convention** — resolve every import the target actually *calls* to a file inside
the repo (skip `node_modules`), pull those into scope, size/token-budget capped. Principled (no domain list),
matches "discovered by convention." Open cost: scope grows → precision/token cost at scale; needs n≥3 Shape-B
cells across domains for a recall RATE (not the n=1 point estimate here). The resolution half is already
[MEASURED] by `2026-06-17-band2-crossfile-spike.md` (builder-in-scope → band-1 3/3).

## Next step (resume anchor)

Band-2 resolver generalization is a DESIGN change (one-way-ish to the resolver) → start with brainstorm→plan,
do not blind-patch the regex. Pilot unit already exists (this cell). Fan-out needs n≥3 Shape-B cells.

## RESOLVED 2026-06-19 — trigger gap CLOSED [MEASURED]

The trigger gap above is FIXED. `resolver.py` #36 DEMOTED `CRITICAL` from a pull-in GATE to an ordering-only
priority hint; `collect_deps` now pulls ALL first-party CALLED imports (Approach A, `docs/specs/2026-06-17-band2-resolver-generalization-approaches.md`),
budget-capped at `--max-scope`. `buildSessionPayload` (keyword-free) is pulled regardless of name. Evidence:
- **barrel-cell dry-run** `gate.py domains/security/corpus/S1-barrel-2fa-on-refresh/vuln.ts --dry-run` →
  `[dep] imported-builder.ts — import buildSessionPayload from vuln.ts` (pulled THROUGH the barrel, keyword-free).
- **`tests/test_gate.py::test_bundle_and_oracle_set_reach_barrel_resolved_def`** — collect_deps reaches through the workspace barrel to the def.
- **budget invariant (no-false-clean)** `tests/test_gate_emit.py::test_emit_dict_degrades_on_dropped_dep` (unit) +
  `::test_over_budget_fanin_drops_real_and_emit_is_degraded` (E2E: real fan-in>cap → drops → `status='degraded'`, dropped symbol in `coverage.unresolved`).

**RESIDUAL (NOT the trigger — do not re-open this as the trigger gap):** the n≥3 Shape-B recall RATE across
distinct non-payments domains. Shape-B (imported insecure default) is corpus-scarce (n=1/85) and synthesizing a
cell for a recall claim is FORBIDDEN — so this stays an n=1 point estimate until REAL fix commits with the
imported-insecure-default shape are harvested across auth/tenant/+1 domains (RAW git). The delivery is shipped;
the open item is corpus harvest, not resolver code.
