# Recall spike — unmeasured classes S1/S5/S7/S8/S10 (2026-06-17)

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

## BLUF

The coverage-knob hypothesis (§3 of the design doc — "the generalist LLM band covers the S1–S11
taxonomy") is **CONFIRMED for single-file logic-bug classes**: all 5 previously-unmeasured classes
surfaced their exact git-fix canonical in a blind k=3 union, at [critical]/[high]. Combined with the
prior S4 (SQLi) + S6 (SSRF) pilots, **7 of 11 classes are now measured, all caught** by the unmodified
v2 prompt @ sonnet/MED. The open problem is **precision/dedup, not coverage** — unions are noisy
(15–28 findings/cell; canonical often 2/3 buried) and paraphrase-split roll counts corrupt the signal.
The one structural non-LLM class remains **S11 (deps/CVE + headers)** — deterministic legs by design,
not an LLM miss.

## Result [MEASURED] — blind, isolated single-file cells, /tmp/sg_cfg clean unseeded config, k=3 union

| class | cell file (pre-fix) | canonical | fix commit | gate result |
|---|---|---|---|---|
| S1 | routes/auth/password.ts | reset-token reusable, no single-use jti (S1-004) | 59ec337 | **CAUGHT** `[critical] reset token not invalidated after use — unlimited reuse within TTL` 2/3 |
| S5 | notifications/email/render.ts | `{{}}` interpolation unescaped → HTML/XSS in email (S5-001/002) | a15deb0 | **CAUGHT** `[high] HTML injection via unescaped vars interpolation` 3/3 |
| S7 | routes/webhooks/whatsapp.ts | inbound webhook sig verify fail-OPEN when app_secret falsy (S7-001..004) | 5a2867f | **CAUGHT** `[critical] signature verification silently skipped when cred.app_secret is falsy` 3/3 |
| S8 | db/queries/attachments.ts | hardDeleteAttachmentRow missing tenant scope → cross-tenant IDOR | 30ebf2a | **CAUGHT** `[critical] hardDeleteAttachmentRow deletes any row across any tenant` 2/3 |
| S10 | routes/oauth/token.ts | auth-code single-use non-atomic (mark-used result ignored) → code replay | 960bb60 | **CAUGHT** `[critical] mark-used and token insertion non-atomic, return value of mark-used ignored` 2/3 |

Each catch is an EXACT match to what the fix changed (verified against the fix diff), not a lenient
read. Reports: `/tmp/sg_spike/S{1,5,7,8,10}_report.md`. Cells: `/tmp/sg_spike/cells/`.

## Method

1. Ground truth = git fix commits (orchestrator-only; gate subagents never see audit docs/commits).
   Pre-fix cell = `git show <fix>~1:<path>` (the vulnerable version).
2. One canonical SINGLE-FILE bug per class (cross-file canonicals deliberately excluded — see Scope).
3. `gate.py <cell> --k 3 --config-dir /tmp/sg_cfg` — oracle leg (payments complete-mediation, SILENT on
   these) + LLM leg = v2 prompt @ sonnet/MED, 3 rolls unioned. No new infra (the S4/S6 pilot move).
4. Orchestrator judged canonical-present against the fix diff.

## HARNESS BUG FOUND + FIXED — RTK truncates `git show` [MEASURED, load-bearing]

The pilot cell (S8) came back with 2/3 rolls reporting **"file is physically truncated."** Root cause:
**RTK (the bash-hook git/pnpm proxy) truncates `git show` stdout** — attachments.ts came through at 130
lines (RTK-routed) vs **298 lines raw**; render.ts at 40 vs 105. Truncation is variable (token-budgeted,
not a fixed line cap), and SILENT. A cell reconstructed through the routed `git show` is missing its tail
→ the canonical (which lived past the cut) is ABSENT → a false "miss". The first S8 run (truncated cell)
MISSED the canonical; the raw re-run CAUGHT it 2/3.

RULE: **reconstruct cells with RAW git, never the routed proxy.** Use `rtk proxy git show <ref>:<path>`
(or `command git --no-pager show`). Verify every cell ends on a clean closing token and contains its
canonical symbol before trusting any result. This is exactly why pilot-before-fan-out is doctrine — one
cell caught a bug that would have corrupted all five.

## Scope — what this spike does and does NOT establish (honest)

- **DOES:** band-1 generalist-LLM single-file recall on 5 logic classes. Each canonical present in k=3
  union. Coverage knob confirmed for these classes.
- **DOES NOT — band-2 (cross-file):** every cell is a single isolated file; sibling imports don't resolve,
  so the orchestration/escalation band was NOT stressed. Cross-file canonicals (e.g. S1-001 refresh
  enforce_2fa defaulting in session.ts) were deliberately excluded. Band-2 recall is still UNMEASURED.
- **DOES NOT — a recall RATE:** n=1 cell per class, not n≥3. This is "the band CAN catch a canonical from
  each class," a point estimate, not "X% recall." A rate needs multiple cells per class (→ bench.py).
- **DOES NOT — precision:** unions are noisy (15–28 findings/cell). The canonical is real but buried, and
  paraphrase-split (S10: 3 separate "auth-code TOCTOU" entries = 1 bug; word-overlap dedup didn't merge).
  Confirms STEP-2 GAP-1 (semantic dedup) is the #1 open problem, not coverage.

## Redirect (what the spike changes downstream) — reordered by [advisor 2026-06-17]

The spike confirmed coverage for the band that was LEAST in doubt (band-1, single-file) while the entire
cross-file apparatus ran INERT — oracle SILENT on every cell, `critical_imports` resolving nothing (cells
have no siblings on disk). Band-2 cross-file is the founding reason this gate exists (C02 was a cross-file
mediation bug). So:

1. **#1 priority = BAND-2 CROSS-FILE recall — existential, above dedup. NOW MEASURED A HOLE (Shape B).**
   [MEASURED 2026-06-17, see `2026-06-17-band2-crossfile-spike.md`] Two cross-file shapes: **Shape A** (visible
   missing-check IDOR — user FK passed onward, no guard) band-1 FLAGS (recall OK); **Shape B** (route calls an
   imported builder/predicate that LOOKS correct, bug = insecure default INSIDE the imported symbol; the C02
   founding shape) band-1 is **SILENT** → silent total miss. Cell: zync `ead618d~1` `refresh.ts` calls
   `buildSessionPayload({...})` omitting `enforce2fa` → 2FA dropped on refresh; band-1 k=3 = ~16 findings, NONE
   the canonical. The bar "catch ALL in 1 round" FAILS for Shape B. **[MEASURED — fix gate] With the imported builder in scope (both files concatenated, k=3) band-1 catches the canonical 3/3 (vs 0/3 single-file) → RESOLUTION is the bottleneck, omission-DETECTION is not; no bespoke omission sub-check needed.** Fix is PROACTIVE escalation (pull every
   security-relevant imported symbol the target calls — Shape B has no flag to react to) + generalize the
   trigger beyond payments names + barrel resolver. The create-tests/corpus skill MUST encode: band-1 covers
   single-file logic + Shape-A cross-file IDOR (as a flag); Shape-B cross-file is a KNOWN band-1 GAP requiring
   band-2 proactive pull. n=1 cell per shape — a RATE needs n≥3 Shape-B cells (bench.py).
2. **#2 = precision — and it is TWO problems, dedup fixes only ONE:**
   (a) **paraphrase-merge** — S10's three "auth-code TOCTOU" entries are ONE bug; word-overlap dedup didn't
       merge them. Semantic dedup fixes this.
   (b) **triage/ranking** — the canonical is REAL but buried at 2/3 among ~20 genuine findings. Dedup does
       NOT fix this; needs severity/exploitability ranking. Do not let "semantic dedup" claim to solve both.
3. **Coverage is no longer the risk** for SINGLE-FILE logic classes — do NOT build deterministic band-3
   detectors for "missed" logic classes; there are none missed. Route any future miss by band (design §3).
4. **S11 deterministic legs** (pnpm audit + header/config check) remain the only known structural coverage
   gap — by design, not an LLM failure.
5. Skills/CLAUDE.md may encode this as PROVEN single-file (band-1) methodology — but NOT cross-file until #1.

## Still unmeasured: S2 (RBAC), S3 (tenant-isolation) [logic, expect catchable], S9 (payments — oracle's
home, separately validated), S11 (deterministic, not LLM).
