Skip to content

Commit 8da7832

Browse files
claude[bot]claude
andauthored
pm(half-states): name the POPULATION each H22 docblock number was measured on (#17793)
Fixes #17626 H22 pages its closed-card window through `closedWindowPagePath` — `GET /repos/{repo}/issues?state=closed&sort=updated&direction=desc&per_page=100&page=N`. Two callers issue the byte-identical request and get different POPULATIONS: the scheduled patrol runner's pages come back **card-only**, a proxied agent container's come back **49.6% pull requests**. Four prose sites in `scripts/pm/check-half-states.mjs` quoted the container's stream while describing the patrol's, so the measurement recipe they carry — followed correctly — yields the wrong number. This is prose only: **no constant moves** (`MEASURED_CLOSED_ISSUE_UPDATES_PER_DAY` stays 139.4, `CLOSED_ISSUE_WINDOW_PAGE_CEILING` stays 40), no H-row, no self-test change. ## The boundary this card asked to survive the fix The population difference itself is **MEASURED**, through the sweep's own numbers. **The runner's `permissions:` block as the MECHANISM is NOT claimed** — the runner's raw response was never read. Every new sentence below is written that way, and the ⚠️ Cost note says it in those words. ## The four sites, before and after **1. The ⚠️ Cost note under `CLOSED_ISSUE_WINDOW_DAYS`** - before: «46% of the rows this stream returns are PULL REQUESTS, filtered out after paging. The horizon is therefore reached in roughly twice the pages a card-only stream would need.» - after: the 46% is named as a **container** reading (49.6%, read 2026-09-11T04:22:36Z, 12 pages / 1,200 rows), the patrol's stream is named card-only, and the runner side is quoted from the sweep's own numbers — the 2026-09-11T01:55:32Z run (34552285557, `2f8ad091`) reports 5 pages, 428 in-window closures, reach 2026-09-07; 428 in-window closures cannot come out of 5 PR-inclusive pages, since only ~250 of those 500 rows would be cards. The 2026-09-09 run is the same shape at 6 pages. **2. The same docblock's present-tense divisor sentence** - before: «re-pin (#16419: the divisor below now reads 415.1)» — present tense against a divisor that now reads 139.4. - after: restated as history — #16419 re-pinned 415.1 on 2026-09-06 from the container stream; #17254 re-pinned on 2026-09-11 from the card-only slice, and the divisor below now reads 139.4. The `~13 pages` this note derives is also marked as a 2026-09-06 container reading, and explicitly **not** comparable to today's 5 pages on population alone — the two readings are five days AND one population apart, with the decomposition left where PR #17627 put it, in `MEASURED_CLOSED_ISSUE_UPDATES_PER_DAY`. **3. `CLOSED_ISSUE_WINDOW_PAGE_CEILING`'s derivation** - before: «4,000 rows reached 12.8 days on the read above (~312/day averaged over that depth), against a 3-day horizon: ~4.3x headroom.» - after: the derivation stands, with a ⚠️ POPULATION note beneath it — that read was container-taken, so only ~2,000 of its 4,000 rows were cards. 40 pages return 4,000 rows either way, but on the runner all 4,000 are cards, so the same ceiling reaches **about twice** as far back: ~25 days rather than 12.8, ~8x headroom rather than ~4.3x. Written as a **note, not a change**: the direction is more headroom and not less, 40 is unchanged, and re-deriving it properly needs a card-only read at depth that nobody has taken. **4. `listRecentlyClosedIssues`'s `rateRows` comment** - before: «the pin this rate is checked against was measured over the RAW stream (400 rows / 0.964 days)» — a description of the 188.3 pin, two re-pins ago. - after: the pin's population as it now stands (500 rows / 3.586 days, read 2026-09-11), plus why the distinction lives at this line: on the patrol runner the stream is card-only, so `rateRows` holds cards and the observed rate is counted on the same population the pin was; the same request from a container returns 49.6% pull requests and `rateRows` would count those too — a rate on one population checked against a pin on another. The `READ` vs `ADMITTED` argument (#4690 with the numbers the right way up) is unchanged. ## The re-measure recipe the file now carries Stated once, in the ⚠️ Cost note, and pointed at from sites 3 and 4: > A container read is NOT the patrol's stream. Filter pull requests OUT of every page BEFORE counting pages or rating rows, and quote the card-only slice. On the 2026-09-11T04:22:36Z container read that slice gives **5 pages / 426 rows / ~139.4 per day**, against **9 pages / 426 / ~256.2 per day** on the whole stream. The slice reproduces the runner's own 5 pages; the raw stream does not. That is the operative half — a seat following the old note from a container reproduced #17254's false `RATE PREMISE DRIFTED` alarm every time. ## Verification All of it taken on the final commit `034c09ace`. Gate families derived with `node scripts/pm/dispatch-gates.mjs --commands` (no paths passed — it takes its own change set from the merge base), each command run with its exit code captured **before any pipe**, then reconciled: > `✓ dispatch-gates --ran: 40 derived famil(ies) accounted for — 40 run, 0 NOT-MEASURED (a DERIVED zero — all 40 recorded an exit code and none of them is 3).` Every one of the 40 exits 0, including `pnpm check:pm-dispatch-gates` (detached — it runs past the foreground cap — and waited on with `tail --pid`). Named readings: - `pnpm check:pm-half-states` — self-test **3656 cases pass** on the base file (`8fa3fe63d`) and **3656 cases pass** after; the count is unchanged because no pin moved and no self-test assertion names any of the rewritten sentences (grepped `46% of the rows`, `415.1`, `0.964`, `312/day` across the tree — the only hits outside this file's own prose are two historical mentions this PR does not touch). - `pnpm check:nul-bytes` — `check-nul-bytes: OK (scanned 8451 text file(s) ... no raw ASCII control bytes)`; plus a self-scan of the edited file, `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'`, zero hits. - `node scripts/check-comment-mask-corpus.mjs` — `6640 files, 0 disagree, 0 unparseable`. - `node scripts/check-scripts-symbol-anchors.mjs` — `3186 anchors across 248 scripts resolve`. - The remaining 36 derived commands exit 0. Repository-wide scans (`pnpm lint` first among them) are CI's run, not this PR's. ## Acceptance notes - noted, not filed: `MEASURED_CLOSED_ISSUE_UPDATES_PER_DAY`'s docblock (landed by PR #17627, outside this card's declared surface) states the runner's token scopes as part of its population paragraph. It does label the reading «Measured, not inferred from the workflow file», so it is not a mechanism claim, but it sits closer to one than the ⚠️ Cost note now does. Successor: the next seat re-pinning that divisor. - noted, not filed: the card names a second possible route — declaring `pull-requests: read` on `half-state-patrol.yml` so the runner and a container read the same stream. This PR takes the recipe route the dispatch chose; the permission route is untouched and its cost (roughly doubling H22's page bill) is unmeasured. - `skip-changeset`: `scripts/pm/**` is not published — no package's `files[]` ships this script. --- _Generated by [Claude Code](https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK)_ --- _Generated by [Claude Code](https://claude.ai/code)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 482d34d commit 8da7832

1 file changed

Lines changed: 70 additions & 21 deletions

File tree

scripts/pm/check-half-states.mjs

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16635,18 +16635,44 @@ async function listRecentlyMergedPullRequests(stats = {}, nowMs = Date.now()) {
1663516635
* needs a different shape (a residue census like H39's, which counts rather than
1663616636
* lists) and is not this window's job.
1663716637
*
16638-
* ⚠️ Cost note: 46% of the rows this stream returns are PULL REQUESTS, filtered
16639-
* out after paging. The horizon is therefore reached in roughly twice the pages
16640-
* a card-only stream would need. ⚖️ The `~6 pages for 3 days` this note used to
16641-
* quote was the pinned divisor's arithmetic and it never described this board:
16642-
* measured 2026-09-06 the horizon sits at ~13 pages, because the LEADING rows
16643-
* run at ~414 updates/day against the 188.3 pinned at the time (the derivation
16644-
* is in `CLOSED_ISSUE_WINDOW_PAGE_CEILING`, and it is why the old 12 bound).
16645-
* Constants here are deliberately NOT self-updating (H8's rule): they are
16646-
* CHECKED against what a sweep observes, never overwritten by it — so that
16647-
* disagreement was closed the one way it can be, by a HAND re-measure and
16648-
* re-pin (#16419: the divisor below now reads 415.1), never by a sweep quietly
16649-
* editing it.
16638+
* ⚠️ Cost note — and the POPULATION every number in it is counted on, which
16639+
* is the half this note had wrong (#17626). The `46% of the rows are PULL
16640+
* REQUESTS` it opened with is a CONTAINER reading: the byte-identical
16641+
* `GET /repos/{repo}/issues?state=closed&sort=updated` page comes back 49.6%
16642+
* pull requests to a proxied agent container (read 2026-09-11T04:22:36Z, 12
16643+
* pages / 1,200 rows) and CARD-ONLY to the scheduled patrol runner, so the
16644+
* "roughly twice the pages" it derived is a container's bill and never this
16645+
* sweep's. The runner side is measured through the sweep's OWN numbers rather
16646+
* than from its response, which no seat can read: the 2026-09-11T01:55:32Z run
16647+
* (34552285557, `2f8ad091`) reports 5 pages, 428 in-window closures and reach
16648+
* 2026-09-07, and 428 in-window closures cannot come out of 5 PR-inclusive
16649+
* pages at all — only ~250 of those 500 rows would be cards. The 2026-09-09
16650+
* run is the same shape at 6 pages. ⛔ WHY the two streams differ is NOT
16651+
* claimed here: the runner's raw response was never read. The population
16652+
* difference itself is measured.
16653+
*
16654+
* ⭐ RE-MEASURE RECIPE, and it is the operative half of this note: a container
16655+
* read is NOT the patrol's stream. Filter pull requests OUT of every page
16656+
* BEFORE counting pages or rating rows, and quote the card-only slice. On the
16657+
* 2026-09-11T04:22:36Z read that slice gives 5 pages / 426 rows / ~139.4 per
16658+
* day against 9 pages / 426 / ~256.2 per day on the whole stream — the slice
16659+
* reproduces the runner's own 5 pages, the raw stream does not. ⛔ Never pin,
16660+
* and never cost a horizon, from the raw stream.
16661+
*
16662+
* ⚖️ The `~6 pages for 3 days` this note quoted before that was the pinned
16663+
* divisor's arithmetic and it never described this board: measured 2026-09-06
16664+
* FROM A CONTAINER the horizon sat at ~13 pages, because the leading rows of
16665+
* that PR-inclusive read ran at ~414 updates/day against the 188.3 pinned at
16666+
* the time (the derivation is in `CLOSED_ISSUE_WINDOW_PAGE_CEILING`, and it is
16667+
* why the old 12 bound). ⛔ That ~13 and today's 5 are not a population
16668+
* comparison: the two readings are five days AND one population apart, and the
16669+
* decomposition is in `MEASURED_CLOSED_ISSUE_UPDATES_PER_DAY`. Constants here
16670+
* are deliberately NOT self-updating (H8's rule): they are CHECKED against what
16671+
* a sweep observes, never overwritten by it — so that disagreement was closed
16672+
* the one way it can be, by a HAND re-measure and re-pin, never by a sweep
16673+
* quietly editing it. #16419 re-pinned 415.1 on 2026-09-06 from the container
16674+
* stream; #17254 re-pinned on 2026-09-11 from the card-only slice, and the
16675+
* divisor below now reads 139.4.
1665016676
*/
1665116677
export const CLOSED_ISSUE_WINDOW_DAYS = 3;
1665216678

@@ -16682,7 +16708,20 @@ export const CLOSED_ISSUE_WINDOW_DAYS = 3;
1668216708
* 4,000 rows reached 12.8 days on the read above (~312/day averaged over that
1668316709
* depth), against a 3-day horizon: ~4.3x headroom, and headroom measured on
1668416710
* the whole depth the cap can actually be spent on rather than on a pinned
16685-
* rate. 40 REST calls is also the budget this sweep gets for the pass, which
16711+
* rate.
16712+
*
16713+
* ⚠️ POPULATION, and it is why ~4.3x is a floor rather than the reading: the
16714+
* read above was taken from a proxied agent container, whose pages carry 49.6%
16715+
* pull requests, while the patrol runner pages the same URL CARD-ONLY (the
16716+
* measurement, the recipe and the boundary are in the ⚠️ Cost note under
16717+
* `CLOSED_ISSUE_WINDOW_DAYS`). 40 pages return 4,000 rows either way, but only
16718+
* ~2,000 of the rows above were cards, so on the runner the same ceiling
16719+
* reaches ABOUT TWICE as far back — ~25 days rather than 12.8, ~8x headroom
16720+
* against the 3-day horizon rather than ~4.3x. ⛔ A note, not a change: the
16721+
* direction is more headroom and not less, 40 is unchanged, and re-deriving it
16722+
* would need a card-only read at depth that nobody has taken.
16723+
*
16724+
* 40 REST calls is also the budget this sweep gets for the pass, which
1668616725
* is the OTHER thing a quota backstop is: ⛔ not a number to raise again the
1668716726
* next time it binds. A pass that binds it is reporting that the board's
1668816727
* closed-issue activity has grown past what one sweep can page — the remedy
@@ -16922,14 +16961,24 @@ async function listRecentlyClosedIssues(
1692216961
let reachedMs = null;
1692316962
// Every row this pass READ, projected to the one stamp the observed update
1692416963
// rate is counted over (#16393). ⛔ Deliberately the rows READ and not the
16925-
// rows ADMITTED: the pin this rate is checked against was measured over the
16926-
// RAW stream (400 rows / 0.964 days), while `out` holds only the in-window
16927-
// closures — a strictly smaller population over a strictly shorter span. Rate
16928-
// them against each other and the difference between two quantities reads as
16929-
// drift in one of them, which is the #4690 inversion with the numbers the
16930-
// right way up. Projected rather than retained whole because one field is all
16931-
// the instrument reads, and these pages are the largest thing this sweep
16932-
// holds.
16964+
// rows ADMITTED: the pin this rate is checked against is measured over the
16965+
// whole stream this pager consumes (500 rows / 3.586 days, read 2026-09-11),
16966+
// while `out` holds only the in-window closures — a strictly smaller
16967+
// population over a strictly shorter span. Rate them against each other and
16968+
// the difference between two quantities reads as drift in one of them, which
16969+
// is the #4690 inversion with the numbers the right way up.
16970+
// ⚠️ POPULATION, and it is why this says READ rather than "every row the
16971+
// endpoint returns": on the patrol runner that stream is CARD-ONLY, so these
16972+
// rows are cards and the rate is counted on the same population the pin was.
16973+
// The byte-identical request from a proxied agent container comes back 49.6%
16974+
// pull requests and `rateRows` would count those too — a rate on one
16975+
// population checked against a pin on another, which is #17626. ⛔ So a hand
16976+
// re-measure filters pull requests out BEFORE counting; the recipe is in the
16977+
// ⚠️ Cost note under `CLOSED_ISSUE_WINDOW_DAYS`. The earlier reading here,
16978+
// `RAW stream (400 rows / 0.964 days)`, described the 188.3 pin and not the
16979+
// 139.4 `MEASURED_CLOSED_ISSUE_UPDATES_PER_DAY` now carries.
16980+
// Projected rather than retained whole because one field is all the
16981+
// instrument reads, and these pages are the largest thing this sweep holds.
1693316982
const rateRows = [];
1693416983
let page = 1;
1693516984
for (; page <= CLOSED_ISSUE_WINDOW_PAGE_CEILING; page++) {

0 commit comments

Comments
 (0)