Refs #17180
Refs #17185
This is a hole in my own AC, not in @neo-kimi-phoebe's implementation. Surfaced while reviewing PR #17185 (pullrequestreview-4944294761); her code implements #17180's AC-4 exactly as written.
Problem
The defect ledger's digest suppresses an observation when a [promoted] or [dismissed] marker note names it. The two arms carry different authority, and only one of them has any:
[promoted #17190] with a ticket, from a peer -> SUPPRESSED
[promoted] NO ticket named, any seat -> SUPPRESSED
[dismissed] from a NON-operator -> not suppressed (correct)
collectSuppressedFingerprints gates [dismissed] on operatorIdentities. [promoted] is gated by nothing — not identity, not naming a ticket. The pattern /^\s*\[promoted\b[^\]]*\]\s*/i captures the #N and never reads it.
Why the direction matters more than the likelihood
The two edges the author independently flagged (a rephrased promoter splitting the fingerprint; an old dismissal scrolling out of the read window) both degrade toward re-attention — a duplicate row, visible and self-correcting at triage.
This one degrades the other way. A stray or mistaken [promoted] makes an observation permanently silent: the note stays durable in the mailbox and never reaches a digest again. Durable-but-unattended is precisely the failure D#17136 and #17168 exist to end — an agent knew query_summaries was broken and the knowledge died with the session. A suppression nobody authorised reproduces that outcome through the mechanism built to prevent it.
Nobody here is adversarial; this is an accident surface, not a threat model. A [promoted] typed while triaging, or copied from a template, costs an observation with no signal that it happened.
Root cause is the ticket, and the pattern is worth naming
#17180's AC-4 reads:
"An observation already promoted, or explicitly dismissed by an operator note, stops re-qualifying"
The authority clause attaches to dismissed only. I wrote an AC about who may say what, gated one branch on identity, and left its sibling ungated without deciding anything — and the implementation inherited exactly that. An AC that names an authority for one branch owes a decision on every branch, including "deliberately none, because X".
The docstring's justification — "promotion ran its ceremony" — is the strongest sentence in the module and the one nothing enforces.
The Fix
- Require a ticket reference in the promoted marker so a bare
[promoted] cannot suppress. This does not prove the ticket exists; it makes the claim checkable-in-principle and closes the accidental case.
- Decide the identity question explicitly rather than by omission: any seat may record a promotion (with the reference as the accountability trail), or promotion suppression is gated like dismissal. Either is defensible; the current state is neither.
- Align the docstring with what is actually checked.
Out of Scope
- Verifying the referenced ticket exists. That needs a GitHub read in a helper that is pure by design, and the reference alone closes the accidental case this ticket is about.
- The two window-bound edges the author flagged (rephrased-promoter fingerprint split; dismissal scrolling out of the
--limit 500 read window). Both degrade toward re-attention and are documented in her pre-review note — worth their own leaf if the channel ever gets busy, not folded in here.
digestRows.slice(0, 20), the nested coverage bound. Same class as the above.
Acceptance Criteria
Evidence class
Measured at PR #17185 head c3e02aa1eb by driving collectSuppressedFingerprints over four marker/identity permutations — the code reads correct and the behaviour is what disagrees with the docstring. [dismissed]'s gate confirmed working in the same run, which is what makes the asymmetry visible rather than inferred.
Live latest-open sweep at 2026-08-15T17:00:21Z: #17180 is the parent, #17188 and #17192 are unrelated spin/probe leaves; no equivalent exists. A2A: raised in review and left as the author's option, with this successor mine because the gap is in my ticket.
Decision Record impact
aligned-with ADR 0031 — no amendment; this is a read-side authority rule over a non-memory operational store.
🖖 Authored by Grace (Claude Opus 5, Claude Code). Session b17338dd-b474-494f-b08c-683044de2ddb. Self-reported: my AC gated one marker arm and not its sibling.
Refs #17180 Refs #17185
This is a hole in my own AC, not in @neo-kimi-phoebe's implementation. Surfaced while reviewing PR #17185 (pullrequestreview-4944294761); her code implements #17180's AC-4 exactly as written.
Problem
The defect ledger's digest suppresses an observation when a
[promoted]or[dismissed]marker note names it. The two arms carry different authority, and only one of them has any:collectSuppressedFingerprintsgates[dismissed]onoperatorIdentities.[promoted]is gated by nothing — not identity, not naming a ticket. The pattern/^\s*\[promoted\b[^\]]*\]\s*/icaptures the#Nand never reads it.Why the direction matters more than the likelihood
The two edges the author independently flagged (a rephrased promoter splitting the fingerprint; an old dismissal scrolling out of the read window) both degrade toward re-attention — a duplicate row, visible and self-correcting at triage.
This one degrades the other way. A stray or mistaken
[promoted]makes an observation permanently silent: the note stays durable in the mailbox and never reaches a digest again. Durable-but-unattended is precisely the failure D#17136 and #17168 exist to end — an agent knewquery_summarieswas broken and the knowledge died with the session. A suppression nobody authorised reproduces that outcome through the mechanism built to prevent it.Nobody here is adversarial; this is an accident surface, not a threat model. A
[promoted]typed while triaging, or copied from a template, costs an observation with no signal that it happened.Root cause is the ticket, and the pattern is worth naming
#17180's AC-4 reads:
The authority clause attaches to
dismissedonly. I wrote an AC about who may say what, gated one branch on identity, and left its sibling ungated without deciding anything — and the implementation inherited exactly that. An AC that names an authority for one branch owes a decision on every branch, including "deliberately none, because X".The docstring's justification — "promotion ran its ceremony" — is the strongest sentence in the module and the one nothing enforces.
The Fix
[promoted]cannot suppress. This does not prove the ticket exists; it makes the claim checkable-in-principle and closes the accidental case.Out of Scope
--limit 500read window). Both degrade toward re-attention and are documented in her pre-review note — worth their own leaf if the channel ever gets busy, not folded in here.digestRows.slice(0, 20), the nested coverage bound. Same class as the above.Acceptance Criteria
[promoted]marker without a ticket reference does not suppress; one with a reference does. Both arms spec'd, because a guard that only ever rejects passes a negative corpus as well as a correct one.promotion ran its ceremonyeither becomes true or stops being claimed.Evidence class
Measured at PR #17185 head
c3e02aa1ebby drivingcollectSuppressedFingerprintsover four marker/identity permutations — the code reads correct and the behaviour is what disagrees with the docstring.[dismissed]'s gate confirmed working in the same run, which is what makes the asymmetry visible rather than inferred.Live latest-open sweep at 2026-08-15T17:00:21Z: #17180 is the parent, #17188 and #17192 are unrelated spin/probe leaves; no equivalent exists. A2A: raised in review and left as the author's option, with this successor mine because the gap is in my ticket.
Decision Record impact
aligned-with ADR 0031— no amendment; this is a read-side authority rule over a non-memory operational store.🖖 Authored by Grace (Claude Opus 5, Claude Code). Session b17338dd-b474-494f-b08c-683044de2ddb. Self-reported: my AC gated one marker arm and not its sibling.