Skip to content

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

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-18473-gate-asymmetry-flip
Sep 16, 2026
Merged

os-zhuang merged 2 commits into
mainfrom
claude/issue-18473-gate-asymmetry-flip

Conversation

@hotlong

@hotlong hotlong commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

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 to origin/main (285f1046… / 557a3bc1…). origin/main had not moved from the branch base 85c6d76e at the pre-PR os-regen-merge.sh run (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/main at 85c6d76e (the card body's :391–392 had drifted by one; on this base the 人工地板 pair is :390–391 and the class-1 floor line :403 reads ③, as the dispatch says).

1. Adding joins the human floor (SKILL.md :390–391, re-wrapped in place)

:390 before (118 B):
- 人工地板同含:安全/权限边界;门禁削弱(降阈值、删必查项、抬 ratchet 上限、跳过测试)。
:390 after (120 B):
- 人工地板同含:安全/权限边界;门禁削弱(降阈/删必查/抬上限/跳测);新增运行时第三方依赖;

:391 before (100 B):
- 人工地板同含:花费/配额/舰队形态/默认模型档位;新增运行时第三方依赖。
:391 after (119 B):
- 花费/配额/舰队形态/默认模型档位;新增必需门禁/hook/棘轮(卡具名所守契约与预期捕获)。

How the added words were paid, in place: the four weakening examples are compressed (降阈/删必查/抬上限/跳测, /), 「抬 ratchet 上限」 becomes 「抬上限」 (the spelling :392 and :785 already use), and :391 drops its repeated 「人工地板同含:」 prefix because :390 now ends in ; and :391 continues 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)

:712 before (110 B):
- 纯文档措辞更正(无契约声明改动);门禁内部参数与扫描器盲区修复(加强,非削弱)。
:712 after (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)

:403 before (110 B):
- ③ 四类地板零移动:安全/权限边界、已发布契约语义、产品能力取舍、门禁强度。
:403 after (108 B):
- ③ 四类地板零移动:安全/权限边界、已发布契约语义、产品能力取舍、门禁强度;

:404 before (77 B):
- 任一地板触碰 ⇒ 照常现场呈报;地板是排除项不是权重。
:404 after (119 B):
- 门禁普查标 retire 的退役除外,总监/技能席引该行裁;触地板即呈报,地板是排除项非权重。

:403 has 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: :403 now ends in ; and ③ continues into :404, which opens with the carve-out (retiring a gate the gate census marks retire is 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 of retire (process class, zero real catches, guards no published contract) lives in the census document and is not restated. The census file docs/audits/gate-census-*.md is #18472's deliverable and is not on origin/main yet — the rule names it as 门禁普查 (a forward reference; no gate reads that path).

3. core-rules.md twins, re-keyed identically (一条规则两处同改)

:95 before (111 B):
- 人工地板恒交维护者:功能新增、ADR、协议与公开契约变化、破坏性或难回滚动作。
:95 after (119 B):
- 人工地板恒交维护者:新功能、ADR、协议/公开契约变化、破坏性/难回滚动作、门禁削弱。

:96 before (116 B):
- 人工地板同样含安全与权限边界、门禁削弱、花费配额与模型档位、新增运行时依赖。
:96 after (120 B):
- 地板含安全/权限边界、花费配额与模型档位、新增运行时依赖、新增必需门禁/hook/棘轮。

:137 before (119 B):
- 记账事不升级(无产品可见行为变化):去重并卡、台账整理、纯文档措辞、门禁盲区加强。
:137 after (119 B):
- 记账不升级(无产品可见行为变化):去重并卡、理台账、纯文档措辞、既有门禁盲区加强。

Declared deviation: core-rules' human-floor list is the two-line block :95–96 with 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; :95 is 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. :137 pays 「既有」 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 now control on origin/main
grep -c '新增必需门禁/hook/棘轮' SKILL.md 1 0
grep -c '新增必需门禁/hook/棘轮' core-rules.md 1 0
grep -A1 '③ 四类地板零移动' SKILL.md | grep -c '门禁普查标 retire' 1 0
grep -c '既有门禁内部参数' SKILL.md 1 0
grep -c '既有门禁盲区加强' core-rules.md 1 0
grep -c '加强,非削弱)' SKILL.md (old spelling, no 非新增) 0 1
git grep -n '新增' SKILL.md | grep -c 人工地板 (the card's own grep) 2 2

The card's own grep is control-insensitive: :389 (功能新增) and the runtime-dependency item already paired 新增 with 人工地板 on origin/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 pipe

node 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. --ran reconciliation 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).

command exit
pnpm check:pm-skill-ratchetSKILL.md is 812 lines (ceiling 812; headroom 0) · core-rules.md is 151 lines (ceiling 151; headroom 0) 0
pnpm check:pm-skill-id-lint27 file(s) clean 0
pnpm check:skill-frame-syncthe one declared copy of the decision frame is internally coherent 0
pnpm check:skill-frame-freshness (outside the derived union, run because the dispatch named it) — current with origin/main 0
pnpm check:pm-governed-prose2 instruction surface(s) name all 5 registered governed surfaces 0
pnpm check:pm-governed-merges 0
pnpm check:pm-half-states 0
pnpm check:nul-bytesscanned 8734 text file(s) … no raw ASCII control bytes 0
node scripts/pm/check-governed-queue-guard.mjs --self-test 0
node scripts/check-closing-keyword-parity.mjs and --self-test 0 / 0
node scripts/check-comment-mask-corpus.mjs 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions (first run exited 3 = declared PREREQUISITE NOT MET, formula/lint unbuilt; built both under os-verify-lock.sh, re-run) 0
pnpm check:agent-test-spelling · check:doc-authoring · check:driver-memory-census · check:refd-timer-probe · check:watch-hint-literal 0 each

Mechanism assumptions from the dispatch, measured: the ratchet and id-lint are the gates that bite (both green at headroom 0); check:skill-frame-sync / -freshness are untouched by these lines (both green, frame structure unchanged); check-governed-prose.mjs pins only backtick code spans in the governed-surface enumeration region, not the 人工地板 block (green, and its region does not include these lines).

Acceptance notes

维护者速读(草稿)

改了什么。 两处规则各改一行组,行数不变(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

…/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>

hotlong commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

总监席,session_01Wj1HUjzyeiBQ8atRf1ZhaL。席内复核 ACCEPT 记录在卡 #18473。受管规则层 ⇒ 等一位授权批准账号 APPROVED 后由席位落地;在此之前保持 draft。

改了什么 SKILL.md 5 行、core-rules.md 3 行,行数不变。① 加一道必需门禁 / hook / 棘轮从此是人工地板:席位要开决策卡、写明它守哪条契约、预期抓到什么,⛔ 不能再零基线自行落地;「门禁盲区修复免升级」收窄为既有门禁的内部修复,新门禁不能借这条。② 拆一道门禁变成一类自裁:门禁普查表标为 retire 的(流程类、零命中、不守任何已发布契约),总监或 skills 席引普查行即可裁,不再要你的字。

为什么改 你的裁决 F。协议原来只把「削弱门禁」放在人工地板上,「加门禁」免费 —— 一支 AI 舰队在这条规则下把每个 finding 都长成一道门:182 个 check 脚本,上周 42% 的合并是机器在管机器。

风险与代价(含回滚) 零产品行为变化。代价:席位今后加门要先问你一次(这正是目的)。回滚 = revert 一个 squash 提交。

席位意见 建议批准。它引用的「门禁普查表」在 #18472 的 PR 里,先后顺序不影响本 PR。

你要做的 一个动作:Approve。落地顺序:#18476 先,本 PR 随后合 main 再入队。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 16, 2026 15:35
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 16, 2026

hotlong commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

Landing provenance (ruling C) — director seat, session_01Wj1HUjzyeiBQ8atRf1ZhaL · 2026-09-16T15:37Z

Governed rules layer (.claude/**). Readings at landing, head 45aeee5d: APPROVED by os-zhuang (review 5224850379, 2026-09-16T15:35:41Z) on this exact head; check-clause2-carriers --pair 18481 exit 0 (Clause-②: no); CI 19 success · 16 skipped, all complete; in-seat ACCEPT on #18473 (stamped 2026-09-16T15:18Z). The approver flipped ready and the PR entered the merge queue at 2026-09-16T15:35:47Z behind #18476 / #18478 (same file SKILL.md, disjoint lines; the queue builds it on top of them); the seat stripped needs-user-decision and confirmed auto-merge (PUT …/ccr/auto_mergeenabled: true, squash). Nothing else remains for a person. Followed to MERGED by the director's check-in; the ADR-0136 enforcement card #18489 is serialised behind this PR on the same file.


Generated by Claude Code

Merged via the queue into main with commit 3dfcee2 Sep 16, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-18473-gate-asymmetry-flip branch September 16, 2026 15:58
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 17, 2026
… 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants