Repository navigation
Commit 6db53ac
docs(os-dev): admit the ruled ceiling raise in the ratchet block and point at the ratchet header (#23868)
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 #23751)
between the order and this branch; `git diff 0af559e f7e836d --
.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 #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 #23766 的 agent 正是读到这里、在 PR
里点名冲突后才照裁决做的)。把契约文字和裁决对齐,后续 agent
不再卡在这一句;规则本身不复述裁决,只指向它的唯一出处(棘轮脚本头部),两处文字不再各自漂移。
- **风险与代价(含回滚)**:零运行时影响,只改 agent 读的文字。风险在措辞:压缩后的「不买者 ⛔
不当筹行拒」依赖同一行前半句的语境,席位复核若认为不够清楚可再调;该行已顶满 120 字节(120/120),再加字需另起一行。回滚 =
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 41e84c0 commit 6db53ac
1 file changed
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
293 | 293 | | |
294 | 294 | | |
295 | 295 | | |
296 | | - | |
297 | | - | |
| 296 | + | |
| 297 | + | |
298 | 298 | | |
299 | 299 | | |
300 | 300 | | |
| |||
0 commit comments