Repository navigation
chore(governance): the human-merge line threshold is 3,000 changed lines (HUMAN_MERGE_LINE_THRESHOLD), per the maintainer's 2026-10-09 ruling - #22490
Merged
Conversation
…nes (HUMAN_MERGE_LINE_THRESHOLD), per the maintainer's 2026-10-09 ruling The maintainer, 2026-10-09, verbatim: 「这种大额改动就应该人工审核,我还是建议5000行的人工审核门槛降到 3000,立卡。」 - scripts/pm/check-governed-merges.mjs: the one declaration moves 5000 → 3000; the header and docblock prose state 3,000 beside the earlier quotes (kept verbatim) with the 2026-10-09 words added; the self-test pins on the line (ruled default, exactly-at under, over-by-one over, the lift's unchanged threshold, the --test / --json runs, the fixture subjects) move to 3000 / 3001; the parse-only probes stay. - scripts/pm/check-governed-queue-guard.mjs: the stated value in the header, the 2026-10-09 words beside the earlier two in the header and in the REFUSED guidance, and the pin on that guidance extended to the new words. - scripts/pm/check-skill-line-ratchet.mjs: the sentence describing the rule line. - scripts/pm/dispatch-gates.mjs: the one pin on the constant (3000 / 3001); nothing else in the frozen file. - .claude/skills/pm-dispatch/SKILL.md, references/landing-operations.md, AGENTS.md: the digit in place, 0 net lines. Claude-Session: https://claude.ai/code/session_01JmWtcHfGbC4ncw4GFKWuRA Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Contributor
Author
维护者速读 — PR #22490(#22451)— skills 席 1,2026-10-09T14:10Z
|
os-zhuang
approved these changes
Oct 9, 2026
os-zhuang
marked this pull request as ready for review
October 9, 2026 14:14
This was referenced Oct 9, 2026
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.
Fixes #22451
Clause-②: no
Summary
The maintainer, 2026-10-09, verbatim and untranslated: 「这种大额改动就应该人工审核,我还是建议5000行的人工审核门槛降到 3000,立卡。」
HUMAN_MERGE_LINE_THRESHOLDmoves from 5000 to 3000 changed lines (additions + deletions, generated files included). It stays declared ONCE, inscripts/pm/check-governed-merges.mjs; the predicate stays STRICTLY greater (exactly 3,000 is under, 3,001 is over). Nothing else about the rule changes: the four-piece terminal set, no Tier S exception, generated files included, the per-repo coverage ofGOVERNED_REPOS. The earlier maintainer quotes (2026-09-18 and 2026-09-27) stay verbatim everywhere they were; the 2026-10-09 words are added beside them, verbatim. No ADR records the number (git grepoverdocs/adr/**anddocs/NORTH-STAR.md: zero hits on the threshold), so no ADR amendment is owed.Lineage recorded on the card: 2026-09-18 「修改代码量超过某个行数(比如5000)就应该人工审核」; 2026-09-27 「所以阈值写死成 5000 行 , 维护者已经批准了就是可以合并。」; 2026-10-09 the words above. PR #22215 (the occasion) is unaffected: no retroactive review of anything already approved or merged.
Notation in this body: the greater-than sign is spelled
[over]wherever a source line carries it, because the platform's body sanitizer eats angle-bracket-shaped fragments.Every edit: site → old → new (file:line as on this head,
cfff9b1a)scripts/pm/check-governed-merges.mjs:183— header section title(maintainer ruling, 2026-09-18)(maintainer ruling, 2026-09-18; the line, 2026-10-09)…check-governed-merges.mjs:189-191— header…check-governed-merges.mjs:193— header proseexceeds 5,000exceeds 3,000…check-governed-merges.mjs:198-201— header prose「比如」 makes 5,000 the ruled DEFAULT, declared once as …「比如」 made the 2026-09-18 figure the ruled DEFAULT; the 2026-10-09 word lowered it to 3,000. It is declared once as ……check-governed-merges.mjs:1102-1114— docblock on the declaration5,000 changed lines is under the threshold, 5,001 is over3,000 changed lines is under the threshold, 3,001 is over…check-governed-merges.mjs:1115— the ONE declarationexport const HUMAN_MERGE_LINE_THRESHOLD = 5000;export const HUMAN_MERGE_LINE_THRESHOLD = 3000;…check-governed-merges.mjs:5989— self-test pin, the ruled defaultthe-threshold-is-the-ruled-default-5000-declared-once,=== 5000the-threshold-is-the-ruled-3000-of-2026-10-09-declared-once,=== 3000…check-governed-merges.mjs:5992-5993— pin, exactly at the lineexactly-5000-changed-lines-is-UNDER-the-threshold,changedLines === 5000exactly-3000…,changedLines === 3000…check-governed-merges.mjs:5994-5995— pin, one over5001-changed-lines-is-OVER-it…,changedLines === 50013001-changed-lines-is-OVER-it…,changedLines === 3001…check-governed-merges.mjs:6062-6063— pin, threshold unchanged by the liftthreshold === 5000,additions: 5000(twice)threshold === 3000,additions: 3000(twice)…check-governed-merges.mjs:6176— pin name,--testover the line--test-with-5001-changed-lines-on-an-ordinary-path-exits-3-and-says-HUMAN-MERGE--test-with-3001-changed-lines-…(the run itself hands inString(HUMAN_MERGE_LINE_THRESHOLD)+ 1 deletion)…check-governed-merges.mjs:6182— pin name,--testexactly atand-exactly-5000-exits-0-the-threshold-is-strictly-greaterand-exactly-3000-exits-0-……check-governed-merges.mjs:6184,:6189— pin,--jsonover the line'--additions', '5001',changedLines === 5001'--additions', '3001',changedLines === 3001…check-governed-merges.mjs:6340,:6344,:6368-6369,:6381-6382,:6390— fixture commit subjects and every reader of them(#5000)/(#5001);PR #5001/PR #5000;pr === 5001(#3000)/(#3001);PR #3001/PR #3000;pr === 3001— the fixture's PR numbers are mnemonics for the line the commit stands at (lines(LINE)andlines(LINE + 1),LINE = HUMAN_MERGE_LINE_THRESHOLD)…check-governed-merges.mjs:6717— self-test summary linethe ruled 5,000 declared oncethe ruled line, 3,000 since the maintainer's 2026-10-09 word, declared oncescripts/pm/check-governed-queue-guard.mjs:335-338— header…check-governed-queue-guard.mjs:340— header proseHUMAN_MERGE_LINE_THRESHOLD (5,000) is declared there ONCEHUMAN_MERGE_LINE_THRESHOLD (3,000) is declared there ONCE…check-governed-queue-guard.mjs:1913— printed REFUSED guidance…check-governed-queue-guard.mjs:3463-3466— pin on that guidance…quoting-both-rulings-untranslated…, twoincludes…quoting-all-three-rulings-untranslated…, a thirdincludeson the 2026-10-09 wordsscripts/pm/check-skill-line-ratchet.mjs:325-328— ceiling-ledger comment describing the rule linea PR over 5,000 changed lines (additions + deletions, generated files included)a PR over the human-merge line (3,000 changed lines since the maintainer's 2026-10-09 word; additions + deletions, generated files included)scripts/pm/dispatch-gates.mjs:26400— the ONE pin (FROZEN file; the constant move breaks this pin, the freeze's own exception)…and it is the ruled 5000,HUMAN_MERGE_LINE_THRESHOLD === 5000,additions: 5001…and it is the ruled 3000,=== 3000,additions: 3001— nothing else in the file: no rewording, no other pin, no--tiernote.claude/skills/pm-dispatch/SKILL.md:186— the rule line改动 [over]5000 行(含生成物)同换终局四件套,⛔ 无 Tier S 例外;读数 = PR additions+deletions。改动 [over]3000 行…— the digit in place: 319/319 lines, widest row 342 bytes, 0 net lines, no re-wrap.claude/skills/pm-dispatch/references/landing-operations.md:58[over]5000 行(含生成物)照 Tier H。[over]3000 行(含生成物)照 Tier H。— the digit in place: 101/101 lines, 0 net linesAGENTS.md:510— Multi-agent discipline §7 (c)changed lines exceed 5,000changed lines exceed 3,000— in place, 1108 lines before and afterReaders that follow the constant unchanged (PM hypothesis 1, measured on this head)
git grep -n HUMAN_MERGE_LINE_THRESHOLD— every code reader reads the one declaration:check-governed-merges.mjssizeVerdict:1582/:1585/:1591, the sweep's printed words:3377/:3383, the self-test:5990-5991,:6012,:6175,:6181,:6251;check-governed-queue-guard.mjsimport:499, printed CLEAR line:1880,:3269, and its own pin:3659(this-file-declares-NO-threshold-of-its-own);dispatch-gates.mjsimport:467,:13145,:26392-26396,:26594,:28568. objectui and cloud carry no copy (the card's reading;GOVERNED_REPOScovers them from this script).The literal pin over the seven touched files
git grep -n -E '\b500[01]\b|5,000'oncfff9b1aover the seven files: 23 hits, every one a quoted maintainer ruling, a parse-only probe, or one regex artifact —check-governed-merges.mjs:187(2026-09-18),:191and:1106(2026-10-09, the words added),:260(2026-09-27),:1103(the 「比如5000」 fragment the docblock always quoted);check-governed-queue-guard.mjs:333,:337,:392,:1867,:1911,:1912,:1913,:3464,:3465,:3466,:3553;check-skill-line-ratchet.mjs:324(the 2026-09-18 quote);check-governed-merges.mjs:6003(a string'5001'is NOT MEASURED),:6107/:6109(--additions 5000 --deletions 1parse as the pair with the CALLER as source),:6196(half a pair,--additions 5001alone, is refused);check-skill-line-ratchet.mjs:779—15,000(the authenticated REST quota) contains5,000as a substring; not the threshold, untouched.No prose restatement outside a quote carries the old figure any more.
The measurement the card asks for: merged pull requests of the last 30 days between 3,001 and 5,000 changed lines
Window and filter, stated exactly. Repository
objectstack-ai/objectstackonly. Window:merged_atin [2026-09-09T12:16:51Z, 2026-10-09T12:16:51Z] (30 days back from the reading, taken at 2026-10-09T12:16:51Z). Source:GET /repos/objectstack-ai/objectstack/pulls?state=closed&sort=updated&direction=desc&per_page=100, paged until a page's oldestupdated_atfell before the window start (27 pages, 2,700 closed pull requests read; a merge inside the window impliesupdated_atat or after it, so no later page can hold one); then oneGET /repos/objectstack-ai/objectstack/pulls/{n}per candidate foradditions/deletions(the list object omits them). Changed lines =additions + deletionsas GitHub reports them, generated files included — the same number the predicate reads. ⛔ This is a reading of one window in one repository, not a claim about every pull request ever merged; objectui and cloud are not in it.(PR numbers are written as plain digits on purpose: titles in this repository begin with
fix/chore/…, and a closing keyword beside a#-reference would make the platform close that card on merge.)Gates: the derived union, every exit captured before any pipe, reconciled with
--ranon headcfff9b1aDerivation:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackoncfff9b1a— its first stderr line names the tree ("gate list derived from the tree of 'objectstack-ai/objectstack' at commit cfff9b1"), the change set is 7 path(s) three-dot off merge basef66c440deoforigin/main(committed 7, working tree 0, untracked 0). 45 commands derived. Each ran as printed,eval "$cmd" ... ; status=$?before any pipe, recorded ascmd :: exit N; the battery ran to completion on the final head with its exit captured to a file (pnpm check:pm-dispatch-gates:✓ dispatch-gates self-test: 2011 cases pass.— 1080.2s on this box; an earlier barenohuprun on the same head also printed2011 cases passbut its exit was never captured, so it is not the record).Reconciliation (
node scripts/pm/dispatch-gates.mjs --ran ran.list, exit 0):Run reconciliation — 45 derived, 45 run, 0 NOT-MEASURED, 0 UNRUN.·✓ dispatch-gates --ran: 45 derived famil(ies) accounted for — 45 run, 0 NOT-MEASURED (a DERIVED zero — all 45 recorded an exit code and none of them is 3).node scripts/check-ci-filter-parity.mjsnode scripts/check-closing-keyword-parity.mjsnode scripts/check-closing-keyword-parity.mjs --self-testnode scripts/check-comment-mask-corpus.mjsnode scripts/check-declaration-mirrors.mjsnode scripts/check-declaration-mirrors.mjs --self-testnode scripts/check-scripts-symbol-anchors.mjsnode scripts/check-scripts-symbol-anchors.mjs --self-testnode scripts/check-self-test-wired.mjsnode scripts/check-self-test-wired.mjs --self-testnode scripts/check-self-test-workflow-commands.mjsnode scripts/check-self-test-workflow-commands.mjs --self-testnode scripts/check-skills-token-ratchet.mjsnode scripts/check-skills-token-ratchet.mjs --self-testnode scripts/check-whole-set-label-write.mjsnode scripts/check-whole-set-label-write.mjs --self-testnode scripts/pm/bare-root-worklist.mjs --self-testnode scripts/pm/check-governed-queue-guard.mjs --self-testnode scripts/pm/check-harness-current.mjs --self-testpnpm check:agent-test-spellingpnpm check:bash32-floorpnpm check:cli-command-idspnpm check:closing-target-claimpnpm check:cross-package-test-inputspnpm check:declared-population-livepnpm check:doc-authoringpnpm check:docs-audit-scopepnpm check:driver-memory-censuspnpm check:entry-guardpnpm check:gitlink-declaredpnpm check:nul-bytespnpm check:parse-guardpnpm check:pm-expected-skipspnpm check:pm-governed-mergespnpm check:pm-governed-prosepnpm check:pm-skill-id-lintpnpm check:pm-skill-ratchetpnpm check:pnpm-filter-targetspnpm check:ratchet-remedy-authoritypnpm check:refd-timer-probepnpm check:required-contextspnpm check:skill-frame-syncpnpm check:watch-hint-literalpnpm --filter @objectstack/lint run check:doc-formula-expressionspnpm check:pm-dispatch-gatesNotes on the run:
pnpm --filter @objectstack/lint run check:doc-formula-expressionsfirst answered exit 3 — PREREQUISITE NOT MET (@objectstack/formulaand@objectstack/lintnot built; "Nothing was measured"). That is not a measurement, so it is not the record: the prescribedpnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lintran under the shared verify lock (os-verify-lock: VERDICT command-exit 0 · held the lock 186s · waited 0s), and the gate re-ran: exit 0. The row above is that re-run.build/test/typecheckis owed locally and none was run beyond that prerequisite build;pnpm lint(the repo-wide eslint sweep) is CI's run, not derived here, and was not run.check:pm-skill-ratchet,check:pm-skill-id-lint,check:pm-governed-prose,check:nul-bytes) are in the union and green;check:pm-skill-ratchetreadsSKILL.md319/319 andlanding-operations.md101/101 with headroom 0, unchanged.Reverse verification: the constant alone back to 5000, every pin left at 3000
PM hypothesis 2 asked for the pins to be found by moving the constant first. Measured as a mutation leg instead, in a throwaway detached worktree at
cfff9b1a(installed;node_modulesremoved and the worktree removed afterwards), throughscripts/ablation-replace.mjsso the on-disk evidence is the tool's own: anchorexport const HUMAN_MERGE_LINE_THRESHOLD = 3000;x1 → x0, replacement… = 5000;x0 → x1, blob6d8be7178d5f→717e33fc3d6d, "ok mutation landed"; after every leg, "ok restored: blob == HEAD (6d8be7178d5f) andgit diff HEADis empty", and a separategit status --porcelainread of 0 lines. Expected direction: RED on the pins that bind the number, GREEN where the number is only imported.node scripts/pm/check-governed-merges.mjs --self-testthe-threshold-is-the-ruled-3000-of-2026-10-09-declared-once: 5000;⭐ exactly-3000-changed-lines-is-UNDER-the-threshold(readchangedLines: 5000, threshold: 5000);⭐ 3001-changed-lines-is-OVER-it-the-count-is-additions-PLUS-deletions(readchangedLines: 5001);and-the-threshold-the-strict-comparison-and-the-generated-files-inclusion-are-UNCHANGED-by-the-lift;--json-carries-governed-false-humanMerge-true-and-the-size-block(3,001 handed in readthreshold: 5000, exceeds: false)node scripts/pm/check-governed-queue-guard.mjs --self-testthis-file-declares-NO-threshold-of-its-ownforbids one) and readsLINE = HUMAN_MERGE_LINE_THRESHOLDthrough the import, so it follows the constant wherever it is — green by design, not a vacuous pinnode scripts/pm/dispatch-gates.mjs --self-test✗ the threshold is read from the gate — no second copy here — and it is the ruled 3000— the one pin at:26400, and nothing else in the frozen fileSo the number binds in exactly six places outside its declaration — five merges pins and the one dispatch-gates pin — which are exactly the rows this PR moved; on the unmutated head all three self-tests are green (below).
Acceptance notes
:3659pin forbids one), so it stays green by design. Same information, reported as a measurement.check-skill-line-ratchet.mjs:325-328: a code comment inside a ceiling-ledger entry; re-wrapped 3 → 4 lines (a.mjsfile, no line ceiling). It names the lowered line without restating the old figure, so the literal pin stays clean.check-governed-queue-guard.mjs:3463: the pin's namequoting-both-rulingsbecamequoting-all-three-rulingsand gained a thirdincludes, so the new printed words are pinned exactly like the earlier two. Battery floors are by battery name and count; the case count is unchanged (296).check-governed-merges.mjs(#5000/#5001) were mnemonics for the line a synthetic commit stands at; moved to#3000/#3001so the pin reads true against the liveLINEand the literal grep stays clean. Synthetic repo, no real PR named.dispatch-gates.mjs(FROZEN, ruling 208 R6): the one pin at:26400only, digits only. The--tiernote from the earlier card is not added; it waits on the letter of its own card ([Decision] lift the ruling-208 freeze on scripts/pm/dispatch-gates.mjs for exactly the roster-as-data split (W3 of the skills-lane diet program; carries the Clause-② note remainder), or keep it frozen #22453).15,000atcheck-skill-line-ratchet.mjs:779matches the5,000alternation as a substring; a quota figure, untouched.skip-changesetapplies — rootpackage.jsonisprivate: true; none of the seven touched paths is owned by any of the 132 workspace packages; positive control:packages/spec/src/index.tsis owned by@objectstack/spec(private: false,files[]present).scripts/pm/**,.claude/**andAGENTS.mdpublish nothing./home/user/objectstackuntouched atf66c440d; worktree only.维护者速读(草稿)
改了什么
把「超过多少行就必须人工审核」这条线从 5000 行降到 3000 行(additions + deletions,含生成物)。数字只在
scripts/pm/check-governed-merges.mjs里声明一次,队列守卫、派发脚本、自检、技能文件与AGENTS.md都跟着这一处读;自检的钉子同步挪到 3000/3001;三条早前的原话原样保留,10 月 9 日的原话加在旁边。为什么改
按维护者 2026-10-09 的裁决原话执行:「这种大额改动就应该人工审核,我还是建议5000行的人工审核门槛降到 3000,立卡。」 字面已给定,不是决策卡。
风险与代价(含回滚)
dispatch-gates.mjs冻结文件只动了那一枚因常量搬家而必红的钉子。席位意见
(留空)
你要做的
本 PR 触及 Tier H(
AGENTS.md)与 Tier S(.claude/**),按治理规则留在 draft:维护者给出 APPROVED 后由认领席落地,或由维护者人工直合。不需要你做别的决定。Generated by Claude Code