You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The cold-open recap (previously_on) and the FTS recall ledger are contaminated by combat/system bookkeeping rows. Every run's setup turn recites mechanical bookkeeping ("Tough 1 takes 5 force damage… Turn advances to Tough 2…") instead of story, and recall ranking is polluted — a recall('Rolan') probe returned 4 of the top 6 hits as bookkeeping (worse than the audit's original 3/6 measurement).
Scope note / not a dup: this is distinct from #749/#763, which is merged in HEAD a245a2c and exact-matches only wrapper-heartbeat lines (wrapper_progress.is_wrapper_progress_line). Combat-event rows and session markers pass straight through that filter — no open issue owns combat-row contamination (re-confirmed against the open-issue set).
Why (root cause, file:line)
recap.py:18 — _STORY_KINDS includes "combat", but _log_combat_event rows (servers/engine/server.py:151-153, schema stamped clawdnd.combat_event.v1 at server.py:130) are purely mechanical.
ledger.py:191 indexes combat+system rows as kind="events" with who=speaker (ledger.py:196), so bookkeeping enters the FTS index and outranks story.
Blast radius is wider than recap+recall: companion_advise (servers/engine/server.py:6851) pulls callbacks from the same contaminated index.
Evidence
recap_probe.py RE-RUN on main @ a245a2c: recap opens with combat bookkeeping exactly as claimed; recall('Rolan') = 4/6 top hits bookkeeping. Reproduced byte-for-byte.
Real-data census: all 149 system rows in an 810-row corpus are session markers (0 DM-authored today).
How to fix (the spec — CORRECTED by the skeptic pass)
The naive option — "drop system from the indexed tuple entirely" — is WRONG: log_event's docstring (server.py:7202) and SKILL.md:47 explicitly prescribe DM-authored system rows via persist_beatso they feed recall ("a terse mechanical/system note for recall… Loose prose only feeds recall if you log it"). Dropping the kind breaks that documented contract. Corrected spec:
recap.format_recap keeps kind=="combat" rows only when the payload is None or lacks the combat-event schema (clawdnd.combat_event.v1) — i.e. narrative combat beats stay, engine bookkeeping goes.
Because all current system rows are markers, observable behavior is identical today, but the spec must not foreclose the documented DM-system-note path.
Test strategy
Recap test: a session log mixing story beats + schema-stamped combat events + session markers yields a recap with story only.
Ledger test: backfill skips schema-stamped combat rows and exact-prefix markers; a DM-authored kind=system note (non-marker) IS indexed and recallable (guards the SKILL.md:47 contract).
Rank regression: re-run the Rolan-style probe fixture — bookkeeping no longer appears in top hits.
Scorecard impact (gate/lens)
story_craft — the cold-open previously_on is consumed by every run's setup turn; contamination is live and reproduced on every current run (unlike the latent unit-07 findings, this one pays out immediately). Also a prerequisite for the retrieval-adoption push (F07-7): recall must return story, not bookkeeping, before mandating its use.
Invariants
Derived-index-only change, no schema change — clean.
effort: S | confidence: high | finding-id: F07-1 | Source: docs/audits/ENGINE-AUDIT-2026-06-11.md (PR #768), unit 07
What is broken
The cold-open recap (
previously_on) and the FTS recall ledger are contaminated by combat/system bookkeeping rows. Every run's setup turn recites mechanical bookkeeping ("Tough 1 takes 5 force damage… Turn advances to Tough 2…") instead of story, and recall ranking is polluted — arecall('Rolan')probe returned 4 of the top 6 hits as bookkeeping (worse than the audit's original 3/6 measurement).Scope note / not a dup: this is distinct from #749/#763, which is merged in HEAD a245a2c and exact-matches only wrapper-heartbeat lines (
wrapper_progress.is_wrapper_progress_line). Combat-event rows and session markers pass straight through that filter — no open issue owns combat-row contamination (re-confirmed against the open-issue set).Why (root cause, file:line)
recap.py:18—_STORY_KINDSincludes"combat", but_log_combat_eventrows (servers/engine/server.py:151-153, schema stampedclawdnd.combat_event.v1at server.py:130) are purely mechanical.ledger.py:191indexes combat+system rows askind="events"withwho=speaker(ledger.py:196), so bookkeeping enters the FTS index and outranks story.companion_advise(servers/engine/server.py:6851) pulls callbacks from the same contaminated index.Evidence
recap_probe.pyRE-RUN on main @ a245a2c: recap opens with combat bookkeeping exactly as claimed;recall('Rolan')= 4/6 top hits bookkeeping. Reproduced byte-for-byte.systemrows in an 810-row corpus are session markers (0 DM-authored today).How to fix (the spec — CORRECTED by the skeptic pass)
The naive option — "drop
systemfrom the indexed tuple entirely" — is WRONG:log_event's docstring (server.py:7202) and SKILL.md:47 explicitly prescribe DM-authoredsystemrows viapersist_beatso they feed recall ("a terse mechanical/system note for recall… Loose prose only feeds recall if you log it"). Dropping the kind breaks that documented contract. Corrected spec:recap.format_recapkeepskind=="combat"rows only when the payload is None or lacks the combat-event schema (clawdnd.combat_event.v1) — i.e. narrative combat beats stay, engine bookkeeping goes.ledger.backfillskips rows whose payload carries the combat-event schema AND skips the two engine session markers by exact-prefix match ("Session N began" / "Session ended.") — same exact-match discipline as [qa][engine] #743 heartbeat is invisible to the player AND contaminates engine memory (recap/FTS/lean tail) #749 — while keeping all othersystemrows indexed (preserving the SKILL.md:47 path).Because all current system rows are markers, observable behavior is identical today, but the spec must not foreclose the documented DM-system-note path.
Test strategy
kind=systemnote (non-marker) IS indexed and recallable (guards the SKILL.md:47 contract).Scorecard impact (gate/lens)
story_craft — the cold-open
previously_onis consumed by every run's setup turn; contamination is live and reproduced on every current run (unlike the latent unit-07 findings, this one pays out immediately). Also a prerequisite for the retrieval-adoption push (F07-7): recall must return story, not bookkeeping, before mandating its use.Invariants
Derived-index-only change, no schema change — clean.
effort: S | confidence: high | finding-id: F07-1 | Source: docs/audits/ENGINE-AUDIT-2026-06-11.md (PR #768), unit 07