# Drill Matching Fix — Session Handoff

## What's done

**Step 1 (Authoring Contract) — PR #2138 OPEN**, branch `feat/drill-match-authoring-contract`, 6 commits:

1. `21f888c9d` — Remove `isGenericContent()` duplicate from `run-content-generator.ts`
2. `1d538b8bb` — Quality gate hardening: shared constants (MAX_GROUPS=3, MIN_GROUPS=2), stem-canonical inflection detection, max group enforcement, Zod schema `.max(3)`, `porterStem` export, `COMMON_LEGAL_STEMS` moved to shared file
3. `c58c4a5b9` — Prompt: "2-3 groups" ceiling, party name rule, word-by-word BAD example, inflection self-check, retry feedback
4. `0fb2ce736` — 16 new quality gate tests (39/39 passing)
5. `92468359f` — Prompt test assertion updated for new wording
6. `1af9c1f71` — Guard inflection-only check against single-entry groups (code review fix)

**Verification:** Types clean, lint clean, build passes, 39/39 quality gate tests, 32/32 prompt tests, 13/13 schema tests. Two pre-existing failures unrelated (debug-gate 404, architecture boundary line count).

## What's next

Read both plan documents first:
- `C:\Users\sallen\Desktop\SHEP\Technical Docs\Runs (Drills, Issue Spotter, etc)\drills\Solutions\Drill Matching Fix - Complete Brief.md`
- `C:\Users\sallen\Desktop\SHEP\Technical Docs\Runs (Drills, Issue Spotter, etc)\drills\Solutions\Drill Matching Fix - Revised Plan.md`

### Remaining steps (in order)

| Step | PR | What | Depends on |
|------|-----|------|------------|
| 2 | PR B | Benchmark harness + degenerate guard + dynamic drill default to guarded | PR A merged |
| 3 | PR C | Content repair: Lane A (groups-only, auto-ships) + Lane B (reassignment, defaults to semantic_review) | PR B merged |
| 4 | PR D | Observability: layer attribution + rescue-rate + false-positive sampling | Can parallel with PR C |
| 5 | PR E | Capability routing: standard/guarded/semantic_review with numeric thresholds | PR D merged |
| 6 | PR F | AI rewrite pipeline for overlap-heavy doctrines | PR B merged |

### Key files to read

| File | Role |
|------|------|
| `apps/web-svelte/src/lib/practice/drill-constants.ts` | Shared constants (MAX_GROUPS=3, MIN_GROUPS=2, COMMON_LEGAL_STEMS) |
| `apps/web-svelte/src/lib/practice/matching.ts` | `stemTokenize`, `porterStem`, `checkMatchGroups` |
| `apps/web-svelte/src/lib/server/paddock/content-quality-gate.ts` | `validateDrillContent()` — 6 sections now |
| `apps/web-svelte/src/lib/server/paddock/drill-prompt.ts` | `buildDrillPrompt()`, `buildRetryFeedback()` |
| `apps/web-svelte/src/lib/drills/DrillView.svelte` | Client-side matching loop (Step 2 degenerate guard goes here) |
| `apps/web-svelte/src/lib/drills/BuildingBlocksPanel.svelte` | Circle rendering (Step 5 routing + provisional state) |

### Uncommitted scripts in main repo

Two simulation/repair scripts exist in the main repo dir (NOT the worktree):
- `scripts/drill-match-simulation.ts` — production matcher simulation harness
- `scripts/repair-drill-content.ts` — Gemini Flash batch repair pipeline

These are working tools from the investigation phase. They may be useful for Steps 2-3.

### Design decisions to honor

- **D1**: Fix content, not algorithm. Don't touch `checkMatchGroups` threshold.
- **D3**: Party names enforced in content, NOT filtered at runtime.
- **D4**: Benchmark confusion matrix is the gate. 5 test types per element. Test bundles versioned, not regenerated.
- **D6**: Three-tier routing. `semantic_review` circles are provisional (no once-lit-stays-lit).
- **D7**: No human review. AI-automated with benchmark as backstop. Lane B/PR F default to `semantic_review`.
- **D8**: Observability lands BEFORE routing. Thresholds need telemetry.
- **D9**: Dynamic drills default to `guarded` until benchmarked.

### Worktree note

Work was done in `C:\Users\sallen\sskit-remediation\.claude\worktrees\sentry-issues-again`. The clean PR branch is `feat/drill-match-authoring-contract`. For Step 2+, create a new branch from main after PR A merges.
