Skip to content

docs(pm-dispatch): one patrol routine per seat, not per project - #28739

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-28699-patrol-per-seat
Nov 1, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-28699-patrol-per-seat

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by 田騏 · project thread

Fixes #28699
Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:pm-dispatch SKILL.md 第 72 行把项目席巡查 routine 的单位从「每项目一个」改成「每席一个」,其余一字不动,净行数 0。
  • 为什么改:SKILL.md 与 seat-lifecycle.md、project-forms.md 自相矛盾;一个项目坐多条车道时,实际做法是每个席位线程各绑一个巡查,因为每席是各自的会话。
  • 风险与回滚:只改规则文字,无代码;不改的风险是读者照旧句只给项目建一个巡查,其它席位醒不来。回滚 = revert 本 commit。
  • 先看:.claude/skills/pm-dispatch/SKILL.md 第 72 行(唯一改动)。
  • 两分钟验证:git grep -n 每项目一个 -- .claude/skills 预期零命中,pnpm check:pm-skill-ratchet 预期绿。
  • 需要你做的:用授权账号批准本 PR(受管面上的规则改动),随后由席位落地。

What changes

.claude/skills/pm-dispatch/SKILL.md line 72, the project-seat wake line, now names the seat as the unit of the self-bound patrol routine: 「每项目一个」 becomes 「每席一个」. The director-seat exception and the rest of the line are unchanged. SKILL.md stays at 319 lines (net 0).

This matches the references on main after #28687: references/seat-lifecycle.md (taking a seat creates the routine and records Patrol: on that seat's stub) and references/project-forms.md (「坐席即建巡查 routine」, one seat thread per seat).

Tests

No code changed, so there are no unit tests. Verification is the gate families derived from the diff (below).

Acceptance notes

  • Wording: the card asks for "one routine per seat thread". 「每席位线程一个」 would put the line at 124 bytes, over the 120-byte cap that pnpm check:pm-skill-ratchet enforces. 「每席一个」 is 115 bytes and reads unambiguously, because the line before it defines a project seat as a project thread (「会话是车队项目的线程」). It also matches project-forms.md's 「每席开一条席位线程」.
  • No other file restates this unit: git grep -n 每项目一个 exits 1 on this head (control: git grep -n 自建自绑巡查 finds line 72).
  • Governed surface (.claude/**): this PR stays draft and waits for its tier's record.

Verification

Head ba301e3691. Gate list from node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (20 families, 1 path, +1/-1). Exit codes were captured before any pipe.

Derived gates: 20/20 exit 0
0  node scripts/check-closing-keyword-parity.mjs
0  node scripts/check-closing-keyword-parity.mjs --self-test
0  node scripts/check-comment-mask-corpus.mjs
0  node scripts/pm/check-governed-queue-guard.mjs --self-test
0  node scripts/pm/check-harness-current.mjs --self-test
0  pnpm --filter @objectstack/lint run check:doc-formula-expressions   (first run exit 3 PREREQUISITE NOT MET; rerun after building formula+lint)
0  pnpm check:agent-test-spelling
0  pnpm check:cross-package-test-inputs
0  pnpm check:doc-authoring
0  pnpm check:driver-memory-census
0  pnpm check:gitlink-declared
0  pnpm check:nul-bytes
0  pnpm check:pm-expected-skips
0  pnpm check:pm-governed-merges
0  pnpm check:pm-governed-prose
0  pnpm check:pm-skill-id-lint
0  pnpm check:pm-skill-ratchet
0  pnpm check:refd-timer-probe
0  pnpm check:skill-frame-sync
0  pnpm check:watch-hint-literal

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)".

Named gate verdict lines
✓ check-governed-prose: 2 instruction surface(s) name all 13 registered governed surfaces that govern objectstack ... and claim no others.
✓ check-skill-id-lint: 106 file(s) clean (pattern /#[0-9]{3,}/g).
✓ check-skill-line-ratchet: declared cross-file moves: 3, total ceilings down 494 lines.
✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent (.claude/skills/pm-dispatch/SKILL.md; ...)

Session: session_017ihL2g7RyXa8ErM6GAkHyc (seat domain:skills#2).


🤖 Generated with Claude Code

…ot one per project

SKILL.md's seat-wake line named the project as the unit of the self-bound
patrol routine, while seat-lifecycle.md and project-forms.md create one on
taking each seat. The line now names the seat; the director seat stays
excepted. Net line count 0.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2g7RyXa8ErM6GAkHyc
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 1, 2026
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Nov 1, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · marchtian · session_017ihL2g7RyXa8ErM6GAkHyc

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: ba301e3691ab0e71abff8951b53bb3fa57052a4d
Local-runs: none
Scope: .claude/skills/pm-dispatch/SKILL.md + references/seat-lifecycle.md 〈座位贴协议〉, references/project-forms.md 〈席位是读出来的〉, references/seat-post-protocol.md (:9, :66), references/execution-duties.md (:157), references/cross-repo-coordination.md (:13), references/dispatch-runbook.md 〈巡查常设项〉

Inputs read: card #28699 body + comments 6559597861, 6560370830, 6560553542; PR #28739 body, file list (1 file, +1/-1), net diff origin/main...ba301e36; check-runs on the head at 2026-11-01T16:26Z. The dispatch order and the dev report's gate table were not used as evidence; the tree and the check-runs were.

① Derived judgments

  • Accept-set: none changes. The diff is one rules line in an internal skill (metadata.internal: true, lives in .claude/, never in the published skills/ dir); no schema, no code, no consumer. Right.
  • Public surface: none. Governed path .claude/** is hit, so the face is rules and the tier is CONTRACT_REVIEW_TIER by path; the PR stays draft under the governed-surface guard (check-run Governed Surface Queue Guard: success). Right.
  • Unit of the patrol routine: 「每席一个」 is scoped by the line's own subject 「项目席唤醒」, so it reads as one routine per project seat, director excepted, triage included (project-forms.md:26 「坐席即建巡查 routine…分诊席加每小时裸卡轮;总监席不建」). Routine 席 is untouched: the line never governed it and execution-duties.md:157 keeps the two wake paths apart. Right.
  • Line budget on the head, measured: SKILL.md 319 → 319 lines; line 72 is 115 bytes (118 on main), under the 120-byte cap scripts/pm/check-skill-line-ratchet.mjs documents. Right.
  • Dedupe of the old unit: git grep 每项目一个 -- .claude has zero hits on the head. Right as stated, but see ④ for the sibling phrase it does not cover.

② Semver level

  • Nothing is published by .claude/**; skip-changeset is on the PR and check-run Check Changeset: success. Right.
  • Clause-②: no on the PR body: no declared capability is added, narrowed or removed; the line restates an operating rule for seats, not a spec. Right.

③ Boundary flags

The report lists three deviations and open_questions: [].

  • Flag 1 (attribution HTML comment as the PR body's first line): answered — .claude/agents/os-dev.md:321 names exactly this as the harness exception (keep it, report it, Fixes #n follows); Fixes #28699 follows after the harness's second line, and check-run PR-body guards: success. Accepted.
  • Flag 2 (PR body ends with the 🤖 Generated with line, not the AGENTS.md session-URL footer): answered — AGENTS.md:430 names the session-URL form for PR bodies, and the same section makes body prose the durable attribution; the body carries Session: session_017ihL2g7RyXa8ErM6GAkHyc in prose. Not a tree defect, no gate reads it. should-fix (PR body only): replace the tail line with the AGENTS.md form on the next body edit; ⛔ not a second footer.
  • Flag 3 (「每席」 instead of a literal 「每席位线程」): answered — 「每席位线程一个」 would be 124 bytes and red under the ratchet; 「每席」 is the word project-forms.md:25 (「每席开一条席位线程」), project-forms.md:36, seat-post-protocol.md:9 and dispatch-runbook.md:134 already use for the same unit, so it is the house term, not a shortening. Accepted.
  • Claim-side note, not a dev flag: the claim ran the dev on opus against a MANDATORY CONTRACT_REVIEW_TIER path and named this skill-face review as the compensation. This record is that review; nothing else is owed on it.
  • No open_questions to escalate.

④ Design judgment

hits file: .claude/skills/pm-dispatch/SKILL.md (line 72). Scenario it is accepted against: the card's measured reach — one fleet project seated on three lanes (pm-dispatch ui skills plus a spec seat), each seat an hourly patrol bound to its own seat thread; the skill has no separate eval prompt, so that measurement is the scenario.

Read against the cited code on this head:

  • seat-lifecycle.md:41 「坐席即建自绑巡查 routine、存根记 Patrol:、发 seat-online;收班同笔删它」: creation, record and deletion all keyed to the act of taking a seat. Per seat.
  • project-forms.md:25-26 「每席开一条席位线程」 then 「坐席即建巡查 routine…总监席不建」: one thread per seat, one routine on seating, director excepted. Per seat.
  • seat-post-protocol.md:9 (多席车道每席一贴) and :66 「项目席巡查默认每小时(总监席无),现值只记存根 Patrol: TRIGGER_ID · CRON」: the routine's id lives on the seat's own stub. Per seat.
  • cross-repo-coordination.md:13, dispatch-runbook.md:134: a lane splits into seats, each with its own post and thread. Per seat.

Attempts to break it:

  • Single-seat project: 「每席一个」 and 「每项目一个」 coincide; nothing regresses.
  • One account, two seats in one project: a routine fires into one session and each seat is its own thread (project-forms.md:25), so 「自建自绑」 is only satisfiable per seat; the old per-project reading left every seat but one unwoken, which is the failure the card measured. The new line is the only one of the two the references can execute.
  • Director: excepted on the line and in project-forms.md:26, seat-post-protocol.md:66. Coherent.
  • Triage seat: builds one plus the hourly bare-card round (project-forms.md:26); 「每席」 includes it. Coherent.
  • Epic PM (seat-lifecycle.md 〈Epic 子树车道〉): a dedicated session that never doubles as a domain:* seat; a per-seat routine does not collide with it.
  • Ratchet / frame / prose gates: the line is 115 bytes, the file is net 0, the decision frame is untouched (check-run Type Check · source gates, which runs check:skill-frame-sync: success); Lint · repo & tooling gates (check:pm-skill-ratchet, check:pm-skill-id-lint, check:pm-governed-prose): success; Lint · PM dispatch-gates: success. Every check-run on the head is completed and none concluded failure (success or skipped, the skips being path-filtered families the diff does not reach).

Findings:

  • should-fix (outside this PR's surface; the card's Wanted says 「no other change」, so not a FAIL here — file a follow-up card in the skills lane): references/dispatch-runbook.md:39 「## 巡查常设项(每项目巡查与总监席摘要)」 and :44 「跨账户复审:每项目巡查跑 is:pr is:open label:needs:contract-review…」 still name the patrol by the project. The card's dedupe grep was 「每项目一个」, which does not match 「每项目巡查」. After this PR the skill says per seat and its runbook heading says per project; two lines, 「每项目巡查」→「每席巡查」, net 0. While there, :45's dedupe 「已有他账户的认领即跳过」 is keyed to the account, so two seats of one account in one project would both pass it; worth one word on the same card.
  • No must-fix. The line holds against every text it cites and the scenario it is accepted against.

Implemented-by: claude/issue-28699-patrol-per-seat
Reviewed-by: session_017ihL2g7RyXa8ErM6GAkHyc

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · marchtian · session_017ihL2g7RyXa8ErM6GAkHyc

维护者速读(席位终稿 · head ba301e3691ab0e71abff8951b53bb3fa57052a4d)

  • 改了什么:SKILL.md:72 一个词:项目席的巡查 routine 从「每项目一个」改为「每席一个」。
  • 为什么改:feat(pm): a project seat's patrol is part of seating, recorded on the stub, and its absence is a half-state reading #28687 合并后,references 已写明坐一个席位就建一个巡查;SKILL.md 还写每项目一个,一个项目坐多个席位时两处自相矛盾。实际做法(本项目 spec/devx/skills 三席各一个巡查)与 references 一致。
  • 风险与回滚:只改一个词,行数不变,无代码。回滚 = revert。
  • 先看:.claude/skills/pm-dispatch/SKILL.md 第 72 行。
  • 两分钟验证:git grep 每项目一个 -- .claude 无命中。
  • 需要你做的:批准本 PR(规则变更以你的批准为裁决)。契约复审 PASS:6560664363(Head-sha: ba301e3691ab0e71abff8951b53bb3fa57052a4d)。

席位意见:ACCEPT. 与 references 四处同口径;复审提出的 runbook 同类措辞已另立 #28740。

席位核对

@objectstack-fleet objectstack-fleet Bot added the needs-user-decision Blocked on a maintainer decision — do not dispatch; decision cards only, never on a PR label Nov 1, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review November 1, 2026 16:31
@os-zhuang
os-zhuang enabled auto-merge November 1, 2026 16:32
@os-zhuang
os-zhuang added this pull request to the merge queue Nov 1, 2026
@objectstack-fleet objectstack-fleet Bot removed the needs-user-decision Blocked on a maintainer decision — do not dispatch; decision cards only, never on a PR label Nov 1, 2026
Merged via the queue into main with commit e735b79 Nov 1, 2026
54 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-28699-patrol-per-seat branch November 1, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pm-dispatch: SKILL.md says one patrol routine per project, the references now say one per seat — pick the seat

2 participants