Skip to content

Commit 9a1d934

Browse files
docs(os-dev): run the scoped platform-checklist check before push on an exported-symbol rename or removal (#23766)
Fixes #23665 Clause-②: no ## What lands Two rule lines in `.claude/agents/os-dev.md` 〈本地验证范围〉, right after the trigger-shaped line (`新 fake engine ⇒ …`) and before ④: - `` - 改名或删除导出符号 ⇒ push 前跑 `node scripts/check-platform-checklist.mjs --changed-from origin/main`。 `` — 119 B - `` - 判定行原样记 `gates`;它非派生族,不在 `--commands` 清单,`--ran` 只把它列为派生外、不报错。 `` — 119 B They implement ruling record 6190922830 on #23653 (letter C, item 3; maintainer 「C (推荐)」, 2026-10-15), verbatim: > 3. **The dev-contract line** (`.claude/agents/os-dev.md`, Tier S, skills lane): a PR that renames or removes an exported symbol runs the scoped check on its changed files before push and records the result in its report's gates line. One line, landing after item 1. The command is the scoped mode's own spelling (`scripts/check-platform-checklist.mjs`, header section "The scoped mode", landed by PR #23677). Item 2 of the same ruling stands: no `dispatch-gates.mjs`, `dispatch-gates.data.mjs` or `dispatch-gates.self-test.mjs` edit, no derived family, no CI or workflow change, and no edit to `docs/qa/platform-checklist/README.md`. The trigger is decidable from the author's own diff (an `export`ed symbol renamed or removed); it is deliberately not "every PR", so the line stays a dev-contract duty and never a de facto gate on every push. ## Paying for the lines — route taken: ruled raise, not deletion `os-dev.md` stood at 402/402 (headroom 0) on `origin/main` `140238a47`. The `.claude/agents/os-dev.md` row of `CEILINGS` in `scripts/pm/check-skill-line-ratchet.mjs` moves 402 → 404, delta +2, with a comment block above the row in the shape of the `execution-duties.md` precedent (PR #23676). - Ordering ruling: record 6190922830 on #23653, letter C, item 3 (quoted above). - Authorizing ruling: record 6184799323 on #23606, letter B, item 1 (maintainer 「同意」, 2026-10-15), verbatim: 「A ruling of record that orders text into a ratcheted file is the authorization to raise that file's ceiling by the measured lines the text needs: the raising PR quotes the ruling comment's id and the measured line delta in its body, and moves the `CEILINGS` row in the same PR by at most that delta. No second word from the maintainer is needed.」 - Measured delta: +2 (402 → 404). The ruling sized the text as "one line"; under the ratchet's 120-byte cap the ruled content does not fit one. Measured: the command alone is 70 B in its code span; the dispatch order's example spelling is 137 B; the tightest one-line spelling that keeps the verbatim command, the trigger and the `gates` clause is 125 B (`` 改名或删导出符号 ⇒ push 前 `…`,记 `gates`。 ``). Trigger plus command alone lands at 119 B, so the `gates` clause and the not-a-derived-family reading take the second line (119 B). Every byte reading is `LC_ALL=C awk length` on the file. - Not taken: deletion. The file is rules-only, one rule per line; a full read on the base found no duplicated rule and so no lossless deletion. No neighbour was re-wrapped. - `os-dev.md` is not a `CROSS_FILE_MOVES` destination, so no `ruledRaises` record applies. ## Verification (final head `5e548689e`) Ratchet, before → after (plain run, exit 0 both): - before: `✓ check-skill-line-ratchet: .claude/agents/os-dev.md is 402 lines (ceiling 402; headroom 0).` - after: `✓ check-skill-line-ratchet: .claude/agents/os-dev.md is 404 lines (ceiling 404; headroom 0).` - `node scripts/pm/check-skill-line-ratchet.mjs --self-test` → `✓ check-skill-line-ratchet self-test: 164 cases pass.` exit 0, before and after. Live proof of the new line's own command, run as written on this branch, exit 0: `check-platform-checklist --changed-from origin/main: 0 anchored files in the change set — nothing judged. 2 changed file(s) since merge base 140238a, and none of them is the target of a checklist symbol anchor.` (followed by the mode's standing caveat that this is not the full gate's verdict). Mechanism reading for "records the result in its report's gates line": `--ran` neither refuses nor warns on an extra command. With `node scripts/check-platform-checklist.mjs --changed-from origin/main :: exit 0` appended to the run record, `dispatch-gates --ran` still exits 0, keeps `39 derived, 39 run, 0 NOT-MEASURED, 0 UNRUN`, and prints `Outside this card's derivation (1) — recorded, and named by nothing this run derived. Not an error: a run beyond the union costs nothing.` Hence the second line: the verdict line goes into `gates` verbatim; the run is not a derived family and does not enter reconciliation. Derived gates: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` with no paths, at `5e548689e`, derived 39 commands (identical to the dispatch order's list). All 39 ran locally with exit codes captured before any pipe; reconciliation: `Run reconciliation — 39 derived, 39 run, 0 NOT-MEASURED, 0 UNRUN.` exit 0. - `pnpm --filter @objectstack/lint run check:doc-formula-expressions` first exited 3 (PREREQUISITE NOT MET: `@objectstack/formula` and `@objectstack/lint` not built). Built both under the verify lock (`VERDICT command-exit 0 · held the lock 11s · waited 0s`) and re-ran: exit 0. The exit-3 reading is not a measurement and was replaced in the record. - `pnpm check:pm-dispatch-gates` (fast tier, 1884 cases, 229.4 s on this box): exit 0. - `pnpm check:pm-skill-id-lint`: `✓ check-skill-id-lint: 87 file(s) clean` — no issue number entered the operating text. - Clause ⑤ (a gate script was edited): the ratchet has no `*.test.ts`; its own suite is its `--self-test` (164 cases, exit 0), and the one other test file naming it, `scripts/pm/dispatch-gates.self-test.mjs`, ran inside `check:pm-dispatch-gates` (exit 0). - Local-only families `check:dev-prereqs` and `check:skill-frame-freshness` are not owed: the diff touches neither `packages/spec` nor a four-axis frame file. - CI runs the full farm; this PR's check-runs are the record for every family CI runs. ## A conflict named, not quietly settled `os-dev.md` L295 (unchanged here) reads 「删不出等量内容 ⇒ 报 `blocked`,⛔ 不抬 ceiling」, and L186–187 make the file win over a dispatch word and require conflicts to be named. The raise route here follows ruling record 6184799323 (letter B, item 1) and the ratchet header that lands it; both post-date L293–295 and explicitly admit a ruled raise, and item 5 of that ruling names `os-dev.md` lines among the raises in force. The clause is stale against the ruling; rewording it at equal line count is a separate skills-lane act, not this card's. L296's exception (land the line, leave the row, report red) does not apply: the dispatch order names the raise route, not measurement-first. ## Acceptance notes - `os-dev.md`'s report JSON template has no `deviations` key while L139 and other lines name one (dispatch §2(e)). Out of scope here and untouched; neither new line references `deviations`. - The ratchet's `--self-test` case "every live ruled-raise record quotes its ruling" covers `ruledRaises` records on `CROSS_FILE_MOVES` destinations. An ordinary raise's comment block is read by the seat's contract-review record and the queue guard's reader, not by the script (ratchet header, ruled-raise clause). - No changeset: the diff publishes nothing (`.claude/**`, `scripts/pm/**`). The `skip-changeset` label is the seat's to write. - Governed, Tier S (`.claude/**`): lands by the owning seat after an at-tier `## Contract review` PASS. The draft stays a draft; no auto-merge is armed. ## 维护者速读(草稿) - **改了什么**:给开发 agent 的工作契约(`.claude/agents/os-dev.md`)加两行规则:凡 PR 改名或删除了导出符号,push 前先跑一遍平台测试清单的「只看改动文件」模式,并把判定行原样写进报告的 `gates` 字段;同时把该文件的行数上限从 402 抬到 404(按裁决记录授权的抬高,附测量说明)。 - **为什么改**:平台测试清单反复变红,根因常是某个 PR 改名/删除了清单锚定的符号,而清单不是逐 PR 门禁,红只在合并后被日巡发现。裁决选了「不加门禁、加开发契约」:让作者在 push 前自己跑一次范围检查,把发现提前到合并之前。 - **风险与代价(含回滚)**:零运行时影响,不发布任何包;只给开发 agent 增加一步秒级自检。两行而非一行,是因为 120 字节的单行上限装不下完整命令加说明;上限抬 2 行按裁决记录授权。回滚 = revert 本 PR,两行与上限一起回退。 - **席位意见**:(留空) - **你要做的**:无需操作;本 PR 为 Tier S,由席位在达档复核 PASS 后入队落地。 --- _Generated by [Claude Code](https://claude.ai/code/session_01VqGhCg9wdsBXPz54uAEWg7)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 49700e4 commit 9a1d934

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

‎.claude/agents/os-dev.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ model: opus
139139
- 仅 diff 改该项目测试或派生清单点名它时本地跑,否则 `deviations` 写明;席位 ACCEPT 读其 CI。
140140
- ③ 读到改动文件的门禁族 = `--commands` 派生清单(按 diff 收窄);派发词清单与全农场归 CI。
141141
- 新 fake engine ⇒ `check:engine-double-contract`;新错误码 ⇒ `check:error-code-casing`。
142+
- 改名或删除导出符号 ⇒ push 前跑 `node scripts/check-platform-checklist.mjs --changed-from origin/main`。
143+
- 判定行原样记 `gates`;它非派生族,不在 `--commands` 清单,`--ran` 只把它列为派生外、不报错。
142144
- ④ 报告 `gates`:CI 跑的每族引 PR check-runs(名+结论),⛔ 不本地重跑;`--ran` 只对账本地子集。
143145
- 推导用 `node scripts/pm/dispatch-gates.mjs --commands` 不传路径,脚本自己从 merge-base 取变更集。
144146
- 变更集含未提交与未跟踪;跑完把已跑清单交给 `--ran <file>` 对账,未跑的本地族它会点名。

‎scripts/pm/check-skill-line-ratchet.mjs‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1432,7 +1432,27 @@ export const CEILINGS = new Map([
14321432
// convention (lowering is always legitimate). Lowered 403 → 402 when the
14331433
// retired contract-review label's reporting line left (ruling record
14341434
// 5770886272 on #19061).
1435-
['.claude/agents/os-dev.md', 402],
1435+
// Raised 402 → 404 by the scoped-checklist ruling — an ORDINARY raise, ⛔ not
1436+
// a cross-file move (card #23665). The text is two rule lines beside the
1437+
// trigger-shaped rules in 〈本地验证范围〉: a PR that renames or removes an
1438+
// exported symbol runs the scoped platform-checklist check on its changed
1439+
// files before push (`node scripts/check-platform-checklist.mjs
1440+
// --changed-from origin/main`, the mode's own spelling) and records the
1441+
// verdict line verbatim in its report's `gates` field; the run is not a
1442+
// derived family — `--commands` never lists it, and `--ran` reports it as
1443+
// outside the derivation, not an error. Ordered by ruling record 6190922830
1444+
// on #23653 (letter C, item 3); maintainer, 2026-10-15, verbatim and
1445+
// untranslated: 「C (推荐)」. The ruling sized the text as one line; measured,
1446+
// the ruled content does not fit one under the 120-byte cap: the command
1447+
// alone is 70 B in its code span, the tightest one-line spelling carrying
1448+
// trigger, command and the `gates` clause is 125 B, and the two lines land
1449+
// at 119 B and 119 B. Authorized under ruling record 6184799323 on #23606
1450+
// (letter B, item 1; maintainer 「同意」): a ruling of record that orders text
1451+
// into a ratcheted file raises that file's ceiling by the measured lines the
1452+
// text needs, the ruling id and the delta quoted in the raising PR's body.
1453+
// Not a CROSS_FILE_MOVES destination, so no `ruledRaises` record applies.
1454+
// Landed count, headroom 0, same convention.
1455+
['.claude/agents/os-dev.md', 404],
14361456
// #9473: the other four `.claude/skills/` are read in full by the sessions
14371457
// that use them too — the erosion mechanism the ratchet exists to stop
14381458
// isn't specific to the pm-dispatch surface. Set at current counts on

0 commit comments

Comments
 (0)