Skip to content

pm: retire the needs:contract-review label from the tree (ruling B step ③) - #19737

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-19061-step3-retire-clause2-label
Sep 23, 2026
Merged

os-zhuang merged 5 commits into
mainfrom
claude/issue-19061-step3-retire-clause2-label

Conversation

@huangyiirene

@huangyiirene huangyiirene commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #19061

维护者速读(草稿)

改了什么:按裁决记录 5770886272(B 字母,第 ③ 步)把 needs:contract-review 标签从代码树里退役。ensure-pm-labels.sh 不再创建它;队列守卫 check-governed-queue-guard.mjs 的标签腿(退出码 6/7、标签读取、载体判定与渲染、#17040 电池)整段删除;check-half-states.mjs 里围绕该标签巡查的五行(H31/H35/H51/H53/H61)连同扫描点、汇总句、计数键、分带登记与自测一起删除,仓库级 issue-event 窗口读取随之消失;check-changeset-no-major.mjs 只读 PR 正文的 Clause-②: 行,标签载体轴与对 check-half-states.mjs 的 import 删除;.claude/**、AGENTS.md、两个 workflow 注释里叫 agent 去挂/读/等这个标签、--pair、双载体或降档保险丝的句子改成只认 ## Contract review 记录。每个受管 PR 一条记录的契约原样保留。

为什么改:维护者原话「不需要 AI 不能自审契约改动 这种」与「我们系统开发了太多无用的门禁,反而在浪费时间」;裁决 B 把三层(标签 + --pair + 记录)收成一层,只留记录给队列守卫读。第 ① 步(抽出 readClause2Line)和第 ② 步(规则文本)已落地;这是最后一步。

风险与代价(含回滚):队列守卫少一条腿,groupExitCode 变成两腿(governed → size),退出码 6/7 从登记表移除;半态巡查少五个家族(自测 5170 → 4897 例,gate 分带保留但暂无成员);changeset 门禁不再把标签当声明载体,以后没写 Clause-②: 行的 PR 读作未声明。回滚 = revert 本 PR 的四个提交(每类一个提交,可单独回退)。⛔ GitHub 上的标签对象本 PR 不删,由席位在合并后、确认没有开着的卡或 PR 还挂着它时移除。一处残留:check-clause2-carriers.mjs 把该标签常量改为文件内局部常量——它的 --pair 扫描已被裁决退役、无人运行,但队列守卫仍懒加载它的记录识别器与 --template,所以文件还不能删;把识别器抽成小模块后整文件连同这个常量一起删,是下一步(见下方 Remainder)。

席位意见:建议批准并合并。 这是裁决 5770886272(B)的最后一步,做的是「减」:标签的创建者、读者、巡查行、changeset 门禁的标签载体轴和九处叫 agent 去挂/读/等标签的句子全部退休,净 −2650 行;裁决要保留的东西一样没少 —— 队列守卫仍先看授权批准、再看 ## Contract review 记录(席位在头上逐段核过守卫的两腿与半态巡查保留的记录读取器),AGENTS.md :275–:281 把 Tier S 写成只认记录。四个自测(279 / 4897 / 339 / 1140 例)与十二个门禁族在席位工作树上重跑全绿。一处残留是量出来的而非选的:check-clause2-carriers.mjs 还不能删,因为队列守卫懒加载它的六个记录识别器与 --template;dev 给它留了本文件内的退休常量并禁止新引用。席位把「抽出识别器、整文件删除」定为 #19061 的第 ④ 步(合并后由 Release: 记在卡上,不另立卡),所以本 PR 首行是 Part of。合并后席位删除 GitHub 上的标签对象、关闭因它而起的 objectui#9867,并放行压在这些文件后面的 #19146 / #19129 ② / #19244 ② ③。复核记录:PR 评论 5779366929(PASS,在席按服务档渲染);ACCEPT 在卡 #19061。CI 读数:33 latest-per-name check runs — 24 success, 9 skipped, 0 in progress, 0 other (the seat's read at 00:13 UTC of this date; the lint-and-repo-gates job success)。

你要做的:本 PR 是 Tier H(AGENTS.md 在登记表上),草稿状态由您手动合并;合并后席位移除 GitHub 标签对象,并为「抽出记录识别器、删除 check-clause2-carriers.mjs」立单。

Summary

Ruling record 5770886272 on #19061 (letter B), step ③: the needs:contract-review label leaves the tree. Every mechanism that created, read, hung, cleared or expected it is retired; the one ## Contract review record per governed PR — the thing the queue guard reads to release .claude/** in the merge group — stays exactly as it was. Part of rather than Fixes: one measured remainder is named below.

Per-path disposition (18 label sites on the base, plus the prose riders)

path class what changed
scripts/pm/ensure-pm-labels.sh CODE the needs:contract-review row (comment block + gh label create) removed; the pointer in the repo:* block reworded. The GitHub label object is NOT deleted here.
scripts/pm/check-governed-queue-guard.mjs CODE the carrier leg retired: EXIT_REFUSED_CARRIER (6) and EXIT_REFUSED_CARRIER_UNREADABLE (7), CONTRACT_REVIEW_LABEL, CARRIER_LEG_NAME, carrierVerdict, runCarrierGuard, renderCarrierVerdict, makeLabelReader, the main-dispatch call, the exit table rows, the header's SECOND-leg section; groupExitCode is two-legged (governed, size); carrierPullsInGroup (still read by the size leg) renamed queuedPullsInGroup; the module-eval-cycle explanation moved onto the surviving REVIEW_OF_RECORD_LOCATION mirror; the #17040 battery (39 cases) removed, floor 24 → 23, its enumeration cases and the two zero-cost-clear scoping pins re-homed in the #19036 size battery; the Tier S prescriptions stop naming --pair N.
scripts/pm/check-half-states.mjs CODE H31 (carrier split), H35 (gate-label removal events, with GATE_SEMANTIC_LABELS, isGateSemanticLabel, the event-window constants and listRecentIssueEvents), H51 (verdict without label stroke), H53 (carrier without increment) and H61 (landed carrier) removed: rows, sweep sites, summary clauses and count keys, band entries and self-test sections; CONTRACT_REVIEW_LABEL removed. KEPT: bindingClosesCard, the record readers (CONTRACT_REVIEW_HEADING_MARKER, H51_SHA_MIN_HEX, H51_SHA_SPAN, contractReviewHeadMatch, latestContractReviewOnHead) with their pins re-homed under a "record readers" section. The #13947 ledger fixtures move from H31 to a stall family (H12); the gate band stays declared, rank 0, with no live member; the H52 reservation pin now asserts the spent number is never re-used.
scripts/check-changeset-no-major.mjs CODE the label carrier axis retired: declarationFromPullRequest reads the Clause-②: body line only (no labels read, no carrier field), judgeLevel/renderLevel drop carrier/carrierUnread and every sentence that named the label; the check-half-states.mjs import goes (the gate's first-party closure is now clause2-line.mjs alone); the #17229 battery (25 cases) removed, floor 20 → 19; the payload-snapshot docblock rewritten around the body.
scripts/pm/check-clause2-carriers.mjs CODE (remainder) NOT deleted — measured: check-governed-queue-guard.mjs lazily imports six record recognisers from it (locateReviewOfRecord, deliveredCardNumber, servedTierStands, isModelIdentifierToken, REVIEW_OF_RECORD_THREADS, REVIEW_OF_RECORD_LOCATION) and contract-review.md points at its --template, so the ruling's deletion precondition ("nothing but the extracted module is imported") does not hold on this base. Its two imports of the retired symbols become a LOCAL CONTRACT_REVIEW_LABEL / isGateSemanticLabel, docblocked as retired and import-forbidden; nothing else in it moves. This is the one CODE site still spelling the label.
scripts/pm/check-widening-tells.mjs PROSE in code no label leg; the design-note sentence reworded ("a review-gate label"); the dated 2026-09-16 census line at :673 is HISTORY and stays.
scripts/pm/check-label-desc-cap.mjs PROSE in code the 97-char/101-byte specimen sentence stops naming the label; the self-test keeps the description string as a fixture (renamed case). Floor MIN_DESCRIPTIONS 12 vs 38 found — untouched.
scripts/pm/check-skill-line-ratchet.mjs HISTORY + rows the two raise-provenance comments naming the label stay (they explain past ceilings); rows lowered: os-dev.md 403 → 402, state-machine.md 42 → 41 (AGENTS.md stays 1116 — the paragraph re-wrapped to the same count).
scripts/pm/dispatch-gates.mjs PROSE in code the CONTRACT_REVIEW_TIER docblock no longer names the re-review sub-round, the fuse or the label bullets; the rulebook pointer goes to references/contract-review.md.
scripts/pm/clause2-line.mjs PROSE in code the "STEP ① … nothing else has landed yet" paragraph rewritten to the landed state; the provenance sentence at :11 and the measured incident at :307 stay.
scripts/pm/check-governed-merges.mjs CODE strings Tier S landing prose and the --test rendering stop prescribing --pair N; two self-test pins flipped to assert its absence; the mirror docblock points at REVIEW_OF_RECORD_LOCATION.
scripts/pm/post-stamped.mjs CODE string the near-miss row stops prescribing --pair.
.github/workflows/lint.yml PROSE the desc-cap specimen comment and the clause-② self-test step comment (the step itself stays: it keeps the recognisers loadable).
.github/workflows/pr-automation.yml PROSE the WHICH LEVEL prose names the one carrier left.
.claude/agents/os-dev.md :303 PROSE line deleted.
.claude/skills/pm-dispatch/SKILL.md :769 PROSE 三职 = 契约复核记录事后审计 …
references/lanes/director.md :27/:31/:33/:35 PROSE duty one audits the records; 落地前检③ → ②; handoff by pm:* label, record stays on PR or card.
references/lanes/ui.md :38 PROSE record-only contract, pointer to ../contract-review.md.
references/state-machine.md :8/:10 PROSE H29/H30 authority; the card-side-first line deleted.
references/dispatch-runbook.md :161 PROSE 独立性件 → 达档复核记录.
references/platform-readings.md :26 PROSE the label row generalised to the still-true mergeable_state: blocked reading.
references/contract-review.md :13/:19 PROSE (unchanged) the --template pointers stay valid because the script stays; they follow the file at the extraction step.
AGENTS.md :278 PROSE Prime Directive #14 Tier S: the --pair N clause removed, paragraph re-wrapped at the 120-byte budget.
.changeset/console-87af769e9a3e.md, docs/adr/0131-…, docs/audits/** HISTORY untouched.

What stays, on purpose

  • One ## Contract review record per governed PR, Served-tier: line, the queue guard's Tier S leg and its lazy import of the recognisers — ruling B, not A.
  • CONTRACT_REVIEW_TIER in dispatch-gates.mjs (path-mandate role) and readClause2Line in clause2-line.mjs (step ①).
  • The GitHub label object: the seat removes it after MERGED once no open card or PR carries it.

Remainder (why Part of)

check-clause2-carriers.mjs still spells the label in a local constant because its deletion — the ruling's own end state for the file — waits on extracting the six record recognisers and --template into a module the queue guard can lazily import (a sibling of step ①, roughly the 2,700-3,000 to 4,300 line band of that file plus its record batteries). Retiring the C1/C3/gate-history rows inside a file that is slated for deletion would rewire the retired --pair sweep for nothing. The seat files that extraction as its own card; with it the last label site goes and objectui#9867 falls moot.

Tests

All on the merged head 8671754c9 (base 106d4c8dd, origin/main 342808cf5 merged clean, no file overlap), exits captured before any pipe:

  • node scripts/pm/check-governed-queue-guard.mjs --self-test — exit 0 — ✓ check-governed-queue-guard self-test: 279 cases pass
  • node scripts/pm/check-half-states.mjs --self-test — exit 0 — ✓ check-half-states self-test: 4897 cases pass (5170 before; batteries H66 182/172 and H67 152/142 each lost one cross-family pin)
  • node scripts/check-changeset-no-major.mjs --self-test — exit 0 — 339 assertions; --base origin/main exit 0 (level axis NOT APPLICABLE with no pull_request)
  • node scripts/pm/check-clause2-carriers.mjs --self-test — exit 0 — 1140 cases pass
  • pnpm check:pm-governed-merges exit 0 · pnpm check:pm-post-stamped 596 cases · pnpm check:pm-dispatch-gates 1905 cases (748 s) · pnpm check:pm-widening-tells 525 cases · pnpm check:pm-label-desc-cap self-test + gate (38 descriptions, all ≤100) · pnpm check:pm-skill-ratchet exit 0 (total ceilings down 9 lines) · pnpm check:pm-skill-id-lint 30 files clean · pnpm check:pm-governed-prose 6/6 surfaces · pnpm check:nul-bytes 9231 files clean · pnpm check:commit-card-trailers 5 commits clean
  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives 84 commands (identical before and after the merge); --ran reconciled — run locally: 80 of them; declared to CI: pnpm --filter @objectstack/lint run check:doc-formula-expressions (needs the package build), pnpm check:partof-closing-keyword (reads the PR body), pnpm check:pm-expected-skips (reads the board); pnpm check:type-check-debt exit 3 = PREREQUISITE NOT MET (needs the packages build closure; this diff touches no package) — NOT MEASURED.
  • Narrowed lint: pnpm exec eslint --no-inline-config --format json over the 11 touched .mjs files — exit 0, 11 files, 0 errors, 0 warnings. Population read from eslint.config.mjs (the **/*.{ts,…,mjs,cjs} block); the config never enables type-aware linting (eslint.config.mjs :326-:328, "no parserOptions.project, no typed @typescript-eslint rules for ANY file"), so this diff moves no untouched file's verdict; the whole-repo pnpm lint is CI's run.
  • node scripts/pm/check-harness-current.mjs: STALE before and after — it compares the shared checkout's HEAD with origin/main, which this branch does not move.
  • node scripts/pm/check-governed-merges.mjs --pr N: run after the PR exists (expected GOVERNED, Tier H via AGENTS.md); reported on the card.

Deviations

  • check-clause2-carriers.mjs keeps a local retired-label constant (see Remainder) — the one departure from "the label retired from the tree", measured and named rather than forced.
  • pnpm check:type-check-debt not measured locally (build prerequisite); pnpm install --frozen-lockfile && pnpm build after the merge was not run because this diff touches no package and every gate run here reads scripts, workflows or .claude/**.

Acceptance notes

  • class: b · scripts/pm/check-widening-tells.mjs still describes --pair's C5 row as its live consumer (:85, :241, :1338) — that consumer is retired by ruling B; the gate's own self-test is what CI runs. Not touched here (not the label); carrier: the extraction card above. Dedupe words: widening-tells --pair C5 consumer retired.
  • scripts/pm/check-expected-skips.mjs :118 still names check-clause2-carriers.mjs as the read ladder it mirrors — true while the file exists; follows the extraction.

Generated by Claude Code


Generated by Claude Code

The label the leg read is retired (ruling record 5770886272 on #19061, letter B,
step ③): exits 6/7, the label reader, the carrier verdict and rendering, the
#17040 battery (floor 24 → 23) and the label mirror go; the module-eval-cycle
explanation moves onto the surviving REVIEW_OF_RECORD_LOCATION mirror; the
enumerator the size leg reads is renamed queuedPullsInGroup and its cases move
into the size battery. The audit's Tier S prescriptions stop naming --pair N.

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

H31, H35, H51, H53 and H61 read the retired needs:contract-review label and go
with it (ruling record 5770886272 on #19061, letter B, step ③): their rows,
sweep sites, summary clauses, count keys, band entries and self-test sections,
the gate-semantic label family, the repo-wide issue-event window and the label
constant. The contract-review record readers (heading marker, head-sha span,
newest-on-head finder) and bindingClosesCard stay, with their pins re-homed;
the #13947 ledger fixtures move to a stall family; the gate band stays declared
with no live member.

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

ensure-pm-labels.sh no longer creates the label (the GitHub object is the
seat's to remove); check-changeset-no-major reads the Clause-② line alone —
the label carrier axis, the check-half-states import and the #17229 battery
(floor 20 → 19) go; check-clause2-carriers.mjs keeps a LOCAL retired constant
because its retired --pair sweep still compares it and the file cannot be
deleted yet (the queue guard lazily imports its record recognisers); the
label-desc-cap specimen, the workflow comments, the CONTRACT_REVIEW_TIER
docblock and post-stamped's near-miss row stop naming the label or --pair.

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

os-dev.md, SKILL.md, the director and ui lane files, state-machine.md,
dispatch-runbook.md, platform-readings.md and AGENTS.md Prime Directive #14 stop
telling a seat to hang, read or expect the retired label, --pair, the double
carrier or the downgrade fuse; the record-only contract stays. Ratchet rows for
os-dev.md (403 → 402) and state-machine.md (42 → 41) follow the landed counts.

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

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 8671754c9d8573a4447342f7906dc834cb49ebeb

① Derived judgments

Rendered in-seat by the skills seat 1 session at the served tier the maintainer named on this date (the fable tier word at get_session → external_metadata.last_served_model, re-read this hour; ruling record 5771798588). The contract is ruling record 5770886272 on #19061 — batch #211 item 3, letter B, the maintainer's 「其他同意」 — step ③ of its three-step order: the needs:contract-review label leaves the tree (its creator, every reader, every rider), ⛔ while the one ## Contract review record per governed PR, CONTRACT_REVIEW_TIER and readClause2Line stay (B, ⛔ not A); the GitHub label object is the seat's to delete after MERGED, ⛔ not the dev's; the held-behind subjects (os-dev.md :286–:287, the check-half-states.mjs H9 channel) untouched.

  • (a) The diff — measured by this seat on a review worktree at the head. Four single-parent commits, one per class (guard / half-states / labels+legs / agent text), then a merge of origin/main 342808cf5 (no file overlap; the squash yields one parent); 22 files, +405 / −3055. git grep 'needs:contract-review' on the head: 18 sites on the base → the survivors are HISTORY (the changeset, ADR-0131 :289, two ratchet raise-provenance comments, the dated census in check-widening-tells :673, two dated comments in clause2-line.mjs), two comments in check-half-states.mjs saying the rows are retired, and the one named remainder — a LOCAL CONTRACT_REVIEW_LABEL constant in check-clause2-carriers.mjs (docblocked 「⛔ RETIRED … nothing new may import it」). Every live mechanism is gone: EXIT_REFUSED_CARRIER / carrierVerdict 0 hits in the queue guard, listRecentIssueEvents 0 in half-states, the check-half-states.mjs import gone from check-changeset-no-major.mjs, ensure-pm-labels.sh no longer creates the label.
  • (b) Premise held — measured. All 18 sites present on 106d4c8dd (the claim's base) and on the merge base; step ② (7e0bfce40) on the base; the two held subjects untouched (the os-dev.md hunk is :300–:306, −1 line; no H9 or RESTART_WHEN_COMMAND_HEADS line in the half-states diff).
  • (c) What survives is the record, read by this seat on the head. The queue guard's approval limb first (GOVERNED_APPROVERS os-zhuang / hotlong, latest-decisive) and the Tier S record leg second (recordVerdict over the lazily imported locateReviewOfRecord / servedTierStands / deliveredCardNumber / isModelIdentifierToken), groupExitCode two-legged (governed → size), exits 6 / 7 struck from the table; the half-states record readers (CONTRACT_REVIEW_HEADING_MARKER, contractReviewHeadMatch, latestContractReviewOnHead) kept under a record-readers section, the gate band declared with no live member (pinned by its self-test); check-changeset-no-major.mjs reads the Clause-②: body line alone through readClause2Line. AGENTS.md :275–:281 states Tier S as 「a ## Contract review record for the PR's current head with Served-tier: CONTRACT_REVIEW_TIER and a PASS verdict and every check is green」 with the --pair N clause gone; --pair has 0 hits in .claude/** and AGENTS.md; contract-review.md :13 / :19 still point at --template, which still exists.
  • (d) The prose riders read the record-only contract, each checked against its base line. os-dev.md :303 (the 「归席位,⛔ 不挂不摘不等;报 … --pair 退出码」 line) deleted; SKILL.md :769 the director's first duty renamed 契约复核记录事后审计; director.md :27 / :31 / :33 (落地前检③ → ②) / :35 reworded to the record and the pm:* hand-over; ui.md :38 to 「按面欠达档复核记录,落 PR 或卡」; dispatch-runbook.md :161 to 「按 contract-review.md 欠达档复核记录」; state-machine.md :8 drops H31 from the authority triple and :10 (the card-side-first intermediate state) deleted; platform-readings.md :26 generalised to the mergeable_state: blocked + mergeable: true reading; AGENTS.md :278 re-wrapped at the same line count; the two workflow comments and the pr-automation.yml axis sentence no longer name the label. Ratchet rows lowered in the ordinary direction only (os-dev.md 403 → 402, state-machine.md 42 → 41, both cited to the ruling); AGENTS.md 1116 / 1116.
  • (e) The remainder is measured, not chosen. check-clause2-carriers.mjs cannot be deleted on this base: the queue guard lazily imports six record recognisers and --template from it, lint.yml and package.json run its self-test to keep those loadable; its --pair sweep (retired by B) is run by nothing. The PR therefore opens Part of #19061; this seat grades the dev's option A in-lane as step ④ of the same card — extract the recognisers and --template into a module the guard imports, repoint contract-review.md :13 / :19 and RECOGNISER_SOURCES, delete the file with its package script, lint.yml step and the local constant — carried by Retire the in-seat clause-② contract review — the rule, its gate label, and the 9k-line checker's gate role #19061's Release: at MERGED, ⛔ no new card (the filing door bars this seat and none is needed).
  • (f) Gates — re-run by this seat on the review worktree at the head after pnpm install --frozen-lockfile --offline. check-governed-queue-guard --self-test 0 (279 cases); check-half-states --self-test 0 (4897 cases, from 5170 — the five retired rows' batteries); check-changeset-no-major --self-test 0 (339 assertions) and --base origin/main 0; check-clause2-carriers --self-test 0 (1140); check:pm-governed-merges 0 (its Tier S self-test pins now assert --pair ABSENT from the prescriptions); check:pm-skill-ratchet 0; check:pm-skill-id-lint 0 (30 files); check:pm-governed-prose 0 (6 / 6 surfaces); check:nul-bytes 0 (9235 files); check:pm-label-desc-cap 0 (38 descriptions); post-stamped --self-test 0 (596); check-widening-tells --self-test 0 (525); check:skill-frame-sync 0; check-governed-merges.mjs --pr 19737 exit 3 — GOVERNED, Tier H (.claude/** ×7, AGENTS.md ×1; 3460 changed lines under the human-merge threshold); the dispatch-gates.mjs --self-test (1905 cases) was started detached by the seat and is read at the 四件套. The dev's derivation: 84 commands, identical across the base merge, --ran 80 / 84 exit 0, one NOT-MEASURED (check:type-check-debt, a build prerequisite — the diff touches no package) and three declared to CI; narrowed eslint over the 11 touched .mjs files 0 / 0. CI at this head at the seat's read: 31 latest-per-name check runs — 17 success, 9 skipped, 5 in progress; check-expected-skips and the 四件套 wait for green.

② Semver level

None — no release. scripts/**, .claude/**, .github/** and AGENTS.md are in no package's files[] (the dev measured every manifest); skip-changeset written through label-write.mjs with read-back.

③ Boundary flags

Implemented-by: claude/issue-19061-step3-retire-clause2-label
Reviewed-by: session_01Wnstp2kTth7sGXfr8fXypc

VERDICT: PASS


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 23, 2026 04:34
@os-zhuang
os-zhuang enabled auto-merge September 23, 2026 04:35
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 23, 2026
Merged via the queue into main with commit 628e55d Sep 23, 2026
57 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-19061-step3-retire-clause2-label branch September 23, 2026 05:06
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…ispatched claims (objectstack-ai#19792)

Fixes objectstack-ai#18964

## 维护者速读(草稿)

**改了什么**:`.claude/skills/pm-dispatch/SKILL.md` 第 266
行删掉一个词「本车道」,其余一字不动,文件行数 815 不变。改前:「- 派发前在飞检查:读本车道 `pm:dispatched`
卡认领评论申报的文件面,本地求交、不另发查询。」改后:「- 派发前在飞检查:读 `pm:dispatched`
卡认领评论申报的文件面,本地求交、不另发查询。」`references/core-rules.md` 没有这句话的对应行,本 PR 不动它。

**为什么改**:执行裁决记录 5780497628(字母
B)。席位认领前的在飞检查原来只读本车道已派发卡申报的文件面,所以另一个车道里已认领、已推分支、但还没开 PR
的同文件工作单对它不可见。objectstack-ai#18314(spec 车道)与 objectstack-ai#18844(skills 车道)的双重派发就是这样漏掉的,objectstack-ai#17518
也是同一形态。改成读所有车道的已派发认领之后,申报的文件面会直接点名文件,两个实例都能命中。卡上原来提议的「按文件名词干扫描分支名」经实测证伪(两个实例
0 命中,开放 PR 上召回率 29%),裁决明确不采用(A、C 均不取)。


**风险与代价(含回滚)**:每次认领要多读其它车道已派发卡的认领评论,仍是本地求交、不另发查询;这项读取成本裁决没有实测,如果某个车道觉得太慢,另立一张带数字的卡,⛔
不悄悄把这个词加回来。没有代码、门禁或发布面变化。回滚 = revert 这一个提交。

**席位意见**:(待席位填写)

**你要做的**:无需操作。本 PR 属 Tier S(`.claude/**`),由席位出具 `## Contract review`
记录、全部检查通过后经合并队列落地。

Clause-②: no

## Summary

Ruling record 5780497628 on the card (letter B, complete; A and C not
taken) removes the lane qualifier from the pre-dispatch in-flight read,
so a seat about to claim reads every lane's `pm:dispatched` claim
comments for their declared file surfaces, still intersected locally
with no extra query. One word, one line, net 0 lines.

```diff
- - 派发前在飞检查:读本车道 `pm:dispatched` 卡认领评论申报的文件面,本地求交、不另发查询。
+ - 派发前在飞检查:读 `pm:dispatched` 卡认领评论申报的文件面,本地求交、不另发查询。
```

| site | before | after |
|---|---|---|
| `.claude/skills/pm-dispatch/SKILL.md` :266 | 121 bytes, contains 本车道
(anchor count 1) | 112 bytes, anchor gone (count 0), new sentence count
1 |
| file length | 815 lines (ceiling 819) | 815 lines (ceiling 819) |

Premise re-measured on base `2cf9db7c4` (the current `origin/main`): the
sentence sat at :266 unchanged after PR objectstack-ai#19737 landed.

## Verification (head `8ead063f3`, the only commit)

Family set derived with `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` (21 commands, 1 path) and
reconciled with `--ran`: 21 derived, 21 run, 0 NOT-MEASURED, 0 UNRUN,
every line carrying its captured exit. All exits captured before any
pipe.

| command | exit | verdict line (excerpt) |
|---|---|---|
| `pnpm check:pm-skill-ratchet` | 0 | SKILL.md is 815 lines (ceiling
819; headroom 4); widest table row is 342 bytes (pin 342; headroom 0) |
| `pnpm check:pm-skill-id-lint` | 0 | 30 file(s) clean |
| `pnpm check:skill-frame-sync` | 0 | the one declared copy of the
decision frame is internally coherent |
| `pnpm check:skill-frame-freshness` (named by the dispatch, outside the
derivation) | 0 | the decision frame in this tree is current with
origin/main |
| `pnpm check:doc-authoring` | 0 | 16196 customer-facing strings clean;
sibling-package prose ids hold the baseline |
| `pnpm check:nul-bytes` | 0 | 9262 text files, no raw ASCII control
bytes |
| `pnpm check:pm-governed-prose` | 0 | 2 instruction surfaces name all 6
registered governed surfaces |
| `pnpm check:pm-settings-deny-roster` (roster under `.claude`, outside
the derivation) | 0 | 17 content-write tools declared = enforced |
| `pnpm --filter @objectstack/lint run check:doc-formula-expressions` |
0 | first run exit 3 PREREQUISITE NOT MET (formula and lint unbuilt,
nothing measured); built both under the verify lock (VERDICT
command-exit 0), re-run exit 0 |
| `node scripts/check-closing-keyword-parity.mjs` and `--self-test` | 0
/ 0 | 3 parsers agree on all 9 keywords |
| `node scripts/check-comment-mask-corpus.mjs` | 0 | 7015 files, 0
disagree |
| self-tests: governed-queue-guard, harness-current, pm-expected-skips,
pm-governed-merges, pm-half-states | 0 each | 279 / 26 / 99 / 441
assertions / 4897 cases pass |
| `pnpm check:agent-test-spelling`, `check:cross-package-test-inputs`,
`check:driver-memory-census`, `check:gitlink-declared`,
`check:refd-timer-probe`, `check:watch-hint-literal` | 0 each | OK |

No package is touched, so there is no dependency-closure build and no
package test or typecheck owed. There is no core-rules twin gate
(`check:core-rules-*` does not exist in `package.json`).

## Changeset

`skip-changeset`: the only path is under `.claude/**`, which is in no
package's `files[]` and publishes nothing.

## Acceptance notes

- `references/core-rules.md` is untouched. `grep -n '本车道'` there gives 1
hit, at :18, which is the round-opening mutex reading (the twin of
SKILL.md :80), not this sentence. The core-rules line that summarises
the cross-domain path (:68, 「跨域单 PR 由分诊席指定一个车道 PM
认领并申报完整文件面,在飞检查同域跨域皆跑。」) stays true after this change.
- SKILL.md :267 (the cross-domain exception path adds every touched
domain's in-flight cards) is now covered by :266 reading every lane. It
is still true, and it stays as it is because the ruling moves nothing
else.
- The other 本车道 readings (SKILL.md :36, :80, :82, :230, :586, :587;
`dispatch-runbook.md` :61; `seat-post-protocol.md` :28) are different
rules (claim scope, round mutex, liveness baseline) and are outside the
ruling.
- The empty probe branch
`claude/issue-18964-claim-time-branch-stem-scan` is neither reused nor
deleted; the seat removes it.
- Serial check at open: 16 open PRs, 308 file rows, 0 unreadable, none
on `SKILL.md` or `core-rules.md` (control: 112 `.changeset/` rows read).
`origin/main` has not moved from the base.

This PR stays draft: `.claude/**` is Tier S, and the seat lands it after
its contract-review record and a fully green run.

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

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…endered records, retriage, durable state (objectstack-ai#19795)

Fixes objectstack-ai#19777

Clause-②: no

## What changed

Three one-line edits, one per reference file, each paid in place under
the file's `check-skill-line-ratchet.mjs` ceiling (241 / 469 / 91 —
counts unchanged, every line ≤ 120 bytes, no re-wrap). Base
`origin/main` at 2cf9db7.

| file · section | line added | line paid |
|---|---|---|
| `dispatch-runbook.md` 〈接手中断的 dev(worktree 接手协议)〉 | `-
账号封禁即死会话:接手者重认领,消失的记录(认领/复核/裁决)按正文行在当前 head 重出。` | folded `- PM 会话已死 ⛔
不推导其 dev 已死;跨账号活性只认 GitHub 产出读数。` and `- 死后恢复查三态:远程(\`git
ls-remote\`)、仅容器磁盘、真没了。` into `- PM 会话已死 ⛔ 不推导其 dev 已死;死后恢复查三态:远程
\`ls-remote\`、仅容器磁盘、真没了。` — the dropped clause 跨账号活性只认 GitHub 产出读数 is
line 135 of the same file (〈Routine 传输〉 block) |
| `platform-readings.md` 〈API 配额〉 | `- 封号隐藏其全部评论、无 timeline
事件;assignee、PR、正文存活;分诊没了挂 \`pm:retriage\`。` | replaced the older
suspension reading in the same block, `- 用户类写绑作者:封号则其评论与卡按作者
404,标签/状态/标题/正文存活。` — the director's measurement (104 cards, zero
`comment_deleted` events; assignee, PRs and bodies persist) supersedes
it; the `⇒ 耐久算按令牌类重算…` line under it stands |
| `seat-post-protocol.md` 〈活性、写侧刷新与收班〉 | `- 耐久状态只住正文或以 App 写入;正文守中继上限
60,000 字节,超大贴由半状态巡查浮出。` | folded `- 超大贴由半状态巡查的 report-only 项浮出,⛔
不等读取失败。` (〈贴的四段与派生视图〉) into it |

Not touched: `contract-review.md` :13 / :19 (objectstack-ai#19061 step ④), `SKILL.md`,
`os-dev.md`, `AGENTS.md`; no gate, hook, ratchet or roster.

## Landing

Tier S (`.claude/**`) at `CONTRACT_REVIEW_TIER`: the director seat
renders the `## Contract review` record on this head and lands it
through the queue. `skip-changeset` — nothing published from any
released package; the label is the seat's to apply (this dispatch
forbids label writes by the dev). The two serial PRs the card named
(objectstack-ai#19737, objectstack-ai#19771) are on `main`; nothing to rebase.

## Verification

Gates derived by `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` on the edited tree at d192977;
each run alone, exit captured before any pipe (`cmd > log 2>&1; ec=$?`).

| command | exit | verdict line |
|---|---|---|
| `node scripts/check-closing-keyword-parity.mjs` | 0 | •
packages/spec/CHANGELOG.md -- 6080503 bytes exceeds the sweep's
2097152-byte cutoff for UNREGISTERED files |
| `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 | ✓
check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of
the shipped parsers each driven to r |
| `node scripts/check-comment-mask-corpus.mjs` | 0 | ✓ comment-mask
corpus sweep [scripts/js-comment-mask.mjs]: 7015 files, 0 disagree, 0
unparseable, 89.9s (compa |
| `node scripts/pm/check-governed-queue-guard.mjs --self-test` | 0 | ✓
check-governed-queue-guard self-test: 279 cases pass (register-driven
verdicts, the queue/PR event split, la |
| `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 | objectstack-ai#11673). |
| `pnpm check:agent-test-spelling` | 0 | which drives this same sweep
RED over a temp tree on disk. |
| `pnpm check:cross-package-test-inputs` | 0 | OK: 29 package(s) read
outside themselves, all declared, and turbo.json hashes every declared
glob (6 of them |
| `pnpm check:doc-authoring` | 0 | ✓ doc authoring guard:
sibling-package prose ids hold the baseline — 819 pinned site(s) across
231 file(s), 90 |
| `pnpm check:driver-memory-census` | 0 | check-driver-memory-census: OK
— every declaration is ledgered, every ledger entry is live, and every
ruled fi |
| `pnpm check:gitlink-declared` | 0 | check-gitlink-declared: OK (9269
index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the
index, so |
| `pnpm check:nul-bytes` | 0 | check-nul-bytes: OK (scanned 9262 text
file(s) -- 9262 tracked, 0 untracked-not-ignored; skipped 7 binary; no |
| `pnpm check:pm-governed-merges` | 0 | live: the real generator
declared 9 output(s) and certified this tree |
| `pnpm check:pm-half-states` | 0 | ✓ check-half-states self-test: 4897
cases pass. Batteries: H66 released queue card 182/172, H19 judged-set
fou |
| `pnpm check:pm-skill-id-lint` | 0 | ✓ check-skill-id-lint: 30 file(s)
clean (pattern /#[0-9]{3,}/g). |
| `pnpm check:pm-skill-ratchet` | 0 | ✓ check-skill-line-ratchet:
declared cross-file moves: 1, total ceilings down 9 lines. |
| `pnpm check:refd-timer-probe` | 0 | 1 code site(s), all inside the
approved module, which is present and still reads it. |
| `pnpm check:required-contexts` | 0 |
governed-surface-guard.yml:governed-surface-guard → 'Governed Surface
Queue Guard' |
| `pnpm check:skill-frame-sync` | 0 | binding sentence present in it; 1
count mention(s) agree; 86 markdown files scanned for undeclared copies.
|
| `pnpm check:watch-hint-literal` | 0 | ✓ check-watch-hint-literal: 71
declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 47,
ROOT_FILE_ |

Also run on this head, named by the dispatch and outside the derived
list: `pnpm check:skill-frame-freshness` exit 0 · `pnpm
check:pm-governed-prose` exit 0. The doc-formula gate measured only
after `@objectstack/lint` and its closure were built through
`scripts/pm/os-verify-lock.sh` (VERDICT command-exit 0). `--ran`
reconciliation: ✓ dispatch-gates --ran: 20 derived famil(ies) accounted
for — 20 run, 0 NOT-MEASURED (a DERIVED zero — all 20 recorded an exit
code and none of them is 3).

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

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…s; H43/H48 stand down on Tier S (objectstack-ai#19802)

Part of objectstack-ai#19146

Clause-②: no

## 维护者速读(草稿)

**改了什么**:两处。① `.claude/agents/os-dev.md` :286–:287 两行(净 0
行,402/402)从已废止的「事实层 = `references/` 目录、余为规则层」改写成登记表现行的两层:受管路径全在
`.claude/**` 者 Tier S,达档复核 PASS 在案即由席位入队落地;余皆 Tier H 等人批;`## 维护者速读(草稿)`
两层同欠(第二行不再豁免「事实层」)。② `scripts/pm/check-half-states.mjs` 的 H43(受管 PR
未向授权账户请审)与 H48(ACCEPT 后缺 `needs-user-decision` 标签或速读评论)在 Tier S PR
上停手:懒加载的登记表多带出 `landingTierOf` 与 `GOVERNED_TIER_S`,一个
`governedLandsOnRecord` 助手在两行已匹配的切片上问登记表,S 则不判;混合 diff 有一条 Tier H
命中仍判;登记表没加载则一律不停手。自测新增 15 例(4897 → 4912),用真实登记表自己的切片驱动;⛔ 不新增巡查行、不新增电池。

**为什么改**:这两行是每个 dev 子代理都读的自我定义,写的是 2026-09-18 分层裁决之前的边界;H43/H48 在 Tier S
PR 上开的处方(请授权账户审、挂维护者收件箱标签)正是裁决取消的那一下点击,且 H43 的理由句「队列守卫仍拒收未批准的受管入队」对 Tier
S 为假(PR objectstack-ai#19351 零批准、凭复核记录经队列落地)。

**风险与代价(含回滚)**:文字面零行为变化。H43/H48 在 Tier S PR 上不再报告——这是裁决的意图,不是丢失:Tier S
的落地由队列守卫按 `## Contract review` 记录把关。Tier H 与混合 diff 的行为字节不变;登记表缺席时仍照旧报
NOT MEASURED。消融证明:把 tier 读取删掉,5/4912 例转红,还原后 blob == HEAD。回滚 = revert
两个提交(各一类,可单独回退)。

**席位意见**:(席位填写)

**你要做的**:本 PR 为 Tier S(`.claude/**`),由归属席位在 `## Contract review` PASS 记录
+ 全绿后经队列落地,⛔ 不需要您点击。卡上余项一条(`SKILL.md:618`,见下方 On the card),由 skills
席位自处置。

## Summary

The two `os-dev.md` lines still spelled the pre-tiering split (fact
layer = the `references/` directory, everything else rules layer). They
are re-keyed to the register's rule as `AGENTS.md` Prime Directive objectstack-ai#14
states it: a PR whose governed paths ALL lie under `.claude/**` is Tier
S and lands on the owning seat's `## Contract review` record; every
other governed surface is Tier H and waits for the maintainer's word.
The maintainer-brief draft is owed on both tiers (SKILL.md :623 has no
tier split; the seat fills 席位意见 on both), so the second line simply
stops exempting a "fact layer".

The card also names `check-half-states.mjs` H48 and H43. Measured on the
base: both rows still exist and are tier-blind (`governedTierFor` /
`landingTierOf`: 0 hits in the file; H43 reads `GOVERNED_APPROVERS`
only). On a Tier S PR each remedy asks for the click the tiering
removed, so both stand down there. The tier is the register's own answer
on the slice the matcher already returned — no second list of surfaces
lives in the patrol.

## Per-site before → after

### `.claude/agents/os-dev.md` (402 → 402 lines, net 0; both lines
within the 120-byte cap)

| line | before | after | bytes |
|---|---|---|---|
| :286 | 「- 受管路径全在 `.claude/skills/pm-dispatch/references/`
者为事实层,席位复审即记录;余为规则层。」 | 「- 受管路径全在 `.claude/**` 者 Tier S,达档复核 PASS
在案即由席位入队落地;余皆 Tier H 等人批。」 | 118 → 120 |
| :287 | 「- 规则层 PR 正文带 `## 维护者速读(草稿)` 节,中文、业务角度,席位意见留空;事实层不欠。」 | 「- 受管面
PR 正文带 `## 维护者速读(草稿)` 节,中文、业务角度,席位意见留空;两层同欠。」 | 117 → 114 |

The rule they now mirror: `AGENTS.md` :272–:280 (Tier H = `docs/adr/**`,
`docs/NORTH-STAR.md`, `skills/**`, `AGENTS.md`, `CLAUDE.md`, an
authorized APPROVED review; Tier S = all of `.claude/**`, a `## Contract
review` record for the current head with `Served-tier:
CONTRACT_REVIEW_TIER` and a PASS verdict, the owning seat lands it
through the queue) and SKILL.md :623 (「草稿归 dev:受管面 PR 正文带 `##
维护者速读(草稿)`」, no tier split). `grep -n 事实层 .claude/agents/os-dev.md` on
the head: 0 hits.

### `scripts/pm/check-half-states.mjs` (H43 / H48)

| site | before | after |
|---|---|---|
| `loadGovernedRegister` | reads `governedPathsIn` +
`GOVERNED_APPROVERS` | also reads `landingTierOf` + `GOVERNED_TIER_S`
(`tierOf`, `recordTier`); a register missing any of the four is "did not
export what this row reads", as before |
| new `governedLandsOnRecord(governed, register)` | — | `true` only when
the register is available AND `landingTierOf(slice) ===
GOVERNED_TIER_S`; `false` for a Tier H or mixed slice, an empty or
tier-less slice, or an unloaded register |
| `h43NeedsReviewProbe(pr, governedCount, approvers)` | took a COUNT |
takes the matched SLICE, stands down on Tier S — a Tier S PR buys no
review page and takes no slot under the oldest-first cap |
| `h43GovernedReviewRequestGap` | fired on every governed PR short of
coverage | `null` on a Tier S slice; the sentence reads "open and
GOVERNED on Tier H" and "refuses an unapproved Tier H enqueue" |
| `h48SpeaksAbout` | population = governed ∧ open | ∧ not Tier S — so
`h48GovernedVerdictWithoutBrief` is `null` there and the sweep buys no
PR comment thread for it |
| H43 / H48 headers, both summary clauses | tier-blind prose | name Tier
H as the population; Tier S stated as out |
| sweep call site | `h43NeedsReviewProbe(pr, governedByPr.get(n)?.length
?? 0, …)` | `h43NeedsReviewProbe(pr, governedByPr.get(n) ?? [], …)` |

Self-test: 15 new `t()` cases (no new battery, no floor moved): the Tier
S and mixed slices come from `GOVERNED_REGISTER.matcher(...)` on the
real register, so the tier answer is the register's; the hand-built
`GOV43` / `GOV48` fixtures carry no `tier` and read as H (fail closed),
which the comments now say. Register pin extended:
`tierOf(matcher(['.claude/agents/os-dev.md'])) === recordTier`. Case
counts: 4897 on the base → 4912.

Why stand down rather than re-aim: the card offered both. Re-aiming H43
at "a Tier S PR without a review of record" would be a new patrol row in
disguise (新增门禁默认否), and the queue guard already refuses a Tier S enqueue
without the record — nothing ships through that gap. Standing down is
the minimal, mechanical repair the card's item 3 spells for H48 and it
is the same change class for H43, so the two ride together.

## Measurement the change rests on (reads taken 2026-09-23T05:24Z–05:36Z
against `origin/main` = `2cf9db7c4`; each item names its own clock)

- 2026-09-23T05:24Z — `.claude/agents/os-dev.md` :286–:287 read
byte-identical to the card's quotation (premise valid).
- 2026-09-23T05:25Z — `check-half-states.mjs` @ `2cf9db7c4`: H48 row at
:10888–:11100, H43 row at :9607–:9850; `governedTierFor` /
`landingTierOf` / `recordTier`: 0 hits in the 34,841-line file;
`GOVERNED_APPROVERS` is H43's only firing control. PR objectstack-ai#19737 retired
H31/H35/H51/H53/H61 and left both rows in place.
- 2026-09-23T05:30Z — the seat's practice on a landed Tier S PR (objectstack-ai#19351,
all `.claude/**` + `scripts/pm/`): 0 reviews, no review request, no
`**ACCEPT**` on the thread, no `needs-user-decision`, no `## 维护者速读`
comment — one `## Contract review` PASS record, landed through the
queue. H43's shape fires on exactly that PR; it fired on objectstack-ai#19379 too
(card comment 5750573385).
- 2026-09-23T05:36Z — register verdict on this PR's two paths:
`check-governed-merges.mjs --test` → `GOVERNED — Tier S(席内达档复核落地)`, exit
3 (= EXIT_TEST_GOVERNED); `scripts/pm/check-half-states.mjs` is not on
the register.
- 2026-09-23T05:25Z — no open PR touches either file (all 16 open PRs'
file lists read over REST at claim time).

## Reverse verification (ablation), run 2026-09-23T05:37Z at head
`bd5bbd2bb` (the file is byte-identical at `c9617adde`)

`node scripts/ablation-replace.mjs --file
scripts/pm/check-half-states.mjs --anchor ' return register.tierOf(list)
=== register.recordTier;' --replacement ' return false; // ABLATION:
tier reading removed' -- node scripts/pm/check-half-states.mjs
--self-test`

- mutation landed on disk: anchor 1 → 0, marker 0 → 1, blob
`d2d9ba38ac63` → `52c8e2e35f0d`
- direction observed: RED — `✗ check-half-states self-test: 5 of 4912
case(s) failed` (the H43 Tier S clean case, the H43 Tier S probe case,
the register-answer join case, the H48 Tier S population case, the H48
Tier S no-finding case); the mixed-slice controls stayed green
- restore proven: blob after restore `d2d9ba38ac63` == blob at HEAD;
`git diff HEAD` empty; re-read on the absolute path: anchor 1, marker 0
- no `dist/` is involved (the patrol runs from source), so no build leg

## Gates on the final head `c9617adde` (run 2026-09-23T06:02Z–06:19Z;
exit codes captured before any pipe; verdict lines from the gate logs)

Derived with `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` on this head (47 commands, list
identical to the derivation at `bd5bbd2bb`); `--ran` reconciliation: `✓
dispatch-gates --ran: 47 derived famil(ies) accounted for — 46 run, 1
NOT-MEASURED (1 DERIVED from a recorded exit 3).`.

| # | command | exit | verdict line (from the gate log) |
|---|---|---|---|
| 01 | `node scripts/check-ci-filter-parity.mjs` | 0 | OK: all 185
declared cross-package glob(s) (132 unique) are covered by `core` or
`crosspkg`, every `crosspkg` entry still covers one, and the `test` j |
| 02 | `node scripts/check-closing-keyword-parity.mjs` | 0 | •
packages/spec/CHANGELOG.md -- 6080503 bytes exceeds the sweep's
2097152-byte cutoff for UNREGISTERED files |
| 03 | `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 |
✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations
of the shipped parsers each driven to red. |
| 04 | `node scripts/check-comment-mask-corpus.mjs` | 0 | ✓ comment-mask
corpus sweep [scripts/js-comment-mask.mjs]: 7015 files, 0 disagree, 0
unparseable, 60.0s (comparator self-test: 26 cases pass). |
| 05 | `node scripts/check-declaration-mirrors.mjs` | 0 |
scripts/invoked-as.d.mts |
| 06 | `node scripts/check-declaration-mirrors.mjs --self-test` | 0 |
All 29 self-test cases passed. |
| 07 | `node scripts/check-scripts-symbol-anchors.mjs` | 0 | ✅
check-scripts-symbol-anchors: 3684 anchors across 280 scripts resolve —
52 symbol (52 declaration, 0 literal), 3632 file-level, 0 cross-repo, 1
exem |
| 08 | `node scripts/check-scripts-symbol-anchors.mjs --self-test` | 0 |
✅ check-scripts-symbol-anchors --self-test: every finding class
provoked, comment-prose projection wired, declined shapes counted not
missed, allowanc |
| 09 | `node scripts/check-self-test-wired.mjs` | 0 | ✓
check-self-test-wired: every one of the 229 script(s) CI runs that ship
a `--self-test` has that self-test run by CI. |
| 10 | `node scripts/check-self-test-wired.mjs --self-test` | 0 |
check-self-test-wired --self-test: 3 live ledger row(s) verified, plus
the comment mask, the right boundary, alias resolution and both audit
direction |
| 11 | `node scripts/check-self-test-workflow-commands.mjs` | 0 | scope:
229 script(s) CI runs ship a `--self-test` (0 of them package-local
gate(s) CI names by path, present because this population is the one
chec |
| 12 | `node scripts/check-self-test-workflow-commands.mjs --self-test`
| 0 | check-self-test-workflow-commands --self-test: both measured parse
rules pinned (legacy form anywhere in a line, current form only at line
start), the |
| 13 | `node scripts/check-whole-set-label-write.mjs` | 0 | PROSE_PROBES
make `run()` refuse rather than pass if it ever stops finding them. |
| 14 | `node scripts/check-whole-set-label-write.mjs --self-test` | 0 |
✓ check-whole-set-label-write --self-test: all cases pass (24 fixture
trees + 5 refusals + 1 allowlist hatch) |
| 15 | `node scripts/pm/bare-root-worklist.mjs --self-test` | 0 | OK
self-test: 81 live row(s), 59 unreachable as spelled, 46 recorded
verdict(s) — none stale, none missing, none contradicted (12 row(s)
whose gate c |
| 16 | `node scripts/pm/board-snapshot.mjs --self-test` | 0 | OK
board-snapshot self-test: 156 cases pass across 12 batteries (open-first
walk order, the delta-first run order and its budget split driven end to
e |
| 17 | `node scripts/pm/check-governed-queue-guard.mjs --self-test` | 0
| ✓ check-governed-queue-guard self-test: 279 cases pass
(register-driven verdicts, the queue/PR event split, latest-decisive
approval reduction, the 20 |
| 18 | `node scripts/pm/check-harness-current.mjs --self-test` | 0 |
check-harness-current --self-test: all 26 cases passed. |
| 19 | `node scripts/pm/sweep-closed-cards.mjs --self-test` | 0 | ✓
sweep-closed-cards self-test: 87 cases pass across 9 batteries (the
imported residue set, the offline screen, the two closing routes with
the measur |
| 20 | `pnpm --filter @objectstack/lint run
check:doc-formula-expressions` | 3 | Exit status 3 |
| 21 | `pnpm check:agent-model-declared` | 0 | ✓
check-agent-model-declared: 1 agent definition(s) under .claude/agents/
all declare a model |
| 22 | `pnpm check:agent-test-spelling` | 0 | ✓
check-agent-test-spelling: 0 violations — 560 file(s) · 9601 bare `--`
token(s) · 1810 launcher-rooted run(s) · 13 separator(s) JUDGED · 6
vitest-ba |
| 23 | `pnpm check:bash32-floor` | 0 | ✓ check-bash32-floor: 33 tracked
shell file(s) under scripts/**, .claude/hooks/**, .githooks/** name no
bash 4+ construct outside a comment, a guarded |
| 24 | `pnpm check:cli-command-ids` | 0 | ✓ check-cli-command-ids: 63
module(s) under packages/cli/src/commands examined, all of them
default-export a class whose inheritance chain reaches ocl |
| 25 | `pnpm check:closing-target-claim` | 0 | ✓
check-closing-target-claim self-test: 105 cases pass. |
| 26 | `pnpm check:commit-card-trailers` | 0 | ✓
check-commit-card-trailers self-test: 81 cases pass. |
| 27 | `pnpm check:cross-package-test-inputs` | 0 | All 255 self-test
cases passed. |
| 28 | `pnpm check:doc-authoring` | 0 | ✓ doc authoring guard:
sibling-package prose ids hold the baseline — 819 pinned site(s) across
231 file(s), 90595 string(s) read in 1247 parsed source |
| 29 | `pnpm check:driver-memory-census` | 0 |
check-driver-memory-census: OK — every declaration is ledgered, every
ledger entry is live, and every ruled file states "objectstack-ai#6664 census: 2 ruled
consume |
| 30 | `pnpm check:entry-guard` | 0 | ✓ check:entry-guard: 280 scripts/
file(s) — every entry guard goes through invoked-as.mjs; 219 export
bindings, 219 of them inert on import (0 known-u |
| 31 | `pnpm check:gitlink-declared` | 0 | ✓ check-gitlink-declared
--self-test: 36 assertions over throwaway git repos (real scan() path) |
| 32 | `pnpm check:issue-citations` | 0 | ✅ check-issue-citations
--self-test: grammar narrowed, four 404 causes kept apart, both board
strategies agree, diff scope red AND green, scope contra |
| 33 | `pnpm check:nul-bytes` | 0 | ✓ check-nul-bytes --self-test: 75
assertions over a temp git repo (real scan() path) |
| 34 | `pnpm check:parse-guard` | 0 |
packages/cli/test/published-subpath-hook-body.pin.test.ts:417
ts.createSourceFile |
| 35 | `pnpm check:partof-closing-keyword` | 0 | ✓
check-partof-closing-keyword self-test: 45 cases pass. |
| 36 | `pnpm check:pm-governed-merges` | 0 | ✓ check-governed-merges
--self-test: 441 assertions (the unified governed predicate + near
misses, subject→PR spellings, window parsing, the objectstack-ai#12633 la |
| 37 | `pnpm check:pm-half-states` | 0 | ✓ check-half-states self-test:
4912 cases pass. Batteries: H66 released queue card 182/172, H19
judged-set founding 37/34, H65 tier declaration spelli |
| 38 | `pnpm check:pm-post-stamped` | 0 | ✓ post-stamped self-test: 610
cases pass across 21 batteries — offline, no network, no token. |
| 39 | `pnpm check:pm-skill-id-lint` | 0 | ✓ check-skill-id-lint: 30
file(s) clean (pattern /#[0-9]{3,}/g). |
| 40 | `pnpm check:pm-skill-ratchet` | 0 | ✓ check-skill-line-ratchet:
declared cross-file moves: 1, total ceilings down 9 lines. |
| 41 | `pnpm check:pnpm-filter-targets` | 0 | ✓
check:pnpm-filter-targets: 152/207 `--filter` occurrence(s) across 41
file(s) resolve against 81 workspace package(s); 55 not judged (2
foreign, 30 |
| 42 | `pnpm check:ratchet-remedy-authority` | 0 | OK self-test: the
lexer holds, messages are bounded, both offer word orders and path-named
registries are reached, declaration registries are not, th |
| 43 | `pnpm check:refd-timer-probe` | 0 | ✓ check-refd-timer-probe
self-test: 11 cases pass, negative controls included. |
| 44 | `pnpm check:single-claim-paths` | 0 | ✓ check-single-claim-paths
self-test: 93 cases pass. |
| 45 | `pnpm check:skill-frame-sync` | 0 | ✓ check-skill-frame-sync: the
one declared copy of the decision frame is internally coherent
(.claude/skills/pm-dispatch/SKILL.md; no second copy to c |
| 46 | `pnpm check:watch-hint-literal` | 0 | ✓ check-watch-hint-literal:
71 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 47,
ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECL |
| 47 | `pnpm check:pm-dispatch-gates` | 0 | ✓ dispatch-gates self-test:
1905 cases pass. (738.5s on this box) |

Row 20 is exit 3 = PREREQUISITE NOT MET (the gate's own NOT-MEASURED
code, see Acceptance notes); every other row exit 0. The same 47 ran at
`bd5bbd2bb` with the same readings before the merge of `origin/main`.

## Line budget

- `.claude/agents/os-dev.md`: 402 / ceiling 402 before and after
(headroom 0, net 0 lines); `check:pm-skill-ratchet` exit 0 on the head.
Max content bytes per line 120 before and after.
- `skills/**` (the published catalog) is not touched, so no whole-file /
whole-package token readings are owed.
- `.claude/**` and `scripts/pm/**` publish nothing from any package's
`files[]` (fast lane), so `skip-changeset` applies and no changeset is
written.

## On the card

- `landing-operations.md` :27–:28 and the queue guard's SUCCESS line:
landed by PR objectstack-ai#19379 (merged `1f53b0b685`); the guard's :236 hit is a
verbatim ruling quotation and stays.
- `os-dev.md` :286–:287, H48, H43: this PR.
- REMAINDER, measured on `origin/main` at `fae870352` and not in this
PR's claimed file surface: `.claude/skills/pm-dispatch/SKILL.md:618`
(the size clause ending 「⛔ 无事实层例外」) still spells the retired word (the
skills seat's addendum 5737973707 joined it to this card), and 「规则层」
survives as a synonym for Tier H at `SKILL.md:617`,
`references/core-rules.md:122`, `references/landing-operations.md:26`
and `references/lanes/skills.md:17` (vocabulary only; each rule stays
true). That is why the first line is `Part of` rather than a closing
keyword: objectstack-ai#19146 remains open after this PR merges, with its own addendum
item still owed. The dispatch asked for a closing first line on the
premise that the two `os-dev.md` lines were the whole remainder; the
tree-wide grep says otherwise, and os-dev.md's rule (a PR whose merge
should not close the card uses `Part of`) wins.

## Acceptance notes (observations, not filed)

- `check-half-states.mjs` H48's sentence still says the handoff exists
because "a Tier H surface lands only on the maintainer's word" —
accurate for Tier H under PD objectstack-ai#14 (the maintainer's hand or an authorized
approval); the pre-existing "by hand" wording was narrowed to that in
the same edit.
- `pnpm --filter @objectstack/lint run check:doc-formula-expressions`
answers exit 3 PREREQUISITE NOT MET in this worktree (the gate needs
`@objectstack/formula` / `@objectstack/lint` built; this diff touches no
package, so no build closure is owed). Recorded as NOT MEASURED, not as
a failure; its population (docs formula expressions) is disjoint from
both changed paths.
- Landing: Tier S — draft stays draft; the owning seat renders the `##
Contract review` record for head `c9617adde` and lands it through the
queue after every check is green.

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

---------

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

Labels

ci/cd documentation Improvements or additions to documentation needs-user-decision size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants