Skip to content

Commit 680df51

Browse files
committed
tooling(pm): H22's closed pass pages to its horizon under a 40-page cap, and states the horizon it reached
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
1 parent 507fd3a commit 680df51

1 file changed

Lines changed: 105 additions & 3 deletions

File tree

scripts/pm/check-half-states.mjs

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14204,7 +14204,7 @@ async function sweepInto(findings, seen, seenPrs, seenMerged, seenUnscoped, seen
1420414204
// as one that passed (#13798).
1420514205
const SELF_TEST_VERDICT = 'check-half-states self-test reached its verdict';
1420614206

14207-
function selfTest() {
14207+
async function selfTest() {
1420814208
const cases = [];
1420914209
const t = (name, actual, expected) => cases.push([name, actual, expected]);
1421014210
// -- Summary-disclosure cases go through THIS, never through the raw line ---
@@ -16843,6 +16843,7 @@ function selfTest() {
1684316843
const richLine = summaryLine({
1684416844
repo: 'o/r', issues: 3, unscoped: 4, prs: 2, merged: 5,
1684516845
closed: 200, closedFloor: '2026-08-28', closedPages: 12, closedWindowTruncated: true,
16846+
closedReachedAt: '2026-09-03',
1684616847
mergedPages: 12, mergedWindowTruncated: true,
1684716848
commits: 300, commitBindings: 51, commitBindingMessages: 44, commitPages: 12, commitWindowTruncated: true,
1684816849
openListingPages: 20, openListingsTruncated: ['listAllOpenIssues'],
@@ -18136,9 +18137,110 @@ function selfTest() {
1813618137
t('open summary: …and a complete pass says none of that', saidBy('openListings', win13606({ openListingPages: 11 })).includes('Ceiling-bound listing(s)'), false);
1813718138
// ⛔ No bare-number rendering of a capped pass: every truncated window must
1813818139
// carry the word, in every medium the summary feeds.
18139-
t('summary: a capped H22 pass never reads as a plain page count', /H22's closed-card window is a TIME cap of 3 day\(s\), read in 12 page\(s\)\./u.test(saidBy('h22Window', win13606({ closedPages: 12, closedWindowTruncated: true }))), false);
18140+
t('summary: a capped H22 pass never reads as a plain page count', new RegExp(`H22's closed-card window is a TIME cap of ${CLOSED_ISSUE_WINDOW_DAYS} day\\(s\\), read in ${CLOSED_ISSUE_WINDOW_PAGE_CEILING} page\\(s\\)\\.`, 'u').test(saidBy('h22Window', win13606({ closedPages: CLOSED_ISSUE_WINDOW_PAGE_CEILING, closedWindowTruncated: true }))), false);
1814018141
t('summary: all three converted windows ride the enumerated contract', ['closedPages', 'closedWindowTruncated', 'commitPages', 'commitWindowTruncated', 'openListingPages', 'openListingsTruncated'].every((k) => SWEEP_COUNT_KEYS.includes(k)), true);
1814118142

18143+
// ---- H22's REACH, and the ceiling that bound before the horizon (#16217) --
18144+
//
18145+
// The state this repairs was SELF-DECLARING and persisted anyway: two live
18146+
// read-only sweeps on 2026-09-06 printed `TRUNCATED at the 12-page quota
18147+
// ceiling BEFORE reaching that horizon`, with the remedy sentence ("the
18148+
// ceiling needs raising") already in the text. What no run ever printed is
18149+
// HOW SHORT the pass was — and that is the whole difference between a pass an
18150+
// hour shy of its horizon and one that read a third of it. So the repair is
18151+
// two-sided, and both sides are pinned here: the cap is sized against the
18152+
// depth it buys, and the clause reports the reach as a date on EVERY run.
18153+
18154+
// The reach reading. ⛔ Deliberately NOT the stop predicate's reading — the
18155+
// stop predicate is conservative on the LAST row so one bad stamp cannot end
18156+
// the pass early, while the reach is a minimum over everything readable so
18157+
// one bad last row cannot erase a reach the page already proved. Same page,
18158+
// two answers, and collapsing them would make one of the two wrong.
18159+
t('H22 reach: the oldest readable stamp on the page is the reach', oldestPageStamp(pg13606(100, 5)), Date.parse(ago13606(5)));
18160+
t('H22 reach: an unreadable LAST row does not erase it', oldestPageStamp([...pg13606(99, 5), { updated_at: 'nope' }]), Date.parse(ago13606(5)));
18161+
t('H22 reach: …while that same page does NOT stop the paging', pageExhaustsWindow([...pg13606(99, 5), { updated_at: 'nope' }], H13606), false);
18162+
t('H22 reach: a page with nothing dateable reached nowhere', oldestPageStamp([{ updated_at: 'nope' }, {}]), null);
18163+
t('H22 reach: an empty page reached nowhere', oldestPageStamp([]), null);
18164+
t('H22 reach: a non-array reached nowhere, and does not throw', oldestPageStamp(null), null);
18165+
t('H22 reach: the field is selectable, like the stop predicate\'s', oldestPageStamp([{ closed_at: ago13606(9) }], 'closed_at'), Date.parse(ago13606(9)));
18166+
t('H22 reach: it renders as a plain date, which is what a reader compares', reachedDate(Date.parse('2026-09-03T17:41:14Z')), '2026-09-03');
18167+
t('H22 reach: ⛔ nowhere renders as nothing, never as today', reachedDate(null), null);
18168+
t('H22 reach: …and an unusable number likewise', reachedDate(Number.NaN), null);
18169+
18170+
// ---- The three shapes, driven through the REAL pager on synthetic pages.
18171+
// The seam is `listRecentlyClosedIssues`'s page reader, so these cases pin
18172+
// the loop the sweep actually runs rather than a re-typed copy of it — the
18173+
// failure this file names by name in `pmLabelListingPath`.
18174+
const closedStream = (byPage) => async (page) => byPage[page - 1] ?? [];
18175+
const fullClosedPage = (daysAgo) =>
18176+
Array.from({ length: 100 }, (_, i) => closed13606(i, daysAgo, daysAgo));
18177+
18178+
// SHAPE 1 — the horizon reached UNDER the cap. The pass stops itself, and
18179+
// says so: three pages, no truncation, and a date for how far it got.
18180+
const reachedStats = {};
18181+
const reachedRows = await listRecentlyClosedIssues(
18182+
reachedStats,
18183+
NOW13606,
18184+
closedStream([fullClosedPage(1), fullClosedPage(2), fullClosedPage(5)]),
18185+
);
18186+
t('H22 pager: a page past the horizon ends the pass', reachedStats.closedPages, 3);
18187+
t('H22 pager: …and that is a boundary, not a ceiling', reachedStats.closedWindowTruncated, false);
18188+
t('H22 pager: …with the reach it actually got, as a date', reachedStats.closedReachedAt, reachedDate(Date.parse(ago13606(5))));
18189+
t('H22 pager: …and only the in-horizon closures are admitted', reachedRows.length, 200);
18190+
t('H22 pager: …the clause says the boundary was reached', saidBy('h22Window', win13606(reachedStats)).includes('boundary reached'), true);
18191+
t('H22 pager: …and states the reach beside the day count', saidBy('h22Window', win13606(reachedStats)).includes(`TIME cap of ${CLOSED_ISSUE_WINDOW_DAYS} day(s), reaching back to ${reachedStats.closedReachedAt}`), true);
18192+
18193+
// SHAPE 1b — the teeth. A stream whose horizon sits on page 13 is the board
18194+
// measured 2026-09-06, and it is the run the old 12-page ceiling structurally
18195+
// could not finish: not late, TRUNCATED, four times a day.
18196+
const deepStats = {};
18197+
await listRecentlyClosedIssues(
18198+
deepStats,
18199+
NOW13606,
18200+
closedStream([...Array.from({ length: 12 }, (_, i) => fullClosedPage(0.2 * (i + 1))), fullClosedPage(5)]),
18201+
);
18202+
t('H22 pager: the 13th page the old 12-page ceiling could never reach ends the pass', deepStats.closedPages, 13);
18203+
t('H22 pager: …so the measured board now completes its horizon', deepStats.closedWindowTruncated, false);
18204+
t('H22 pager: …which the retired ceiling was one page short of', deepStats.closedPages > 12, true);
18205+
18206+
// SHAPE 2 — the cap biting FIRST. Every page still inside the horizon, so the
18207+
// pass runs out of quota; it must announce that AND say how far it got.
18208+
const cappedStats = {};
18209+
await listRecentlyClosedIssues(
18210+
cappedStats,
18211+
NOW13606,
18212+
closedStream(Array.from({ length: CLOSED_ISSUE_WINDOW_PAGE_CEILING + 5 }, (_, i) => fullClosedPage(i / 20))),
18213+
);
18214+
t('H22 pager: a stream that never crosses the horizon spends the whole cap', cappedStats.closedPages, CLOSED_ISSUE_WINDOW_PAGE_CEILING);
18215+
t('H22 pager: …and that is TRUNCATED, not a completed window', cappedStats.closedWindowTruncated, true);
18216+
t('H22 pager: …with the reach it got before the quota ran out', cappedStats.closedReachedAt, reachedDate(Date.parse(ago13606((CLOSED_ISSUE_WINDOW_PAGE_CEILING - 1) / 20))));
18217+
const cappedClause = saidBy('h22Window', win13606(cappedStats));
18218+
t('H22 pager: …the clause says TRUNCATED', cappedClause.includes('⛔ TRUNCATED'), true);
18219+
t('H22 pager: …names the ceiling that bound it', cappedClause.includes(`${CLOSED_ISSUE_WINDOW_PAGE_CEILING}-page quota ceiling`), true);
18220+
t('H22 pager: …states the reach anyway, which is what makes it a reading', cappedClause.includes(`reaching back to ${cappedStats.closedReachedAt}`), true);
18221+
// ⛔ The sentence #16217 retires: a truncated pass that names its reach needs
18222+
// no remedy prescribed for it, and the one it used to print was wrong as
18223+
// often as not — a ceiling is a budget, not a number to raise on every bind.
18224+
t('H22 pager: …and no longer prescribes raising the ceiling', cappedClause.includes('the ceiling needs raising'), false);
18225+
// …while the callers that CANNOT state a reach keep that sentence, because
18226+
// for them it is still the only actionable half. #16217 is one leg, not a
18227+
// rewording of the shared clause.
18228+
t('H22 pager: H23\'s truncated clause is untouched by that retirement', saidBy('h23Window', win13606({ commitPages: COMMIT_WINDOW_PAGE_CEILING, commitWindowTruncated: true })).includes('the ceiling needs raising'), true);
18229+
t('H22 pager: …and so is the open listings\' one', saidBy('openListings', win13606({ openListingPages: 20, openListingsTruncated: ['listAllOpenIssues'] })).includes('the ceiling needs raising'), true);
18230+
18231+
// SHAPE 3 — an empty board. ⛔ The one shape that must not be dated: it read
18232+
// nothing, so it reached nowhere, and a clause rendering today here would be
18233+
// #4690 in a new costume — an unread input reading as a complete one.
18234+
const emptyStats = {};
18235+
const emptyRows = await listRecentlyClosedIssues(emptyStats, NOW13606, closedStream([]));
18236+
t('H22 pager: an empty board yields no rows', emptyRows.length, 0);
18237+
t('H22 pager: …costs the one page it takes to learn that', emptyStats.closedPages, 1);
18238+
t('H22 pager: …is a clean pass, not a truncated one', emptyStats.closedWindowTruncated, false);
18239+
t('H22 pager: …and reached NOWHERE, which it states as no date at all', emptyStats.closedReachedAt, null);
18240+
t('H22 pager: …so the clause invents no date', saidBy('h22Window', win13606(emptyStats)).includes('reaching back to'), false);
18241+
t('H22 pager: …and still discloses which bound ended it', saidBy('h22Window', win13606(emptyStats)).includes('boundary reached'), true);
18242+
t('H22 pager: the reach rides the enumerated forwarding contract', SWEEP_COUNT_KEYS.includes('closedReachedAt'), true);
18243+
1814218244
// -- H26: a block whose target can never close, + the stale chain (#11219) --
1814318245
// The measured cards, by name, and both directions of every leg.
1814418246
const waiting = (number = 1119) => ({
@@ -20390,7 +20492,7 @@ if (isMain) {
2039020492
process.exit(2);
2039120493
}
2039220494
if (process.argv.includes('--self-test')) {
20393-
if (selfTest() !== SELF_TEST_VERDICT) {
20495+
if ((await selfTest()) !== SELF_TEST_VERDICT) {
2039420496
console.error(
2039520497
'\n✗ check-half-states self-test: selfTest() returned without reaching its verdict,\n'
2039620498
+ 'so no success line was printed. Exiting 0 here would report a self-test\n'

0 commit comments

Comments
 (0)