fix(check-partof-closing-keyword): the already-pushed red says what discharges it — a merge whose squash message is the PR body — beside the rewrite ban - #16831
Merged
Conversation
…h red, beside the rewrite ban The already-pushed paragraph said that no author action clears the red and forbade the rewrite, but never what does clear it, so a reader was left knowing only what not to do. It now states the discharge as a CONDITION on the repository setting: a merge whose squash message is the PR BODY is what keeps the trailer out of the default branch; at `COMMIT_MESSAGES` that takes the lander replacing the assembled commit list with the PR body by hand at the merge button (a queue merge edits nothing, so there the residue lands); at `PR_BODY` every squash does it, queue included. Worded on the setting's value rather than today's value, so it stays true after the ruled setting change is applied. The header carries the same paragraph as the authority on detail. Detection is untouched: RULE 2 and its four counterfactuals are byte-identical, as are the finding sentence, the repair paragraph and the six existing guidance pins. Three new pins hold the discharge sentence, the setting and both of its values, and that the sentence sits BESIDE the prohibition rather than in place of it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P58euzUXCVJNwmhuPC9DXY
…eue-entry-third-case
hotlong
marked this pull request as ready for review
September 8, 2026 09:54
hotlong
enabled auto-merge
September 8, 2026 09:54
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.
Part of #16516
This PR delivers the gate half of the card — item 2 of triage's re-scope (comment 5579821742): the
BRANCH ALREADY PUSHEDparagraph ofscripts/check-partof-closing-keyword.mjsnow states, positively, what discharges the red. The other half — the queue-entry rule's third case in.claude/skills/pm-dispatch/SKILL.mdand itsreferences/core-rules.mdtwin — is not in this PR: it stopped under the dispatch's 回翻条款 because it cannot be expressed in place or paid for by a fold in either ratcheted file (measurements below). It needs a ceiling decision that is the maintainer's, not a seat's; the full reading and the ready-to-land text are in the dev report on the card.What changed —
scripts/check-partof-closing-keyword.mjsonly (+43 / −0)Output. In
judge(), the already-pushed paragraph — after…and it does not decide whether the pull request merges.— gains one paragraph:Header. The same statement, as the authority on detail, in the section
RULE 2 — what the output may ask for, and when it may ask for nothing, directly under the measured-squash paragraph it conditions.Self-test. Three pins in the RULE 2 battery (its ledger count is a floor, so no ledger edit): the discharge sentence prints on the already-pushed branch; the setting is named with BOTH of its values and the by-hand clause; and the sentence sits BESIDE
⛔ Do NOT amend, rebase or force-push, never in place of it.Why this wording, and the setting-D probe
The card set the wording's timing on setting D (
squash_merge_commit_messagemoving fromCOMMIT_MESSAGEStoPR_BODY, the maintainer's own change ruled on #16502). Probed at claim time onorigin/main7862fb711(re-read on7f96e1417): the three newest multi-commit squashes —68fd85a41(#16812),30b099078(#16788),094b8fd9c(#16775) — each begin their body with a*bullet followed by a commit subject, theCOMMIT_MESSAGESshape; aPR_BODYsquash would begin with the PR body's first line. D is not in effect. So the sentence takes the before-D form — the merge needs the PR body as its squash message, and today that is a by-hand act — but it is written as a CONDITION on the setting's value rather than as today's value, so it stays true once D is applied and no history is rewritten either way. The existing fact 2 (assembled from the COMMIT messages … 0a61db1f5, pinned) is untouched; the new paragraph names it as the measurement behind theCOMMIT_MESSAGESvalue.What is deliberately untouched
commitRelations(),commitTrailerFindings(), the four counterfactual cases — byte-identical (the diff is 43 insertions, 0 deletions).d4401f75b: the finding sentence at 594, the repair paragraph at 746, the guidance pins at 1017–1018) — each present exactly once, byte-identical, checked by content rather than line number.Verification
node scripts/check-partof-closing-keyword.mjs --self-test→ exit 0,✓ check-partof-closing-keyword self-test: 95 cases pass.(92 before, 3 new).b93320823, blobfb822185aacb5f3887c3f1099eec8faf9fb3722f): the output paragraph deleted on disk (anchorWhat DISCHARGES it is the merge, and only a mergecounted 1 → 0;git diff --stat HEAD= 7 deletions) → self-test exit 1,3 of 95 case(s) failed, exactly the three new pins. Restored withgit checkout HEAD -- scripts/check-partof-closing-keyword.mjs;git hash-objecton the restored file = the HEAD blob above;git diff HEADempty, porcelain empty; self-test 95/95 again.node scripts/pm/check-governed-merges.mjs --test scripts/check-partof-closing-keyword.mjs→ exit 0,NOT governed(the diff no longer touches.claude/**; the seat routes the landing).git merge-tree --write-treefrom a bare--sharedprobe clone againstorigin/main7862fb711and again against7f96e1417(fix(pm): dispatch-gates' reconciliation line enumerates every OUTSIDE block, not three of five #16802,scripts/pm/dispatch-gates.mjsonly) → exit 0, clean.origin/main7862fb711is merged into the branch;7f96e1417is not (it is disjoint from this file — §10 scoping).Gate reconciliation
Derived in the worktree on the merged head
27bea86dcwithnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths; the change set is read from the merge base): 31 commands, identical before and after the merge. The seat's list (39 ond4401f75b, derived over three paths) carried eight more —check-governed-queue-guard --self-test,check:doc-formula-expressions,check:doc-authoring,check:pm-governed-merges,check:pm-governed-prose,check:pm-skill-id-lint,check:pm-skill-ratchet,check:skill-frame-sync— every one of them placed by the two.claude/skills/**paths this PR does not touch; they belong to the stopped half.Every command was run from a script that captures the exit by redirect before any pipe (
bash -c "$cmd" > log 2>&1; ex=$?),NODE_OPTIONS=--max-old-space-size=4096, no verify lock (no build or test — the diff touches no package):✓ check-partof-closing-keyword self-test: 95 cases pass.,check-nul-bytes: OK (scanned 8302 text file(s) … no raw ASCII control bytes),✓ check-self-test-wired: every one of the 191 script(s) …,check-closing-keyword-parity: OK (3 parsers agree …),✓ comment-mask corpus sweep … 6356 files, 0 disagree,✓ check-whole-set-label-write --self-test: all cases pass,check-ratchet-remedy-authority: 227 scripts swept ….pnpm check:pm-dispatch-gates(exceeds the container's foreground cap; run detached with output to a file and awaited withtail --pid, restarted once on the merged tree, 09:03Z → 09:15Z): its own verdict line✓ dispatch-gates self-test: 1552 cases pass., no signal branch printed.node scripts/pm/dispatch-gates.mjs --ranover the run record: exit 0,✓ dispatch-gates --ran: 31 derived famil(ies) accounted for — 31 run, 0 NOT-MEASURED.Not in this PR's derived total and named as such by the tool: the always-runs tail, 10 whole-root families, 1 CI-measured family (this very script, read from the workflow event payload — its self-test is the local half and is green above), 3 workflow-valued families, and the artifact-roster families (silent on every card; not clearances).
Mirror reading
skills/objectstack-pm-dispatch/SKILL.md(the published mirror) carries no queue-entry rule — 0 hits for 入队 / 队列, and itsqueuementions are thepm:queuebacklog label;check:skill-frame-synccompares only the decision frame (COPIES: the internal and the published SKILL.md);check:pm-skill-id-lintscans.claude/skills/pm-dispatch/**,os-dev.mdandAGENTS.md. Two references restate the all-green rule as pointers —references/review-checklist.md:43andreferences/true-green.md:3— no gate holds them to SKILL.md's wording; they become the follow-up's concern when the third case lands.验收备注
review-checklist.md:43andtrue-green.md:3restate 「入队资格 … 全 check 绿」 without the third case; a pointer, not a gated mirror — 承接者: the follow-up PR that lands the two skill loci of this card.dispatch-gates.mjs --commandsprintedSTALE TREE … 1 file(s) it derives from CHANGEDon27bea86dcimmediately after merging7862fb711; the file wasscripts/pm/dispatch-gates.mjsitself, moved by fix(pm): dispatch-gates' reconciliation line enumerates every OUTSIDE block, not three of five #16802 one commit later — correct behaviour, recorded so the seat does not read it as a derivation defect. 承接者: 无.assembled from the COMMIT messages, not from the PR body, pinned with0a61db1f5) reads as a live fact today and as a dated measurement once D lands; the new paragraph conditions it on the setting's value, so no edit is owed now. 承接者: whoever applies setting D reads the paragraph, not the fact.维护者速读(草稿)
改了什么:
check-partof-closing-keyword门禁在「分支已推送」那段输出里补了一句正面陈述:这个红由合并化解,且只有 squash 提交信息取 PR 正文的合并才化解;仓库设置squash_merge_commit_message在COMMIT_MESSAGES时要人在合并按钮手动换成 PR 正文(队列合并不改信息,残留会落地),在PR_BODY时每次 squash 自动完成;两种情况都不改写历史。文件头同步一段,自测加三条钉子。为什么改:此前输出只说「什么都清不掉、⛔ 不许改写历史」,没说它到底怎么被清掉;读到红的 agent 不知道该做什么、也不知道可以什么都不做。措辞按设置值写成条件句,D 生效前后都成立。
风险与代价(含回滚):只加不删(+43/−0),检测逻辑与四条反事实逐字未动;三处已落地成果逐字未动。回滚 = revert 这一个提交。⚠️ 本 PR 只交付卡的门禁那一半;入队规则第三种情形那一半(
SKILL.md+core-rules.md)实测无法在既有行内表达、两文件均无可折并的相邻行(601 对与 121 对实测 0 对 ≤120 字节),需要天花板裁决,已在卡上报告。席位意见:(留空)
你要做的:一个动作 —— 对卡上报告里的天花板问题作裁决(两文件各 +1 行,还是别的路);设置 D 仍未生效,顺手改了这一半就自动化解。
🤖 Generated with Claude Code
Generated by Claude Code
Generated by Claude Code