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
feat(pm): H22 judges closed cards against a dated closure floor (#12906)
* feat(pm): H22 judges closed cards against a dated closure floor
The half-state patrol's closed-card row reports a card that left the board
still carrying a `pm:*` state label. A sibling install measured its own closed
surface at ~87% residue density and had to ship with the row switched off: at
that density H22 reports the CONVENTION rather than a defect, and the rows
exhaust the anchor body budget every other predicate shares.
That install's card framed the choice as two-way — either stripping is the rule
and ~815 closed cards need a backfill first, or the row is simply not wanted.
`PM_SWEEP_CLOSED_FLOOR` is the third option both readings omit: judge only
cards closed on/after a cutover date. Historical `pm:*` on an old closed card
is inert (the loop reads state on open cards only), so the row gets its whole
value — residue produced from now on, while the paired write is still a live
duty — at zero backfill and zero historical noise. No code path here writes a
label, so no bulk rewrite of closed cards is reachable.
Unset is the default and preserves today's behaviour exactly. A malformed floor
is refused with exit 2 rather than degrading to "no floor", which on the
install that needs one would restore the flood four times a day; the parse is
round-tripped because `Date.parse` rolls `2026-02-31` to March rather than
rejecting it. The rendered summary names the floor, so a floored pass cannot
overstate what it judged.
* docs(pm): codify strip-`pm:*`-on-close in the label-discipline section
The convention was ambiguous enough that two seats read the same board and
landed on opposite rules. Fleet practice has since settled it — the 2026-08-27
/28 landing accounting stripped `pm:*` from every closed card as a hard step —
so this writes the answer down where the loop reads it, which is the cure the
original card asked for.
Ratchet is zero-headroom, so this is net 0 lines. Cut ledger in the PR body.
---------
Co-authored-by: Claude <noreply@anthropic.com>
// Honoured, both directions. The old card is the ~815-card backlog in
9669
+
// miniature: it carries real residue and is deliberately NOT a finding.
9670
+
t('H22 floor: a card closed BEFORE the floor is out of scope', h22ClosedCardPmResidue(closedOn(['pm:dispatched'], '2026-08-01T09:00:00Z'), FLOOR), null);
9671
+
t('H22 floor: …however much residue it carries', h22ClosedCardPmResidue(closedOn(['pm:dispatched', 'pm:queue', 'pm:blocked'], '2026-01-01T00:00:00Z'), FLOOR), null);
9672
+
t('H22 floor: a card closed AFTER the floor is judged', typeof h22ClosedCardPmResidue(closedOn(['pm:dispatched'], '2026-08-29T09:00:00Z'), FLOOR), 'string');
9673
+
t('H22 floor: …and the row still names the residue label', h22row(closedOn(['pm:dispatched'], '2026-08-29T09:00:00Z'), FLOOR).includes('`pm:dispatched`'), true);
9674
+
// The boundary is inclusive: the cutover date is the first day the convention
9675
+
// applies, so a card closed within it is the convention's own population.
9676
+
t('H22 floor: a card closed ON the floor date is judged', typeof h22ClosedCardPmResidue(closedOn(['pm:queue'], '2026-08-28T00:00:00Z'), FLOOR), 'string');
9677
+
t('H22 floor: …and later the same day too', typeof h22ClosedCardPmResidue(closedOn(['pm:queue'], '2026-08-28T23:59:59Z'), FLOOR), 'string');
9678
+
t('H22 floor: one second before the floor is out', h22ClosedCardPmResidue(closedOn(['pm:queue'], '2026-08-27T23:59:59Z'), FLOOR), null);
9679
+
// The floor narrows scope; it never invents findings. A clean recent card is
9680
+
// still clean, and an OPEN card is still not this row's.
9681
+
t('H22 floor: a clean card after the floor is still clean', h22ClosedCardPmResidue(closedOn(['domain:cli'], '2026-08-29T09:00:00Z'), FLOOR), null);
9682
+
t('H22 floor: the closed gate still outranks the floor', h22ClosedCardPmResidue({ ...issue(['pm:dispatched']), state: 'open', closed_at: null }, FLOOR), null);
9683
+
// Fail-OPEN on an unreadable closure date: the floor cannot be applied, so
9684
+
// the card stays visible rather than being dropped on unread data (#4690).
9685
+
t('H22 floor: a card with no closed_at is judged, not dropped', typeof h22ClosedCardPmResidue(closedOn(['pm:dispatched'], null), FLOOR), 'string');
9686
+
t('H22 floor: …and an unparseable one likewise', typeof h22ClosedCardPmResidue(closedOn(['pm:dispatched'], 'not-a-date'), FLOOR), 'string');
9687
+
9688
+
// Floor ABSENT — the default, and the property that makes this change a
9689
+
// no-op for the install that wants every card in the window judged.
9690
+
t('H22 floor: absent floor judges an old closed card exactly as before', typeof h22ClosedCardPmResidue(closedOn(['pm:dispatched'], '2026-01-01T00:00:00Z')), 'string');
9691
+
t('H22 floor: …an explicit null is the same as omitting it', typeof h22ClosedCardPmResidue(closedOn(['pm:dispatched'], '2026-01-01T00:00:00Z'), null), 'string');
9692
+
t('H22 floor: …and a clean old card is still clean', h22ClosedCardPmResidue(closedOn(['domain:cli'], '2026-01-01T00:00:00Z'), null), null);
9693
+
9694
+
// resolveClosureFloor — the env reading, including the loud refusal.
9695
+
t('closure floor: unset means no floor', resolveClosureFloor({}).floor, null);
9696
+
t('closure floor: …and that is a VALID reading, not an error', resolveClosureFloor({}).valid, true);
9697
+
t('closure floor: …reported as the default source', resolveClosureFloor({}).source, 'default');
t('closure floor: a YYYY-MM-DD date resolves to UTC midnight', resolveClosureFloor({ PM_SWEEP_CLOSED_FLOOR: '2026-08-28' }).floor.toISOString(), '2026-08-28T00:00:00.000Z');
9700
+
t('closure floor: …and is valid', resolveClosureFloor({ PM_SWEEP_CLOSED_FLOOR: '2026-08-28' }).valid, true);
t('summary: …and says the earlier closures are not a reading about them', summaryLine({ repo: 'r', issues: 1, unscoped: 1, prs: 0, merged: 0, closed: 200, closedFloor: '2026-08-28' }, 0).includes('NOT a reading about them'), true);
0 commit comments