Repository navigation
fix(pm): the queue guard's pull_request leg attributes to the payload PR and reads the net diff - #26568
Conversation
… PR and reads the net diff On the pull_request leg, enumerateRows now returns one row: the net diff from the merge-base to the head, attributed to the payload's own pull request number. A commit subject naming an issue no longer sends the review read to that issue, and a branch that merged origin/main no longer forecasts every path main already landed. The merge_group leg keeps its per-first-parent-commit decomposition and subject attribution unchanged. Self-test: seven cases in the decomposition battery (6 -> 13) and one in the pull_request early-warning battery (5 -> 6), driven through a new runGit seam on enumerateRows. Claude-Session: https://claude.ai/code/session_01JQwxba3WdR4pYYA7CdMgAJ Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Director seat (summon #52, ledger objectstack#12708), by the maintainer's word 「#26566、#26568、#26570、#26585 也要追加复审」: the PR is an open draft at this head with no review on it; this record is read-only — the diff, card #26316, the head's check runs. ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
Retracted: this comment was a duplicate post of the director seat's contract-review record on this PR; the record of record is comment 6439760427 above (same head, same verdict). Nothing else changes. Generated by Claude Code |
维护者速读改了什么: 席位核对ACCEPT ·
Generated by Claude Code |
Requested by Warren · project thread
Fixes #26316
Clause-②: no
Metadata-protocol: none
维护者速读
scripts/pm/check-governed-queue-guard.mjs的pull_request腿不再按提交拆行:整段 diff 读成一行「合并基点 → head 的净差异」,归到事件载荷里的 PR 号。merge_group腿(按首父提交拆、按标题(#N)归属、各种拒绝)一字不改。自测加 8 例,两组电池下限按实测抬高。origin/main时,合并提交的首父 diff 把 main 已落地的几十个路径算进预警,且每行都是「无归属」。预警本来就不会变红,但读的人会被误导。enumerateRows(L2386 起)新的pull_request分支;②readEventDiff那一行调用(L2794)把事件传进去;③ 自测 decomposition 电池里的 7 个新用例。node scripts/pm/check-governed-queue-guard.mjs --self-test→ 末行✓ check-governed-queue-guard self-test: 401 cases pass(改前 393)。What changes
Card #26316's 「Wanted」, and nothing wider. One file,
scripts/pm/check-governed-queue-guard.mjs:enumerateRowsreads by event. Themerge_groupreading is the old one, byte for byte: one row per first-parent commit, attributed bypullNumberFromSubject, with thehead_reffallback only for a one-commit group. On thepull_requestleg it now returns ONE row:diff-tree baseSha headSha(the caller already hands in the merge-base), attributed to the payload's own pull request number, carryingcommits= the range's first-parent count. Shape chosen: the single net row, because it makes both negatives provable with no intersection logic. The subject is not read for attribution on this leg at all; a subject naming an issue cannot redirect the review read, and a merge oforigin/maincannot add a path the net diff does not hold.readEventDiffpasses{ event: context.event }to it. The merge-base call it already made (L2793) is unchanged; the premise reading in the claim held: the missing piece was the per-commit enumeration, not a merge-base.commitsInRange(rows)keeps the header line honest:pull request #N — 3 commit(s) in rangestill counts the range's commits. Onmerge_grouprows carry nocommits, so it equalsrows.length, the old count.runGit(args)seam onenumerateRows, defaultnull(production reads the checkout as before), so the self-test drives the enumeration offline, as its header promises (no network, no git).pull_requestleg is not decomposed, and why.Not touched:
.github/workflows/governed-surface-guard.yml,REQUIRED_CONTEXTS, the register, any refusal text,decomposeGovernedWork,queuedPullsInGroup,runSizeGuard.Tests
Self-test 393 → 401 cases, exit 0. Eight new cases, all driven through the
runGitseam:decomposition, and the multi-PR group trap(floor 6 → 13, measured 13):⭐ pull_request-leg: a-subject-naming-an-ISSUE-is-attributed-to-the-PAYLOAD-pr-never-the-issue: the PR ci(release): the hotcrm downstream smoke resolves hotcrm's latest release tag at run time #25965 shape (one commit, subject ends(#25770), payload PR 25965) gives one row with PR 25965, governed entry 25965, zero unattributed.⛔ CONTROL merge_group-leg: the-same-subject-still-attributes-by-its-trailing-number-unchanged: the same range onmerge_groupstill reads 25770 from the subject.⭐ pull_request-leg: a-branch-that-merged-origin-main-carries-ONLY-its-net-rows-against-the-merge-base: the PR ci(governed-surface-guard): the pull_request leg checks out commits and trees only and installs the toolchain on demand #26311 shape (own commit, merge of main carrying.github/workflows/lint.yml,AGENTS.md,packages/core/src/x.ts, own commit) gives one governed entry, PR 26311, paths exactly.github/workflows/governed-surface-guard.yml.and-it-reads-the-net-diff-base-to-head-never-a-per-commit-first-parent-diff: the recorded git reads hold the two-treediff-treeand no--first-parentdiff-tree.and-the-header-still-counts-the-ranges-three-commits.⛔ CONTROL merge_group-leg: the-same-range-is-still-one-row-per-first-parent-commit-unattributed-without-a-subject-number: three rows, all PR null, the merge row still carriesAGENTS.md.and-an-empty-pull_request-range-is-no-rows.the pull_request leg is an EARLY WARNING and never reddens(floor 5 → 6, measured 6):⭐ the-early-warning-names-the-payloads-pull-request-and-never-the-issue-its-subject-names: the rendered warning carries#25965 — governedand no#25770.Floor binding checked once: with the decomposition floor at 14 the run exits 1 naming
registered 13 case(s), below its pinned floor of 14. The self-test's success line is otherwise identical before and after; only the count moves (393 → 401).SELF_TEST_BATTERY_FLOOR(29) is unchanged: no battery added.Acceptance notes
The card's three acceptance lines:
pull_requestrun on a PR whose commit subjects name an issue number prints the PR's own review state: yes, the fixture run below prints#25965 — governedwhere it printed#25770 — governedbefore.origin/mainprints only the PR's net rows: yes, 3 unattributed rows (one of them the merge commit's 7 workflow paths) became 1 governed entry with 1 path.--self-testgreen; themerge_groupcases unchanged: 401 pass; every pre-existing case passes unedited; the livemerge_groupoutput on both fixtures is byte-identical before and after (below).This PR's own
pull_requestrun is a live case of the second line: its branch carries a merge oforigin/main(25 commits of main), so the guard's check-run on this PR should readpull request #THIS — 2 commit(s) in rangeand name no governed path (the diff touches none).Verification
Fixtures: a throwaway worktree off
d2ca7079with two branches built to the card's shapes; payloads point the guard at them; reviews unreachable on purpose (API URL at a closed local port) so the output is deterministic. "Before" = the guard atd2ca7079; "after" = this branch.PR #25965 shape: one commit, subject names issue 25770
Before:
After:
PR #26311 shape: own commit, merge of main, own commit
Before:
After:
merge_group leg, same two ranges: byte-identical
cmpof before and after, each run with amerge_grouppayload over the same range (head_refnaming the PR):Fixture b on the queue leg still reads
3 commit(s) in rangeand3 unattributed governed commit(s): the queue's decomposition and its refusal are untouched.--toolchain-needed on the pull_request leg
Local gates on 64d0d4f: 32 derived, 32 run, all exit 0
Derived with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon64d0d4fd(branch withorigin/mainata3009cbfmerged in, so the tree is not stale against the families). Each run's exit code captured before any pipe;check:pm-dispatch-gatesran underos-verify-lock.sh(slotissue-26316):VERDICT command-exit 0 · held the lock 380s.node scripts/check-closing-keyword-parity.mjs→ exit 0node scripts/check-closing-keyword-parity.mjs --self-test→ exit 0node scripts/check-comment-mask-corpus.mjs→ exit 0node scripts/check-declaration-mirrors.mjs→ exit 0node scripts/check-declaration-mirrors.mjs --self-test→ exit 0node scripts/check-self-test-wired.mjs→ exit 0node scripts/check-self-test-wired.mjs --self-test→ exit 0node scripts/check-self-test-workflow-commands.mjs→ exit 0node scripts/check-self-test-workflow-commands.mjs --self-test→ exit 0node scripts/check-whole-set-label-write.mjs→ exit 0node scripts/check-whole-set-label-write.mjs --self-test→ exit 0node scripts/ci/plan-test-core-shards.mjs --self-test→ exit 0node scripts/pm/bare-root-worklist.mjs --self-test→ exit 0node scripts/pm/check-governed-queue-guard.mjs --self-test→ exit 0pnpm check:agent-test-spelling→ exit 0pnpm check:bash32-floor→ exit 0pnpm check:ci-filter-parity→ exit 0pnpm check:cli-command-ids→ exit 0pnpm check:closing-target-claim→ exit 0pnpm check:cross-package-test-inputs→ exit 0pnpm check:driver-memory-census→ exit 0pnpm check:entry-guard→ exit 0pnpm check:gitlink-declared→ exit 0pnpm check:nul-bytes→ exit 0pnpm check:parse-guard→ exit 0pnpm check:pm-dispatch-gates→ exit 0pnpm check:pnpm-filter-targets→ exit 0pnpm check:pnpm-flag-spellings→ exit 0pnpm check:ratchet-remedy-authority→ exit 0pnpm check:refd-timer-probe→ exit 0pnpm check:scripts-symbol-anchors→ exit 0pnpm check:watch-hint-literal→ exit 0--ranreconciliation (exit codes recorded):Run reconciliation — 32 derived, 32 run, 0 NOT-MEASURED, 0 UNRUN.·✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 32 run, 0 NOT-MEASURED (a DERIVED zero — all 32 recorded an exit code and none of them is 3).That reading was taken withorigin/mainat1c632311, 2 commits past the merge; the one derived-from file those moved isscripts/engine-double-contract.pinned.json, which no family on this card's list reads.Left to CI, as the derivation names: the workflow-payload families (
check:closing-target-claim's live leg),ci.yml · Plan Test Core shards, the type-check program steps, the repo-widepnpm lint. No package was touched, so there is no build closure and no package test or typecheck to run; this script has no*.test.tsbeside it, and its own--self-testis the suite.Human Minimum
Each item is one rule from CONTRIBUTING.md › Human Minimum.
packages/specholds no runtime logic. (No schema change.)pnpm lintis CI's run (repo-wide scan).main, one pull request.scripts/pm/**,skip-changeset); both declaration lines are filled in above.packages/specnot touched.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code