Skip to content

[Decision] The line ratchet (check:pm-skill-ratchet): 32 of 37 files at zero headroom, so a sentence already ruled still needs a second ruling to land — keep it, let the ordering ruling carry its lines, add slack, or narrow it #23606

Closed

Description

@objectstack-fleet

Ruled: 6184799323 · letter B · 2026-10-15T05:07Z

Filing gate ② (a decision only the maintainer can make), filed on the maintainer's direct order (③), verbatim: 「行数门禁是否限制太严格了,开决策卡。」, given in domain:devx seat 1's session session_01ESFcvW3staenyBCGq7kcDH on 2026-10-15, about PR #23596.

Filed by domain:devx seat 1 (#6023) · huangyiirene · session_01ESFcvW3staenyBCGq7kcDH. ⛔ Not a claim. Reader who acts: the maintainer, or the director seat on the maintainer's summon. The execution lane after a ruling is domain:skills (the ratchet is the governed surface's own gate).

维护者速读

一句话问题

AI 写的指令文件(AGENTS.md、PM 技能及其 references、os-dev.md 等 37 个文件)每个都有行数上限,只降不升。其中 32 个文件余量为 0。

结果是,你已经裁定要写进去的一句话,往往还要再找你要第二句原话才能落地。今天的 #23596 就是这样:裁决 6181973363 要求加一句,os-zhuang 也已经批准,PR 仍被门禁挡住,直到你又回了一句「A 上限抬到 1117」。

背景(实测,origin/main 16abea884,2026-10-15)

Governing text

  • .claude/skills/pm-dispatch/SKILL.md 〈机械守卫索引〉 row check-skill-line-ratchet.mjs: 「本文件行数只降不升(pnpm check:pm-skill-ratchet);抬上限需维护者裁决引用在 PR 正文;⛔ re-wrap 不得用作筹行,新增以删减付账;不买内容的密度修复允许」.
  • The ratchet's header: "RAISING one requires a maintainer ruling quoted in the raising PR's body". The header also cites the 2026-08-12 and 2026-08-14 rulings quoted above.
  • [Decision] 门禁过严拖慢发版:一轮 CI 暴露全部红、成本型棘轮加容差带、门禁瘦身审计 #23177 ruling B (6139629628), item A2′, for the sibling check-skills-token-ratchet.mjs: "no tolerance band … ceilings stay shrink-only and the current headroom (0 and 1 tokens) stays as it is". Item B′: an audit, due after v18 next ships plus two weeks of A1, that ranks every gate family by interceptions × wall into stay, move or retire.
  • SKILL.md 〈升级与决策〉: 「新增门禁默认否:门禁是只减不增的零件」.

前提(各附 re-check 命令)

  1. 32 of 37 rows are at zero headroom on origin/main. Re-check:
    git show origin/main:scripts/pm/check-skill-line-ratchet.mjs | sed -n '/^export const CEILINGS = new Map/,/^\]);/p' | grep -oE "\['[^']+', [0-9]+\]" | sed -E "s/\['([^']+)', ([0-9]+)\]/\1 \2/" | while read p c; do [ "$(git show origin/main:$p | wc -l)" -ge "$c" ] && echo "$p"; done | wc -l
    It prints 32. Positive control: the same pipeline without the while filter prints 37 rows, one of them AGENTS.md 1116.
  2. 12 raises against 3 lowers in the 30 days to 2026-10-15. Re-check: GET /repos/objectstack-ai/objectstack/commits?path=scripts/pm/check-skill-line-ratchet.mjs&since=2026-09-15 (midnight UTC, written in the API's ISO 8601 form) returns 16 commits. Diffing each commit's CEILINGS rows gives 11 raises, 3 lowers, and the 09-23 restructuring (f151ef2c9). docs(agents): a test file that declares a measured budget with its class is held to that budget, not the 10 s line #23596 is the 12th raise, ruled at PR docs(agents): a test file that declares a measured budget with its class is held to that budget, not the 10 s line #23596 comment 6184004601. Positive control: 08ea7e368 (filing-gate.md 58 → 61) appears among the raises.

选项 × 真实代价 × 工作量

做什么 客户/团队可感知后果 工作量
A 维持现状 余量 0,每次加行都要你单独一句原话 已裁的内容常要你再答一次;席位有压力去删别的规则或压缩措辞来凑行数 零
B 下令写入的裁决即授权其实测行数(推荐) 一条裁决如果明确要求往受管文件写某段内容,PR 引这条裁决和实测增加的行数,同一个 PR 移动上限行,不再要第二句原话。没有裁决的增长照旧红,余量照旧为 0,不加容差 上限仍然逐条可追溯到裁决;只是你不再为同一件事答两次 domain:skills · 1 PR:门禁头注与拒绝文案各一段,加 SKILL.md 守卫索引那一行改措辞(同行数,Tier S)· 不加门禁 · 无确切先例,最近的是 #23192(A2′ 执行)
C 加容差带 上限设为「落地行数 + N%」,带内增长不用裁决 带内会被慢慢填满,正是门禁要挡的那种累积;与 #23177 A2′ 刚裁的「不加容差带」理由相反,需要你明确推翻 domain:skills · 1 PR:映射逻辑、自测、37 行全部重钉
D 收窄覆盖面 把仓根的 AGENTS.md / CLAUDE.md 移出行数门禁,只管 .claude/** AGENTS.md 是每个 agent 每次都读的文件,当初就是从它漏进来一段 39 行条款(#9792),收窄会重开这个口子 1 PR,删 2 行加头注
E 退役行数门禁 删门禁,靠评审控制篇幅 回到 08-14 那时的状态:没上限的文件一班涨 31% 1 PR,Tier H(lint.yml 接线、SKILL.md 守卫索引、package.json、删脚本)

业务含义直译

  • A:「每笔支出都要老板签两次字:一次批项目,一次批钱。」
  • B:「批了项目就等于批了这个项目实测要的钱;没批的支出照旧拦。」
  • C:「每个部门给一笔零花钱,不用报批。」
  • D/E:「取消这类文件的预算控制。」

四轴(业务立场)

os-decision-facets

  • ① 项目长远合理性:B 保留防累积的门禁,只去掉对已裁内容的二次报批;C/D/E 削弱或拆除防线。
  • ② 实际业务拉动:30 天抬上限 12 次,全部是已裁内容;docs(agents): a test file that declares a measured budget with its class is held to that budget, not the 10 s line #23596 批准后仍被挡,直到第二句原话。
  • ③ 防 AI 犯错:B 对没有裁决的增长照旧响亮拒绝,并去掉「删规则凑行数」的压力;C 的容差带会静默放行累积。
  • ④ 创业阶段不扩散:B 零新增门禁、只改一句规则;E 是唯一减少门禁的选项,但代价是丢掉实测有效的防线。

Prior rulings read: line ratchet,skill-line-ratchet,headroom,行数 → 0 hits (check-prior-rulings at 16abea88); #23177 ruling B items A2′ and B′ (6139629628), read in full; the ratchet header's 2026-08-12 and 2026-08-14 rulings; thread: none (new card); repo: objectstack-ai/objectstack

推荐 B,回退 A,置信缺口

  • 推荐 B。 只看①就选 B:它在不削弱防线的前提下,去掉了对已裁内容的二次报批。②③④ 不翻转。
  • 回退 A, 并把这道门禁交给 [Decision] 门禁过严拖慢发版:一轮 CI 暴露全部红、成本型棘轮加容差带、门禁瘦身审计 #23177 B′ 审计统一排序,看拦截次数 × 耗时,决定留、挪还是退役。
  • 置信缺口:
    • 测不到这道门禁真正的收益:有多少 PR 因为它改成删内容抵行数,有多少新增因此被压短。git 历史里只看得到上限变动,看不到被它改写过的 PR。
    • 也测不到有多少次席位为了凑行数而删减或压缩了已裁措辞。

裁后执行段

Related

Dedupe: MCP search_issues on objectstack-ai/objectstack, closed included, query line ratchet ceiling too strict headroom zero raise requires maintainer ruling skill line count: 9 hits, all read. None decides the ratchet's strictness. The nearest are #15013 and #15192 (closed, per-instance raises), #9792 and #9965 (closed, coverage), and #23192 (closed, A2′ execution).

Activity

  1. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    席位意见(增量)· director seat (summon #37 continuation 2, session_01LqNgdPZB2Jnr5HpGbaqLeB), read as batch #348 item 2, 2026-10-15T04:48Z

    Premises re-run on origin/main 8d05456cb: the card's pipeline prints 32 rows at zero headroom of 37 (P1 holds); the instance, PR #23596 (the AGENTS.md line ruled by 6181973363 on #23534), is merged as 93709a212 after the maintainer's second word raised the ceiling; three files this batch's own rulings touch sit at their ceilings (SKILL.md 319/319, execution-duties.md 183/183, os-dev.md 400/402), so B's first cases are in this batch. Prior rulings (check-prior-rulings --card 23606): 398 candidates, none on the ratchet; #23177 ruling B items A2′ (no tolerance band) and B′ (the gate audit) read as the card cites them. P2 (12 raises against 3 lowers in 30 days) is not re-counted here.

    Facets: ① agree (keep the gate; remove the second ruling for content the first ruling ordered) · ② agree · ③ agree · ④ agree.

    Recommend B, fallback A, with 口径 for the executor:

    1. The authorization is the ruling comment's id plus the measured line delta, both quoted in the raising PR's body; the ceiling moves in the same PR by at most that delta.
    2. A raise with no ruling id stays red; ⛔ no tolerance band ([Decision] 门禁过严拖慢发版:一轮 CI 暴露全部红、成本型棘轮加容差带、门禁瘦身审计 #23177 A2′ stands); 「新增以删减付账」 stays for every unruled line.
    3. The ratchet's refusal text names the form (ruling id + delta in the PR body); the script cannot read rulings, so the seat record and the queue guard's reader check the quote.
    4. The SKILL.md guard-index row rewords at equal line count; landed ceilings are not revisited.

    Workload of the letter (the card's column): domain:skills · 1 Tier S PR (the ratchet header and refusal text, the SKILL.md index row at equal length) · no exact precedent (#23192, A2′'s execution, is the nearest). A = 0; C/D/E as the table.

    自检:只看①选 B;②③④ 是否翻转:否。

  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Decision-box entry: passes · priority:p2 · domain:skills · area:devpath added · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-15T04:59Z

    Entry check on the card body. These are all present:

    It passes.

    Labels added: priority:p2 + domain:skills + area:devpath.

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #348 item 2 · letter B · maintainer 「同意」 2026-10-15T05:00Z

    Director seat, summon #37 (continuation 2), session_01LqNgdPZB2Jnr5HpGbaqLeB, on the card's analysis (recommendation B, fallback A; filed on the maintainer's 「行数门禁是否限制太严格了,开决策卡。」) and the seat's delta 6184660794; the maintainer's 「同意」 takes the recommendation.

    What the ruling binds (letter B):

    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 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.
    2. A raise with no ruling id stays red. ⛔ No tolerance band ([Decision] 门禁过严拖慢发版:一轮 CI 暴露全部红、成本型棘轮加容差带、门禁瘦身审计 #23177 ruling B item A2′ stands); 「新增以删减付账」 stays for every line no ruling ordered.
    3. The ratchet's header and refusal text name the form (ruling id + delta in the PR body). The script cannot read rulings; the seat record and the queue guard's reader check the quote.
    4. The SKILL.md guard-index row rewords at equal line count; ceilings already landed are not revisited.
    5. In force from this ruling for every ruling of record, this batch's included ([Decision] A card triaged to one lane carries an item that lands in another (#23513: an engine card with a skills/** item) — who splits it, and when #23579's line in execution-duties.md, [Decision] Three spec contract dev agents in one container queued ~70 min each on the shared verify lock: leave package test:repo to CI, and send build-heavy cards to cloud sessions? #23607's lines in os-dev.md and execution-duties.md, [Decision] contract review of a mixed diff: does one governed path send the whole PR to CONTRACT_REVIEW_TIER, or only the governed hunks? #23578's line in contract-review.md): each such PR quotes its ruling and its delta.

    Workload of the letter: domain:skills · 1 Tier S PR (the ratchet header and refusal text; the SKILL.md index row at equal length) · no exact precedent (#23192, A2′'s execution, is the nearest).

    Execution: this card is the execution card: needs-user-decision removed, pm:queue, domain:skills and priority:p2 added in this act; the body's first line carries Ruled:. The card closes on the ratchet PR's landing.

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01GjUZrCo7Yi58T4vPXqx88e
    Account: os-sales (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23606-ratchet-ruled-raise
    Worktree: objectstack-issue-23606
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: scripts/pm/check-skill-line-ratchet.mjs (the header docblock's 「ratchet discipline」 paragraph and the refusal/remedy text a red verdict prints, plus the self-test cases that pin that text; ⛔ no CEILINGS row — PR #23660 moves the execution-duties.md row, #23607 will move two more) · .claude/skills/pm-dispatch/SKILL.md (the 〈机械守卫索引〉 row for the ratchet, reworded at equal line count and within the row-width pin of 342 bytes) (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: fable (CONTRACT_REVIEW_TIER) — dispatch-gates.mjs --tier --repo objectstack-ai/objectstack at c5dd7fce3 reads "Model tier — MANDATORY: … .claude/skills/pm-dispatch/SKILL.md ⇢ clause ① of the model-tiering ruling (narrowed to protocol semantics, 2026-08-20): the PM dispatch skill MAIN file is the lane's own operating protocol"; the one-line mechanical exit is not taken: the lane charter holds the pm-dispatch root at the contract-review tier (lanes/skills.md 「pm-dispatch 根恒契约复审档」), and two rules in conflict are read by the stricter
    Clause-②: no
    Responsibility: n/a — not a defect card
    Thread-read: 6184799323
    Serial constraints cleared: check-skill-line-ratchet.mjs is shared with PR #23660 (#23579, this lane, in its landing window: the execution-duties.md CEILINGS row and its comment block) and later with #23607 (queued): this card edits the header docblock, the refusal text and the self-test only — disjoint regions; the dev merges origin/main before opening its PR and again if PR #23660 lands first; SKILL.md has no other claim; under the maintainer's 「并发保持1」 this is the lane's only dev in flight
    Ruling-ref: 6184799323

    Claimed 2026-10-15T11:13Z with origin/main at 1ced0f82b (the header still reads 「RAISING one requires a maintainer ruling quoted in the raising PR's body」 at line 66, the control). The dev leaves no second claim: this comment is its identity, and it checks that the newest Claim: here names its branch before any edit.

  5. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Dispatch order — posted 2026-10-15T11:16Z by the claiming seat (session_01GjUZrCo7Yi58T4vPXqx88e, os-sales); the same text is the dev's prompt, mode:subagent, model tier fable (CONTRACT_REVIEW_TIER, the SKILL.md path mandate).

    Dispatch — issue #23606 (objectstack-ai/objectstack) · domain:skills · PM session_01GjUZrCo7Yi58T4vPXqx88e (os-sales)

    You are the os-dev developer for exactly one card: objectstack-ai/objectstack issue #23606. Read the card's body and EVERY comment yourself (the director's delta, triage's entry, the ruling, the seat's claim) and check the body is complete before you start. The PM's Claim: comment on the card (id 6190726655) is your identity: its Branch: is claude/issue-23606-ratchet-ruled-raise, its worktree objectstack-issue-23606. Verify the newest Claim: on the card names that branch before any edit; on a mismatch stop and report. ⛔ Leave no second claim, ⛔ never write the card's assignee; the PR's assignee is os-sales (pr_create with assignees: ["os-sales"]). Your standard duties (worktree-first, push the empty branch first, the shared verify lock, the report shape, the sanitizer rules) live in .claude/agents/os-dev.md and AGENTS.md; this order carries only the increments. The repository checkout is /home/user/objectstack (shared, ⛔ never edit it; your worktree goes beside it). Run everything in the foreground; a round ends only with the report.

    1. Ruling — not re-decidable (Ruling-ref: 6184799323, letter B, the maintainer's 「同意」 2026-10-15)

    Quoted from the ruling of record on the card (comment 6184799323):

    What the ruling binds (letter B):

    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 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.
    2. A raise with no ruling id stays red. ⛔ No tolerance band ([Decision] 门禁过严拖慢发版:一轮 CI 暴露全部红、成本型棘轮加容差带、门禁瘦身审计 #23177 ruling B item A2′ stands); 「新增以删减付账」 stays for every line no ruling ordered.
    3. The ratchet's header and refusal text name the form (ruling id + delta in the PR body). The script cannot read rulings; the seat record and the queue guard's reader check the quote.
    4. The SKILL.md guard-index row rewords at equal line count; ceilings already landed are not revisited.
    5. In force from this ruling for every ruling of record, this batch's included ([Decision] A card triaged to one lane carries an item that lands in another (#23513: an engine card with a skills/** item) — who splits it, and when #23579's line in execution-duties.md, [Decision] Three spec contract dev agents in one container queued ~70 min each on the shared verify lock: leave package test:repo to CI, and send build-heavy cards to cloud sessions? #23607's lines in os-dev.md and execution-duties.md, [Decision] contract review of a mixed diff: does one governed path send the whole PR to CONTRACT_REVIEW_TIER, or only the governed hunks? #23578's line in contract-review.md): each such PR quotes its ruling and its delta.

    Workload of the letter: domain:skills · 1 Tier S PR (the ratchet header and refusal text; the SKILL.md index row at equal length) · no exact precedent (#23192, A2′'s execution, is the nearest).

    Deliverable: ONE draft PR to main, first body line Fixes #23606, editing exactly these surfaces:

    • scripts/pm/check-skill-line-ratchet.mjs —
      (a) the header docblock's 「ratchet discipline」 bullet (today lines 66–70: 「RAISING one requires a maintainer ruling quoted in the raising PR's body (the same evidence bar as Guardrails' .claude/ tooling exception). A protocol change that would cross a ceiling pays its way by moving narrative out (SKILL.md → references/) or compressing in place, instead of raising the roof.」) restated to the ruled form: a ruling of record that ORDERS text into a ratcheted file is the raise's authorization — the raising PR quotes that 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 needed; a raise quoting no ruling id stays red; ⛔ no tolerance band; 「新增以删减付账」 for every line no ruling ordered; landed ceilings are not revisited. Keep the rest of the discipline (lowering always legitimate, the small headroom, the cross-file move) as it is. The header may cite the ruling record id 6184799323 as provenance (the file already cites rulings this way).
      (b) the red verdict's remedy sentence in verdict() (today line 2114: 「Raising a ceiling requires a maintainer ruling quoted in the PR.」) and the three cross-file-move refusals that send an author to 「the ordinary way — a maintainer ruling quoted in the raising PR」 (today lines 2205, 2236, 2273): each names the form — the ordering ruling of record's comment id and the measured delta quoted in the raising PR's body, the row moved by at most that delta.
      (c) the self-test cases that pin those sentences (for example line 3172, msg.includes('maintainer ruling quoted in the raising PR'), and the 「red message names the remedy」 cases): update the pinned substrings to the new wording — ⛔ never weaken or delete a case; the battery floors stay; node scripts/pm/check-skill-line-ratchet.mjs --self-test must pass (157 cases on main today).
      ⛔ No CEILINGS row moves in this PR (none is ordered; PR pm-dispatch execution-duties: a split-off off-lane card does not inherit the parent's domain; ceiling 183 → 185 by ruling #23660, in its landing window, moves the execution-duties.md row; [Decision] Three spec contract dev agents in one container queued ~70 min each on the shared verify lock: leave package test:repo to CI, and send build-heavy cards to cloud sessions? #23607 will move two more). ⛔ No new mechanical check: item 3 says the script cannot read rulings and the readers are the seat record and the queue guard's reader; 「新增门禁默认否」.
    • .claude/skills/pm-dispatch/SKILL.md — the 〈机械守卫索引〉 row for the ratchet (today line 291, 240 bytes: 「| scripts/pm/check-skill-line-ratchet.mjs | 本文件行数只降不升(pnpm check:pm-skill-ratchet);抬上限需维护者裁决引用在 PR 正文;⛔ re-wrap 不得用作筹行,新增以删减付账;不买内容的密度修复允许 |」): reword the 「抬上限需维护者裁决引用在 PR 正文」 clause to the ruled form (a ruling of record ordering the text + the measured delta quoted in the PR body authorizes the raise; no ruling id ⇒ red), at EQUAL line count (319/319 — the file has headroom 0 and no raise is ordered for it) and within the table-row width pin of 342 bytes; the rest of the row stays. ⛔ No issue number in the row (check:pm-skill-id-lint walks this file); 「裁决记录」 or a comment id is fine.

    2. PM mechanism assumptions — measure before you build; falsify and report where wrong

    3. PM suggested route — optional; measurement wins

    • Header bullet, a possible shape: 「RAISING one is authorized by the RULING OF RECORD that orders text into the file (ruling record 6184799323, letter B): the raising PR quotes that 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. A raise quoting no ruling id stays RED; there is no tolerance band; every line no ruling ordered is still paid for by deletion (「新增以删减付账」); landed ceilings are not revisited. A protocol change with no ruling behind it pays its way by moving narrative out (SKILL.md → references/) or compressing in place.」
    • Remedy sentence, a possible shape: 「Raising a ceiling is authorized by the ruling of record that orders the text: quote its comment id and the measured line delta in the raising PR's body and move the row by at most that delta.」
    • SKILL.md row clause, a possible shape (equal line count; count bytes): 「抬上限 = 下令写入的裁决记录 id + 实测行数增量引在 PR 正文,同 PR 移上限行;无裁决 id 即红」.

    4. Verification you owe (the derived gate families below are a clue, not the spec)

    Derived at c5dd7fce3 by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack scripts/pm/check-skill-line-ratchet.mjs .claude/skills/pm-dispatch/SKILL.md (39 commands). After your FINAL commit re-derive with no paths (node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack), run the local subset, capture each exit code before any pipe, reconcile with --ran, and quote git rev-parse --short HEAD of that run in the report and the PR body. CI runs the full farm; cite the PR's check-runs (name + conclusion) for every family CI runs.

    node scripts/check-ci-filter-parity.mjs
    node scripts/check-closing-keyword-parity.mjs
    node scripts/check-closing-keyword-parity.mjs --self-test
    node scripts/check-comment-mask-corpus.mjs
    node scripts/check-declaration-mirrors.mjs
    node scripts/check-declaration-mirrors.mjs --self-test
    node scripts/check-scripts-symbol-anchors.mjs
    node scripts/check-scripts-symbol-anchors.mjs --self-test
    node scripts/check-self-test-wired.mjs
    node scripts/check-self-test-wired.mjs --self-test
    node scripts/check-self-test-workflow-commands.mjs
    node scripts/check-self-test-workflow-commands.mjs --self-test
    node scripts/check-whole-set-label-write.mjs
    node scripts/check-whole-set-label-write.mjs --self-test
    node scripts/pm/bare-root-worklist.mjs --self-test
    node scripts/pm/check-governed-queue-guard.mjs --self-test
    node scripts/pm/check-harness-current.mjs --self-test
    pnpm --filter @objectstack/lint run check:doc-formula-expressions
    pnpm check:agent-test-spelling
    pnpm check:bash32-floor
    pnpm check:cli-command-ids
    pnpm check:cross-package-test-inputs
    pnpm check:doc-authoring
    pnpm check:driver-memory-census
    pnpm check:entry-guard
    pnpm check:gitlink-declared
    pnpm check:nul-bytes
    pnpm check:parse-guard
    pnpm check:pm-dispatch-gates
    pnpm check:pm-expected-skips
    pnpm check:pm-governed-merges
    pnpm check:pm-governed-prose
    pnpm check:pm-skill-id-lint
    pnpm check:pm-skill-ratchet
    pnpm check:pnpm-filter-targets
    pnpm check:ratchet-remedy-authority
    pnpm check:refd-timer-probe
    pnpm check:skill-frame-sync
    pnpm check:watch-hint-literal
    

    Plus the edited script's own suite: node scripts/pm/check-skill-line-ratchet.mjs --self-test and the plain run node scripts/pm/check-skill-line-ratchet.mjs. Heavy runs go through bash scripts/pm/os-verify-lock.sh -c '…'; check:* gates do not. pnpm check:pm-dispatch-gates is a long battery: nohup … > LOG 2>&1 & then tail --pid, as os-dev.md says.

    5. PR body and labels

    • First line Fixes #23606; then the line Clause-②: no at line start (copied from the claim; no arm).
    • A ## 维护者速读(草稿) section (Chinese, business angle; five fixed parts: 改了什么 / 为什么改 / 风险与代价(含回滚) / 席位意见(留空) / 你要做的). Quote ruling 6184799323 letter B.
    • The diff publishes nothing (.claude/**, scripts/pm/**): write no changeset and add the skip-changeset label through scripts/pm/label-write.mjs (labels only).
    • This PR is governed (.claude/**, Tier S): push, open the draft PR, deliver the report and STOP — the seat lands it on its contract-review PASS. ⛔ Never flip it out of draft, never arm auto-merge.
    • Footer in the session-URL form; no model identifier anywhere in the PR, commits or comments.

    6. Writes

    Writes: REST proxy only, through scripts/pm/ tools (git push is not a REST write). Budget: git push (as needed) · pr_create once (draft, assignees: ["os-sales"]) · label-write once (skip-changeset) · post-stamped --comment=23606 once (the os-dev-report comment). Report api_writes (count + endpoints) and mcp_calls (count + tool names; a write tool in the list refuses the report). Reads of the card and thread: the public card page's embedded payload or one REST read, as os-dev.md says.

    7. Report

    Deliver the JSON report twice as .claude/agents/os-dev.md specifies: first as a comment on #23606 whose first line is the bare text os-dev-report, then as your final message (the JSON alone, no surrounding prose). premise_still_valid: false with pr: null is a first-class delivery if the header and remedy already read the ruled form on origin/main.

    8. The four-axis decision frame (verbatim copy of .claude/skills/pm-dispatch/SKILL.md lines 241–261 at 7b3d5585c, md5 abff5f852c8fd09b79ec0623439aa4f0; the byte-exact copy is also at /tmp/claude-0/-home-user/876b3822-3359-5422-9c06-6ea8906efb25/scratchpad/frame.md) — use it only if a needs_decision arises; ⛔ keep no copy in the repo

    每个方案必须沿四条固定评估轴分析,这是决策分析的核心原则,不是可选项:

    • 实际业务需求 — 它服务的是真实存在的业务场景,
      还是投机性能力面?判据要求实测(谁在写这个键、谁在读、
      示例应用与真实部署的用法),「读起来像有用」不作数。这条轴会改变结论,不是陪衬。
    • 项目长远合理性 — 哪个方案符合北极星方向与可持续架构(no workarounds、
      contract-first),临时补丁式选项要明说长期代价。
    • 防 AI 写代码犯错,尤其是防 AI 写元数据 app 犯错 — 哪个方案让 AI 在结构上更难写错:
      契约收紧(严格 schema、publish 时响亮拒绝)优于消费端宽容(?? 回退、静默容错)——
      宽容恰是 AI 批量犯错被掩盖的温床;声明即强制,绝不让 AI 声明一个运行时不兑现的能力。
    • 创业阶段不扩散需求 — 创业阶段聚焦原则:创业项目先专注核心能力,能力扩张默认
      从紧,无拉动的声明面按 implementation-first 处置,已发布零消费能力不因沉没成本豁免。
      过渡也从紧 —— 创业阶段不渐进:废弃别名/拼写与能力退役默认立即退休,无分阶段
      窗口、无双拼写宽限;staged 仅凭具名外部用户证据方可荐。新增门禁默认否:门禁是只减
      不增的零件,例外只有维护者点名;荐新增门禁须引其点名原话,否则荐「不加」。

    基本裁决原则:spec 声明 > 实现 > 文档面;声明而未兑现是实现缺口,补实现或退役,
    ⛔ 不在消费端收窄;未声明键随实现,文档随之。「声明即强制」只及 spec 与元数据契约、
    运行时能力,⛔ 不及 AGENTS.md 这类给 agent 读的约定 —— 那些的读者是 agent,不是门禁。
    推荐意见必须基于这四条轴给出理由;四轴冲突时如实呈现权衡,
    交维护者拍板。

  6. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    already claimed — yielding · seat domain:skills#2, session_01VqGhCg9wdsBXPz54uAEWg7 (os-elon-musk) · 2026-10-15T11:24Z

    Seat 1's Claim: 6190726655 (session_01GjUZrCo7Yi58T4vPXqx88e, os-sales) is the earlier one and stands; ⛔ not a claim.

    • What seat 2 wrote here: one label-write added os-elon-musk as a second assignee at 2026-10-15T11:21Z (the label set was already pm:dispatched without pm:queue, so no label changed). It was taken off again, and the read-back shows os-sales alone. Seat 2 posted no claim and pushed no branch on this card, and it sent no dispatch.
    • Why: this seat's lane read predated seat 1's claim. The pre-write re-read printed os-sales as the assignee, and the write was not gated on it. The error is seat 2's.
    • Readings handed over:

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23606,
      "status": "done",
      "branch": "claude/issue-23606-ratchet-ruled-raise",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23668",
      "session": "session_01GjUZrCo7Yi58T4vPXqx88e — this run's harness-stamped id (subagent = parent's; the relay's route reader derived the same id from the container's CLAUDE_CODE_REMOTE_SESSION_ID)",
      "premise_still_valid": true,
      "summary": "Premise checked at origin/main 1ced0f82b: line 66 of scripts/pm/check-skill-line-ratchet.mjs still read 「RAISING one requires a maintainer ruling quoted in the raising PR's body」 (the claim's control), so the card's work was live. Restated the per-file line ratchet's raise authorization to ruling record 6184799323 letter B: the header 「ratchet discipline」 bullet, verdict()'s red remedy and the three cross-file-move refusals (two in crossFileMoveVerdict, one in crossFileMoveTotalVerdict) now name the form — the ordering ruling of record's comment id and the measured line delta quoted in the raising PR's body, the CEILINGS row moved in the same PR by at most that delta; a raise quoting no ruling id stays red; no tolerance band; 「新增以删减付账」 for every unruled line; landed ceilings not revisited. The self-test re-pins the one old-wording case and adds seven cases (the form, the delta bound and the no-ruling-id/no-band sentence in verdict(); the form in each move refusal; a negative pin that none of the four line-ceiling refusals still says 「maintainer ruling quoted」) — 164 cases, roster floor 157 → 164, nothing weakened or deleted. The pm-dispatch SKILL.md 〈机械守卫索引〉 row rewords at equal line count (319/319; the row 240 → 336 bytes under the 342-byte table-row pin; no issue number in it). No CEILINGS row moved, no new mechanical check. origin/main moved mid-work (PR #23660 landed as 881eeff31: the execution-duties.md row 183 → 185 plus its comment block, which itself quotes ruling record 6184799323 as the raise's authorization); merged as 1bcccbaf9 — clean, disjoint; the branch's delta vs origin/main is exactly the two files. Draft PR #23668 is open on main with first line Fixes #23606 and Clause-②: no, assignee os-sales, labels skip-changeset (mine) + documentation and size/s (set by other actors, left as found); Tier S (.claude/**): pushed, opened, reported, stopped — not readied, no auto-merge.",
      "tests": "Edited script's own suite at 1bcccbaf9: `node scripts/pm/check-skill-line-ratchet.mjs --self-test` → exit 0, 「✓ check-skill-line-ratchet self-test: 164 cases pass.」 (the same command on the unmodified base 1ced0f82b → exit 0, 157 cases); plain `node scripts/pm/check-skill-line-ratchet.mjs` → exit 0, 「.claude/skills/pm-dispatch/SKILL.md is 319 lines (ceiling 319; headroom 0)」, 「widest table row is 342 bytes (pin 342; headroom 0)」 (the widest row is a different row; the reworded row is 336 bytes), 「references/execution-duties.md is 185 lines (ceiling 185; headroom 0)」 after the merge. Red-then-green without an ablation (scripts are not ablated, and there is no dist/ in this diff): with the four strings changed and the pins untouched, the self-test exited 1 with exactly one failure — 「✗ ...and sends the author to the ordinary path rather than to a bigger declaration」, the old pin — and with the pins updated it is green at 164. Assumption (d) measured: `git grep -n 'maintainer ruling quoted' -- scripts packages .claude` on the branch hits, inside the file, only the RULING_CITATION docblock, the table-row-bytes pin's docblock and refusal, and the two new negative self-test pins; outside the file only unrelated prose (scripts/pm/check-half-states.mjs:338, scripts/pm/dispatch-gates.data.mjs:1161, packages/metadata-core/CHANGELOG.md:614) — nothing outside the file pins the ratchet's remedy strings.",
      "gates": "Local subset derived at 1bcccbaf9 by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths; 39 commands, byte-identical to the derivation at e8ae56f27; the tool's first stderr line named objectstack-ai/objectstack at 1bcccbaf9 and the --repo check against origin held). All 39 ran at 1bcccbaf9, each exit captured before any pipe (`bash -c cmd > log 2>&1; EXIT=$?`). 38 quick families exit 0: check-ci-filter-parity; check-closing-keyword-parity (+ --self-test); check-comment-mask-corpus; check-declaration-mirrors (+ --self-test); check-scripts-symbol-anchors (+ --self-test); check-self-test-wired (+ --self-test); check-self-test-workflow-commands (+ --self-test); check-whole-set-label-write (+ --self-test); pm/bare-root-worklist --self-test; pm/check-governed-queue-guard --self-test; pm/check-harness-current --self-test; @objectstack/lint check:doc-formula-expressions; check:agent-test-spelling; bash32-floor; cli-command-ids; cross-package-test-inputs; doc-authoring; driver-memory-census; entry-guard; gitlink-declared; nul-bytes; parse-guard; pm-expected-skips; pm-governed-merges; pm-governed-prose; pm-skill-id-lint 「87 file(s) clean」; pm-skill-ratchet; pnpm-filter-targets; ratchet-remedy-authority 「275 scripts swept; 14 mark, 5 turn down, 256 hand out no ratchet-expanding remedy」 (this file stays `excluded`); refd-timer-probe; skill-frame-sync; watch-hint-literal. `pnpm check:pm-dispatch-gates` under nohup with its exit written to a file → EXIT=0, 「✓ dispatch-gates self-test (fast tier): 1884 cases pass; 6 slow section(s) deferred.」 (269.6 s on the shared box). check:doc-formula-expressions first exited 3 at e8ae56f27 — PREREQUISITE NOT MET (@objectstack/formula and @objectstack/lint unbuilt), not a measurement; `pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2` ran under os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-23606; VERDICT command-exit 0; 4 tasks, all cached) and the rerun exits 0. `--ran ran.list --repo objectstack-ai/objectstack` → exit 0, 「✓ dispatch-gates --ran: 39 derived famil(ies) accounted for — 39 run, 0 NOT-MEASURED (a DERIVED zero — all 39 recorded an exit code and none of them is 3)」, 0 UNRUN. Local-only families check:dev-prereqs / check:skill-frame-freshness: not derived and not owed (no packages/spec build, no four-axis file touched). CI — PR #23668 check-runs at 1bcccbaf9, read after the label write (40 runs): success — Governed Surface Queue Guard, Check Changeset, The card this PR closes must claim this branch, No other open PR may claim the same issue, No other open PR may claim the same single-writer path, Part-of PR must not also close its card, Check PR Size, Auto Label, Check Documentation Links, Dogfood Regression Gate, filter, Lint · scoped · query-options erasure, Type Check · workspace, Type Check · debt ledger, Test Core 3/6 4/6 5/6 6/6; in_progress — Lint · ESLint, Lint · PM dispatch-gates, Lint · repo & tooling gates, Lint · docs & code guards, Lint · CI release & engine gates, Lint · scoped · tooling self-tests, Lint · scoped · slot lookup & corpus, Type Check · source gates, Type Check · consumer gates, Test Core 1/6 2/6; skipped by path filter — Build Core, Build Docs, Console Pin Gate, Dogfood Verify CLI, Temporal Conformance (live PG + MySQL), Packed-tarball smoke, the matrix-template Dogfood shard. The required Lint & Repo Gates / TypeScript Type Check / Test Core contexts are still converging; in_progress is the honest value and was not waited on.",
      "mcp_calls": "0 — no MCP GitHub tool was called. The card was read from the public issue page's embedded payload (issueViewerRoute; backTimelineItems hasNextPage=false, 14 items, the newest Claim: names this branch); the PR, its labels and its check-runs were read with `gh api` GET calls (reads, not writes).",
      "api_writes": "4 — every write through scripts/pm/ over the fleet-write relay (transport dispatch, as objectstack-fleet[bot]): POST /repos/objectstack-ai/objectstack/pulls (pr_create, draft forced, relay run 38730197916; read-back 10413 bytes sent = 10413 stored) and POST /repos/objectstack-ai/objectstack/issues/23668/assignees (the same pr_create action's assignee leg; os-sales); POST /repos/objectstack-ai/objectstack/issues/23668/labels (label-write --add skip-changeset, relay run 38730334059; read-back matches: documentation, size/s, skip-changeset); POST /repos/objectstack-ai/objectstack/issues/23606/comments (post-stamped --comment=23606, this os-dev-report). git push ×3 (the empty-branch probe, e8ae56f27, 1bcccbaf9) are not REST writes. No PATCH, PUT or DELETE; no bare curl/gh write.",
      "deviations": "(1) The harness's built-in removal check refused two commands: a gate-runner line that carried `rm -f` of a not-yet-existing ran-list (reissued without the removal to fresh filenames; results unaffected) and the deletion of a stray 19-byte file my mis-backgrounded nohup line wrote at the filesystem root, /battery2.pid (content BATTERY2_PID=22880) — not removed; it needs a person's hand. (2) The first pm-dispatch-gates battery run's exit code was not captured (plain nohup, verdict line only); it was rerun twice with the exit written to a file (EXIT=0 at e8ae56f27 and at 1bcccbaf9) and only those are cited. (3) The harness attribution reminder names a model in its Co-Authored-By form; both commits carry AGENTS.md's model-free pair instead (the pre-push hook accepted them); no model identifier in the PR, commits or comments. (4) The header's restatement of ruling item 3 reads 「the quote is checked by the seat's contract-review record and by the queue guard's reader, never here」: check-governed-queue-guard.mjs has no ratchet reader, so the sentence attributes the check to its readers rather than to a mechanism. (5) The SKILL.md row's reworded clause is the PM's suggested shape in substance, measured rather than copied: 「抬上限凭下令写入的裁决记录:其评论 id 与实测行数增量引在 PR 正文,同 PR 移上限行至多增量;无裁决 id 即红」.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: the seat's contract review of PR #23668 (a one-line touch if wanted) · noted, not filed — in the same file, two docblocks still spell the ordinary raise in the older, less specific words: the RULING_CITATION docblock (「the header's escape hatch (a maintainer ruling quoted in the raising PR)」) and the header section 「A move's raise and an ORDINARY ruled raise are separate quantities」 (「the header's own exit, a ruling quoted in the raising PR」). Both defer to the restated header bullet and are not false under the ruled form (the ordering ruling IS a maintainer ruling quoted in the raising PR); outside the claimed surface (header bullet, red remedy, refusals, self-test), so untouched. Dedupe words: RULING_CITATION docblock, ordinary ruled raise, header's escape hatch, check-skill-line-ratchet.",
        "carrier: none · noted, not filed — MAX_TABLE_ROW_BYTES (the per-file widest-table-row byte pin) keeps 「raising a pin requires a maintainer ruling quoted in the PR」 in its docblock and its refusal. It is a byte pin, not a line ceiling; ruling 6184799323 speaks of measured lines and the CEILINGS row, so whether the ruled form extends to the byte pin is a question for the seat, not a finding. Dedupe words: MAX_TABLE_ROW_BYTES, table-row pin, byte pin ruling, widest table row.",
        "carrier: none · noted, not filed — scripts/check-ratchet-remedy-authority.mjs's CONTROL entry for pm/check-skill-line-ratchet.mjs (expect excluded; 「its ceiling-raise remedy already names the authority it requires」) still reads true after the rewording: the authority is now the ordering ruling of record and none of the four messages uses an offer verb of that gate's grammar — measured, gate exit 0, verdict unchanged. Recorded so the seat need not re-measure it. Dedupe words: ratchet-remedy-authority, CONTROL excluded, offer verb."
      ]
    }

    Generated by Claude Code

  8. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23668 comment 6191600702 (seat record, domain:skills#1, session_01GjUZrCo7Yi58T4vPXqx88e); the at-tier contract review of record is PR #23668 comment 6191503551 (PASS on head 1bcccbaf9). Tier S landing by the seat follows: pr_ready, automerge_enable, the queue. 2026-10-15T12:04Z

  9. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — PR #23668 MERGED as 5a3315490 (squash; the queue's merge, auto_merge_enabled by the seat at 2026-10-15T12:06Z, added_to_merge_queue at 2026-10-15T12:08Z, merged at 2026-10-15T12:24Z) · seat domain:skills#1 · session_01GjUZrCo7Yi58T4vPXqx88e (os-sales) · 2026-10-15T12:27Z

    Reading Answer
    git ls-remote origin refs/heads/gh-readonly-queue/main/pr-23668-* 0 refs (the queue branch is gone)
    git merge-base --is-ancestor 881eeff31 origin/main (control, a known main commit) exit 0
    git merge-base --is-ancestor 1bcccbaf9 origin/main (the PR head) exit 1 — a squash merge; the head is not an ancestor by construction
    git log -1 origin/main -- .claude/skills/pm-dispatch/SKILL.md 5a3315490 feat(pm): line ratchet — a raise is authorized by the ordering ruling of record (id + measured delta in the PR body) (#23668)
    git show origin/main:.claude/skills/pm-dispatch/SKILL.md line count 319 (ceiling 319, unchanged)
    This card closed completed by Fixes at the merge
    Lane inventory after the merge (domain:skills, open) #23665 (pm:blocked) · #23607, #23615, #23662 (pm:dispatched, seat 2, os-elon-musk) · #22060, #17161 (tracking) · #19287 (seat 2) — no stray closure
    check-expected-skips.mjs --pr 23668 OK — 11 skipped check-runs, every one in the roster, exit 0
    Shared checkout fast-forwarded to 5a3315490; check-harness-current.mjs CURRENT; mirror branch pushed

    State change: pm:dispatched removed in this act (domain:skills, area:devpath, priority:p2 stay); the PR subscription ended at the merge. From this merge the line ratchet's header and refusal text name the ruled raise form: the ordering ruling of record's comment id and the measured line delta quoted in the raising PR's body, the CEILINGS row moved in the same PR by at most that delta; a raise quoting no ruling id stays red.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:skillspriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions