Repository navigation
fix(pm): board-snapshot reconciles a disagreeing census and settles its cursor, so the patrol is green again - #27769
Merged
Conversation
…ts cursor, so the patrol is green again Every scheduled snapshot since 2026-10-26T15:11Z failed its count check with a SURPLUS of 1 to 3. Measured against the API: the archive held three open issues the board does not. #25896 was transferred to objectstack-ai/hotcrm#2307, and the listing never returns a transferred number. #26084 and #26638 were closed seconds before the run's cursor: the listing served their pre-close rows while serving later rows fresh, and the cursor taken from the newest row skipped them for good. The same lag left four closed pull requests archived open. - A live walk's cursor is stored no later than LISTING_SETTLE_MS (15 min) before its last listing read, so the next run re-reads the window the listing may not have caught up on. - A census that disagrees with the board is reconciled before it is reported: the open listing is compared with the archive's open records, each disagreeing number is read on its own (redirects not followed), a live record is archived again, a 301 to another repository is written onto the record as transferred_to and counted apart, and a 404/410 is left as archived so it still reds the run. The board's arithmetic is then read again and the census retaken. Self-test: a new battery reproduces today's red (stale close + transfer), the settle window alone, and a destroyed number that stays red; each fix ablated turns its cases red. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cyJuqtXc5LcmkT6E4D
…cile, and reconciles every verdict Seat review r1 of the reconcile found paths where a real drift could still read green. Each is now pinned in the self-test and ablated: - An issue whose own read answers 404/410 and that no ledger answers for keeps the run red whatever the counts say (withDestroyedIssues; verdict `destroyed` when the arithmetic agrees). - The reconcile runs on an agreeing census too, since errors of opposite sign cancel in the counts and never in the records. - A reconcile cut short by its budget reports the census from before it against the board read before it, keeps what it read, and says CUT SHORT. It runs under a reserve (BOARD_READ_RESERVE) so the second board read fits. - A gone-ledger number is subtracted only while the census counts it open, so a ledgered transfer cannot absorb a real surplus. - The fake fetch follows redirects unless told manual, and a 200 that names another number or repository is unreadable, never archived. - A 5xx on one number's read is that number's verdict, not the run's. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cyJuqtXc5LcmkT6E4D
Contributor
Author
|
Seat review r1 addressed at head 1150f2c. Each item is pinned in
Live, against a fresh copy of Note on acceptance: Generated by Claude Code |
…ly, and names the census a cut-short run reports Seat review r2: the census's open-number set held open pull requests too, so a ledgered deleted pull request could cancel part of a real issue surplus. The ledger is now subtracted only for numbers counted as open issues (censusArchive openIssueNumbers), pinned and ablated. On a cut-short reconcile the archive line now says it is the census after the repairs, while the count check is the census from before them. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cyJuqtXc5LcmkT6E4D
Contributor
Author
|
domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS 维护者速读
席位意见:ACCEPT。席位复核三轮(第一轮 6 条、第二轮 1 条,均已改正并带自测钉子与消融),CI 全绿。 席位核对
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Elon · project thread
Fixes #27726
Clause-②: no
Metadata-protocol: none
维护者速读
scripts/pm/board-snapshot.mjs,不发布任何包。被销毁(404)的卡照样报红,没有放宽。回滚就是 revert 这一个提交。scripts/pm/board-snapshot.mjs里的reconcileOpenSet(核对逻辑),然后是settledCursor和numberReadVerdict。node scripts/pm/board-snapshot.mjs --self-test,预期最后一行是OK … 191 cases pass across 14 batteries。What changes
scripts/pm/board-snapshot.mjsonly.The cursor settles. A live walk's stored cursor (the delta's, or the incremental walk's) is now no later than
LISTING_SETTLE_MS(15 min) before the instant its last listing page was read (settledCursor). The next run re-reads that trailing window.sinceis inclusive, so this is an over-read that writes identical bytes unless a row really changed. On a quiet board the cursor is already older and does not move.A disagreeing census is reconciled before it is reported (
reconcileOpenSet). When the first count check reads SHORTFALL or SURPLUS, the open listing (openSetPath, creation order) is compared with the archive's open records (reconcileCandidates; gone-ledger numbers excluded, capped atRECONCILE_MAX_NUMBERS). Each number the two disagree on is read on its own, with redirects not followed (numberReadVerdict):transferred_to. The record stays, and the census counts it apart (counts.issues_transferred).--restore.The board's arithmetic is then read again and the census retaken. The reported verdict is that second reading. The first one is kept in
run.reconcileand printed on thereconcileline.The read helper gains a
replymode for the per-number read, and stays the file's onlyfetch. The header gains § "A listing that lags, and a card that moved", and the SURPLUS wording now says that a transfer is recorded rather than ledgered.Why — measured
Every scheduled snapshot since 2026-10-26T15:11Z reported SURPLUS 1 to 3, read from the 22 manifests on
board-archive(ok through 10-26T08:38Z, then 1, 2, 3). I diffed the archive tip (run 40947805554, 20:21Z: archived 323, gone 62, board 258) against the API. Exactly three open issues were archived that the board does not hold:So it was not a count race. Both candidates on the card are partly true. It is a persistent drift with two classes: a transferred number, and a row the listing served stale inside the read window, after which the newest-row cursor skipped it for good. The same lag had left four closed PRs archived open (#20052, #20072, #20074, #22635). The issue-only count check could not see those.
Tests
New battery the lagging listing and the moved card (22 cases, floor 13 → 14 batteries) in
--self-test. The fake board gainslagging/lagListings(serves a row's pre-update version),moved(301) anddestroyed(404):transferred_to. The board is read twice, and the second read comes after the repair. The next run reconciles nothing and never reads the moved number again.--restore=301. A gone-ledger number is never read. A blank reconcile listing compares nothing and reads no number.settledCursor,reconcileCandidates,numberReadVerdict(cross-repo 301, same-repo 301, 404/410, 5xx) andopenSetPath.Ablation: with the reconcile disabled, 9 cases go red. With the settle disabled, 2 cases go red. Restored, all 191 pass.
Acceptance notes
ObjectSchema.fieldsconstructor/prototype refusal through the bannedKeys arm (#19346) #19538, feat(spec):ISecurityServicegainsresolveEffectiveObjectPermissions, the effective-object-permission reader (#19539) #19540) are destroyed records outside the issue count check. A reconcile reads them each time it runs (5 requests) and names them as destroyed. Nothing quiets them except the gone ledger, which is unchanged.gone.jsonstay there and are excluded from the reconcile, so nothing is counted twice.Fleet Patrolssnapshot run going green. The live reading below predicts it.Verification
Live run of this head against a scratch copy of board-archive (read-only against GitHub, wrote only the copy)
A second run straight after: no reconcile,
count check ok, 34 numbers in 47 requests (the settle window's re-read), EXIT=0.dispatch-gates
node scripts/pm/dispatch-gates.mjs --commandsderives 38 families. All 38 were run with exit codes captured before any pipe. Nine first exited 3 (yaml/@changesets/climissing in a fresh worktree) and were re-run afterpnpm install --frozen-lockfile, exit 0.--ranreconcile:38 derived famil(ies) accounted for — 38 run, 0 NOT-MEASURED. Changed lines 501 (+471 / −30), under the 3000 threshold.Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses (eslint on the changed file, exit 0; the full run is CI's).main, one pull request.scripts/pm/**publishes nothing;skip-changeset.packages/spectouched: n/a.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4cyJuqtXc5LcmkT6E4D