docs(pm-skill): flip the gate asymmetry — adding a required gate/hook/ratchet joins the human floor; census-marked retirement becomes class-1 (ruling F) - #18481
Conversation
…/ratchet joins the human floor, census-marked retirement becomes class-1 Maintainer ruling 「F」: two re-keys, line-neutral (SKILL.md 812/812, core-rules.md 151/151), every touched line ≤120 bytes. 1. 人工地板 gains 新增必需门禁/hook/棘轮 (the card names the guarded contract and the expected catch); the 具名不升级 wording is scoped to an EXISTING gate's internals (既有 … 非新增) so a new gate cannot ride it. 2. The class-1 self-adjudication floor 门禁强度 gains the carve-out: retiring a gate the gate census marks retire is not floor movement; the director or the skills seat rules it citing the census row. 3. core-rules.md twins re-keyed identically. Claude-Session: https://claude.ai/code/session_01Wj1HUjzyeiBQ8atRf1ZhaL Co-authored-by: Claude <noreply@anthropic.com>
…k/棘轮 so both files grep identically Line 96 stays ≤120 bytes (exactly 120) and core-rules.md stays 151 lines. Claude-Session: https://claude.ai/code/session_01Wj1HUjzyeiBQ8atRf1ZhaL Co-authored-by: Claude <noreply@anthropic.com>
维护者速读(终稿)总监席, 改了什么 为什么改 你的裁决 F。协议原来只把「削弱门禁」放在人工地板上,「加门禁」免费 —— 一支 AI 舰队在这条规则下把每个 finding 都长成一道门:182 个 check 脚本,上周 42% 的合并是机器在管机器。 风险与代价(含回滚) 零产品行为变化。代价:席位今后加门要先问你一次(这正是目的)。回滚 = revert 一个 squash 提交。 席位意见 建议批准。它引用的「门禁普查表」在 #18472 的 PR 里,先后顺序不影响本 PR。 你要做的 一个动作:Approve。落地顺序:#18476 先,本 PR 随后合 main 再入队。 Generated by Claude Code |
|
Landing provenance (ruling C) — director seat, Governed rules layer ( Generated by Claude Code |
… list, report-only (ruling F) (objectstack-ai#18497) Fixes objectstack-ai#18472 `skip-changeset`: the diff is one file under `docs/audits/`, which no released package's `files[]` ships. ## What this is The gate census the maintainer's ruling **F** asked for, verbatim 「F」 on 「现在有各种门禁的开发在浪费我的各种时间,我们的项目是不是门禁用的太重了。有这个必要吗?」 — **one table, report-only**. No gate is removed, disabled or edited by this PR; the retirement batch is its own card(s) after the maintainer's one-word 「认可」 on the table. `docs/audits/gate-census-2026-09.md`: - **Inventories**: ① 182 check files (`scripts/**/check-*.mjs` 178 + `packages/*/scripts/check-*.mjs` 4) · ② 26 root `check:*` scripts that are not a thin alias (of 164; 138 collapse onto their file row) · ③ 10 hooks (5 PreToolUse guards + 5 self-tests; the base tree had 12 — objectstack-ai#18478 removed the enqueue guard on `main` after the base) · ④ 7 required contexts (read from `GET /repos/objectstack-ai/objectstack/rules/branches/main`) → **union = 225 rows**, the table has 225 rows. - **Verdicts**: **retire 59** (58 rule-derived + `retire (ruled)` for `check-reference-carrier-shape.mjs`, objectstack#18095 E) · **report-only 16** · **keep 150** (133 plain, 2 ruled — the governed queue guard and its context —, 5 too new to judge, 5 session hooks + 5 hook self-tests). - **Classes**: process 115 · contract 60 · correctness 50. - **Column 5 (real catches)**: sampled over the last 30 days of failed PR CI (2026-08-17..09-16): 1,230 failed runs in the eight PR-triggered gate workflows, 1,287 failed jobs read step-by-step, 1,287 annotation reads, 9 sampled job logs, attribution by step name, split by annotation tag where a step hosts several gates, counted as distinct PRs, PRs that edited the gate's own file excluded. Every zero is a measured zero; every `unmeasured` names why; no count is guessed. - **Three sections**: retirement list (per row: files to delete, root scripts to drop, workflow `file:line`, count of other references to fix; a nine-row CI-integrity sub-group presented as one decision), report-only list, method + limits (incl. what is outside the four inventories: 70 per-package `check:*`, 31 workflow-direct non-`check-*` steps, two inline workflow gates — the inline `Require a changeset` step alone reddened 107 PRs). - Zod validation inside `packages/spec` / the runtime is the product, out of scope, said in one line. Standing verdicts recorded as given: `check-governed-queue-guard.mjs` = `keep (ruled)`; `check-reference-carrier-shape.mjs` = `retire (ruled)`. ## Acceptance notes - Dispatch-derived gates (`node scripts/pm/dispatch-gates.mjs --commands docs/audits/gate-census-2026-09.md`, 17 families) all exit 0 on the merged tree except `pnpm check:cross-package-test-inputs` (exit 1, at the base and again on the merged tree): its finding names `packages/cli/test/init-created-files-summary.e2e.test.ts` walking `packages/spec/dist/` with no declared glob — not a path this diff touches (one docs file). Reported to the seat in the dev report for filing; not fixed here (scope rule). - `pnpm --filter @objectstack/lint run check:doc-formula-expressions` first answered exit 3 (PREREQUISITE NOT MET: `@objectstack/formula` and `@objectstack/lint` not built) — built both through the verify lock and re-ran: exit 0. - noted, not filed: the four inventories the card defines leave 31 workflow-direct gate steps and two inline workflow gates without a row; the census names them in Method so the union stays honest. 承接者: the director's retirement batch (it decides whether a ⑤ is worth a follow-up census). - noted, not filed: two of the 25 `Docs anchors resolve to real headings` step failures could not be attributed between `check-doc-anchors.mjs` and `check-system-context-census.mjs` (no tag in the annotation); recorded as `unmeasured` on the doc-anchors row. 承接者: none. - Drift: `origin/main` moved seven commits before this PR opened; the branch merged `bf61f0a1` and the census was re-derived on the merged tree (Drift paragraph in the file). objectstack-ai#18481 (the protocol flip: a census-marked retirement becomes class-1) landed in that range and is the other half of ruling F. - Local verification scope: no package is touched, so no build/test closure is owed; `packages/spec`, `@objectstack/formula` and `@objectstack/lint` were built only as prerequisites of the derived gates. Repo-wide scans (`pnpm lint`) are CI's. ## 维护者速读(草稿) **改了什么**:新增一份审计文档 `docs/audits/gate-census-2026-09.md`,把仓库里全部门禁放到一张表上:182 个 `check-*.mjs`、26 个非别名的根 `check:*` 脚本、10 个 `.claude/hooks` 文件、7 个 main 分支必过的 CI 上下文,合计 225 行。每行六列:名字、类别(contract / correctness / process)、守的是什么契约、是否必过与波及面、落地以来真实抓到过几次(近 30 天 1,230 次失败的 PR 运行逐步归因,去掉门禁自己的 PR)、结论。⛔ 本 PR 不删、不停、不改任何门禁。 **为什么改**:您在直连通道的裁决 **F**(「门禁是不是用的太重了」→ 先普查、再按表退役)。这张表就是普查结果:**59 行建议退役**(其中 1 行 `check-reference-carrier-shape` 是 objectstack-ai#18095 已裁 E),**16 行只是报告不拦合并**,**150 行保留**(含您已裁定保留的治理队列守卫)。波及面最大的三处:`check-changeset-no-major`(Clause-② 等级规则,30 天红了 **74 个 PR**)、`check-partof-closing-keyword`(**31 个 PR**,但它只在非必过的工作流里跑)、`check-system-context-census`(必过、全仓,**21 个 PR**)。表外还有一个最大的红源:`pr-automation.yml` 里的内联「Require a changeset」步骤,30 天红了 107 个 PR。 **风险与代价(含回滚)**:本 PR 只加一份文档,零运行时改动,回滚即删除该文件。真正的代价在下一步:退役清单里有 9 行是「CI 自身接线」的守卫(必过上下文名字钉、聚合器 needs 花名册、Node/pnpm 获取、self-test 接线等),按规则它们 30 天零抓获所以列为退役,但它们的价值是威慑而非抓获——表里把这 9 行单独成组,供您一次决定。抽样只有 30 天:一季度才响一次的门禁会读成零。 **席位意见**:(留空,席位定稿) **你要做的**:读表,认可则回一个字「认可」;若对某行有异议(尤其 CI 接线 9 行组、以及 5 个会话 hook 的保留),点名该行即可,director 会把退役批次按您的意见立卡。 --- _Generated by [Claude Code](https://claude.ai/code/session_01Wj1HUjzyeiBQ8atRf1ZhaL)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #18473
Maintainer ruling F (verbatim 「F」, 2026-09-16 ~14:4xZ) on the direct-channel question 「我们的项目是不是门禁用的太重了。有这个必要吗?」. The card body's "Why" and "Deliverable" sections are the spec; this PR is the two re-keys, line-neutral, every touched line ≤120 bytes.
Surface:
.claude/skills/pm-dispatch/SKILL.md(812 → 812 lines) and.claude/skills/pm-dispatch/references/core-rules.md(151 → 151 lines). Governed rules layer: this PR stays draft; no ready flip, no review request, no arming — the director does the four-piece after ACCEPT and the maintainer merges.skip-changeset:.claude/**publishes nothing (fast-track class).Serialisation: #18468's PR #18476 (
SKILL.md:92) is still an open draft; #18434 (SKILL.md:523) remains queued. Neither line is touched here — both are hash-identical toorigin/main(285f1046…/557a3bc1…).origin/mainhad not moved from the branch base85c6d76eat the pre-PRos-regen-merge.shrun (Already up to date), so nothing was merged under this branch yet; the merge is re-run before enqueue per the claim.What changed — every line, before / after, byte counts
Line numbers are on
origin/mainat85c6d76e(the card body's:391–392had drifted by one; on this base the 人工地板 pair is:390–391and the class-1 floor line:403reads ③, as the dispatch says).1. Adding joins the human floor (SKILL.md :390–391, re-wrapped in place)
:390before (118 B):- 人工地板同含:安全/权限边界;门禁削弱(降阈值、删必查项、抬 ratchet 上限、跳过测试)。:390after (120 B):- 人工地板同含:安全/权限边界;门禁削弱(降阈/删必查/抬上限/跳测);新增运行时第三方依赖;:391before (100 B):- 人工地板同含:花费/配额/舰队形态/默认模型档位;新增运行时第三方依赖。:391after (119 B):- 花费/配额/舰队形态/默认模型档位;新增必需门禁/hook/棘轮(卡具名所守契约与预期捕获)。How the added words were paid, in place: the four weakening examples are compressed (降阈/删必查/抬上限/跳测,
、→/), 「抬 ratchet 上限」 becomes 「抬上限」 (the spelling:392and:785already use), and:391drops its repeated 「人工地板同含:」 prefix because:390now ends in;and:391continues it. Every existing floor item survives verbatim (安全/权限边界 · 门禁削弱 · 花费/配额/舰队形态/默认模型档位 · 新增运行时第三方依赖). The new item is 新增必需门禁/hook/棘轮 with the card requirement (the card names the contract it guards and the catch it expects). The ⛔ "no longer lands zero-baseline on a seat's own warrant" half is carried by floor membership itself —:389「代裁人工地板(恒交维护者)」 — and did not fit as separate words; stated here so the reader knows it is implied, not written.1b. 具名不升级类 scoped to an EXISTING gate's internals (SKILL.md :712)
:712before (110 B):- 纯文档措辞更正(无契约声明改动);门禁内部参数与扫描器盲区修复(加强,非削弱)。:712after (117 B):- 纯文档措辞更正(无契约声明改动);既有门禁内部参数与盲区修复(加强,非削弱,非新增)。「既有」 plus the explicit 「非新增」 close the ride: a new gate cannot claim this class. Paid by dropping 「扫描器」 (the subject 门禁 carries the scanner sense).
2. Retiring becomes class-1 (SKILL.md :403–404, same list)
:403before (110 B):- ③ 四类地板零移动:安全/权限边界、已发布契约语义、产品能力取舍、门禁强度。:403after (108 B):- ③ 四类地板零移动:安全/权限边界、已发布契约语义、产品能力取舍、门禁强度;:404before (77 B):- 任一地板触碰 ⇒ 照常现场呈报;地板是排除项不是权重。:404after (119 B):- 门禁普查标 retire 的退役除外,总监/技能席引该行裁;触地板即呈报,地板是排除项非权重。:403has 10 B of slack, so the carve-out could not sit inside it; per the ruling it is paid by tightening the adjacent line of the same list::403now ends in;and ③ continues into:404, which opens with the carve-out (retiring a gate the gate census marksretireis not 门禁强度 movement; the director or the skills seat rules it citing that census row) and keeps both of its own clauses (触地板即呈报 · 地板是排除项非权重; the 「照常现场」 sense is carried by:407「三类(地板)照旧现场呈报」). The census's three-part meaning ofretire(process class, zero real catches, guards no published contract) lives in the census document and is not restated. The census filedocs/audits/gate-census-*.mdis #18472's deliverable and is not onorigin/mainyet — the rule names it as 门禁普查 (a forward reference; no gate reads that path).3. core-rules.md twins, re-keyed identically (一条规则两处同改)
:95before (111 B):- 人工地板恒交维护者:功能新增、ADR、协议与公开契约变化、破坏性或难回滚动作。:95after (119 B):- 人工地板恒交维护者:新功能、ADR、协议/公开契约变化、破坏性/难回滚动作、门禁削弱。:96before (116 B):- 人工地板同样含安全与权限边界、门禁削弱、花费配额与模型档位、新增运行时依赖。:96after (120 B):- 地板含安全/权限边界、花费配额与模型档位、新增运行时依赖、新增必需门禁/hook/棘轮。:137before (119 B):- 记账事不升级(无产品可见行为变化):去重并卡、台账整理、纯文档措辞、门禁盲区加强。:137after (119 B):- 记账不升级(无产品可见行为变化):去重并卡、理台账、纯文档措辞、既有门禁盲区加强。Declared deviation: core-rules' human-floor list is the two-line block
:95–96with 4 B of slack in:96, and the identical re-key needs 33 B, so the block was re-wrapped across both lines exactly as the SKILL.md pair was — 门禁削弱 moved up to:95, 功能新增 → 新功能, 与/或 →/. Every item of both lines survives;:95is the twin of SKILL.md:389, which the ruling did not touch, so this is the one place the payment crossed into a neighbour line.:137pays 「既有」 with 记账事 → 记账 and 台账整理 → 理台账, keeping the class boundary phrase 「无产品可见行为变化」 byte-identical to SKILL.md:711. core-rules has no twin of the class-1 floor line (no 自裁/零移动 line exists there), so item 2 has no core-rules half. No other reference file twins any changed phrase (grep -rn 门禁削弱|门禁强度|加强,非削弱|门禁盲区加强|四类地板over.claude/ docs/ AGENTS.md skills/hits only the two files).Positive greps, with controls (
origin/main=85c6d76e)grep -c '新增必需门禁/hook/棘轮' SKILL.mdgrep -c '新增必需门禁/hook/棘轮' core-rules.mdgrep -A1 '③ 四类地板零移动' SKILL.md | grep -c '门禁普查标 retire'grep -c '既有门禁内部参数' SKILL.mdgrep -c '既有门禁盲区加强' core-rules.mdgrep -c '加强,非削弱)' SKILL.md(old spelling, no 非新增)git grep -n '新增' SKILL.md | grep -c 人工地板(the card's own grep)The card's own grep is control-insensitive:
:389(功能新增) and the runtime-dependency item already paired 新增 with 人工地板 onorigin/main, so it reads 2 both before and after; the first five rows are the discriminating evidence.Gates — run on the final head
45aeee5d, exit codes captured before any pipenode scripts/pm/dispatch-gates.mjs --commands(no paths; changeset from the merge-base) derived 17 families — byte-identical to the list derived from the two paths the dispatch named.--ranreconciliation on the exit-coded record: 17 derived, 17 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero — all 17 recorded an exit code and none is 3).pnpm check:pm-skill-ratchet—SKILL.md is 812 lines (ceiling 812; headroom 0)·core-rules.md is 151 lines (ceiling 151; headroom 0)pnpm check:pm-skill-id-lint—27 file(s) cleanpnpm check:skill-frame-sync—the one declared copy of the decision frame is internally coherentpnpm check:skill-frame-freshness(outside the derived union, run because the dispatch named it) —current with origin/mainpnpm check:pm-governed-prose—2 instruction surface(s) name all 5 registered governed surfacespnpm check:pm-governed-mergespnpm check:pm-half-statespnpm check:nul-bytes—scanned 8734 text file(s) … no raw ASCII control bytesnode scripts/pm/check-governed-queue-guard.mjs --self-testnode scripts/check-closing-keyword-parity.mjsand--self-testnode scripts/check-comment-mask-corpus.mjspnpm --filter @objectstack/lint run check:doc-formula-expressions(first run exited 3 = declared PREREQUISITE NOT MET, formula/lint unbuilt; built both underos-verify-lock.sh, re-run)pnpm check:agent-test-spelling·check:doc-authoring·check:driver-memory-census·check:refd-timer-probe·check:watch-hint-literalMechanism assumptions from the dispatch, measured: the ratchet and id-lint are the gates that bite (both green at headroom 0);
check:skill-frame-sync/-freshnessare untouched by these lines (both green, frame structure unchanged);check-governed-prose.mjspins only backtick code spans in the governed-surface enumeration region, not the 人工地板 block (green, and its region does not include these lines).Acceptance notes
新增+人工地板≥ 1) cannot distinguish before from after on this base; the PR carries discriminating greps instead. 承接者: PM (this report).docs/audits/gate-census-*.md, which lands with [audit] gate census — every check-*.mjs, check:* script, hook and required job on one table: what it guards, real catches since landing, blast radius — and the retirement list (maintainer ruling F) #18472; until then the carve-out has no row to cite. 承接者: [audit] gate census — every check-*.mjs, check:* script, hook and required job on one table: what it guards, real catches since landing, blast radius — and the retirement list (maintainer ruling F) #18472.维护者速读(草稿)
改了什么。 两处规则各改一行组,行数不变(SKILL.md 812/812,core-rules.md 151/151),每行 ≤120 字节:① 人工地板新增一项「新增必需门禁/hook/棘轮」——席位要立决策卡、写明它守的契约与预期能抓到什么,不再凭席位自授零基线落地;「门禁内部参数与盲区修复(加强)」这一免升级类改为只覆盖既有门禁,并写明「非新增」。② 一类自裁的「门禁强度」地板加一条例外:门禁普查标为
retire的门禁(流程类、零真实捕获、不守任何已发布契约),退役不算动地板,由总监席或技能席引普查行裁定。core-rules.md 的对应行同改。为什么改。 维护者裁决 「F」(2026-09-16,对「我们的项目是不是门禁用的太重了。有这个必要吗?」的回答)。现行规则把「削弱门禁」放在人工地板上,而新增门禁是免费的:182 个
check-*.mjs、164 个check:*脚本,上周 597 次合并里 42% 是门禁形状。这个不对称让舰队只会加门禁、拆不了门禁;本 PR 把方向翻过来:加要过维护者,拆(普查判定为 retire 的)由席位裁。风险与代价(含回滚)。 纯规则文本,不碰任何脚本或门禁本身;付账方式是压缩既有措辞(削弱四例缩写、去掉重复前缀、core-rules 两行重排),没有删任何一条规则。代价是这几行的可读性略降。回滚 = revert 本 PR 一次即可(两个文件、8 行)。依赖:例外条款引用的门禁普查文件
docs/audits/gate-census-*.md由 #18472 落地,落地前例外无行可引,但规则文本本身不依赖该文件存在。席位意见。 (留空,席位定稿成评论。)
你要做的。 这是受管规则层(
.claude/**):PR 保持 draft;总监席 ACCEPT 后做四件套,合并由你点击。看一眼上面「every line, before / after」八行是否合你的意;尤其 core-rules.md:95为付账被重排(门禁削弱上移一行)——若你希望 core-rules 那一侧只动:96,请说,改法是把:96压成更短的摘要。Generated by Claude Code