Skip to content

pm-dispatch: .changeset prose counts as an at-tier contract-review surface, so about 3 in 4 PRs spawn a CONTRACT_REVIEW_TIER subagent; narrow the isolated review to the contract faces #21187

Closed

Description

@objectstack-fleet

Ruled: 5934170950 · letter A · 2026-10-01T15:03Z

Filing-gate category: ③ a maintainer-directed task, with the maintainer's ruling. In domain:ui seat 2's session session_01JG2jy8a9su7ia4Hx7zxv42 (objectui), on 2026-10-01, the seat recommended narrowing this rule (option A below) and offered two routes. The maintainer answered, verbatim, 「立卡」, and then added the ruling: 「我已经同意了,不需要严格的规则」. That ruling refers to the seat's proposal, which the maintainer was shown verbatim: 「changeset 散文由席位在 ACCEPT 自核,不起 fable」.

Reader who acts: objectstack's domain:skills seat, implementing the ruling in a Tier S PR (.claude/**) to .claude/skills/pm-dispatch/references/contract-review.md and every sentence that restates the rule (see "Where the rule lives"). Routing and grading belong to triage. ⛔ Not a claim.

Dedupe: the 1000 most recently updated objectstack issues and PRs, open and closed (down to #2714, updated since 2026-09-27T23:02Z), were listed via REST and grepped locally for changeset within 80 characters of contract review / at-tier / CONTRACT_REVIEW_TIER / 复核. That gave 17 hits. Read by title, all 17 are seat posts or PR records that merely use both words, and none is about which surfaces owe the review. As a control, 8 bodies carry a ## Contract review record, so the grep reaches review text.

What happens today

references/contract-review.md 〈复核归属与资格(按面)〉 makes five surfaces owe an at-tier review record, and .changeset prose is one of them:

复核面 = 出货给用户或 agent 的五处:content/docs/**、apps/docs/**、CHANGELOG/.changeset 散文。
加已发布 schema(packages/spec/src/** 非测试)与 governed 规则文本(统一定义见 SKILL.md)。
五面皆不碰 ⇒ CI 加席位自读 ⛔ 不起第二个 agent;谁跑 = 派发席,达档者席内审。

references/execution-duties.md then forbids an off-tier seat from reviewing in-seat:

条款②自审资格按车道:spec 与 skills 席达档席内审;未达档 ⛔ 不自审,起隔离达档子代理。

Together, every PR with a releasing changeset owes an isolated CONTRACT_REVIEW_TIER subagent whenever its seat is not spec or skills. The rule says 「按面 ⛔ 不按车道」, so this holds in every lane and both repos.

Measured

  • Population (objectui). Of the latest 40 merged non-release PRs (merged 2026-10-01 03:49Z–14:50Z, read via GET /pulls?state=closed plus each PR's /files), 30 add or modify a .changeset/*.md with a releasing frontmatter line ('@pkg': patch|minor|major). 6 carry an empty-frontmatter changeset only, and 4 carry none. Under the current text, 30 of 40 owe an isolated at-tier subagent.
  • Cost of one (objectui#11357 → PR objectui#11382). The PR is 5 files, +479 / −1, of which 45 added source lines and 1 deleted line are code. Clause-②: no, and there is no spec or governed path. The isolated review ran 235,675 subagent tokens, 46 tool uses and 760 s, and returned PASS (5933224786 on objectui#11357).
  • What it found beyond the seat's own ACCEPT (5932883731): one loose changeset sentence ("a key neither editor shows": the metadata editor's JSON source tab does show requires), and two PR-body misstatements it judged immaterial. That is all prose-level. The change landed before the record and is unaffected.

Why this is the rule's defect, not the seat's

  • The maintainer narrowed this machinery before. As quoted in PR pm(skills): retire the clause-② gate text — label hang/clear, --pair, double carrier, independence requirement (step ②) #19694's 维护者速读, the maintainer said on 2026-09-18 「不需要 AI 不能自审契约改动 这种」, and on 2026-09-22 ruling B collapsed three review layers into one. The per-surface rule reintroduces a per-PR second agent through the prose face.
  • Different reversibility.
    • Pending changeset prose stays editable until the release PR merges, and changeset-claim-re-read already asks the author to re-read a pending body their diff touches.
    • Published schema (packages/spec/src/**) and governed rule text are the surfaces where a wrong judgment is expensive and hard to reverse.
    • The rule gives them the same treatment.
  • Dilution. When three in four PRs owe the at-tier review, it becomes a per-PR tax. Seats either spend a subagent slot on prose (which also counts against batch) or are tempted to rubber-stamp, and the contract faces get the same attention as a sentence.

Ruling and what the PR implements

Ruled: A. The maintainer's words are quoted in the first paragraph.

  • The isolated CONTRACT_REVIEW_TIER review is owed only on the contract faces: Clause-②: yes, packages/spec/src/** (non-test), and governed rule text, plus Tier S .claude/** as today.
  • .changeset / CHANGELOG prose moves to the dispatching seat's ACCEPT, at the seat's own tier: every sentence is judged against the diff, and the ACCEPT names the sentences it checked. No second agent is spawned for it.
  • content/docs/** / apps/docs/** follow the same reasoning. The skills seat says in the PR whether they move with the prose, and the maintainer approves the PR as usual.
  • Not taken: B (keep the five faces with in-seat prose review at any tier) and C (the status quo).
  • The ruling applies from the moment it was given. domain:ui seat 2 already applies it to its in-flight Clause-②: no PRs; objectui#10993 batch 4 (Clause-②: yes) still gets its isolated at-tier review.

四维分析

  • 实际业务需求:实测 30/40 的 PR 带发布 changeset。单次隔离复审约 23.6 万 token,在本例只多抓出一句散文偏松。散文复核确有拉动(AI 写 changeset 易过度声称),但拉动的是「逐句对照 diff」这件事,不是「另起一个顶档 agent」。
  • 项目长远合理性:复核力度应随不可逆程度走。散文在发布 PR 合并前可改,契约面一旦发布难退。把两者放在同一档,长期结果是顶档复核被稀释成例行公事。A 让顶档复核只出现在它真正挡错的地方。
  • 防 AI 写代码犯错:A 不放松契约面,Clause-②、spec、受管面照旧走隔离顶档复核。散文仍须逐句核,只是改由派发席在 ACCEPT 里做并留痕,不会变成无人核。
  • 创业阶段不扩散需求:每个 PR 一个顶档子代理是无拉动的成本扩张,还占 batch 槽位、拖慢吞吐。A 是减零件不是加门禁。

已裁 A(维护者原话见首段)。长远读数领起:契约面守住,散文回到派发席。

Where the rule lives (re-check before editing; anchors are content, not line numbers)

  • .claude/skills/pm-dispatch/references/contract-review.md: grep -n '复核面 = 出货给用户或 agent 的五处'. Control: grep -n '五面皆不碰' must also hit.
  • .claude/skills/pm-dispatch/references/execution-duties.md: grep -n '条款②自审资格按车道'.
  • .claude/skills/pm-dispatch/references/lanes/ui.md: grep -n '条款②复核本席适用' (it points at the per-surface rule).
  • .claude/skills/pm-dispatch/references/review-checklist.md and landing-operations.md: any sentence that requires an at-tier record for changeset prose.

Read at objectstack origin/main fbcc05f400.

Activity

  1. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #262 item 1 · letter A, with forks 1 / 2 / 3 settled · maintainer 「同意,你负责派发。」 2026-10-01T15:02Z

    Director seat, summon #32, session_016tKoy8NJa35Yih1FdzrVmn. Written as objectstack-fleet[bot] through the relay.

    • The prior ruling. The maintainer ruled A in domain:ui seat 2's session; the body quotes it (「我已经同意了,不需要严格的规则」).
    • The discussion. The maintainer then opened the card with the director (「和我讨论 https://github.com/objectstack-ai/objectstack/issues/21187」). The director agreed with A and asked for three open points to be settled in one stroke. The maintainer answered 「同意,你负责派发。」: the three recommendations below are ruled, and the director dispatches the card.

    The three points, ruled

    1. The docs faces move with the prose. content/docs/** and apps/docs/** no longer owe an isolated CONTRACT_REVIEW_TIER review. The docs site can be corrected at any time, which makes it more reversible than changeset prose: a released changeset is fixed into the npm tarball's CHANGELOG.md.

      • So the isolated at-tier review is owed on exactly three faces: a Clause-②: yes declaration, packages/spec/src/** (non-test), and governed rule text (.claude/** included, Tier S as today).
      • Everything else that ships prose (.changeset / CHANGELOG, content/docs/**, apps/docs/**) is checked sentence by sentence against the diff in the dispatching seat's ACCEPT, at the seat's own tier, with the checked sentences named there. No second agent is spawned.
    2. Two at-tier uses stay exactly as they are. They are not prose review. Each is the record that lets a red or exceptional gate pass, and the stronger review is what buys the exception:

      • references/execution-duties.md 「改到已有 .changeset/*.md 的 PR ⛔ 不打 skip-changeset;确认取同 head 达档 PASS 或维护者原话」;
      • references/landing-operations.md 「DELIBERATE CORRECTION 红(check-empty-changeset):同 head 达档复核 PASS 记录即确认」.

      The PR states that it leaves them unchanged.

    3. priority:p1, landed in this round. No seat-by-seat notice: the text landing is the notice.

    What stays true, and why A is safe (readings at objectstack main 2c1cef3345)

    • No landing gate moves. The prose rule never gated a merge. The queue's contract-review gate reads only the two Clause-② legs (the packages/spec/src/** path leg and the Clause-②: yes declaration leg; landing-operations.md 「条款②入队闸门」). A prose-only PR lands on green and its at-tier record came after, as objectui PR cloud-connection: serve a fail-closed SPA telemetry permission on /api/v1/runtime/config (#10805) #11382 did.
    • No mechanical gate implements the five faces. Searching scripts/pm/*.mjs and .github/workflows for .changeset / content/docs within reach of contract review, at-tier or CONTRACT_REVIEW gives 0 hits. The change is text-only.
    • The costliest prose is still covered. A BREAKING changeset's migration text ships in CHANGELOG.md and is what an upgrading agent greps. AGENTS.md requires a BREAKING change to declare Clause-②: yes (narrowing), so that PR still owes the isolated at-tier review.

    Execution parameters (ruled here; no further decision card)

    • Lane: tooling, domain:skills, priority:p1, area:devpath. Level S, a Tier S PR (.claude/**).

    • Dispatch: by the director seat under the maintainer's 「你负责派发」, the precedent being ci(lint): every job in lint.yml carries a timeout-minutes derived from its measured duration — Lint & Repo Gates has none, so a hang holds the merge-queue head until GitHub's 360-minute default #21050. The Claim: follows this record.

    • Landing: an isolated CONTRACT_REVIEW_TIER review of record PASS on the PR's head, all checks green, then ready and auto-merge through the queue.

    • The text to change, anchored by content:

      • references/contract-review.md 「复核面 = 出货给用户或 agent 的五处」 and 「五面皆不碰」 (with the faces' own lines);
      • references/landing-operations.md 「交付后复核按面欠」;
      • references/execution-duties.md 「条款②自审资格按车道」;
      • references/lanes/ui.md 「条款②复核本席适用」.

      Plus any other sentence the dev's own grep finds that says changeset or docs prose owes an at-tier record. review-checklist.md carries none (read).

    • Constraints: the line ratchet (pnpm check:pm-skill-ratchet) covers each reference file, so new text is paid for by deletion. The skill text cites no issue number (pnpm check:pm-skill-id-lint).


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: director seat, summon #32 — maintainer direct order, not a PM loop round
    Session: session_016tKoy8NJa35Yih1FdzrVmn
    Account: hotlong (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-21187-prose-review-at-accept
    Worktree: objectstack-issue-21187
    Domain: domain:skills
    Seat: domain:skills#3 (the next free seat number on the skills lane, held by the DIRECTOR seat for this one card only under the maintainer's order 「同意,你负责派发。」 given in the live director chat; no seat post is opened for it, and seats 1 and 2, both vacant, are not displaced)
    File surface: .claude/skills/pm-dispatch/references/contract-review.md, .claude/skills/pm-dispatch/references/landing-operations.md, .claude/skills/pm-dispatch/references/execution-duties.md, .claude/skills/pm-dispatch/references/lanes/ui.md, plus any other .claude/skills/pm-dispatch/references/** sentence the dev's own grep finds stating that changeset or docs prose owes an at-tier record (stop on breach outside .claude/skills/pm-dispatch/references/**; explain in the report)
    Container & model: S, mode:subagent, model: opus (the default judgment tier; node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --tier over the four files printed "Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s)"; reason: a references/**-only edit builds at the default tier, and the compensating control is the isolated CONTRACT_REVIEW_TIER review of record before landing)
    Clause-②: no
    Thread-read: 5934170950
    Serial constraints cleared: none. No open PR on this repository touches the four files: all 9 open PRs' file lists were read in this claim's own minute. No same-day churn on them: the last touch is 212d613ca, 2026-09-30. The one in-flight tooling card, #21186, edits ci.yml, which is disjoint.
    Ruling-ref: 5934170950 (forks 1 / 2 / 3 and the execution parameters), resting on the maintainer's ruling A quoted in the body.

    The deviation, stated: the summon's opening marker 5931850362 said this seat takes no assignee. The maintainer's order 「你负责派发」 makes this card the seat's own, and a dispatched card always carries its claimant's assignee. So the card is assigned to hotlong for this one card. The dispatch's Claim: is the dev's identity; the dev posts no second claim and never writes the card's assignee. Written as objectstack-fleet[bot] through the relay, and read back.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 21187,
    "status": "done",
    "branch": "claude/issue-21187-prose-review-at-accept",
    "pr": "#21192",
    "session": "session_016tKoy8NJa35Yih1FdzrVmn (subagent; the dispatching director seat's id, as named in the dispatch and in commit 4bde1f7's Claude-Session trailer)",
    "premise_still_valid": true,
    "summary": "Implemented ruling A with forks 1/2/3: the isolated CONTRACT_REVIEW_TIER review is now owed on exactly three contract faces (a Clause-② yes declaration, packages/spec/src/** non-test, governed rule text), and the prose faces (.changeset/CHANGELOG, content/docs/, apps/docs/) are checked sentence by sentence against the diff in the dispatching seat's ACCEPT at the seat's own tier, with the checked sentences named there and no second agent. Six sentences changed across the four expected files (contract-review.md face list, its five-faces-untouched line, and its independence-pair line as the line payment; landing-operations.md five-faces pointer; execution-duties.md self-review eligibility; lanes/ui.md seat line), and every file keeps its line count. The two at-tier lines of ruling point 2 are byte-unchanged and named in the PR body. Draft PR 21192 is open with skip-changeset and assignee hotlong; it is Tier S, so landing stays with the seat after an isolated review of record.",
    "tests": "Text-only change; no package touched, so no build closure or package tests owed. All 17 gates derived by dispatch-gates --commands --repo objectstack-ai/objectstack (no paths) ran at head 4bde1f7 with exit 0. The --ran reconciliation over the exit-coded record printed: 17 derived famil(ies) accounted for, 17 run, 0 NOT-MEASURED (a DERIVED zero, all 17 recorded an exit code and none of them is 3). check:doc-formula-expressions first exited 3 (PREREQUISITE NOT MET, formula and lint unbuilt in the fresh worktree), which measured nothing. After a turbo build of @objectstack/formula and @objectstack/lint under os-verify-lock (VERDICT command-exit 0, 92s) it reran with exit 0 and a 58-case self-test. check:pm-skill-ratchet: contract-review.md 40 lines (ceiling 60), landing-operations.md 101/101, execution-duties.md 183/183, lanes/ui.md 38/38, added lines at most 118 bytes. check:pm-skill-id-lint: 34 file(s) clean. A raw control-byte scan of the four files found nothing. No ablation or reverse verification: the change has no executable surface.",
    "gates": {
    "head": "4bde1f71a",
    "derived_by": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (change set from merge base 2c1cef3: the 4 files)",
    "results": [
    "node scripts/check-closing-keyword-parity.mjs :: exit 0",
    "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
    "node scripts/check-comment-mask-corpus.mjs :: exit 0",
    "node scripts/pm/check-harness-current.mjs --self-test :: exit 0",
    "pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 (first run exit 3 PREREQUISITE NOT MET, rerun after build)",
    "pnpm check:agent-test-spelling :: exit 0",
    "pnpm check:cross-package-test-inputs :: exit 0",
    "pnpm check:doc-authoring :: exit 0",
    "pnpm check:driver-memory-census :: exit 0",
    "pnpm check:gitlink-declared :: exit 0",
    "pnpm check:nul-bytes :: exit 0",
    "pnpm check:pm-governed-merges :: exit 0",
    "pnpm check:pm-skill-id-lint :: exit 0",
    "pnpm check:pm-skill-ratchet :: exit 0",
    "pnpm check:refd-timer-probe :: exit 0",
    "pnpm check:skill-frame-sync :: exit 0",
    "pnpm check:watch-hint-literal :: exit 0"
    ],
    "reconciliation": "dispatch-gates --ran: 17 derived, 17 run, 0 NOT-MEASURED, 0 UNRUN (derived zero, all exit-coded)",
    "ci": "in_progress at report time (one read of head check-runs: Lint & Repo Gates, three Type Check legs and Governed Surface Queue Guard in progress; Test Core, Dogfood Regression Gate, Check Changeset and Type Check workspace success); not awaited per contract"
    },
    "line_budget": {
    ".claude/skills/pm-dispatch/references/contract-review.md": "lines 40 → 40 (ceiling 60), bytes 3349 → 3408; the new face text needs one more line than the old one, paid by deleting the second spelled-out copy of node scripts/pm/record-recognisers.mjs --template on the independence-pair line (the full command is still spelled once on the Served-tier line); no re-wrap",
    ".claude/skills/pm-dispatch/references/landing-operations.md": "lines 101 → 101 (ceiling 101), bytes 8763 → 8763",
    ".claude/skills/pm-dispatch/references/execution-duties.md": "lines 183 → 183 (ceiling 183), bytes 17365 → 17364",
    ".claude/skills/pm-dispatch/references/lanes/ui.md": "lines 38 → 38 (ceiling 38), bytes 2601 → 2602"
    },
    "files_changed": [
    ".claude/skills/pm-dispatch/references/contract-review.md",
    ".claude/skills/pm-dispatch/references/landing-operations.md",
    ".claude/skills/pm-dispatch/references/execution-duties.md",
    ".claude/skills/pm-dispatch/references/lanes/ui.md"
    ],
    "deviations": [
    "contract-review.md: the line payment touches one sentence unrelated to the faces (the independence-pair line). Its duplicated command spelling is deleted and replaced by a pointer to the same --template. Declared in the PR body as sentence 3.",
    "lanes/ui.md: beyond renaming the line to the three faces, it adds the clause that prose faces go to ACCEPT, since the ui seat's changeset-only PRs are the population that raised the card. It stays within its 120-byte line and 0-line budget.",
    "execution-duties.md: spec 与 skills became spec/skills only to keep the line within the 120-byte cap (118 bytes).",
    "PR body: the seat's proposal quoted in the card body carries a model-name token, so the PR describes it in words and quotes only the maintainer's two rulings verbatim.",
    "Attribution: the commit uses AGENTS.md's model-free trailer pair (the pre-push hook refuses a model identifier) and the PR body ends with AGENTS.md's session-URL footer block, in place of the harness-suggested trailer and footer that carry a model name or a second block.",
    "Mechanism assumptions re-measured on base 2c1cef3: the four anchors hold. A grep of scripts/ and .github/ finds 0 lines putting contract-review terms within 4 lines of .changeset, content/docs or apps/docs. The only script that reads contract-review.md as text (the dispatch-gates self-test) checks the CONTRACT_REVIEW_TIER constant and the retired fuse text, both unaffected. Falsified nothing."
    ],
    "mcp_calls": "0 — no MCP GitHub tool called",
    "api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), executing 4 REST writes as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/pulls (pr_create, draft, PR 21192); POST /repos//issues/21192/labels (skip-changeset); POST /repos//issues/21192/assignees (hotlong); POST /repos//issues/21187/comments (this os-dev-report). Plus 2 git pushes (empty branch probe, then 4bde1f7), which are not REST writes.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted in PR Acceptance notes, not filed · the ACCEPT verdict line in execution-duties.md 〈复核〉 does not itself list prose sentences; the duty is stated in contract-review.md and lanes/ui.md. Adding it there is 137 bytes in a 0-headroom file, and review-checklist.md is outside this claim's file surface · dedupe words: ACCEPT prose sentences, review-checklist changeset prose, 散文面 ACCEPT",
    "carrier: 承接者:无 · noted in PR Acceptance notes, not filed · the card's rationale cites a changeset claim re-read; that facility is objectui's (.github/workflows/changeset-presence.yml, scripts/render-changeset-claims-comment.mjs), with 0 hits in objectstack's tree, so on objectstack the ACCEPT check is the only prose control before release · dedupe words: changeset claim re-read objectstack, changeset-presence port"
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 21187,
    "status": "done",
    "branch": "claude/issue-21187-prose-review-at-accept",
    "pr": "#21192",
    "session": "session_016tKoy8NJa35Yih1FdzrVmn (subagent; the dispatching director seat's id, as named in the dispatch and in both commits' Claude-Session trailer)",
    "premise_still_valid": true,
    "summary": "Review round 1 landed as 27e976d on top of 4bde1f7 (no force-push, same PR). Finding 1: review-checklist.md 〈范围与 changeset〉 gains one line stating that changeset/CHANGELOG, content/docs/** and apps/docs/** are checked sentence by sentence against the diff, that the ACCEPT names the checked sentences, and that no subagent is spawned. The line is paid in the same file by compressing the two-line dev-union head check into one; no ⛔ line is touched, and execution-duties.md was not touched again. Finding 2: contract-review.md's trigger now reads 「diff 或认领申报碰下列任一面」, rewritten in place at 119 bytes with no line added. All 18 derived gates are green at 27e976d. The PR body was NOT patched (see deviations); the replacement body is in pr_body_replacement for the seat to write.",
    "tests": "All 18 gates derived by dispatch-gates --commands --repo objectstack-ai/objectstack (no paths; change set 5 files vs merge base 2c1cef3) ran at head 27e976d with exit 0. check:required-contexts is newly derived because of review-checklist.md. The --ran reconciliation over the exit-coded record printed: 18 derived famil(ies) accounted for, 18 run, 0 NOT-MEASURED (a DERIVED zero, all 18 recorded an exit code and none of them is 3). check:doc-formula-expressions first exited 3 in the recreated worktree (PREREQUISITE NOT MET), which measured nothing. After a turbo build of formula and lint under os-verify-lock (VERDICT command-exit 0, a cache hit) it reran with exit 0 and a 58-case self-test. check:pm-skill-ratchet: review-checklist.md 77 lines (ceiling 77, headroom 0), contract-review.md 40 (ceiling 60), others unchanged; every added line is at most 119 bytes. check:pm-skill-id-lint: 34 file(s) clean. A raw control-byte scan of the touched files found nothing.",
    "gates": {
    "head": "27e976d73",
    "derived_by": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (change set from merge base 2c1cef3: 5 files, +11/-11)",
    "results": [
    "node scripts/check-closing-keyword-parity.mjs :: exit 0",
    "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
    "node scripts/check-comment-mask-corpus.mjs :: exit 0",
    "node scripts/pm/check-harness-current.mjs --self-test :: exit 0",
    "pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 (first run exit 3 PREREQUISITE NOT MET in the recreated worktree; rerun after a turbo build that hit cache)",
    "pnpm check:agent-test-spelling :: exit 0",
    "pnpm check:cross-package-test-inputs :: exit 0",
    "pnpm check:doc-authoring :: exit 0",
    "pnpm check:driver-memory-census :: exit 0",
    "pnpm check:gitlink-declared :: exit 0",
    "pnpm check:nul-bytes :: exit 0",
    "pnpm check:pm-governed-merges :: exit 0",
    "pnpm check:pm-skill-id-lint :: exit 0",
    "pnpm check:pm-skill-ratchet :: exit 0",
    "pnpm check:refd-timer-probe :: exit 0",
    "pnpm check:required-contexts :: exit 0",
    "pnpm check:skill-frame-sync :: exit 0",
    "pnpm check:watch-hint-literal :: exit 0"
    ],
    "reconciliation": "dispatch-gates --ran: 18 derived, 18 run, 0 NOT-MEASURED, 0 UNRUN (derived zero, all exit-coded)",
    "ci": "in_progress at report time (one read of head 27e976d check-runs: 12 success, 9 skipped, 4 in progress); not awaited per contract"
    },
    "line_budget": {
    ".claude/skills/pm-dispatch/references/contract-review.md": "lines 40 → 40 (ceiling 60), bytes 3349 → 3423; round 0 paid its extra face-list line by deleting the second spelled-out --template command; round 1 rewrites the trigger line in place (119 bytes), no line added",
    ".claude/skills/pm-dispatch/references/review-checklist.md": "lines 77 → 77 (ceiling 77, headroom 0), bytes 6318 → 6321; +1 line (the prose-check line, 119 bytes) paid by compressing the two dev-union head-check lines into one (119 bytes); no re-wrap, no ⛔ line touched",
    ".claude/skills/pm-dispatch/references/landing-operations.md": "lines 101 → 101 (ceiling 101), bytes 8763 → 8763 (unchanged in round 1)",
    ".claude/skills/pm-dispatch/references/execution-duties.md": "lines 183 → 183 (ceiling 183), bytes 17365 → 17364 (unchanged in round 1)",
    ".claude/skills/pm-dispatch/references/lanes/ui.md": "lines 38 → 38 (ceiling 38), bytes 2601 → 2602 (unchanged in round 1)"
    },
    "files_changed": [
    ".claude/skills/pm-dispatch/references/contract-review.md",
    ".claude/skills/pm-dispatch/references/landing-operations.md",
    ".claude/skills/pm-dispatch/references/execution-duties.md",
    ".claude/skills/pm-dispatch/references/lanes/ui.md",
    ".claude/skills/pm-dispatch/references/review-checklist.md"
    ],
    "deviations": [
    "CONFLICT, stated rather than resolved silently: the rework message asks the dev to update the PR body's sentence list, but the dev-agent definition says the dev writes the PR body once, at pr_create, and never PATCHes it; later changes are named in the report and the seat writes them. Per that definition, which wins over a dispatch, the body was not patched. The full replacement body is in pr_body_replacement, without the attribution footer block. Platform readings: a REST PATCH of a PR body always appends a bare footer and keeps any existing footer, so the edit side sends no footer. Changes against the live body: 'All four files' becomes 'All five files', with a commit split note; new sentence entries 7 and 8 (before and after); a review-checklist.md row in the line budget and contract-review.md bytes 3423; gates at head 27e976d, 18 commands, a check:required-contexts row, and the 18-family reconciliation quote; the first Acceptance note is replaced by its resolution; the 维护者速读 改了什么 paragraph names the checklist line and 5 files / 11 lines.",
    "review-checklist.md new line: to fit the 120-byte cap it spells the faces as changeset/CHANGELOG plus the two docs paths, drops the 散文面 label, and says ⛔ 不起子代理 rather than 不起第二个 agent (same meaning).",
    "review-checklist.md line payment: the compressed head-check line drops words that restate the dev's own obligation (run the union after the final commit; quote the short sha in the report and the body). Both survive in .claude/agents/os-dev.md, as does the 死树读数 label, whose both-directions rule the same section states two lines above. Of the two old lines, neither carried ⛔.",
    "Round 0 deviations stand unchanged: the contract-review.md --template dedupe, ui.md's 散文面归 ACCEPT clause, spec/skills spelling in execution-duties.md, the paraphrased seat proposal, and the model-free attribution forms."
    ],
    "mcp_calls": "0 — no MCP GitHub tool called (both rounds)",
    "api_writes": "Round 1: 1 relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executing POST /repos//issues/21187/comments (this os-dev-report), plus 1 git push (27e976d). Round 0, already reported: 3 relay dispatches executing POST /pulls (PR 21192), POST /issues/21192/labels, POST /issues/21192/assignees and POST /issues/21187/comments (comment 5934679331), plus 2 git pushes. No PR body PATCH in either round.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted in PR Acceptance notes, not filed · the card's rationale cites a changeset claim re-read; that facility is objectui's (.github/workflows/changeset-presence.yml, scripts/render-changeset-claims-comment.mjs), with 0 hits in objectstack's tree, so on objectstack the ACCEPT check is the only prose control before release · dedupe words: changeset claim re-read objectstack, changeset-presence port"
    ],
    "pr_body_replacement": "Fixes #21187\n\nClause-②: no\n\n## What this changes\n\nreferences/contract-review.md named five faces that owe an at-tier contract review, and three of them were prose: .changeset / CHANGELOG, content/docs/** and apps/docs/**. The eligibility line in references/execution-duties.md then forbids an off-tier seat from reviewing in-seat. Together, every PR carrying a releasing changeset owed an isolated CONTRACT_REVIEW_TIER subagent whenever its seat was not spec or skills.\n\nThis PR implements the ruling. The isolated at-tier review is now owed on exactly three contract faces:\n\n- a Clause-②: yes declaration;\n- published schema (packages/spec/src/**, non-test);\n- governed rule text (the SKILL.md definition, .claude/** included; Tier S as today).\n\nThe prose faces (.changeset / CHANGELOG, content/docs/**, apps/docs/**) are checked sentence by sentence against the diff in the dispatching seat's ACCEPT, at the seat's own tier, and the ACCEPT names the sentences it checked. No second agent is spawned for them.\n\nThe change is text-only. No script or workflow implements the face list (search below), and the queue's contract-review gate reads only the two Clause-② legs (landing-operations.md 「条款②入队闸门」), which this PR does not touch.\n\n## Rulings implemented\n\n- Maintainer, ruling A, quoted in the card body: 「我已经同意了,不需要严格的规则」. It answers the seat's proposal (quoted verbatim in the card body) that changeset prose be self-checked by the seat at ACCEPT, with no at-tier subagent spawned for it.\n- Maintainer to the director seat, settling forks 1, 2 and 3 of ruling record 5934170950 on the card: 「同意,你负责派发。」\n 1. The docs faces move with the prose: content/docs/** and apps/docs/** no longer owe an isolated review.\n 2. Two at-tier uses stay exactly as they are (see the next section but one).\n 3. priority:p1, landed this round.\n\n## Every sentence changed (before, then after)\n\nAll five files keep their line counts. Anchors are content, not line numbers. Sentences 1 to 6 landed in 4bde1f71a; sentences 7 and 8 landed in 27e976d73 (review round 1).\n\n1. references/contract-review.md, the face list (two lines become three):\n\ntext\n- 复核面 = 出货给用户或 agent 的五处:`content/docs/**`、`apps/docs/**`、CHANGELOG/`.changeset` 散文。\n- 加已发布 schema(`packages/spec/src/**` 非测试)与 governed 规则文本(统一定义见 SKILL.md)。\n\n\ntext\n- 复核面 = 契约三面:`Clause-②: yes` 申报、已发布 schema(`packages/spec/src/**` 非测试)、governed\n 规则文本(统一定义见 SKILL.md);`.changeset`/CHANGELOG、`content/docs/**`、`apps/docs/**` 散文面\n ⛔ 不在其列:派发席按本席档在 ACCEPT 逐句对照 diff 核,ACCEPT 点名所核句。\n\n\nThe line breaks fall at a source space (governed 规则文本, 散文面 ⛔), so the rendered text is unchanged by them.\n\n2. references/contract-review.md, 「五面皆不碰」 (renamed; meaning kept for the three-face set):\n\ntext\n- 五面皆不碰 ⇒ CI 加席位自读 ⛔ 不起第二个 agent;谁跑 = 派发席,达档者席内审。\n\n\ntext\n- 三面皆不碰 ⇒ CI 加席位自读 ⛔ 不起第二个 agent;谁跑 = 派发席,达档者席内审。\n\n\n3. references/contract-review.md, the independence-pair line (this is the line payment, see "Line budget"):\n\ntext\n- 独立性对:`Implemented-by:`/`Reviewed-by:` 取值见\n `node scripts/pm/record-recognisers.mjs --template`;子代理记采纳它的席位。\n\n\ntext\n- 独立性对:`Implemented-by:`/`Reviewed-by:` 取值同见 `--template`;子代理记采纳它的席位。\n\n\n4. references/landing-operations.md, 「交付后复核按面欠」:\n\ntext\n- 交付后复核按面欠 ⛔ 不按车道(五面见 `references/contract-review.md`);双肢命中即 spec 车道。\n\n\ntext\n- 交付后复核按面欠 ⛔ 不按车道(三面见 `references/contract-review.md`);双肢命中即 spec 车道。\n\n\n5. references/execution-duties.md, 「条款②自审资格按车道」:\n\ntext\n- 条款②自审资格按车道:spec 与 skills 席达档席内审;未达档 ⛔ 不自审,起隔离达档子代理。\n\n\ntext\n- 契约三面自审资格按车道:spec/skills 席达档席内审;未达档 ⛔ 不自审,起隔离达档子代理。\n\n\nspec 与 skills became spec/skills only to keep the line within the ratchet's 120-byte cap (118 bytes).\n\n6. references/lanes/ui.md, 「条款②复核本席适用」:\n\ntext\n- 条款②复核本席适用:按面欠达档复核记录,落 PR 或卡,归属与资格见 `../contract-review.md`。\n\n\ntext\n- 契约三面复核本席适用:按面欠达档记录落 PR 或卡,散文面归 ACCEPT,见 `../contract-review.md`。\n\n\nThe ui seat is the lane whose changeset-only PRs started this card, so its line says where the prose check now sits.\n\n7. references/review-checklist.md 〈范围与 changeset〉, the ACCEPT-side prose check (new line, review round 1). The path a seat walks at ACCEPT is execution-duties.md 〈复核〉 into this checklist, so the duty is stated here as well as in contract-review.md:\n\ntext\n(none)\n\n\ntext\n- changeset/CHANGELOG、`content/docs/**`、`apps/docs/**`:逐句核 diff,ACCEPT 点名所核句,⛔ 不起子代理。\n\n\nThe line is paid in the same file by compressing the two-line dev-union head check into one. The dropped words restate the dev's own obligation, which .claude/agents/os-dev.md carries (run the union after the final commit, quote the short sha in the report and the body), and the both-directions rule that the same section states two lines above (「不一致的双向都不入账」). No ⛔ line is touched.\n\ntext\n- dev 本地并集同样先钉 head:最后一次提交之后跑,`git rev-parse --short HEAD` 抄进报告与正文。\n- 与 PR 当前 `head.sha` 比一次,对不上即死树读数、双向都不入账;没抄 ⇒ 按没有读数处理。\n\n\ntext\n- dev 本地并集钉 head:所抄 `git rev-parse --short HEAD` 不符 PR `head.sha` 或没抄 ⇒ 双向都不入账。\n\n\n8. references/contract-review.md, the trigger (review round 1). The first contract face is a Clause-②: yes declaration, which lives in the claim comment, not in the diff:\n\ntext\n- 欠不欠按面判 ⛔ 不按车道:diff 碰下列任一面即欠达档复核,交付后当轮完成。\n\n\ntext\n- 欠不欠按面判 ⛔ 不按车道:diff 或认领申报碰下列任一面即欠达档复核,交付后当轮完成。\n\n\n## Deliberately unchanged (ruling point 2)\n\nThese two lines are not prose review. Each is the record that lets a red or exceptional gate pass, so they stay exactly as they are:\n\n- references/execution-duties.md: 「改到已有 .changeset/*.md 的 PR ⛔ 不打 skip-changeset;确认取同 head 达档 PASS 或维护者原话」\n- references/landing-operations.md: 「DELIBERATE CORRECTION 红(check-empty-changeset):同 head 达档复核 PASS 记录即确认」\n\nBoth lines grep exactly once at head, and neither is an added or removed line in the diff (the second shows up only as hunk context).\n\n## Where the rule lives: the search\n\nBase 2c1cef334. Searched .claude/, AGENTS.md and CLAUDE.md:\n\n- Face-list wording, 五面|五处|复核面|按面|四面|三面: the rule hits only the anchors changed above. The other hits are unrelated: execution-duties.md 「三面都查」 (premise check), lanes/devx.md and lanes/spec.md (spec lane slicing), and platform-readings.md 「按面不按路由」 (footer readings).\n- At-tier wording, 达档|CONTRACT_REVIEW_TIER|at-tier|契约复[审核]: none of these ties prose to an at-tier record. dispatch-runbook.md 「无主阻塞项的契约面(含 packages/spec)」 names contract faces only, and SKILL.md (the skills-hunk, Tier S and governed-definition lines) and .claude/agents/os-dev.md (Tier S landing) are about governed text.\n- Prose wording, 散文, content/docs|apps/docs, contract[- ]review|prose, and changeset on the same line as 复核|review|达档|复审: no further site. review-checklist.md, SKILL.md and .claude/agents/os-dev.md carry no restatement of the face list, so nothing outside references/** needed an edit.\n- Mechanism: 7 files under scripts/ and .github/ mention both a contract-review term and one of .changeset / content/docs / apps/docs. In each of them, 0 lines put the two within 4 lines of each other. No script reads the changed sentences. The one script that reads contract-review.md as text (the dispatch-gates.mjs self-test: the CONTRACT_REVIEW_TIER constant is present and the retired fuse text is absent) is unaffected, and its gate is green.\n- Sister checkouts (objectui 0a3e540, cloud 90b1af0, hotcrm fb408a7): 0 hits for 五面|复核面|五处|按面欠|CONTRACT_REVIEW_TIER outside CHANGELOGs.\n\n## Line budget\n\n| file | lines before → after | ceiling | bytes before → after |\n|:--|:--|:--|:--|\n| references/contract-review.md | 40 → 40 | 60 | 3349 → 3423 |\n| references/landing-operations.md | 101 → 101 | 101 | 8763 → 8763 |\n| references/execution-duties.md | 183 → 183 | 183 | 17365 → 17364 |\n| references/lanes/ui.md | 38 → 38 | 38 | 2601 → 2602 |\n| references/review-checklist.md | 77 → 77 | 77 | 6318 → 6321 |\n\nThe new text in contract-review.md needs one line more than the old face list. That line is paid by deleting content in the same file: the second spelled-out copy of node scripts/pm/record-recognisers.mjs --template (sentence 3). The full command is still spelled once, eleven lines above. No line was re-wrapped to free space. review-checklist.md pays for its new line the same way (sentence 7). Every added line is at most 119 bytes.\n\n## Local gates\n\nRun at head 27e976d73, after the review-round-1 commit. The list was derived by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (18 commands, no paths passed; check:required-contexts joined the list with review-checklist.md). The --ran reconciliation over the exit-coded record printed: 「18 derived famil(ies) accounted for — 18 run, 0 NOT-MEASURED (a DERIVED zero — all 18 recorded an exit code and none of them is 3)」.\n\n| command | exit |\n|:--|:--|\n| node scripts/check-closing-keyword-parity.mjs (and --self-test) | 0, 0 |\n| node scripts/check-comment-mask-corpus.mjs | 0 |\n| node scripts/pm/check-harness-current.mjs --self-test | 0 |\n| pnpm --filter @objectstack/lint run check:doc-formula-expressions | 0 (see note) |\n| pnpm check:agent-test-spelling | 0 |\n| pnpm check:cross-package-test-inputs | 0 |\n| pnpm check:doc-authoring | 0 |\n| pnpm check:driver-memory-census | 0 |\n| pnpm check:gitlink-declared | 0 |\n| pnpm check:nul-bytes | 0 |\n| pnpm check:pm-governed-merges | 0 |\n| pnpm check:pm-skill-id-lint | 0, 「34 file(s) clean」 |\n| pnpm check:pm-skill-ratchet | 0, the five files at 40/60, 101/101, 183/183, 38/38, 77/77 |\n| pnpm check:refd-timer-probe | 0 |\n| pnpm check:required-contexts | 0 |\n| pnpm check:skill-frame-sync | 0 |\n| pnpm check:watch-hint-literal | 0 |\n\nNote: check:doc-formula-expressions first exited 3 (PREREQUISITE NOT MET: @objectstack/formula and @objectstack/lint were not built in the fresh worktree), so that first run measured nothing. After pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2 under the shared verify lock (VERDICT command-exit 0), it ran with exit 0 and a 58-case self-test. The same happened at 27e976d73 in the recreated worktree: first run exit 3, rebuild (a turbo cache hit), rerun exit 0. A raw control-byte scan over the four files found nothing. The full farm is CI's.\n\nNo changeset: the diff publishes nothing (.claude/** only), so the PR takes skip-changeset.\n\n## Acceptance notes\n\n- Resolved in review round 1: the ACCEPT path now names the prose check (sentence 7). execution-duties.md 〈复核〉 was not touched again, because its 「核对清单结论」 already carries the checklist into the ACCEPT.\n- The card's rationale cites a changeset claim re-read that asks authors to re-read pending changeset bodies. That facility is objectui's (.github/workflows/changeset-presence.yml, scripts/render-changeset-claims-comment.mjs there), and this repository's tree has 0 hits for it. On objectstack, the ACCEPT check is the only prose control before a release consumes the changeset. Noted, not filed; no carrier.\n- Landing: Tier S (.claude/** only). The dev does not ready, queue or arm this PR. The owning seat lands it after an isolated CONTRACT_REVIEW_TIER review of record PASS on the current head, with every check green.\n\n## 维护者速读(草稿)\n\n改了什么:PM 规则里「哪些改动必须另起一个顶档 agent 做隔离契约复核」的清单,从五处缩到三处契约面:Clause-②: yes 申报、packages/spec/src/**(非测试)、受管规则文本(含 .claude/**)。changeset/CHANGELOG 与 content/docs/**、apps/docs/** 的散文改由派发席在 ACCEPT 时按本席档逐句对照 diff 核对,并在 ACCEPT 里点名核过的句子,不再另起 agent。另在 ACCEPT 复核清单(review-checklist.md)补一行,写明散文面逐句核、ACCEPT 点名、不起子代理。只动 .claude/skills/pm-dispatch/references/ 下 5 个文件共 11 行,每个文件行数不变。\n\n为什么改:卡片实测 objectui 最近 40 个合并 PR 中有 30 个带发布 changeset,按旧规则每个都要一次隔离顶档复核;单次约 23.6 万 token,那一例只多抓出一句散文偏松。您已裁 A(「我已经同意了,不需要严格的规则」),并对三个分叉答「同意,你负责派发。」。\n\n风险与代价(含回滚):契约面(条款②申报、spec、受管面)照旧走隔离顶档复核;入队闸门只读条款②两肢,本 PR 不碰。两条「同 head 达档 PASS 即确认」的例外条款原样保留。代价是散文核对的质量落在派发席本档,靠 ACCEPT 逐句点名留痕。回滚 = revert 本 PR,不牵连任何脚本或数据。\n\n席位意见:\n\n你要做的:无需操作。本 PR 属 Tier S,由席位在隔离达档复核 PASS 后落地;对措辞有异议请在本 PR 留言。\n"
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR #21192 at 27e976d73; landing follows Lint & Repo Gates success

    Director seat, summon #32, holding domain:skills#3 for this card, session_016tKoy8NJa35Yih1FdzrVmn, 2026-10-01T15:57Z. Checked against the diff, the card and the head's check-runs.

    • Claim: 5934212807. Dev reports: 5934679331 (round 0) and 5934891734 (round 1).
    item reading
    ruling A + forks 1/2/3 (5934170950) The isolated at-tier review is owed on exactly three faces: the Clause-②: yes declaration, packages/spec/src/** (non-test), and governed rule text. Prose (.changeset/CHANGELOG, content/docs/**, apps/docs/**) is checked sentence by sentence against the diff in the dispatching seat's ACCEPT, which names the sentences checked; no second agent. The faces appear in contract-review.md, landing-operations.md, execution-duties.md and lanes/ui.md.
    REWORK round 1 (the seat's two findings) Resolved at 27e976d73. (1) The ACCEPT path now carries the prose check: one line in review-checklist.md 〈范围与 changeset〉, the checklist execution-duties.md 〈复核〉 runs every report against. (2) The trigger reads 「diff 或认领申报碰下列任一面」, because the first face is a claim declaration and not a diff path.
    fork 2 The two at-tier exception lines (execution-duties.md 「改到已有 .changeset/*.md 的 PR …」, landing-operations.md 「DELIBERATE CORRECTION 红 …」) are byte-unchanged at head.
    contract review PASS, record 5935215613, at CONTRACT_REVIEW_TIER on this head. Isolated, read-only, Local-runs: none. Served tier verified from the reviewer's own transcript: every request was at the constant's tier.
    scope 5 files, +11 / −11, all under .claude/skills/pm-dispatch/references/**. The claim's surface plus review-checklist.md, which the seat's REWORK order added within references/**. No package, script or workflow.
    semver skip-changeset (publishes nothing). Clause-②: no.
    ratchet 40/60, 101/101, 183/183, 38/38 and 77/77 lines; every added line ≤ 119 bytes. The verdict is Lint & Repo Gates, pending at this write.
    prose faces under the new rule None in this diff, so there are no sentences to check.
    PR body Replaced by the seat with the dev's pr_body_replacement (the dev may not edit a body after pr_create), and read back byte-identical with one footer.
    CI on 27e976d73 20 success, 12 skipped by the paths filter for a .claude/**-only diff, 1 in progress (Lint & Repo Gates). No failure.

    Deviations accepted:

    • The round-0 contract-review.md --template dedupe was not forced by the ratchet (that file has 20 lines of headroom), but it is loss-free, as the record notes.
    • spec/skills is a spelling change.
    • The PR body paraphrases the seat's proposal because the original text carries a model token.

    Out-of-scope note (the dev's), not filed: objectstack has no changeset claim re-read facility of its own (it is objectui's), so here the ACCEPT check is the only prose control before a release.

    Landing (Tier S): when Lint & Repo Gates concludes success on this head, the seat sends relay pr_ready + automerge_enable, then confirms MERGED on both the queue branch and origin/main. The card closes on Fixes.


    Generated by Claude Code

  6. added a commit that references this issue on Oct 7, 2026
    5e5ce48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:skillspriority:p1High: required for production / M2tooling

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions