I’m implementing all eight findings quals-first. The state fixes will be structural: final pending work will be flushed through the same exchange fold, queued timestamps will use a monotonic activity frontier, and the generic repeated-prompt suppression will be removed rather than widened.
The only conditional changes I currently expect are: recognizing the known Claude command wrapper, recognizing Copilot’s autoModeResolution, and choosing between a resolved model and the recorded model. The EOF, timing, deduplication, and repeated-prompt fixes should not need new case-specific if statements.
One additional branch is necessary to preserve the existing parallel-denial behavior: the broad four-part suppression in paired() will be removed, and replaced by a narrower check keyed by Claude’s real promptId only where typed denial feedback is recovered. This reduces branching overall and stops affecting ordinary repeated prompts or other providers.
The red suite now isolates the eight reported failures. A parallel Markdown review also found an attribute-injection variant in the same escaping code, so I’m adding that security qual before changing the renderer; the fix requires no new product branch.
The security qual fails with a real onmouseover attribute, as expected. I’m moving to green now: first the shared exchange-state simplification, then the format parsers and Markdown escaping.
The state review found a cleaner boundary: EOF work becomes an unconditional tail in the existing fold, and denial fanout is deduplicated only while adjacent, keyed by Claude’s own promptId plus result. I’ll remove the broad repeated-prompt branch entirely. The only new source conditions are: reject malformed Claude command wrappers; suppress an adjacent duplicate denial record; classify/validate Copilot auto-model metadata; and prefer that resolved model when present. EOF, clock, Markdown, and weave fixes add no branches.
The first implementation pass is in. It also credits work already performed when a new human prompt interrupts a turn—the same accumulator now closes on a reply, a prompt, or EOF instead of having three separate loss points. I’m running the full qual suite before inspecting real transcript exports.
A repository-hygiene check caught sourcery.html being deleted again by the qual run itself. That is a separate qual isolation bug, not an intended product change. I’m tracing which CLI qual targets the checked-in artifact before restoring it, so the next verification run cannot repeat the deletion.
All 106 quals are green. The checked-in HTML has been restored; repeated class-by-class and full-suite runs now leave it untouched, so I could not reproduce the deletion once the parallel reviews had finished. Next I’m exercising the parser against the actual local Claude, Codex, and Copilot stores and comparing extraction counts/metadata for regressions.
The real Sourcery stores now export successfully: 41 exchanges (38 Claude, 2 Codex, 1 Copilot), the raw Claude wrapper becomes /insights, no wrapper XML survives, and the real Copilot /export exchange is labeled gpt-5.4 instead of copilot/auto. I’m doing the release-level polish now; this repository increments the minor version for each shipped behavior change, so these fixes will be pinned as 4.8.0.
The independent qual/state audit found two real gaps before finalization: synthetic Claude harness notices could now donate bogus EOF time, and denial fanout identity was tied to machine wrapper text instead of the recovered human text. I’m adding red quals for those, plus restoring the original no-promptId denial contract and pinning partial wrapper rejection and repeated Claude prompts. No new product branch is needed: one existing synthetic check moves earlier, and the denial key becomes (promptId, recovered text).
The second red/green pass is green: synthetic notices no longer contribute timing; denial fanout now follows the recovered human act across machine-wrapper variants; no-ID fanout remains supported; distinct promptIds remain distinct; and both halves of malformed command scaffolding fail loudly. I’m rerunning the complete suite and real-store export once more.
Final QA is clean: 110 quals pass, the current real stores export 41 prompts, /insights and gpt-5.4 appear correctly, sourcery.html remains untouched, and two independent re-reviews found no remaining state, format, or qual issue. I’m closing with the exact files changed and verification evidence.
Implemented as v4.8.0 in [sourcery.py](/Users/dreeves/lab/sourcery/sourcery.py:45), with 19 new/strengthened quals in [quals.py](/Users/dreeves/lab/sourcery/quals.py:203) and the Python requirement in [README.md](/Users/dreeves/lab/sourcery/README.md:4).
Fixed all eight defects, plus:
- Interrupted-turn work accounting.
- Synthetic-notice timing leakage.
- Reproduced Markdown attribute injection.
- Malformed Claude command wrappers now fail loudly.
Verification:
- 110 quals pass on Python 3.13.6.
- Real-store export succeeds: 41 prompts across all three providers.
- Real
/insights and Copilot gpt-5.4 records render correctly. git diff --check passes.sourcery.html is untouched.- Python 3.10 itself was not run because only 3.13 is installed.
Conditional audit: removed the broad repeated-prompt condition and timestamp membership condition. Added only malformed-wrapper rejection, adjacent Claude-denial suppression, Copilot auto-mode classification/validation, and resolved-model preference. The existing synthetic guard moved earlier.
The pre-existing AGENTS.md modification remains untouched.