Skip to content

docs(os-dev): admit the ruled ceiling raise in the ratchet block and point at the ratchet header - #23868

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23770-os-dev-ruled-ceiling-raise
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23770-os-dev-ruled-ceiling-raise

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #23770
Clause-②: no

What lands

Two lines of the ratchet block in .claude/agents/os-dev.md (L296–L297 on the base) are rewritten in place. Net 0 lines (404 → 404), no CEILINGS row moves, no line is freed or added, and the file is the only path in the diff.

  • L296 before (90 B): - 密度优化只随净减内容的 PR;分界只问折行有没有为新增内容买行。
  • L296 after (120 B): - 密度优化只随净减内容的 PR;分界只问折行有没有为新增内容买行;不买者 ⛔ 不当筹行拒。
  • L297 before (116 B): - ⛔ 不把不买内容的密度修复当筹行拒掉;删不出等量内容 ⇒ 报 `blocked`,⛔ 不抬 ceiling。
  • L297 after (117 B): - 删不出等量内容 ⇒ 报 `blocked`,⛔ 不自抬 ceiling;裁决记录下令写入者除外(见棘轮头部)。

Every byte reading is LC_ALL=C awk length on the file at 7ba991b9a.

Why

The stale clause told a dev 「删不出等量内容 ⇒ 报 blocked,⛔ 不抬 ceiling」 with no exception, while ruling record 6184799323 on #23606 (letter B, item 1, maintainer 「同意」) admits one: a ruling of record that orders text into a ratcheted file authorizes the raise, quoted with its id and measured delta in the raising PR. The ruling's single source in the tree is the ratchet header (scripts/pm/check-skill-line-ratchet.mjs, section 「The ratchet discipline」, the RAISING bullet, L66–77 on this base) and the SKILL.md guard-index row (L291). The new L297 admits the exception in one clause and points at the header — it restates nothing: the form (ruling id plus delta in the PR body; at most that delta; no tolerance band) stays where it is landed.

What each clause keeps (dispatch §2(d)):

  • 「删不出等量内容 ⇒ 报 blocked」 — a dev with no ruling behind its lines still reports blocked when it cannot delete equal content.
  • 「⛔ 不自抬 ceiling」 — never on its own word, never on a dispatch word alone (a dispatch order is not a ruling of record).
  • 「裁决记录下令写入者除外(见棘轮头部)」 — the one admitted raise: text a ruling of record ordered written; its form is the header's.
  • The exception sits after both prohibitions behind a 「;」 so it governs both: with ruled text, neither 「报 blocked」 nor 「不抬」 applies, and the ruled raise is the route.
  • 「头部」 rather than the card's 「头注」: the file already names script headers 「头部」 twice (L1 and the nul-bytes rule), so the pointer reads like the others.

Paying for the bytes — a move within the block, not a deletion and not a raise

Measured first, as dispatch §3 asked: keeping L297's first clause and appending the ruled-raise tail lands at 179 B; the card's example tail alone, as a line, at 126 B; the tightest tail that keeps 「报 blocked」, the ⛔ and the header pointer at 117 B. So the first clause 「⛔ 不把不买内容的密度修复当筹行拒掉」 could not stay on L297.

Instead of deleting it, it moves onto L296, compressed to 「不买者 ⛔ 不当筹行拒」 — the same permission (a density edit that buys no content is not refused as a 筹行), now beside the dividing line whose negative branch it is (「分界只问折行有没有为新增内容买行」). L296 goes 90 → 120 B. Nothing is dropped, so no deletion is named and no single source is claimed for one.

Why this is not re-wrapping: 「新增以删减付账」 and the ⛔ on re-wrap are about LINES — merging lines to free one and spending it on new content. Here no line is freed and no line is added; two adjacent rule lines are edited in place under the ratchet header's 120-byte line convention (its 「Why 120 bytes」 section). The ratchet's count is unchanged, so there is nothing to pay.

  • No CEILINGS move: no ruling orders this text, so item 2 of the ruling applies.
  • L294 (the PM's net budget, 「抬它归维护者」) and L298 (the measurement-first exception) are untouched; neither is the CEILINGS clause.

Mechanism assumptions (dispatch §2), measured on the base

  • (a) holds. origin/main moved 0af559e80 → f7e836da1 (PR docs(pm-dispatch): let an execution seat accept a filer-labelled card when the lane fits the domain table and the body passes the filing gate; triage spot-checks after #23751) between the order and this branch; git diff 0af559e80 f7e836da1 -- .claude/agents/os-dev.md is empty. 404 lines, L297 at 116 B, headroom 0, L292–298 as the order read them.
  • (b) holds. Both sources re-read on f7e836da1: the ratchet header's RAISING bullet (L66–77; the paragraph runs two lines past the card's L75) and the SKILL.md guard row (L291: 「抬上限凭下令写入的裁决记录……无裁决 id 即红……不买内容的密度修复允许」).
  • (c) holds, and the suggested route in §3 does not: the first clause cannot stay (179 B). Net 0, every edited line at most 120 B, no CEILINGS move, no re-wrap. No deletion was needed, so none is named.
  • (d) preserved — the clause-by-clause reading above.

No conflict between the file's current text and the order was met: the order's budgets add to the file's rules without contradicting any line of it.

Verification (final head 7ba991b9a)

Ratchet verdict for the file, plain run, exit 0 both times:

  • before (f7e836da1): ✓ check-skill-line-ratchet: .claude/agents/os-dev.md is 404 lines (ceiling 404; headroom 0).
  • after (7ba991b9a): ✓ check-skill-line-ratchet: .claude/agents/os-dev.md is 404 lines (ceiling 404; headroom 0).
  • pnpm check:pm-skill-ratchet (self-test then gate): ✓ check-skill-line-ratchet self-test: 164 cases pass. and the line above; exit 0.

Derived gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack with no paths at 7ba991b9a derived 20 commands, identical to the dispatch order's list. All 20 ran locally, each exit code captured before any pipe (output redirected to a log first, the status read next), all exit 0. Reconciliation: Run reconciliation — 20 derived, 20 run, 0 NOT-MEASURED, 0 UNRUN. exit 0.

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions needs @objectstack/formula and @objectstack/lint built: their dependency closures were built under the verify lock (VERDICT command-exit 0 · held the lock 112s · waited 0s), then the gate exited 0. A first attempt without the closure stopped at tsup dts on an unbuilt @objectstack/spec (VERDICT command-exit 1) — a build-order fact, not a measurement, superseded by the closure build.
  • pnpm check:pm-skill-id-lint: ✓ check-skill-id-lint: 87 file(s) clean — no issue number enters the operating text (the ruling is reached through its header, not by id).
  • pnpm check:skill-frame-sync: exit 0 — the file carries no second copy of the decision frame.
  • pnpm check:nul-bytes: exit 0; the edited file also passes the raw control-byte grep from the file's own byte discipline (no match).
  • Local-only families (readings only): pnpm check:skill-frame-freshness exit 0 (1/1 framework files are byte-identical to the ref). pnpm check:dev-prereqs exit 1 — 「The workspace is not built — 1 unmet precondition」: 65 of 69 packages have no dist/ in this fresh worktree, where only the formula/lint closure was built. A box-state reading, not a verdict on the diff; CI's fresh checkout builds the workspace.
  • Clause ⑤ (a gate or tool script edited): not owed — the diff touches no script.
  • No ablation: the diff changes no tested behaviour (a rule line in an agent definition).
  • CI runs the full farm; this PR's check-runs are the record for every family CI runs.

Acceptance notes

  • The report-JSON template in os-dev.md names no deviations, line_budget or files_changed key, while dispatch §7 asks for them as machine-checkable fields and the file's own L139 writes to deviations. PR docs(os-dev): run the scoped platform-checklist check before push on an exported-symbol rename or removal #23766 noted the deviations half. Out of scope here and untouched; the report carries the keys anyway. Carrier: none — noted, not filed.
  • The ratchet prints an info line for .claude/skills/spec-property-retirement/SKILL.md (max-table-row pin 326, measured 324: 「lower the pin to 324」) — an opportunistic tightening the gate itself suggests, on a path not this card's. Carrier: none — noted, not filed.
  • No changeset: the diff publishes nothing (.claude/**). The skip-changeset label is the seat's to write; this PR writes no label.
  • Governed, Tier S (.claude/**): lands by the owning seat after an at-tier ## Contract review PASS. The draft stays a draft; no auto-merge, no reviewer request.

维护者速读(草稿)

  • 改了什么:改开发 agent 工作契约(.claude/agents/os-dev.md)里关于「行数上限」的两行。原来写死「删不出等量内容就报 blocked,绝不抬上限」;现在加上唯一的例外——维护者裁决记录下令写进去的文字,可以按棘轮门禁脚本头部写明的格式抬上限(PR 正文引裁决评论 id 与实测增量)。另一句「不买内容的密度修复不拒」原样保留,只是挪到上一行并压缩。总行数不变、上限不动、不发布任何包。
  • 为什么改:这条规则早于您的裁决(记录 6184799323,B 项),与裁决矛盾:按字面读,开发 agent 遇到裁决下令的加行也会报 blocked 停工(上一张卡 PR docs(os-dev): run the scoped platform-checklist check before push on an exported-symbol rename or removal #23766 的 agent 正是读到这里、在 PR 里点名冲突后才照裁决做的)。把契约文字和裁决对齐,后续 agent 不再卡在这一句;规则本身不复述裁决,只指向它的唯一出处(棘轮脚本头部),两处文字不再各自漂移。
  • 风险与代价(含回滚):零运行时影响,只改 agent 读的文字。风险在措辞:压缩后的「不买者 ⛔ 不当筹行拒」依赖同一行前半句的语境,席位复核若认为不够清楚可再调;该行已顶满 120 字节(120/120),再加字需另起一行。回滚 = revert 本 PR,两行各回原文。
  • 席位意见:(留空)
  • 你要做的:无需操作;本 PR 为 Tier S,由席位在达档复核 PASS 后入队落地。

Generated by Claude Code

The dev contract's ratchet block told a dev to report blocked and never
raise a ceiling, which contradicted the ruling of record landed in the
header of scripts/pm/check-skill-line-ratchet.mjs: a ruling that orders
text into a ratcheted file authorizes the raise. The clause now admits
that one exception and points at the ratchet header for its form, at
equal line count and under the 120-byte line cap; the permission for a
density fix that buys no content moves onto the preceding line.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqGhCg9wdsBXPz54uAEWg7
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Oct 16, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读

改了什么

  • 开发 agent 工作契约 .claude/agents/os-dev.md 的行数棘轮段改了两行,行数 404 → 404,上限不动,每行不超过 120 字节。
  • 原第 297 行「删不出等量内容 ⇒ 报 blocked,⛔ 不抬 ceiling」改为「删不出等量内容 ⇒ 报 blocked,⛔ 不自抬 ceiling;裁决记录下令写入者除外(见棘轮头部)」。
  • 原第 297 行前半句(不买内容的密度修复不当筹行拒掉)压缩后并入第 296 行,没有删掉任何规则。

为什么改

风险与代价(含回滚)

  • 纯规则文本,不发布任何包,不改代码。
  • 唯一放开的口子是「裁决记录下令写入」的文字;开发自己说了不算,派发令单独说了也不算。没有裁决的新增文字仍须靠删内容付账。
  • 回滚:revert 本 PR。

席位意见

  • 建议落地。语义与裁决逐条对齐,指向的单一出处(棘轮脚本头部)确实写了裁决的形式(PR 正文引裁决 id 与实测行数)。

你要做的

  • 无需审批:本 PR 是 Tier S,达档契约复核 PASS 后由席位落地。落地时要挂 skip-changeset 并转正式,若再被权限分类器拦,我会来问你。

席位核对

Seat domain:skills#2 · session_01VqGhCg9wdsBXPz54uAEWg7 (os-elon-musk) · read 2026-10-16T10:17Z · head 7ba991b9a · verdict: ACCEPT (Tier S — the seat lands it after the at-tier PASS)

Implemented-by: claude/issue-23770-os-dev-ruled-ceiling-raise
Reviewed-by: session_01VqGhCg9wdsBXPz54uAEWg7

  1. Shape. Draft PR against main. Body line 1 is Fixes #23770; line 2 is Clause-②: no, copied from claim 6212771865. One file, .claude/agents/os-dev.md, +2/−2. Merge base f7e836da1, which is current main.
  2. The two lines, read by the seat.
    • New L297 「删不出等量内容 ⇒ 报 blocked,⛔ 不自抬 ceiling;裁决记录下令写入者除外(见棘轮头部)」. It admits exactly the raise that ruling 6184799323 B item 1 authorizes. A dev still reports blocked when no ruling ordered the text, and still never raises on its own word; a dispatch word is not a ruling of record. Item 2 (「新增以删减付账」 for every unruled line) stays carried by L295.
    • The pointer target exists: scripts/pm/check-skill-line-ratchet.mjs's header, 「The ratchet discipline」, names the form (the ruling comment's id and the measured delta in the PR body, the CEILINGS row moved by at most that delta). The file uses 「头部」 for script headers elsewhere.
    • New L296 carries old L297's first clause, compressed to 「不买者 ⛔ 不当筹行拒」 beside the dividing rule it qualifies. No rule is lost.
  3. Budgets.
    • 404 → 404 lines, CEILINGS untouched (ceiling 404, headroom 0).
    • Bytes: L296 90 → 120, L297 116 → 117; every line in L292–299 is at most 120 B (LC_ALL=C awk length, read by the seat).
    • No re-wrap: the clause moved and was compressed, it did not buy a line.
  4. Gates.
    • The dev's local union at 7ba991b9a: 20 derived, 20 run at exit 0, 0 NOT MEASURED; --ran reconciled.
    • CI at this read: 34 check-runs, all completed, one red: Check Changeset. The diff publishes nothing (.claude/**), so skip-changeset is owed and is the seat's to write at landing.
  5. Out of scope (noted, not filed; no reach:):
  6. Landing (Tier S). The isolated CONTRACT_REVIEW_TIER reviewer is launched on this head in this act. On PASS: skip-changeset, the pre-landing checks, then pr_ready + automerge_enable.

Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 7ba991b9ae6cdc438c568dbe586ba8cb3dca6ed8
Local-runs: none
Scope: .claude/agents/os-dev.md + scripts/pm/check-skill-line-ratchet.mjs (header 「The ratchet discipline」 L62 ff., RAISING bullet L66–77; CEILINGS row L1455; the verdict() refusal text), .claude/skills/pm-dispatch/SKILL.md (guard-index row L291)

Read 2026-10-16T10:26Z by the isolated reviewer, on the inputs alone: card #23770 (body and all four comments — the claim 6212771865, the order, the os-dev-report 6213241462 and the seat's ACCEPT 6213309412), PR #23868 (body, file list, net diff f7e836da1..7ba991b9a, its one comment 6213294727), ruling record 6184799323 on #23606 in full, and the head's 34 check-runs (the last completed 2026-10-16T10:16Z). Nothing built, run or re-run: the byte and line readings below are LC_ALL=C awk length and wc -l over git show of the head, as the brief asks. The diff outside Scope: is empty — the PR touches one file — so there is no lane-seat TIER_DEFAULT remainder.

① Derived judgments

  1. The one admitted raise — RIGHT. New L297 「删不出等量内容 ⇒ 报 blocked,⛔ 不自抬 ceiling;裁决记录下令写入者除外(见棘轮头部)。」 admits exactly ruling 6184799323 letter B item 1 (「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 excepted thing is text a 裁决记录 ordered written, nothing else. No wider: 「不自抬」 keeps the dev's own word out, and a dispatch order is not a 裁决记录 (os-dev.md L185–186 keeps 裁决区 apart from the order's other two sections), so a dispatch word alone raises nothing; the exception sits behind the 「;」 after both prohibitions, so with ruled text neither 「报 blocked」 nor 「不抬」 applies and the ruled raise is the route — the ruling's 「No second word from the maintainer is needed」. No narrower: the form (ruling id + measured delta quoted in the raising PR's body, CEILINGS moved in the same PR by at most that delta, no tolerance band) is delegated by the pointer, neither restated nor tightened. 「…者」 parses either as the text so ordered or the writer so ordered; both parses require a ruling record, so the ambiguity admits nothing extra.

  2. Item 2 still carried — RIGHT. 「新增以删减付账」 for every unruled line and ⛔ no tolerance band: L295 is untouched (「付行数棘轮的唯一合法货币是删内容:⛔ 不拿 re-wrap(折行合并)当筹行,新增以删减付账。」) and L297's first clause still sends a dev with no ruling behind its lines to blocked. L295's 「唯一」 reads absolute two lines above the exception; the ruling's own text keeps 「新增以删减付账」 absolute and sets the exception beside it the same way, and the ratchet header (L71–72) says the same — a reading, not a defect.

  3. No rule lost — RIGHT. Old L296 is kept verbatim with one clause appended; old L297's first clause 「⛔ 不把不买内容的密度修复当筹行拒掉」 moves to L296 as 「不买者 ⛔ 不当筹行拒」, where 「不买者」 binds to 「分界只问折行有没有为新增内容买行」 directly before it — the permission SKILL.md L291 spells 「不买内容的密度修复允许」. Old L297's second clause survives as the new line's first two clauses with 「不抬」 → 「不自抬」, which narrows nothing a dev may do on its own.

  4. The pointer resolves — RIGHT. 「见棘轮头部」: the file names the gate only as 「行数棘轮」 (L295) and uses 「头部」 for a script header at L13 and L393; the one ratchet on this file is scripts/pm/check-skill-line-ratchet.mjs (CEILINGS row L1455, ['.claude/agents/os-dev.md', 404]), whose header RAISING bullet (L66–77) names ruling record 6184799323 and the form, and whose verdict() refusal text repeats it. The pointer is by name, not path: L296 stands at 120/120 B and L297 at 117/120 B, so a path cannot fit without the re-wrap L295 forbids. 「头部」 over the card's 「头注」 follows the file's own usage.

  5. Rest of the block and file — RIGHT, nothing contradicted. L294 (the PM's net-line budget, 「抬它归维护者」) agrees: a ruling of record IS the maintainer's word. L298 (a dispatch-named measurement-first ledger: land the lines, do not move the ceiling, report red) is a different case and untouched. L188 「派发词与本文件冲突时以本文件为准」 is why this fix is owed in the file — PR docs(os-dev): run the scoped platform-checklist check before push on an exported-symbol rename or removal #23766's dev met the old clause and had to name the conflict; after this change the contract and the ruling agree. L300 keeps .claude/** on the publishes-nothing fast lane. No line in L1–404 contradicts the new text.

  6. Ceiling and cap, read by the reviewer — RIGHT. wc -l: 404 at f7e836da1 and at 7ba991b9a; CEILINGS row 404 untouched (the diff touches one file); headroom 0. Bytes: L296 90 → 120, L297 116 → 117; L292–299 read 114/64/118/117/120/117/116/114. Three pre-existing lines over 120 B (L371 152, L372 189, L378 218) sit inside the report-JSON fence — the fence exemption class — and are not in the diff. All seven Lint shards and the Lint & Repo Gates aggregate are success on the head, so the ratchet family CI runs is green.

  7. Governed accept set — RIGHT. .claude/** only ⇒ Tier S: draft PR, no label written by the dev, no reviewer request, no auto-merge; Governed Surface Queue Guard success. The landing is the owning seat's after this record.

  8. Public surface — none. .claude/agents/os-dev.md ships in no package files[]; the diff adds no changeset and edits none.

  9. Rule-text hygiene — RIGHT. No issue number enters the operating text (check:pm-skill-id-lint rides the green Lint shards); the provenance (ruling 6184799323) is in the PR body and the commit message, where AGENTS.md puts it. Commit 7ba991b9a ends with the model-free trailer pair; no model identifier in the PR title, body, commit or comments (the hunk header's model: opus is the file's own frontmatter context, not PR text).

  10. PR shape — RIGHT. Body L1 Fixes #23770, L2 Clause-②: no copied from claim 6212771865 with no arm; one file, +2/−2; base f7e836da1 is the merge base and was origin/main when the PR opened; session-URL footer.

② Semver level

  • Nothing published moves: skip-changeset is the right declaration (route 2 of the gate's own text — .claude/ releases nothing; route 0 does not match, the diff has zero .changeset/*.md rows). Clause-②: no on the PR body L2, no arm, matches a diff that widens and narrows no published payload.
  • Check-runs on the head: 34. Every gate-carrying job is success; Check Changeset is failure for the absent label alone — its log reads ADDED: 0, the label window closed after 6 reads with documentation and size/xs on the PR, while its LEVEL AXIS (this PR declares clause-② no), ADR-0087 and no-major steps all passed. That red is the gate waiting for the seat's skip-changeset write at landing, not a verdict on the diff. The skipped rows are the path filter's selection.

③ Boundary flags

open_questions: none. The dev's seven deviations, each answered:

  1. Dispatch §3 route not taken (first clause kept + ruled tail) — answered, measured: with the card's example tail the line is 179 B; with the landed tail 170 B; both breach the 120-byte cap by 50+, so the clause could not stay on L297 and the move onto L296 is the right payment. Not a re-wrap: no line freed, no line added, 404 → 404.
  2. origin/main moved 0af559e80 → f7e836da1 before the worktree cut — answered: git diff --stat 0af559e80 f7e836da1 -- .claude/agents/os-dev.md is empty; the order's readings hold on the base.
  3. 「头部」 over the card's 「头注」 — accepted, ① item 4.
  4. First closure build exit 1 (tsup dts on an unbuilt spec) — answered: a build-order fact superseded by the closure build; no gate reading rests on it.
  5. check:dev-prereqs exit 1 — answered: a local-only family (os-dev.md L151–153) judging box state; CI's fresh checkout cannot and need not read it.
  6. size/xs and documentation set by the labelers, zero labels written by the dev — answered: another actor's state; the order's no-label narrowing is one L303 permits.
  7. Reads by gh api GET, no MCP — answered: read-only, within the write budget (mcp_calls: 0; 3 relay writes and 2 pushes).

The two out_of_scope_findings (the report-JSON template's missing keys; the spec-property-retirement pin info line) are correctly outside class a/b/c, carrier none — noted on the PR, nothing to escalate.

Implemented-by: claude/issue-23770-os-dev-ruled-ceiling-raise
Reviewed-by: session_01VqGhCg9wdsBXPz54uAEWg7

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 16, 2026
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 16, 2026 10:28
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 16, 2026 10:28
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 16, 2026
Merged via the queue into main with commit 6db53ac Oct 16, 2026
38 of 39 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-23770-os-dev-ruled-ceiling-raise branch October 16, 2026 10:57
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/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants