Skip to content

docs(os-dev): label step scope and precedence; maintainer digest owed on the rules layer only - #18898

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-18699-os-dev-label-scope
Sep 18, 2026
Merged

os-zhuang merged 4 commits into
mainfrom
claude/issue-18699-os-dev-label-scope

Conversation

@os-elon-musk

Copy link
Copy Markdown
Collaborator

Fixes #18699
Fixes #18812
Fixes #18821
Clause-②: no

Family fold of three graded cards on ONE file, .claude/agents/os-dev.md (governed, rules layer, CONTRACT_REVIEW_TIER): the label-timing clause that had no scope (chain head), the unconditional 速读 clause against the tiered landing, and the label step against a dispatch order that forbids it. One commit per card, in that order. #18698 remains open and #18882 remains open — neither is addressed here.

What changed (three commits; anchored on content — the cards' line numbers were readings at older shas)

Commit 1 — the label band gets its scope, its exception and the empty-intersection action.

  • The timing line 「本仓库:标签是真实机制 … PR 一开出就打」 gains a scope line directly under it: 「范围 = 派发词点名的标签,needs:contract-review 除外;交集为空 ⇒ 零写,报告写明。」
  • The carve-out line 「needs:contract-review 归席位,⛔ 不挂不摘不等;报 PR 上有无与 --pair PR-NUMBER 退出码作读数。」 moves down UNCHANGED from the PR-body band into the label band, so scope, exception and the empty-intersection action are three consecutive lines — no new special-case sentence, which the triage names as the source of the contradiction.
  • Paid in-file: the size-labeler line is retired by folding — its cause 「size-labeler 整组 PUT」 into the read-back-is-necessary-not-sufficient line, its wrap-up read-back 「收尾再读一次」 and 「清单进报告」 into the read-back line, and its 「标签没了就重挂」 was already that line's 「重挂」. Bytes on the two folded lines came from 「并发」 and 「语义」 (the ratchet's 120-byte line budget; both were adjectives whose meaning the neighbouring lines still carry).

Commit 2 — the label step is a default the dispatch may narrow or forbid.

  • 「打标签是你的步骤、不是 CI 的」 becomes 「打标签是你的默认步骤」 and the line ends 「;派发词可收窄或禁写。」; the scope line's action becomes 「禁写或交集为空 ⇒ 零写,报告写明」.
  • Category, said once: the step is a DEFAULT, not an unconditional clause. The standing precedence line 「派发词与本文件冲突时以本文件为准:无条件条款住这里,错了也在这里改。」 is untouched and does not contradict this: it governs the unconditional clauses, and the label line now says of itself that it is not one — a dispatch that forbids the write is not in conflict with this file, it is exercising what this file grants.
  • The write-budget line 「写预算四笔 …」 is untouched: 「预算」 plus 「预算外零写」 already read as a ceiling, and the scope line now names the dispatch as the source of the label list, so the budget cannot be read as an entitlement to a label the dispatch did not name.
  • 「、不是 CI 的」 is dropped for bytes: 「你的默认步骤」 and 「PR 一开出就打」 already say nobody else applies it for you.

Commit 3 — the 速读 draft is owed on the rules layer only.

  • 「受管面(见 AGENTS.md)PR 正文带 ## 维护者速读(草稿) 节 …」 becomes two lines: the tiering 「受管路径全在 .claude/skills/pm-dispatch/references/ 者为事实层,席位复审即记录;余为规则层。」 then the per-layer rule 「规则层 PR 正文带 ## 维护者速读(草稿) 节,中文、业务角度,席位意见留空;事实层不欠。」 The predicate is the one AGENTS.md Prime Directive 14 and pm-dispatch SKILL.md 「受管面两层」 already use. 「(见 AGENTS.md)」 is dropped for bytes — the file's own preamble makes AGENTS.md binding.
  • 「PR 正文 dev 只写一次 … ⛔ 不 PATCH」 is untouched; the conflict closes by the definition tracking the landing, not by allowing a body patch.
  • Paid in-file: the first bullet of the wrap-up section, 「终报消息之前,把同一段 JSON 发成 issue 评论,首行单独一行、就是字面纯文本 os-dev-report。」, duplicated the preamble's sentence; its two extra bits fold into the preamble line, now 「报告交付两次,GitHub 优先:同一段 JSON 先作 issue 评论,首行单独一行是纯文本 os-dev-report。」 (「字面」 dropped for bytes; the next preamble sentence already refuses the HTML-comment spelling). This continues the dedup the previous os-dev.md PR started in the same spot.

Reader tests — a dev reading ONLY os-dev.md

  1. 「the only label I could hang is needs:contract-review — what do I do?」 → the scope line: it is 除外, so the intersection is empty ⇒ 零写,报告写明; the next line: report presence on the PR and the --pair exit code. Write nothing, say so.
  2. 「my PR's governed paths are all under .claude/skills/pm-dispatch/references/ — do I write the 速读 section?」 → the tiering line says that is the fact layer and the seat's review is the record; the rule line says 事实层不欠. No.
  3. 「my dispatch order forbids the label write — do I still do it?」 → the timing line: 派发词可收窄或禁写; the scope line: 禁写 ⇒ 零写,报告写明. No; the dispatch wins; the report names what is now the seat's to hang.

No answer needs a second text.

Line budget (check:pm-skill-ratchet, run at ee4c3c6f9)

.claude/agents/os-dev.md is 403 lines (ceiling 403; headroom 0) before and after; every line within the 120-byte budget. Added: the scope line, the tiering line (+2). Retired: the size-labeler line (folded, commit 1) and the wrap-up section's duplicate report-comment line (folded into the preamble, commit 3) (−2). Moved unchanged: the needs:contract-review carve-out line. Net 0 at each of the three commits, so the ratchet is green at every commit.

Verification

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at ee4c3c6f9 derived 19 commands (change set: 1 path vs merge base 600b1e2ab); all 19 run with redirect-then-capture, exit 0 each; --ran reconciliation: 「19 derived, 19 run, 0 NOT-MEASURED, 0 UNRUN」. Named families: check:pm-skill-ratchet (403/403 as above), check:pm-skill-id-lint (27 files clean), check:agent-model-declared (os-dev.md → opus), check:nul-bytes, check:skill-frame-sync, check:agent-test-spelling, check:doc-authoring, check:commit-card-trailers, check:pm-governed-merges, check:cross-package-test-inputs, check:watch-hint-literal, check:refd-timer-probe, check:driver-memory-census, the comment-mask corpus sweep, closing-keyword parity plus its self-test, the governed-queue-guard self-test, the harness-current self-test, and @objectstack/lint check:doc-formula-expressions (first run exit 3 = PREREQUISITE NOT MET on unbuilt formula/lint packages, so not a measurement; both rebuilt under the verify lock, rerun exit 0). Also run, outside the derived set because the derivation marks its roster as sitting under .claude: check:pm-settings-deny-roster, exit 0. The 14 pending-changeset families do not apply: this PR carries no changeset (skip-changeset — nothing under any package's files[] moves; the file is under .claude/**, the fast lane).

The pre-push trailer check passed on the push: three commits, no card relation, no model identifier in the trailer pair.

Acceptance notes

  • noted, not filed: the 「或 tail --pid 等它退出」 line in the wrap-up section names no pid source — a rider the previous seat left for the next os-dev.md PR; untouched here (this fold edits the section's first bullet, not that band). 承接者:the next entry on the os-dev.md serial.
  • noted, not filed: os-dev.md keeps ASCII sentence punctuation after Han characters throughout (the ratchet's own comment measures it); the new lines follow it. No gate pins the convention. 承接者:无.
  • The harness-injected attribution reminder for this session names a model in the co-author line and prescribes a different PR footer; AGENTS.md (which that reminder itself defers to) declares the trailer pair model-free and fixes the footer form, and check:commit-card-trailers refuses the model-named form at push — the commits and this body follow AGENTS.md. This is the shape of the card still in the decision box (#18698 remains open); not re-litigated here.

维护者速读(草稿)

改了什么:os-dev.md(开发 agent 的标准合同)三处子句改写,行数不变(403/403)。① 挂标签那条补齐范围、例外与交集为空时的动作;② 写明挂标签是默认步骤,派发词可收窄或禁;③ 「维护者速读」只在规则层受管面欠,事实层(references/ 目录)不欠,以席位复审为记录。

为什么改:三张卡量到同一个病:合同里的子句与回路实际跑的分层脱节,每次都靠现场的 dev 自行裁断。已量到的代价:一次升级轮加一次板上半写状态;两次事实层 PR 靠派发词手工豁免;一次云端卡上 dev 从零裁断先后关系。三位 dev 都做对了(声明冲突而不是静默选边),但「dev 推理出了正确答案」不是规则。

风险与代价(含回滚):纯文本改动,不发布、不动门禁、不动 frontmatter。风险在措辞:读者只读 os-dev.md 能否答出三个问题——正文 Reader tests 逐一作答。回滚 = revert 三个 commit 中任一或全部,每个 commit 各自净 0 行,互不依赖。

席位意见:(留空)

你要做的:审阅三条改写后的子句是否与你对分层落地的理解一致,一致即批准(需 GOVERNED_APPROVERS 账户的 APPROVED)。


Generated by Claude Code

…pty-intersection action

The label-timing clause stated an obligation with no scope, and the
`needs:contract-review` carve-out sat twelve lines above it in the PR-body
band; on a card where that carve-out was the only label owed, the literal
reading hung the clause-② gate on the dev's own PR. The label band now reads
as one block: scope = the labels the dispatch names, the seat's label excepted;
an empty intersection means write nothing and say so in the report. The
carve-out line moves down unchanged to sit inside the band it governs.

Paid in-file (403/403): the size-labeler line is folded — its cause into the
read-back-is-not-sufficient line, its wrap-up read-back and list-in-report into
the read-back line, and its re-hang instruction was already stated there.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF
…forbid

The write budget and the label-timing clause read as an entitlement, while a
dispatch order from a repo whose label mechanism is the seat's forbids the dev
the write; each dev on such a card re-adjudicated the precedence from scratch.
The timing line now names the step a default and says the dispatch may narrow
or forbid it; the scope line says a forbidden write, like an empty
intersection, means write nothing and say so in the report. The standing
「派发词与本文件冲突时以本文件为准:无条件条款住这里」 clause is untouched: it
governs the unconditional clauses, and this step now says once that it is not
one. Bytes for the tail come from dropping 「、不是 CI 的」, which 「你的默认步骤」
plus 「PR 一开出就打」 already state.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF
The 速读 clause was unconditional over the governed surface while the landing
is tiered: a PR whose governed paths all lie under the pm-dispatch references
directory lands through the queue on the seat's contract review, so no
maintainer reads its body and the five paragraphs had no reader; the body may
not be patched after creation, and every fact-layer dispatch waived the clause
by hand. The definition now tracks the standing tiering: the fact layer is
named by its path predicate with the seat's review as its record, and the
draft section is owed on the rules layer only.

Paid in-file (403/403): the report-comment sentence at the top of the
wrap-up section duplicated the preamble's; its two extra bits (the same JSON,
the marker alone on its first line) fold into the preamble line, and the byte
budget takes 「字面」 there — the next sentence already refuses the HTML-comment
spelling.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF
…he file's own skip-changeset criterion

The scope line landed in this branch made the dispatch the only source of
the label list, while the block six lines above still makes `skip-changeset`
a label the dev decides by the file's own criterion; a dev whose dispatch
does not name it held two readings of one file — the shape this branch
treats. The scope now names both: the labels the dispatch names plus the
`skip-changeset` the criterion above yields. The `needs:contract-review`
carve-out leaves the scope line and is stated once, on the line directly
below it (「归席位,⛔ 不挂不摘不等」), which is where it already lived; the
forbidden/empty action is unchanged. 403/403, the line measures 118 bytes.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF

Copy link
Copy Markdown
Collaborator Author

CI reading on PR #18898 @ ee4c3c6f94 (skills seat, session_01BTeBejoPUvRHN8WdAJC6oF, 2026-09-18T05:09Z): TypeScript Type Check reported failure after 4 seconds (05:07:46Z → 05:07:50Z, run 35308831944, job 105488666100). Step conclusions read from the job record: first failing step = Verify every type-check lane succeeded; steps: Set up job=success; Verify every type-check lane succeeded=failure; Complete job=success. The diff is one prose file (.claude/agents/os-dev.md, +8 / −8), the same check is success on the base tip 84ba4a847 (04:51Z) and on the merge-base 600b1e2ab (04:31Z), and the sibling PR #18903's type-check legs on bc0c2ec41e are success — the failure names nothing this diff touches and died before any type-check body ran. No manual re-run is spent: a patch commit for the seat's round-2 review is being pushed on this branch and carries a full set of runs on the new head; if the same step fails there in the same shape, that second failure is real and gets its own reading. The job log itself is not readable through this seat's proxy (CONNECT 403 to the log blob host) — the step record above is the reading.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Correction to the CI reading above — the aggregator failed because a LANE did not succeed

2026-09-18T05:10Z · the failing step of TypeScript Type Check is 「Verify every type-check lane succeeded」, the aggregator over the four Type Check · lanes, so 「died before any type-check body ran」 in my comment above is WRONG: a lane ran and did not succeed. Lane readings from the check-run and job records (this act):

  • Type Check · workspace on ee4c3c6f94: cancelled (2026-09-18T04:55:50Z -> 2026-09-18T05:07:43Z); first non-success step: Type check workspace packages (cancelled); steps: Set up job=success; Checkout repository=success; Setup Node.js=success; Setup pnpm=success; Get pnpm store directory=success; Setup pnpm cache=success; Restore Turbo cache=success; Install dependencies=success; Build workspace packages=success; CLI transcripts in content/docs match the registry they quote=success; Type check workspace packages=cancelled; Save Turbo cache (main only)=skipped; Post Setup pnpm cache=skipped; Post Setup Node.js=skipped; Post Checkout repository=success; Complete job=success; the same lane on the base tip 84ba4a847: [(None, None), ('success', '2026-09-18T04:51:11Z')].

Disposition unchanged: the patch commit for the seat's round-2 review is being pushed on this branch and carries a full set of runs; the seat reads the lane on the new head before any landing act, and a repeat of the same step in the same shape on a prose-only diff is judged against the base's own run of that lane, never re-run blind.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: ea7d40f8e8c926e2c93d1351a81d7b0fe944def9

① Derived judgments

② Semver level

  • skip-changeset is correct: .claude/** publishes nothing (the file's own fast lane). Clause-②: no declared on the claim and in the body; PM_SWEEP_REPO=objectstack-ai/objectstack node scripts/pm/check-clause2-carriers.mjs --pair 18898 at 2026-09-18T05:14Z: exit 0, one live claim per thread, no widening tell.

③ Boundary flags

Implemented-by: claude/issue-18699-os-dev-label-scope
Reviewed-by: session_01BTeBejoPUvRHN8WdAJC6oF

VERDICT: PASS


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

维护者速读(终稿)— PR #18898 · 席位定稿 2026-09-18T05:16Z(草稿在正文,以本评论为准)

改了什么:os-dev.md(开发 agent 的标准合同)三处子句改写,四个 commit,行数不变(403/403),每行不超 120 字节。① 挂标签这一步补齐范围、例外与交集为空时的动作,定稿三行:「打标签是你的默认步骤,PR 一开出就打;派发词可收窄或禁写」/「范围 = 派发词点名的标签 + 上文判据下的 skip-changeset;禁写或交集为空 ⇒ 零写并报告」/「needs:contract-review 归席位,⛔ 不挂不摘不等」;② 「维护者速读」只在规则层受管面欠,事实层(references/ 目录)不欠、以席位复审为记录。正文里 commit 1 那段引的是第一轮的旧句,以上面的定稿为准。

为什么改:三张卡量到同一个病——合同子句与回路实际跑的分层脱节,每次都靠现场 dev 自行裁断。已量到的代价:一次升级轮加一次板上半写状态(#18699)、两次事实层 PR 靠派发词手工豁免(#18812)、一次云端卡上 dev 从零裁断先后关系(#18821)。第一轮的范围句只认派发词,与四行之上的 skip-changeset 「唯一判据」又成了两种读法,第二轮改成两个来源都认。

风险与代价(含回滚):纯文本,不发布、不动门禁、不动 frontmatter;19 条派生门禁全绿。风险只在措辞:只读 os-dev.md 的 dev 能否答出三个问题(唯一可挂的标签是 needs:contract-review 怎么办 / 事实层 PR 要不要写速读 / 派发令禁写还挂不挂),席位按定稿逐一验过。回滚 = revert 任一或全部 commit,各自净 0 行。

席位意见:建议批准。三处都是把已经在跑的分层与先后关系写进合同,不新增机制;唯一取舍是为字节预算去掉了「(见 AGENTS.md)」指针,序言已说明 AGENTS.md 有约束力。

你要做的:审阅定稿三行 + 速读两行是否与你对分层落地的理解一致;一致即 APPROVE(GOVERNED_APPROVERS 账户),之后由本席按裁决 C 落地。


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Landing record — ruling C, on an authorized APPROVED (skills seat, session_01BTeBejoPUvRHN8WdAJC6oF) · 2026-09-18T11:23Z

os-zhuang (GOVERNED_APPROVERS) approved this PR (review 5247206503 at 2026-09-18T11:22Z), marked it ready at 2026-09-18T11:21Z and added it to the merge queue in the same minute — the two CCR calls this seat's channel could not make, made by the approver's own hand. The seat's pre-landing reads on head ea7d40f8e8: the review of record 5725524949 names this head; PM_SWEEP_REPO=objectstack-ai/objectstack node scripts/pm/check-clause2-carriers.mjs --pair 18898 exit 0 on all three cards (#18699, #18812, #18821 — each Fixes); checks at 2026-09-18T11:22Z: 17 success · 13 skipped · 1 in progress (the queue's run), none red. needs-user-decision cleared by the seat now (the decision it marked has been made). The merge is the queue's; the three cards close on it, and the seat clears their pm:dispatched / assignee residue after the merge lands and lifts the os-dev.md serial (#18908 · #18882 · #19002).


Generated by Claude Code

This was referenced Sep 18, 2026
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…this file (objectstack-ai#19167)

Fixes objectstack-ai#18698

Clause-②: no

One clause in `.claude/agents/os-dev.md`, a governed Tier S surface
(`.claude/**`): landing is the skills seat's contract-tier review of
record through the queue. This PR stops at draft.

## What changed

`.claude/agents/os-dev.md`, Definition-of-done list, right after the
trailer line — today `:284`, kept byte-identical because
`scripts/check-commit-card-trailers.mjs` cites that sentence verbatim
and its self-test holds the citation to the file. New `:285` (120 B):

> - harness 归属提醒凭其优先级句让位本文件;harness 自写含模型名 trailer 只报,⛔ 不仿不改史。

It restates the governing text, `AGENTS.md` :440–:444 (quoted with the
two angle-bracket placeholders spelled out in words, because GitHub
mutates body bytes):

> **Commit message:** an agent commit ends with the model-free trailer
pair `Claude-Session: https://claude.ai/code/session_ID` and
`Co-authored-by: Claude (noreply at anthropic.com)`, and the pre-push
hook refuses a model identifier in that pair; no model identifier lands
in a PR title or body, a comment, a changeset, a doc or a code comment.
Two exemptions: a harness-written `Co-Authored-By` trailer (REPORTING:
not declared a deviation; landed history is not rewritten) and a
verbatim maintainer ruling preserved as a quotation block.

The precedence sentence the clause relies on is in the harness
attribution reminder itself — read in this session, verbatim: 「the
user's own instructions about these lines, such as a CLAUDE.md or memory
rule, take precedence over this reminder」. `CLAUDE.md → AGENTS.md` is
that instruction, so the reminder defers; the clause restates AGENTS.md,
never the reminder.

## Ruling — director record on the card (batch objectstack-ai#154 item 5, maintainer
「同意」 2026-09-18T04:56Z), operative part verbatim

> - `.claude/agents/os-dev.md:283` gains the one clause that would have
saved the escalation: **the harness attribution reminder yields to this
file by its own precedence sentence; a trailer the harness itself writes
with a model name is `AGENTS.md`'s exemption — report it, ⛔ do not
imitate it, ⛔ do not rewrite history.** Line-neutral; on the os-dev.md
serial queue behind objectstack-ai#18599, in one round with objectstack-ai#18699 as triage
suggested.
> - ⛔ **B** — contradicts `AGENTS.md:442` and the hook, and lets a
reminder that changes without a PR drive landed history in four
repositories.
> - `Clause-②: no`; `skip-changeset`; governed surfaces ⇒ human merge by
the approver.

Readings, not identifiers: the ruling's `:283` reads `:284` on today's
`main` (the file moved when PR objectstack-ai#19038 landed at 2026-09-18T23:52Z); the
serial 「behind objectstack-ai#18599, with objectstack-ai#18699」 is discharged — both landed before
this PR (PR objectstack-ai#18725 and PR objectstack-ai#18898). The landing route is the later Tier S
ruling (the seat's contract-tier review of record through the queue),
superseding the last bullet's human merge.

## Line budget — ratchet row `['.claude/agents/os-dev.md', 403]`

| reading | before (`5d0ee8f`) | after (`9612c8d`) |
|---|---:|---:|
| lines | 403 | 403 |
| widest line | 120 B | 120 B |
| new clause | — | 120 B at `:285` |
| diff | — | +1 / −1, one file |

**Payment (line-neutral):** the removed bullet is the former `:285`
「标题与散文用英文(见 AGENTS.md);引用的中文裁决保持原文不译,改写引文就是改写裁决。」 — a true duplicate
that cited its own source. Its content survives verbatim in `AGENTS.md`
§ Communication: `:25` 「**GitHub 产物一律使用英文**:issue 与 PR 的标题、正文、评论。」 and
`:26–:27` 「**引用中文裁决时保持原文、不翻译**,即使承载它的 issue/PR 正文通篇是英文——改写引文就是改写裁决。」;
os-dev.md `:19` already binds AGENTS.md before the first edit. No
re-wrap bought the line and no ceiling moved. Measured before choosing:
zero gate scripts pin any phrase of the removed line (grep over
`scripts/`, `.github/`, `.claude/skills/`, `package.json`); the only
pinned sentence in this list is `:284`, which is untouched
(`check-commit-card-trailers` self-test: 「✓ every sentence inside the
corner brackets is verbatim in the cited rules file」).

The clause names no model and no card. Frontmatter untouched (`model:
opus` line unchanged). The wording was measured down from the seat's 157
B suggestion; the three-verb prohibition without objects follows the
file's own register (`:303` 「⛔ 不挂不摘不等」).

## Verification — all at `9612c8d`, every exit code captured before any
pipe

Gate list derived in the worktree with `node
scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands` (change set: `.claude/agents/os-dev.md` only, 2 changed
lines; 19 commands — identical to the dispatch's 19) and reconciled with
`--ran`: 「✓ dispatch-gates --ran: 19 derived famil(ies) accounted for —
19 run, 0 NOT-MEASURED」.

| command | exit | the gate's own verdict line |
|---|---:|---|
| `node scripts/check-closing-keyword-parity.mjs` | 0 |
check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and
both measured separators; sweep found 5 file(s) carrying the grammar
across 8991 tracked file(s), all registered). |
| `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 | ✓ 40
assertions, 5 mutations of the shipped parsers each driven to red. |
| `node scripts/check-comment-mask-corpus.mjs` | 0 | ✓ comment-mask
corpus sweep: 6894 files, 0 disagree, 0 unparseable. |
| `node scripts/pm/check-governed-queue-guard.mjs --self-test` | 0 | ✓
check-governed-queue-guard self-test: 261 cases pass. |
| `node scripts/pm/check-harness-current.mjs --self-test` | 0 |
check-harness-current --self-test: all 26 cases passed. |
| `pnpm --filter @objectstack/lint run check:doc-formula-expressions` |
0 | ✓ 14 predicate(s) on a statically determinable field layer judged
clean; 6 skipped as undeterminable. (First run refused with exit 3
PREREQUISITE NOT MET — `@objectstack/formula` and `@objectstack/lint`
unbuilt in a fresh worktree; built both under the verify lock, `VERDICT
command-exit 0`, then this reading.) |
| `pnpm check:agent-model-declared` | 0 | ✓ 1 agent definition(s) under
.claude/agents/ all declare a model — os-dev.md → opus. |
| `pnpm check:agent-test-spelling` | 0 | ✓ 0 violations — 516 file(s) ·
9159 bare `--` token(s) · 13 separator(s) JUDGED. |
| `pnpm check:commit-card-trailers` | 0 | ✓ check-commit-card-trailers
self-test: 81 cases pass (incl. 「every sentence inside the corner
brackets is verbatim in the cited rules file」). |
| `pnpm check:cross-package-test-inputs` | 0 | OK: 29 package(s) read
outside themselves, all declared. |
| `pnpm check:doc-authoring` | 0 | ✓ doc authoring guard: 402 files
clean — no bare metadata literals (+ the three sibling verdict lines,
all ✓). |
| `pnpm check:driver-memory-census` | 0 | check-driver-memory-census: OK
— every declaration is ledgered, every ledger entry is live. |
| `pnpm check:nul-bytes` | 0 | check-nul-bytes: OK (scanned 8984 text
file(s); no raw ASCII control bytes). |
| `pnpm check:pm-governed-merges` | 0 | ✓ check-governed-merges
--self-test: 392 assertions. |
| `pnpm check:pm-skill-id-lint` | 0 | ✓ check-skill-id-lint: 27 file(s)
clean (pattern /#[0-9]{3,}/g). |
| `pnpm check:pm-skill-ratchet` | 0 | ✓ .claude/agents/os-dev.md is 403
lines (ceiling 403; headroom 0). ✓ widest table row is 0 bytes (pin 0).
|
| `pnpm check:refd-timer-probe` | 0 | OK: 6889 source file(s) swept; the
probe is read in the approved module and nowhere else. |
| `pnpm check:skill-frame-sync` | 0 | ✓ the one declared copy of the
decision frame is internally coherent; 74 markdown files scanned for
undeclared copies. |
| `pnpm check:watch-hint-literal` | 0 | ✓ 71 declaration(s) across 4
rostered name(s), every one an array of quoted literals. |
| `pnpm check:pm-settings-deny-roster` (extra — the derivation flagged
its roster as living under `.claude`) | 0 | ✓ 17 content-write tool(s)
declared = enforced in .claude/settings.json. |

Manual readings on the file: `wc -l` 403; `awk` widest 120 B; `grep
-naP` for raw control bytes: no output (exit 1); `grep -c` of the
removed line's text: 0. Pre-push hook on the push: 「✓
check:commit-card-trailers: 1 commit message(s) on this push carry no
card relation and no model identifier in the trailer pair.」

Package tests / typecheck: none owed — the diff touches no package (no ①
closure, no ② suite); the two-package build above was a gate
prerequisite only. Repo-wide `pnpm lint` is CI's run.

## Acceptance notes

- **Live instance of the clause, reported, not a deviation.** This
session's harness attribution reminder asked for a model-bearing
co-author trailer and a different PR footer block. Per the reminder's
own precedence sentence and `AGENTS.md` :440, the commit carries the
model-free pair and this body carries the session-URL footer; nothing
was rewritten.
- noted, not filed: `check:doc-formula-expressions` exits 3
(PREREQUISITE NOT MET) in any fresh worktree until
`@objectstack/formula` and `@objectstack/lint` are built — the gate says
so itself and names the fix; by design, not a defect. 承接者:无.
- Context on the card that this PR does not act on (the devx seat's
evidence): CI runs `check-commit-card-trailers` as `--self-test` only,
so the pre-push hook is the only leg that refuses a model-bearing
trailer; a session without `.githooks/` installed pushes one unrefused.
Listed in the report's `out_of_scope_findings` as a class-(b) candidate
with dedupe words for the triage seat; no card is opened here.
- Out of scope, untouched: `AGENTS.md`, every `SKILL.md`, the hook, CI.
objectstack-ai#18599 and objectstack-ai#18699 remain landed history; objectui#9441 is the ui lane's
twin of the ruling.

## 维护者速读(草稿)

- **改了什么**:`.claude/agents/os-dev.md` 的 Definition of done 列表,在 trailer
那一行之后新增一条(120 B):harness 的归属提醒按它自己的优先级句让位于本文件;harness 自己写入的含模型名 trailer
是 AGENTS.md 的例外——只报告,不仿写、不改历史。为守住 403 行上限,删掉了一条原文照抄
AGENTS.md「沟通」节的重复条目(GitHub 产物用英文;引用中文裁决不翻译),该内容在 AGENTS.md :25–:27 原样保留。
- **为什么改**:每一次派发,dev 都同时收到两份指令——仓库契约(model-free trailer)与 harness
注入的归属提醒(含模型名)。已有 dev 因此写不出 commit、只能升级上报。答案其实早就写在 AGENTS.md
里,也写在提醒自己的优先级句里;这一条把答案放到 dev 真正读的那一行旁边,省掉下一次升级。
- **风险与代价(含回滚)**:零机制变化——不动 hook、不动 CI、不动 frontmatter;行数 403/403、最宽 120 B
不变,19 个派生门禁全绿。风险只在措辞:若你觉得「只报,⛔ 不仿不改史」过于压缩,可在同一行内换词(须 ≤ 120 B)。回滚 =
revert 这一个 commit(1 行换 1 行)。
- **席位意见**:
- **你要做的**:无需你点击合并——本 PR 在 `.claude/**`(Tier S),由 skills
席位按合约档复核记录经队列落地。若对措辞有意见,在本 PR 留一句即可。

---
_Generated by [Claude
Code](https://claude.ai/code/session_01W5y9kRg1YtYaMQYExVLRc2)_

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