Skip to content

docs(agents): os-dev.md — the Clause-② copy line is conditional on the claim carrying one - #19305

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-19096-clause2-copy-line-repo-conditional
Sep 20, 2026
Merged

os-steve merged 1 commit into
mainfrom
claude/issue-19096-clause2-copy-line-repo-conditional

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes #19096

Clause-②: no

What changed

One line of .claude/agents/os-dev.md (:279), rewritten in place. Net 0 lines (403 / 403, headroom 0); the new line is exactly 120 bytes, the file's MAX_LINE_BYTES cap. No other line of the file moved.

Before (4efb988, verbatim):

  • 正文行首照抄认领的 Clause-②: 行:Check Changeset 读正文不读卡,开 PR 那一笔就带上。

After (fba3bb3, verbatim):

  • 认领带 Clause-②: 行才照抄进正文行首:Check Changeset 读正文不读卡;无则零写,⛔ 不自造。

Why

The old line told every dispatched dev, unconditionally, to copy the claim's Clause-②: line into the PR body. Both halves are conditional and the file said so nowhere: a claim may carry no such line (the clause-② flow is the objectstack dual-carrier mechanism), and the reader the rationale names does not exist in objectui. A dev following the unconditional wording either spends a step on a non-existent obligation or, worse, invents the line, and Check Changeset reads the body, so an invented declaration would be believed.

The shape is the one the card's triage grading points at (an unconditional clause takes its condition, as :68's landing-repo precedent does) with the PM's pick between the three named shapes: condition on the claim, not the repository, and name the reader once, so the line stays true in both repositories without naming either. Evidence that the claim, not the repo, is the right condition: scripts/pm/check-clause2-carriers.mjs's own fixtures (:9306–9320 at 4efb988) hold objectui claims that carry a Clause-②: line (the objectui 7804 rows, the later objectui 7696 row) and one that carries none (the first objectui 7696 row). A repo-conditional line would be false in both directions on that board; a claim-conditional line is true on every row.

The dropped clause 「开 PR 那一笔就带上」 restates :56 (「PR 正文 dev 只写一次,在开 PR 那一笔,⛔ 不 PATCH」), so removing it loses no rule; that is how the added negative branch (「无则零写,⛔ 不自造」) is paid for inside the same 120-byte line. No line elsewhere was retired.

Premise re-verified on the base (4efb988, origin/main at branch time)

  • :279 reads verbatim as the card quotes; Clause-② occurs exactly once in the file (grep -c → 1); wc -l → 403.
  • The reader that makes the line true is scripts/pm/check-clause2-carriers.mjs (header: 「the dual carrier is asserted by mechanism」, 「the claim comment SELECTED as the carrier」). objectui has none, in its own words: scripts/check-governed-queue-guard.mjs :187 「scripts/pm/check-clause2-carriers.mjs, and this repository has no such file」 and :1959 「⚠️ objectui has no check-clause2-carriers.mjs to defer the verdict question」, read at objectui origin/main 0c2eb5e. Controls on the same tree: ls scripts | wc -l → 124; git ls-tree --name-only -r origin/main | grep -ci clause2 → 0.
  • The 403 ceiling is pinned by scripts/pm/check-skill-line-ratchet.mjs (CEILINGS row ['.claude/agents/os-dev.md', 403], MAX_LINE_BYTES = 120); 14 lines of the file already sit at exactly 120 bytes, none over. The :68 precedent for a one-line repo-conditional clause is 119 bytes.
  • check:pm-skill-id-lint scans this file with /#[0-9]{3,}/; the new line has 0 hits.
  • The file's two latest landings (fe36a40 → :285; 87f776b → rule 4 and the label band) did not touch :279.

Gates (union run on head fba3bb3; every exit captured before any pipe)

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack with no paths (changed set from the merge-base) printed 19 commands, identical to the dispatch-time list. All 19 ran and exited 0:

# command exit
1 node scripts/check-closing-keyword-parity.mjs 0
2 node scripts/check-closing-keyword-parity.mjs --self-test 0
3 node scripts/check-comment-mask-corpus.mjs 0
4 node scripts/pm/check-governed-queue-guard.mjs --self-test 0 (296 cases)
5 node scripts/pm/check-harness-current.mjs --self-test 0
6 pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 (see note)
7 pnpm check:agent-model-declared 0
8 pnpm check:agent-test-spelling 0
9 pnpm check:commit-card-trailers 0 (81 self-test cases)
10 pnpm check:cross-package-test-inputs 0
11 pnpm check:doc-authoring 0
12 pnpm check:driver-memory-census 0
13 pnpm check:nul-bytes 0
14 pnpm check:pm-governed-merges 0
15 pnpm check:pm-skill-id-lint 0 — 「27 file(s) clean (pattern /#[0-9]{3,}/g)」
16 pnpm check:pm-skill-ratchet 0 — 「.claude/agents/os-dev.md is 403 lines (ceiling 403; headroom 0)」
17 pnpm check:refd-timer-probe 0
18 pnpm check:skill-frame-sync 0
19 pnpm check:watch-hint-literal 0

Reconciliation: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE (one line per command as COMMAND :: exit CODE) → 「19 derived famil(ies) accounted for — 19 run, 0 NOT-MEASURED (a DERIVED zero — all 19 recorded an exit code and none of them is 3)」.

Note on row 6: the first run exited 3 (PREREQUISITE NOT MET: @objectstack/formula and @objectstack/lint unbuilt; the gate says 「Nothing was measured」). Not a measurement. After pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint under the verify lock (VERDICT command-exit 0) the gate ran and exited 0.

Push-time hook on the one commit: 「check:commit-card-trailers: 1 commit message(s) on this push carry no card relation and no model identifier in the trailer pair」.

Not run locally, CI-owned: pnpm lint (repo-wide eslint). The diff touches one Markdown file under .claude/, no lintable source, so there is no narrowing to declare. Byte hygiene: grep -naP for control bytes over the file → 0.

Tier the landing guard will read

node scripts/pm/check-governed-merges.mjs --test .claude/agents/os-dev.md → 「GOVERNED — Tier S(席内达档复核落地)」, .claude/** ×1 (exit 3, the governed code). This PR stays draft; the owning seat's in-seat contract-tier review record lands it. No changeset: .claude/** publishes nothing (skip-changeset).

Acceptance notes

  • noted, not filed: the carriers checker's fixtures show objectui claims both with and without a Clause-②: line (:9306–9320); evidence for the chosen shape, not a defect. Bearer: the skills seat reviewing this PR.
  • noted, not filed: triage's census suggestion (sweep os-dev.md once for every repo-conditional clause instead of one card per collision) is a seat decision, not a dev's. Retire the in-seat clause-② contract review — the rule, its gate label, and the 9k-line checker's gate role #19061 remains open (a proposal that could remove this line entirely; not a dependency of this PR).
  • noted, not filed: dispatch-gates.mjs refuses --commands together with --ran (exit 2, clear message); the reconciliation is a second invocation with --ran alone. Bearer: none.

维护者速读(草稿)

改了什么:os-dev 开发 agent 定义文件里的一行指令改成条件式:认领评论带 Clause-②: 行才照抄进 PR 正文行首;没有就不写、⛔ 不自己编一行。只改这一行,净行数 0(403 / 403),行宽恰在 120 字节上限。

为什么改:原句是无条件的。objectui 卡的认领评论常常不带这一行,那边也没有读这行的门禁;dev 照做会扑空,更坏的是自己编一行——而 objectstack 这边的 Check Changeset 恰恰读正文不读卡,会把编造出来的声明当真。按「认领有没有这一行」取条件,两个仓都成立,且不用点名任何仓;载体检查器自己的 fixture 里 objectui 认领有带的也有不带的,说明按仓取条件在两个方向上都会出错。

风险与代价(含回滚):一行改动、无生成物、无 changeset、19 个派生门禁全绿。措辞更紧凑但读者名与理由都保留;去掉的「开 PR 那一笔就带上」已由第 56 行「正文只写一次」覆盖。回滚 = revert 这一个 commit。

席位意见:

你要做的:本 PR 属 Tier S(.claude/**),由 skills 席在席内达档复核后经队列落地,不需要你点击。若你不认同「按认领取条件」这个形状(另两种:按落地仓取条件、点名双载体的归属车道),在卡上留一句即可。


Generated by Claude Code

…e claim carrying one

The line told every dispatched dev, unconditionally, to copy the claim's
`Clause-②:` line into the PR body. Both halves are conditional: a claim
may carry no such line (the clause-② flow is the objectstack dual-carrier
mechanism; objectui's own gate states it has no `check-clause2-carriers.mjs`
reader), and a dev following the unconditional wording either spends a step
on a non-existent obligation or, worse, invents the line — which the body
reader would then believe. The rewrite conditions the obligation on the
claim itself (true in both repositories without naming either), keeps the
`Check Changeset` reads-the-body rationale, and names the negative branch:
no line ⇒ zero write, never fabricate. The dropped "carry it on the
PR-open write" clause restates the body-written-once rule already at :56.

Net 0 lines on a zero-slack file (403 / 403); the rewritten line sits at
the 120-byte cap.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi
@os-steve os-steve added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 20, 2026 — with Claude
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Sep 20, 2026

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: fba3bb338f3a8fdfda85fc3f51f2f34dc6ccc314

① Derived judgments

  • Accept set / public surface: none moves — one line of the dev-agent definition (.claude/agents/os-dev.md :279), protocol semantics, no code. Judged correct.
  • The clause, before → after: 「正文行首照抄认领的 Clause-②: 行:Check Changeset 读正文不读卡,开 PR 那一笔就带上。」 → 「认领带 Clause-②: 行才照抄进正文行首:Check Changeset 读正文不读卡;无则零写,⛔ 不自造。」 The obligation is now conditional on the claim comment actually carrying the line (true in both repositories without naming either — the carriers checker's own fixtures hold objectui claims with and without one, the dev's evidence), the reader is named once, and the failure mode the card measured (a dev inventing the line) is forbidden in as many words. Judged correct.
  • The dropped clause 「开 PR 那一笔就带上」 survives at :56 (「PR 正文 dev 只写一次,在开 PR 那一笔,⛔ 不 PATCH」) — verified on the head by grep. No rule lost.
  • Ratchet and lint: 403 / 403, :279 at exactly 120 B (cap 120); seat-run on this head: check-skill-line-ratchet.mjs exit 0, check-skill-id-lint.mjs exit 0 (no card number in operative text).

② Semver level

None — .claude/** publishes nothing; skip-changeset on the PR is the correct declaration. Judged correct.

③ Boundary flags

open_questions empty. Three noted, not filed read: the carriers fixtures (evidence, not a defect); triage's census suggestion for every repo-conditional clause of this file (a seat decision, noted on the seat post); dispatch-gates --commands with --ran refusing in one call (usage, not a defect). None owes a card. The PR body carries ## 维护者速读(草稿) with 席位意见 empty, as a rules-layer draft should.

Implemented-by: claude/issue-19096-clause2-copy-line-repo-conditional
Reviewed-by: session_017ETYWqMQD4qMtZzAGovWNi

VERDICT: PASS


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review September 20, 2026 11:08
@os-steve
os-steve enabled auto-merge September 20, 2026 11:09
@os-steve
os-steve added this pull request to the merge queue Sep 20, 2026
Merged via the queue into main with commit 81e12e1 Sep 20, 2026
32 checks passed
@os-steve
os-steve deleted the claude/issue-19096-clause2-copy-line-repo-conditional branch September 20, 2026 11:34
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