Skip to content

fix(mt#4810): Read the claim's subject from its sentence, not its matched token - #3518

Merged
edobry merged 2 commits into
mainfrom
task/mt-4810
Aug 31, 2026
Merged

edobry merged 2 commits into
mainfrom
task/mt-4810

Conversation

@minsky-ai

@minsky-ai minsky-ai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

pre-narration's identity correlation read matches[].phrase. For the dominant review-approved
pattern that phrase is the bare token APPROVED, which carries no subject — so such a claim could
never be identity-backed, and the merge evidence mt#4498 added to identityScopedTools was inert
for it. The record has carried the containing sentence as context since mt#3198, and nothing read
it.

The headline number did not move: 73 firing → 73 firing. mt#4810's SC2 asks for movement and
does not get it. That is reported here rather than worked around, and mt#4810's SC5 names this
outcome in advance as the signal to stop — so the follow-up is a posture decision, not a fourth
tune. Filed as mt#4819.

Key changes

  • extractUniqueClaimedPrNumber — the PR number a claim's SENTENCE names, or null when it names
    none or more than one. The uniqueness guard keeps PR fix(mt#4498): Scope the pre-narration merge evidence and reach the second MCP alias #3484 R1's finding closed: a sentence
    naming two PRs is ambiguous, so it yields nothing and the claim fires. For a suppressor the safe
    degrade direction is MORE fires (ADR-024's fail-to-Rung-1 invariant).
  • The correlation call site reads phrase → sentence. matches[].phrase is untouched, so
    mt#4074's SC3 constraint (extractDistinctPhrases keys the review-due diversity axis on that
    field) holds by construction rather than by careful design.
  • SUPPRESSION_IDENTITY_SCOPED_CONTEXT — a distinct suppression reason, so this path's delta is
    measurable rather than inferred from an unchanged total (mem#1208).
  • scripts/diagnose-pre-narration-window.ts keeps a duplicate of this correlation, and its own
    comment says a divergence there "would misreport the very fix this script exists to measure."
    This change would have created exactly that divergence; the script is updated in the same commit.

Why the number did not move

Suppression needs a subject and evidence to correlate it against. Both halves were measured
separately for the first time, over the union corpus (1124 records; 177 recorded fires; 96
phrase-anchored):

  • Of 31 with-context review-approved fires, 22 (71%) name no subject at all — no PR number, no
    task id. No subject-capture fix reaches them at any window width. This ceiling was stated before
    implementing.
  • The 7 that name a PR in their sentence are all replayable (transcripts present), so the
    fallback ran against them. None was suppressed: the named PR has no in-window
    session_pr_merge / merge_pull_request to correlate against.
  • identity-backed is 0 across the still-firing set, before and after — including after the
    diagnostic script was taught the same two-step, so this is not a measurement artifact.

The leak decomposition in mt#4810 mis-attributes the cause. The gap is not "the claim's subject is
unreachable"; it is "there is no evidence in the window to correlate a subject against."
Direction (b) (window width) does not help either — those windows are empty, not narrow.

Corpus note (mem#1236). mt#4748 moved calibration telemetry to
~/.local/state/minsky/projects/<hash>/. The repo-local .minsky/pre-narration-calibration.jsonl
still returns real-looking records that stop silently at the cutover. The first measurement in this
session read only that frozen half and under-reported the firing count by 3; every figure above is
over the union of the frozen and live logs, which are contiguous and non-overlapping.

Testing

Execution evidence:

AT1 (replay before/after on the same log) — union corpus, bun scripts/diagnose-pre-narration-window.ts --log <union>:

before (main):     73 still fire, 21 now suppressed, 2 no longer matched, 81 unreproduced
after (session):   73 still fire, 21 now suppressed, 2 no longer matched, 81 unreproduced

AT3 (suppressed count did not decrease; matched count did not decrease) — satisfied by the same
run: suppressed holds at 21, no-longer-matched holds at 2.

Unit + integration, bun test --preload ./tests/setup.ts ./.minsky/hooks/pre-narration-detector.test.ts:

 79 pass
 0 fail
 160 expect() calls
Ran 79 tests across 1 file. [229.00ms]

73 of those 79 predate this PR; 6 are new.

AT2 — negative control, below.

Negative control: the two-step call site reverted to the phrase-only read

(fail) pre-narration: the claim's subject read from context (mt#4810) > a bare APPROVED whose SENTENCE names the merged PR is suppressed
 78 pass
 1 fail

Stated honestly: the two tests named NEGATIVE CONTROL stay green in both states by design — they
assert the claim still FIRES (evidence for a different PR; a sentence naming two PRs), which is also
the pre-fix behaviour. They guard the fix against over-reach; they do not demonstrate it. The one
red-to-green test above is what the control actually proves. The revert was of the behavioural
change only (both edits together, so nothing half-reverted); a full file revert additionally breaks
the test file's imports.

Typecheck: 8 projects, 0 errors (session workspace, incl. tsconfig.hooks.json and
tsconfig.scripts.json). Lint: 4246 files, 0 errors.

Success criteria

  • SC1 (direction chosen, reasoned against the leak decomposition) — met; recorded in mt#4810's
    ## Measurement and direction decision.
  • SC2 (re-run the replay, record before/after; the firing count must actually move) —
    before/after recorded; the count did not move. NOT MET.
  • SC3 (suppressed count does not fall, no claim stops matching) — met (21 and 2, unchanged).
  • SC4 (a negative control per new suppression path) — met.
  • SC5 (if the direction also fails to move the number, say so and stop rather than iterating) —
    met: this PR says so, and mt#4819 carries the posture decision instead of a fourth tune.

Deploy verification: not applicable. isDeploySurfaceFile returns false for all four changed files
(.minsky/hooks/pre-narration-detector.ts, its test, the generated .claude/hooks/ mirror,
scripts/diagnose-pre-narration-window.ts).

edobry added 2 commits August 31, 2026 16:28
…ched token [no-deploy-impact]

The pre-narration correlation read `matches[].phrase`. For the dominant
`review-approved` pattern that phrase is the bare token `APPROVED`, which carries
no subject, so such a claim could never be identity-backed. The record has
carried the containing sentence as `context` since mt#3198 and nothing read it.

The call site now reads phrase first, then the sentence, with a uniqueness guard:
a sentence naming two PRs stays ambiguous and the claim fires. That is PR #3484
R1's blocking finding in miniature - a merge of one PR must not back a claim
about another. `matches[].phrase` is untouched, so mt#4074's diversity-axis
constraint holds by construction rather than by design.

`scripts/diagnose-pre-narration-window.ts` keeps a duplicate of this correlation,
and its own comment says a divergence there would misreport the very fix it
exists to measure. Updated in the same commit.

Measured: 73 firing -> 73 firing over the union calibration corpus. The tune does
NOT move the number, and mt#4810 SC5's condition has fired. The subject was never
the binding constraint: the 7 fires whose sentence names a PR are all replayable,
and none has an in-window merge of that PR to correlate against.

Deploy verification: not applicable - isDeploySurfaceFile returns false for all
four changed files.
@minsky-ai minsky-ai Bot added the authorship/co-authored Co-authored by human and AI agent label Aug 31, 2026
@minsky-reviewer

minsky-reviewer Bot commented Aug 31, 2026 •

Copy link
Copy Markdown

Minsky Reviewer Status

Review in progress...

@minsky-reviewer minsky-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent adversarial review (Chinese-wall)
Reviewer: minsky-reviewer[bot] via openai:gpt-5
Tier: 2


Solid, disciplined change: subject extraction now reads the matched sentence and records a distinct suppression reason, with tests and the diagnostic script kept in lockstep. Notably, SC2 is explicitly not met and the PR documents that outcome per SC5. I found two non-blocking concerns: (1) subject extraction operates on elided text, so PR numbers appearing only in quoted spans within the sentence are blanked and become undiscoverable; sourcing from the raw pre-elision context (or trying both) would avoid losing identity evidence. (2) The sentence matcher requires the literal “PR” token; if bare “#1234” or numeric forms occur in-context, they will be missed — clarify intent or expand carefully while maintaining the uniqueness guard. Documentation impact appears nil; there’s no doc for this hook and no posture flip. Overall, the PR is mergeable as-is with the above caveats noted.

Findings

  • [NON-BLOCKING] .minsky/hooks/pre-narration-detector.ts:720 — Subject extraction runs on elided context — quoted PR numbers are blanked and become undiscoverable
    In detectPreNarrationWithSuppression, the context passed to extractUniqueClaimedPrNumber(matched.context) is produced by extractMatchContext(text, …), where text is the ELIDED assistant prose (elideMarkdownContexts + elideDoubleQuotedSpans). This means PR numbers that appear only inside quotes in the containing sentence will have been replaced with whitespace before subject extraction runs, so extractUniqueClaimedPrNumber will never see them. That narrows the new correlation path unintentionally and can mask legitimate identity-backed cases (e.g., APPROVED — "PR #123" will lose the #123). Consider sourcing the subject from the UN-elided raw context (or running the extraction over both elided and raw forms) while keeping elision for the pattern match itself. This preserves the anti-quote FP property for matching without discarding potentially-usable identity evidence.
  • [NON-BLOCKING] .minsky/hooks/pre-narration-detector.ts:221 — Regex for sentence-based PR extraction ignores bare-number forms without the 'PR' label
    extractUniqueClaimedPrNumber only matches /\bPR\s*#?(\d+)/gi. Some sentences may name a PR number without the PR token (e.g., “Approved — #3484 is good to go.”, “Approved — 3484 passed,” or repo conventions that use just “#1234”). The code comment says it handles “either spelling” in tests, but the implementation requires the PR prefix, so those bare-number shapes are missed. If intentional, add a comment clarifying the intended scope; otherwise, consider broadening the pattern (e.g., also accept /#(\d+)/ when clearly in a PR context) with appropriate ambiguity guards to preserve the uniqueness constraint.

Spec verification

Criterion Status Evidence
A direction is chosen and the reason recorded, against the leak decomposition above rather than against a fresh guess. Met Reasoning and decision are embedded in code comments and PR description; the implementation chooses read-site (sentence) extraction via extractUniqueClaimedPrNumber and documents the ceiling. Evidence in .minsky/hooks/pre-narration-detector.ts:210-236 (new function docblock) and the call-site change at :713-723.
Whichever lands, re-run scripts/diagnose-pre-narration-window.ts and record before/after. The bar mt#4498 failed is the one that matters: the firing count must actually move. Not Met PR body explicitly states “The tune did not move the number: 73 firing → 73 firing,” and updates scripts/diagnose-pre-narration-window.ts to mirror the detector’s two-step subject extraction (extractUniqueClaimedPrNumber), but the before/after counts are unchanged. A follow-up posture decision is filed as mt#4819. Code evidence: scripts/diagnose-pre-narration-window.ts:556-563 mirrors the change; execution evidence in PR description records no movement.
Suppressed count does not fall, and no claim stops matching — a tune achieved by suppressing everything is the failure mode (mt#4498's ## Outcome shows what this looks like when it nearly happened). Met PR description shows unchanged suppressed (21) and no-longer-matched (2) counts on the same corpus before/after. The detector’s logic preserves match-first semantics and only changes identity-correlation source; no broadening of requiredTools occurs. No code path was added that would stop matching outright; see unchanged OUTCOME_CATEGORIES and pattern list.
A negative control per new suppression path: the same claim without its evidence still fires. Met New tests in .minsky/hooks/pre-narration-detector.test.ts:1169-1211 include two negative controls: (1) evidence for a different PR does not suppress; (2) a sentence naming two PRs is treated as ambiguous and still fires. These assert the new path does not overreach.
If the chosen direction ALSO fails to move the number, say so and stop rather than iterating — that would be the third tune on this detector and the signal to reconsider the detector, not the patterns. Met PR body explicitly records SC2 as not met and defers posture/next steps to mt#4819 rather than iterating further. No further code churn; only the read-site change and mirrored diagnostic change shipped.

Adoption sweep

Symbol Kind Consumers found Classification Notes
.minsky/hooks/pre-narration-detector.extractUniqueClaimedPrNumber function .minsky/hooks/pre-narration-detector.ts:720 — used to extract PR number from matched sentence when phrase lacks one, scripts/diagnose-pre-narration-window.ts:559 — mirrored in diagnostic script to avoid measurement drift, .claude/hooks/pre-narration-detector.ts:723 — generated mirror uses it identically Adopted New public export used immediately in the same module and mirrored in the generated hook and diagnostic script per design comments.

Documentation impact

  • no-update-needed — Behavioral change is internal to detection/suppression logic (source of subject for identity correlation). No CLI, config, or user-facing contract changed; exported API surface adds a helper but module semantics remain the same, and no docs file for this hook exists under docs/architecture/hooks/ (verified — no pre-narration-detector.md). The PR does not flip posture. Therefore no docs updates are required.

@minsky-reviewer minsky-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent adversarial review (Chinese-wall)
Reviewer: minsky-reviewer[bot] via openai:gpt-5
Tier: 2


Verification pass: prior NON-BLOCKING findings still apply, but there were no prior BLOCKING findings to re-check, and this fix commit introduces no new critical defects. The read-site change is implemented correctly: sentence-based subject extraction (extractUniqueClaimedPrNumber) with a conservative uniqueness guard, wired phrase-first/sentence-fallback, and a distinct suppression reason. Tests exercise the new path and its negative controls; the diagnostic script mirrors the logic to avoid measurement drift. I’m leaving two NON-BLOCKING notes: (1) subject extraction runs on the elided sentence, so PR numbers appearing only inside double-quoted spans are blanked and unreachable; consider attempting extraction against the raw sentence too. (2) the sentence extractor requires a literal “PR” token and will miss bare “#1234” shapes; if intentional, document; otherwise consider broadening carefully while preserving uniqueness. With SC2 explicitly not met but recorded per SC5, and no new critical issues found, this PR is approved.

Findings

  • [NON-BLOCKING] .minsky/hooks/pre-narration-detector.ts:328 — Subject extraction still runs on ELIDED context, so quoted PR numbers in the sentence are blanked and undiscoverable
    In detectPreNarrationWithSuppression, the context used for extractUniqueClaimedPrNumber(matched.context) is produced from text, which is elideDoubleQuotedSpans(elideMarkdownContexts(rawText)) (.minsky/hooks/pre-narration-detector.ts:300-309). This means any PR numbers appearing only inside double-quoted spans within the containing sentence will have been replaced with whitespace before subject extraction runs. As a result, identity-scoped suppression can miss legitimate cases where the only subject mention is quoted (e.g., APPROVED — "PR #123"). Consider sourcing the subject from the un-elided raw sentence (or attempting extraction against both raw and elided forms) while retaining elision for the pattern match itself, so you keep the anti-quote FP property for matching without discarding potentially-useful identity evidence.
  • [NON-BLOCKING] .minsky/hooks/pre-narration-detector.ts:230 — Sentence-based PR extractor requires a literal “PR” token; bare “#1234” or numeric-only mentions are ignored
    extractUniqueClaimedPrNumber scans with /\bPR\s*#?(\d+)/gi, so it will not recognize cases where the containing sentence names a PR only as “#3484” (or a repo-convention bare number) without the PR label. Tests cover “PR 3484” and “PR #3484” but not “#3484”. If this omission is intentional (to avoid ambiguous issue refs), consider documenting that scope at the function docblock. Otherwise, consider carefully broadening the pattern (e.g., also accepting /#(\d+)/ when clearly in a PR-context clause) while preserving the uniqueness guard to avoid accidental cross-pairing.

Spec verification

Criterion Status Evidence
A direction is chosen and the reason recorded, against the leak decomposition above rather than against a fresh guess. Met Direction (read-site subject from sentence) is implemented and documented in-code. See .minsky/hooks/pre-narration-detector.ts:218-247 (extractUniqueClaimedPrNumber docblock) and its invocation at .minsky/hooks/pre-narration-detector.ts:365-383 (phrase-first, sentence-fallback). PR body records rationale and ceiling.
Whichever lands, re-run scripts/diagnose-pre-narration-window.ts and record before/after. The bar mt#4498 failed is the one that matters: the firing count must actually move. Not Met PR body records: "The tune did not move the number: 73 firing → 73 firing." The diagnostic script mirrors the new two-step subject extraction at scripts/diagnose-pre-narration-window.ts:556-563, but before/after counts are unchanged.
Suppressed count does not fall, and no claim stops matching — a tune achieved by suppressing everything is the failure mode (mt#4498's ## Outcome shows what this looks like when it nearly happened). Met PR body reports suppressed (21) and no-longer-matched (2) unchanged before/after over the same corpus. Code preserves category patterns and only changes identity-correlation source; see unchanged OUTCOME_CATEGORIES and suppression gating at .minsky/hooks/pre-narration-detector.ts:334-363 and :385-418.
A negative control per new suppression path: the same claim without its evidence still fires. Met New tests at .minsky/hooks/pre-narration-detector.test.ts:1188-1211 verify two negative controls: (1) evidence for a different PR does not suppress; (2) sentence naming two PRs remains ambiguous and fires.
If the chosen direction ALSO fails to move the number, say so and stop rather than iterating — that would be the third tune on this detector and the signal to reconsider the detector, not the patterns. Met PR body explicitly acknowledges SC2 not met and records the stop decision with follow-up (mt#4819). No further widening attempted; only the read-site change and mirrored diagnostic update shipped.

Adoption sweep

Symbol Kind Consumers found Classification Notes
.minsky/hooks/pre-narration-detector.extractUniqueClaimedPrNumber function .minsky/hooks/pre-narration-detector.ts:365-383 — used at the correlation call site (phrase-first, sentence-fallback), scripts/diagnose-pre-narration-window.ts:556-563 — mirrored in diagnostic script to avoid drift, .claude/hooks/pre-narration-detector.ts:372-390 — generated mirror uses it identically Adopted Helper is exported and immediately consumed by the detector and its diagnostic script; no external wiring required by the spec.

Documentation impact

  • no-update-needed — Internal behavior change to suppression identity-correlation source; no CLI flags, config, or operator-facing posture changes. No docs/architecture/hooks/pre-narration-detector.md exists (checked docs/architecture/hooks/), and posture (INJECTION_ENABLED) remains false. Therefore no documentation updates are required.

@edobry
edobry merged commit 757f849 into main Aug 31, 2026
13 checks passed
@edobry
edobry deleted the task/mt-4810 branch August 31, 2026 20:45

@minsky-reviewer minsky-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent adversarial review (Chinese-wall)
Reviewer: minsky-reviewer[bot] via openai:gpt-5
Tier: 2


Verification round: no prior BLOCKING findings to re-check; this iteration introduces no new critical issues. The detector now sources the claim subject from the matched sentence via extractUniqueClaimedPrNumber, wired phrase-first/sentence-fallback, with a distinct suppression reason and mirrored logic in the diagnostic script. Tests cover the new path and negative controls. SC1/SC3/SC4/SC5 are Met; SC2 is explicitly Not Met and recorded per the spec’s stop condition. One NON-BLOCKING observation remains: subject extraction runs over elided text, so quoted-only PR numbers are blanked; consider a raw-sentence fallback. Documentation impact: none (internal change, no posture flip). Approved to merge.

Findings

  • [NON-BLOCKING] .minsky/hooks/pre-narration-detector.ts:345 — Subject extraction still runs on ELIDED context; quoted PR numbers in the sentence are blanked and undiscoverable
    extractUniqueClaimedPrNumber(matched.context) reads from matched.context, which is sourced via extractMatchContext(text, …) where text is the ELIDED assistant prose (elideMarkdownContexts + elideDoubleQuotedSpans). Any PR numbers appearing only inside double-quoted spans within the containing sentence will have been replaced with whitespace before subject extraction runs, so identity-scoped suppression can miss legitimate cases where the only subject mention is quoted (e.g., APPROVED — "PR #123"). Consider attempting extraction against the raw pre-elision sentence as a fallback (or capturing an un-elided rawContext alongside context) while keeping elision for the pattern match itself, so you preserve the anti-quote FP benefit for matching without discarding potentially-useful identity evidence.

Spec verification

Criterion Status Evidence
A direction is chosen and the reason recorded, against the leak decomposition above rather than against a fresh guess. Met Direction (read-site subject from sentence) implemented and documented inline. See .minsky/hooks/pre-narration-detector.ts:218-247 (docblock for extractUniqueClaimedPrNumber) and its use at .minsky/hooks/pre-narration-detector.ts:365-383 (phrase-first, sentence-fallback). PR body explains rationale and ceiling.
Whichever lands, re-run scripts/diagnose-pre-narration-window.ts and record before/after. The bar mt#4498 failed is the one that matters: the firing count must actually move. Not Met PR body states: “The tune did not move the number: 73 firing → 73 firing.” The diagnostic script mirrors the two-step subject extraction at scripts/diagnose-pre-narration-window.ts:556-563, but the before/after counts are unchanged. Follow-up posture decision filed as mt#4819.
Suppressed count does not fall, and no claim stops matching — a tune achieved by suppressing everything is the failure mode (mt#4498's ## Outcome shows what this looks like when it nearly happened). Met PR body records suppressed (21) and no-longer-matched (2) unchanged before/after on the same corpus. Implementation only changes the identity-correlation source; category patterns and suppression gating remain intact (see .minsky/hooks/pre-narration-detector.ts:334-363, :385-418).
A negative control per new suppression path: the same claim without its evidence still fires. Met Tests at .minsky/hooks/pre-narration-detector.test.ts:1188-1251 include two negative controls: evidence for a different PR does not suppress; a sentence naming two PRs remains ambiguous and fires.
If the chosen direction ALSO fails to move the number, say so and stop rather than iterating — that would be the third tune on this detector and the signal to reconsider the detector, not the patterns. Met PR body explicitly acknowledges SC2 not met and records the stop decision (no further widening), with follow-up filed as mt#4819. No additional mechanism churn beyond the read-site change and mirrored diagnostic update.

Adoption sweep

Symbol Kind Consumers found Classification Notes
.minsky/hooks/pre-narration-detector.extractUniqueClaimedPrNumber function .minsky/hooks/pre-narration-detector.ts:365-383 — used at correlation call site (phrase-first, sentence-fallback), scripts/diagnose-pre-narration-window.ts:556-563 — mirrored in diagnostic script to avoid drift, .claude/hooks/pre-narration-detector.ts:372-390 — generated mirror uses it identically Adopted Helper is exported and immediately consumed by the detector, its generated mirror, and the diagnostic script.

Documentation impact

  • no-update-needed — Change is internal to detection logic (source of identity-correlation subject: phrase-first, sentence-fallback). No CLI flags, config, or operator posture changed; no docs/architecture/hooks/pre-narration-detector.md exists (checked docs/architecture/hooks/). Diagnostic script updated to mirror behavior. Therefore, no documentation updates are required.

@minsky-reviewer minsky-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent adversarial review (Chinese-wall)
Reviewer: minsky-reviewer[bot] via openai:gpt-5
Tier: 2


Verification complete: the change reads a claim’s subject from its matched sentence (via extractUniqueClaimedPrNumber) and wires it phrase-first/sentence-fallback with a conservative uniqueness guard. The diagnostic script and generated hook mirror the logic to prevent measurement drift; a distinct suppression reason makes this path measurable. Tests exercise the new path and negative controls. SC1/SC3/SC4/SC5 are Met; SC2 is explicitly Not Met and recorded per the spec’s stop condition. No prior BLOCKING items to re-verify, and no new critical defects found in this diff. Approving as correct and safe to merge.

Spec verification

Criterion Status Evidence
A direction is chosen and the reason recorded, against the leak decomposition above rather than against a fresh guess. Met The implementation adopts the read-site approach and documents it inline. See .minsky/hooks/pre-narration-detector.ts:196-233 for the extractUniqueClaimedPrNumber docblock explaining the rationale and ceiling, and its use at .minsky/hooks/pre-narration-detector.ts:673-681 (phrase-first, sentence-fallback). The same helper and rationale are mirrored in the generated hook at .claude/hooks/pre-narration-detector.ts:199-236 and used at .claude/hooks/pre-narration-detector.ts:676-684.
Whichever lands, re-run scripts/diagnose-pre-narration-window.ts and record before/after. The bar mt#4498 failed is the one that matters: the firing count must actually move. Not Met The PR body records: “The tune did not move the number: 73 firing → 73 firing.” The diagnostic script mirrors the detector’s two-step extraction at scripts/diagnose-pre-narration-window.ts:556-563, ensuring the replay measures the intended behavior, but the before/after counts remain unchanged.
Suppressed count does not fall, and no claim stops matching — a tune achieved by suppressing everything is the failure mode (mt#4498's ## Outcome shows what this looks like when it nearly happened). Met The behavior change is limited to identity-correlation source selection and a new suppression reason; pattern lists and outcome categories are unchanged. The code distinguishes SUPPRESSION_IDENTITY_SCOPED_CONTEXT at .minsky/hooks/pre-narration-detector.ts:689-699, preserving existing reasons otherwise. The PR description reports suppressed (21) and no-longer-matched (2) unchanged on the same corpus.
A negative control per new suppression path: the same claim without its evidence still fires. Met New tests assert non-overreach: ambiguous sentences and evidence for a different PR still fire. See .minsky/hooks/pre-narration-detector.test.ts:1207-1251 — tests “NEGATIVE CONTROL: evidence for a DIFFERENT PR does not silence the claim” and “NEGATIVE CONTROL: a sentence naming two PRs stays ambiguous and fires.”
If the chosen direction ALSO fails to move the number, say so and stop rather than iterating — that would be the third tune on this detector and the signal to reconsider the detector, not the patterns. Met The PR explicitly records that SC2 did not move (73→73) and stops per SC5, deferring the posture decision to mt#4819. No further widening or iteration is attempted in code; only the read-site change and mirrored diagnostic update are present.

Adoption sweep

Symbol Kind Consumers found Classification Notes
.minsky/hooks/pre-narration-detector.extractUniqueClaimedPrNumber function .minsky/hooks/pre-narration-detector.ts — used in detectPreNarrationWithSuppression (phrase-first, sentence-fallback), scripts/diagnose-pre-narration-window.ts — mirrored in diagnostic script to avoid drift, .claude/hooks/pre-narration-detector.ts — generated mirror uses it identically Adopted Helper is exported and immediately consumed by the detector and the diagnostic script; no external wiring required by the spec.

Documentation impact

  • no-update-needed — Internal logic change only: reads claim subject from the matched sentence with a new suppression reason. No CLI flags, config, or operator posture changed (INJECTION_ENABLED remains false). There is no dedicated doc for this hook under docs/architecture/hooks/ (checked directory listing). Diagnostic script updated solely to mirror detector behavior; no user-facing semantics altered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

authorship/co-authored Co-authored by human and AI agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant