Repository navigation
Commit a3f3c48
feat(pm): a class-(b) finding names its seam — the
Fixes #18901
Clause-②: no
Ruling-ref: 5727134819 — director seat batch #157 item 3, letter A′ on
#18900 (item ①, this card, as filed); triage handover 5725479658 binds
(every governed text at its ceiling; the retired line is named below).
Seat `domain:skills#2` · claim 5749402494 · branch
`claude/issue-18901-seam-line-filing-rule` · head `5033c4d` (on
`origin/main` `13d5294`).
## What lands
### 1. `.claude/agents/os-dev.md` 六条基本规则 3 — net 0 (403 / 403), every
touched line under the 120 B line ratchet
- :42 before (97 B): 「 - (a) 可复现缺陷(复现或失败探针具名);(b) 违背已声明契约(引契约原文);」
- :42 after (113 B): 「 - (a) 可复现缺陷(复现或失败探针具名);(b) 违背已声明契约(引契约原文,带
`Seam:` 行);」
- :43 NEW (112 B), the grammar in ONE line directly under (b): `Seam:
spec:KEY → runtime:CALL_SITE | renderer:COMPONENT`, then 「,无消费者写
`consumer: none`。」 — in the file the three placeholders are written in
Chinese inside ASCII angle brackets (键或符号 / 调用点 / 组件), spelled out here
as words because this body is a GitHub body.
- RETIRED to pay for it — :53 at `13d5294` (115 B): 「 - ⛔ 不用 MCP GitHub
写工具;令牌按会话定:installation ⇒ `claude[bot]`,user-to-server ⇒ 用户。」 Surviving
homes, clause by clause: the ban lives on :51 「GitHub 写一律走 REST
代理(`curl` 带 `GITHUB_TOKEN`)」 (all writes REST ⇒ no MCP write), :307 「不走
MCP」, :308 「⛔ 不换路重发(curl/MCP/手工)」 and the report template :371
`mcp_calls` 「a write tool in the list = this report is refused」; the
token → login fact lives at
`.claude/skills/pm-dispatch/references/platform-readings.md:130` 「容器
curl 的 REST 通道令牌两类:installation(`claude[bot]`)与 user-to-server(用户)」, and
the rule that fact served — 「归属 = 文本里的 session ID,非 `user.login`」 —
stays on :51. Line numbers are pre-edit; after the edit the REST line is
:52 and :307 / :308 / :371 are unchanged (one insert and one delete
above them cancel). No gate pins the retired line's phrases (grepped
`scripts/`, `.claude/`, `.github/`).
- Spelling agreed with the routing half (#18902, in flight on this
seat): the key is backticked `Seam:` in both texts.
### 2. `scripts/pm/check-half-states.mjs` — H68, ONE report-only row,
net +120 (124 insertions / 4 deletions)
- Predicate `h68ClassBWithoutSeamLine(issue)` with its docblock, placed
after H63's; readers `classBDeclaration(body)` — a markdown heading
naming the class, or a line opening with it (list / quote / bold
decoration and a leading `Finding` tolerated), the shapes measured below
— and `hasSeamLine(text)` = `directiveValues(text, 'Seam')`, the reader
`Blocked-by:` / `Restart-when:` share (decoration tolerated, a same-line
value required, a bare key with nothing after it is no line).
- Band `state`, registered beside H67 with the three refusals argued
(`familyRegistryCoverage`: 0 missing / 0 extra; registry 62 / cap 64).
- Sweep call beside H63's in the UNSCOPED listing — the class is
declared in the body before any grade, so an ungraded `finding` carrier
is first visible there; two body reads on a row already held, no
request, no thread.
- Battery `H68 class-(b) seam line` beside H63's cases (26 registered,
pin 24; ⛔ not at `selfTest()`'s tail); `SELF_TEST_BATTERY_FLOOR` 6 → 7
with the three existing exact pins moved.
- ⛔ Untouched: the ownership markers and `markerMatches`, the H26 region
(#19255), every workflow file, and `directiveValues`'s JSDoc `key` union
(that line sits in #19255's hunk; the reader is untyped at runtime).
- ⛔ Never a half-state verdict by itself: the file's contract is
report-only (exit 0 on a completed sweep, no label written); the row
lists a card by number and prescribes the line. The VALUE after `Seam:`
is deliberately not judged here — presence at line start is the filed
contract; the value is the routing half's reading.
## The class-(b) signal, measured (board read 2026-09-20T11:12Z, 537
open non-PR cards, saved listing replayed against the finished row)
- Bodies saying `class (b)` / `判据 (b)` anywhere: 20. DECLARING it — a
heading naming the class (`## Class (b) — …`, `## Why it is class (b)`,
`## The defect — class (b), …`, `## 判据 (b):…`) or a line opening with it
(`Class (b): …`, `**Class (b)** — …`, `⇒ class (b): …`, `Finding class
(b), …`): 16, one of them the `pm:seat` post #6015 (never judged) ⇒ 15
listable. Mid-sentence only: 4 — #19030, #18697, #17735 and #18901, this
card, which is ABOUT the rule and is the false positive a mention-reader
would list.
- Comment channel: `finding` cards 20 (5 with `domain:*`, 6 with any
comment) — a comment naming the class on 0 of 20; on the 20 body hits, 8
also carry such a comment; comment-only cards: 0. The body declaration
strictly dominates and costs no request ⇒ the row reads the body only;
the comment channel is not read.
- `Seam:` at line start on the whole open board: 0 (6 cards mention
`Seam:`, all about the rule) — every (b) card listed today predates the
rule, which is the population the routing half needs the line on.
- Would list today (15): #19320 #19307 #19171 #19160 #19155 #19146
#19124 #19120 #19118 #19043 #18964 #18957 #18743 #18277 #18132.
- Specimen LISTED: #19160 (`pm:queue` · `domain:skills` · `priority:p2`)
— 「## Class (b) — it violates a contract this repository publishes」, no
`Seam:` line; the row quotes that heading back.
- Specimen NOT listed: the same #19160 body with `Seam: spec:… →
runtime:…` appended (a fixture — no live (b) card carries the line;
#19085 is closed and carries neither signal), and #18901 itself
(mid-sentence mention).
## Reader test
「I found a declared key the runtime never reads — what do I write?」 ⇒
the (b) line — 违背已声明契约(引契约原文,带 `Seam:` 行): cite the contract text and
add `Seam: spec:THE_KEY → consumer: none` (you measured no consumer).
Where a consumer exists but does not honour the key: `Seam: spec:THE_KEY
→ runtime:THE_CALL_SITE`, or `Seam: spec:THE_KEY →
renderer:THE_COMPONENT`.
## Verification — all on head `5033c4d`, every exit code captured before
any pipe
- `node scripts/pm/check-half-states.mjs --self-test` → exit 0 — 「✓
check-half-states self-test: 5107 cases pass. Batteries: H66 released
queue card 183/172, H19 judged-set founding 37/34, H65 tier declaration
spelling 46/42, H67 queued merged-delivery reading 152/142, H2/H47/H66
decorated ownership marker 213/184, ISSUE_BODY_LIMIT measured cap 55/52,
H68 class-(b) seam line 26/24」.
- `pnpm check:pm-skill-ratchet` → exit 0 — 「✓ check-skill-line-ratchet:
.claude/agents/os-dev.md is 403 lines (ceiling 403; headroom 0)」.
- Gate union from `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` at `5033c4d` (47 commands, no paths passed):
47 / 47 ran on `5033c4d`, every one exit 0 — `--ran` reconciliation: 「47
derived famil(ies) accounted for — 47 run, 0 NOT-MEASURED (a DERIVED
zero — all 47 recorded an exit code and none of them is 3)」. The list:
`node scripts/check-changeset-no-major.mjs --base origin/main` · `node
scripts/check-changeset-no-major.mjs --self-test` · `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/board-snapshot.mjs --self-test` · `node
scripts/pm/check-governed-queue-guard.mjs --self-test` · `node
scripts/pm/check-harness-current.mjs --self-test` · `node
scripts/pm/sweep-closed-cards.mjs --self-test` · `pnpm --filter
@objectstack/lint run check:doc-formula-expressions` · `pnpm
check:agent-model-declared` · `pnpm check:agent-test-spelling` · `pnpm
check:bash32-floor` · `pnpm check:changeset-gate-self-tests` · `pnpm
check:cli-command-ids` · `pnpm check:closing-target-claim` · `pnpm
check:commit-card-trailers` · `pnpm check:cross-package-test-inputs` ·
`pnpm check:doc-authoring` · `pnpm check:driver-memory-census` · `pnpm
check:entry-guard` · `pnpm check:nul-bytes` · `pnpm check:parse-guard` ·
`pnpm check:partof-closing-keyword` · `pnpm check:pm-dispatch-gates` ·
`pnpm check:pm-governed-merges` · `pnpm check:pm-half-states` · `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:single-claim-paths` · `pnpm
check:skill-frame-sync` · `pnpm check:watch-hint-literal`.
- `node scripts/pm/check-governed-merges.mjs --test
.claude/agents/os-dev.md scripts/pm/check-half-states.mjs` → exit 3 =
GOVERNED, Tier S (`.claude/**` ×1; `scripts/pm/check-half-states.mjs`
not on the register) — the expected reading: this PR stays DRAFT until
the seat's `## Contract review` record for the current head.
- Build for `check:doc-formula-expressions`: `pnpm
--workspace-concurrency=2 --filter '@objectstack/lint...' build` under
`scripts/pm/os-verify-lock.sh` — 「VERDICT command-exit 0 · held the lock
220s」.
## Acceptance notes (noted, not filed)
- Three live (b) cards declare the class only mid-sentence (#19030,
#18697, #17735) and are deliberately not listed; 承接者: the seat that next
grades or writes on each — a heading or line-start restatement puts them
on the row.
- `directiveValues`'s JSDoc `key` union does not name `'Seam'`; 承接者:
#19255's lander (one word on a line already in that hunk).
- `SELF_TEST_BATTERY_FLOOR`: #19255 (in flight) bumps the same 6 → 7 and
adds its own roster row; the later lander resolves the roster merge and
sets 8.
- PM mechanism assumption 3 refined: the graded-(b) population does not
live under `finding` + `domain:*` (5 cards, none with a class comment) —
`finding` is transient (「定级即离标」, H63), so the measurement ran over the
whole open board.
## 维护者速读(草稿)
**改了什么**:给开发 agent 的立卡规则加了一句:凡是「协议里声明了、运行时或渲染器没兑现」这一类(b
类)发现,卡面上必须带一行机器可读的 `Seam:`,写明这条缝的两端(哪个协议键 → 哪个运行时调用点或哪个渲染组件;实测没有消费者就写
`consumer: none`)。同时巡检脚本新增一行只报不判的 H68:把已经声明为 b
类却没写这一行的开放卡按编号列出来。文件行数不变(403 / 403),为此退休了一行重复条款(MCP 写工具禁令 +
令牌说明),它的内容在同规则的 REST-only 行、标签写入条款、报告模板和 platform-readings 里都还在。
**为什么改**:你 9-18 同意的五项攒批第 ①
项。今天缝卡按「修复落地的包」路由,缝的两端各落一层、各修一次;有了这一行,路由那一半(#18902)才能按缝派发,一个键在一次落地里要么被兑现要么退役。板面实测:15
张开放 b 类卡今天都没有这一行,巡检会把它们列出来。
**风险与代价(含回滚)**:只加一行规则、一行巡检;不改标签、不写板面、不判红。误报边界已量:句中顺带提到「class (b)」的卡不列(3
张),席位帖子不列。回滚 = revert 本 PR。巡检脚本的行数配额已用满(+120);自测下限 6 → 7,与在飞的 #19255
撞同一行,后落地者改为 8。
**席位意见**:
**你要做的**:受管面(`.claude/**`,Tier S)⇒ 席内达档复核后由席位落地,不需要你点击。若你希望巡检也校验 `Seam:`
行的取值格式(今天只查有没有这一行),回一个字,另立卡。
---
_Generated by [Claude
Code](https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi)_
Co-authored-by: Claude <noreply@anthropic.com>Seam: line on os-dev.md rule 3, and the H68 patrol row for a (b) card without one (#19356)1 parent 9602f30 commit a3f3c48
2 files changed
Lines changed: 127 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
| 42 | + | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| |||
50 | 51 | | |
51 | 52 | | |
52 | 53 | | |
53 | | - | |
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
| |||
0 commit comments