Found while converting the remaining count-shaped windows in PR #13628 (card #13606). Not fixed there — it is a defect in existing test scaffolding, outside that card's file-surface remit of "the windows and their disclosure", and the workaround it forced is itself the evidence.
The shape
summaryLine returns ONE long sentence carrying every pass's disclosure. H8's window-disclosure cases (landed in PR #13601) assert against that whole string:
t('H8 summary: a completed window says the horizon was reached',
h8win({ mergedPages: 9, mergedWindowTruncated: false }).includes('horizon reached'), true);
t('H8 summary: …and does NOT claim the horizon was reached',
h8win({ mergedPages: MERGED_WINDOW_PAGE_CEILING, mergedWindowTruncated: true }).includes('horizon reached'), false);
Both were exact and falsifiable when H8 was the only window on that line. They are not scoped to H8's clause — .includes searches the entire summary — so any OTHER clause containing the same phrase satisfies the positive case and breaks the negative one.
Measured, not suspected
PR #13628 adds three more disclosures to the same line. Drafting them with the natural parallel wording ("horizon reached") turned the negative case RED immediately: a TRUNCATED H8 window now had "horizon reached" in its summary, contributed by H22's healthy clause standing beside it.
That red was the lucky direction. The unlucky one is the positive case a completed window says the horizon was reached, which a neighbouring clause satisfies silently — it would keep passing even if H8's own disclosure were deleted outright. That is a check that cannot fail, in the file whose entire subject is refusing exactly that.
PR #13628 worked around it by giving the shared helper a distinct phrase ("boundary reached"), documented at describeWindowBound. That keeps every current case falsifiable, but it is a naming convention holding the line, and it does not survive the next author who reaches for the obvious word.
Why a card rather than a fix in that PR
The repair is to scope each window's assertions to that window's own clause rather than to the whole sentence — e.g. extract the clause per window and assert on it, so a case can only be satisfied by the speaker it names. That is a change to how the summary's cases are written across every window that has one (H8, H22, H23, H35, the open listings), which is broader than the converting card's surface and would have mixed a scaffolding refactor into a behavioural conversion.
Suggested acceptance: no case asserting a window's disclosure can be satisfied by text another window contributed. A cheap proof is an ablation per window — delete that window's clause and confirm ITS cases go red while the others stay green.
File surface: scripts/pm/check-half-states.mjs (the selfTest summary cases).
Generated by Claude Code
Found while converting the remaining count-shaped windows in PR #13628 (card #13606). Not fixed there — it is a defect in existing test scaffolding, outside that card's file-surface remit of "the windows and their disclosure", and the workaround it forced is itself the evidence.
The shape
summaryLinereturns ONE long sentence carrying every pass's disclosure. H8's window-disclosure cases (landed in PR #13601) assert against that whole string:Both were exact and falsifiable when H8 was the only window on that line. They are not scoped to H8's clause —
.includessearches the entire summary — so any OTHER clause containing the same phrase satisfies the positive case and breaks the negative one.Measured, not suspected
PR #13628 adds three more disclosures to the same line. Drafting them with the natural parallel wording ("horizon reached") turned the negative case RED immediately: a TRUNCATED H8 window now had "horizon reached" in its summary, contributed by H22's healthy clause standing beside it.
That red was the lucky direction. The unlucky one is the positive case
a completed window says the horizon was reached, which a neighbouring clause satisfies silently — it would keep passing even if H8's own disclosure were deleted outright. That is a check that cannot fail, in the file whose entire subject is refusing exactly that.PR #13628 worked around it by giving the shared helper a distinct phrase ("boundary reached"), documented at
describeWindowBound. That keeps every current case falsifiable, but it is a naming convention holding the line, and it does not survive the next author who reaches for the obvious word.Why a card rather than a fix in that PR
The repair is to scope each window's assertions to that window's own clause rather than to the whole sentence — e.g. extract the clause per window and assert on it, so a case can only be satisfied by the speaker it names. That is a change to how the summary's cases are written across every window that has one (H8, H22, H23, H35, the open listings), which is broader than the converting card's surface and would have mixed a scaffolding refactor into a behavioural conversion.
Suggested acceptance: no case asserting a window's disclosure can be satisfied by text another window contributed. A cheap proof is an ablation per window — delete that window's clause and confirm ITS cases go red while the others stay green.
File surface:
scripts/pm/check-half-states.mjs(theselfTestsummary cases).Generated by Claude Code