Skip to content

Commit 4e606ce

Browse files
docs(pm-dispatch): a project-coordinator reference — the cross-lane scheduling rules a Claude Code project runs by, so its instructions name only its lanes (#25255)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} --> _Requested by **Elon** · [project thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DKyk33tmijDaSFzML54k2pQ)_ Fixes #25219 Clause-②: no Metadata-protocol: none ## What changed Four files, all under `.claude/skills/pm-dispatch/**` plus one ceiling row; no code, no package. 1. **New reference `references/coordinator.md`** (49 lines, every line ≤ 120 bytes, no table row, no issue number). It is the project coordinator's interface with the seat threads — the role that opens seat threads and card threads and schedules across lanes — beside `seat-lifecycle.md`, because the coordinator is not a `domain:*` seat and so not under `lanes/`. Seven sections in the card's order, each naming its reader, each pointing at the rule's single source instead of restating it: 1. 车道归属登记在座位贴 — a project's instructions name only the lanes it manages; each seat thread sits the lane's vacant seat post and writes 「由 X 账户的项目负责」 in the post's 说明 section; one lane, one project; the seat post (not project memory) is the arbiter; another project's in-flight cards are finished by its own seat, and its sign-off brief is the release (seat-lifecycle's own rule). 2. 跨车道取卡 — the intake face is the project's lanes' open `priority:p1`/`priority:p2` cards under `execution-duties.md`'s candidate rule; each card goes to its lane's seat thread; a lane with no seat thread and a vacant post gets a seat thread first; the maintainer names no lane per card. 3. 全项目一个上限,p1 先 — one project-wide card-thread cap, the number the maintainer states for the project (the sum of the seats' `batch` terms only when none is stated); seats hand candidates over at any time; p1 ahead of p2; a thread waiting on a human or on the seat's review holds no slot; in-seat S subagents count only against the seat's `batch`. ⛔ No number is written as the rule. 4. effort 与档位按难度 — points at `execution-duties.md` 〈派发〉 and `dispatch-gates --tier`; skill (protocol-semantics) cards at `CONTRACT_REVIEW_TIER`; the coordinator sets model and effort at thread creation on the seat's request carrying the maintainer's word (`dispatch-runbook.md`). 5. 卡线程的 `needs_decision` — re-pointed after #25348 revoked every delegated-ruling channel: the rule lives in `lanes/director.md` and the 〈卡线程〉 section of `dispatch-runbook.md`, ⛔ not restated; the seat writes the four-axis analysis and a recommendation and the card joins the ruling batch the maintainer rules by hand, ⛔ no ruling thread, no delegated ruling; a thread waiting on a ruling holds no slot; the ruling record is the ruling comment on the card, ⛔ never a project file or memory. 6. 额度压力 — near the usage wall (the reading of `seat-lifecycle.md` 〈断粮与跨墙恢复〉) the coordinator opens no new card thread, lets in-flight ones finish, and tells the maintainer once. 7. 语言与汇报 — the maintainer's language in the project, English on GitHub (SKILL.md's invariant); the coordinator reports on a result, a blocker or a decision, as the seats do. 2. **`SKILL.md`, one row in 〈入口与角色〉**: `coordinator` — 以项目协调者身份运行(项目会话:开席位线程与卡线程、跨车道调度;接口见 `references/coordinator.md`), 154 bytes against the file's 342-byte widest-row pin. **Paid by one deletion in 〈升级与决策〉**: 「项目总监席:维护者在所在仓召唤 `/pm-dispatch director`;⛔ 无 Routine/cron;未回字 = 不在 = 停。」 — every clause of it survives in `references/lanes/director.md` (授权面 = 人工定期召唤,⛔ 无 Routine、无 cron; 入口 … `/pm-dispatch director`; 未回字 = 不在 = 停), which the `director` row of the same entry table already points at. SKILL.md stays line-neutral (319/319 after merging `main` with #25348); no ceiling moved. PR #25247 lowers the ceiling to 318 at its own landed count; this PR changes no count, so either landing order holds. 3. **`references/dispatch-runbook.md`, one line edited in place** (241/241, line-neutral): the 〈卡线程〉 cap line read 「全项目上限 = 各席 `batch` 之和」, which contradicts the card's item 3 (the maintainer sets one number per project — the two values set so far differ). It now reads 「全项目上限由维护者按项目定(`coordinator.md`)」 and the sum is the new file's stated default when no number is given. This is the one SKILL/reference line that would otherwise contradict the new file (the handover's allowance). 4. **`scripts/pm/check-skill-line-ratchet.mjs`**: a `CEILINGS` row for the new file at its landed count (49) and a `MAX_TABLE_ROW_BYTES` pin of 0 (it carries no table row). A new file is not a raise and funds nothing. No other script is touched. The maintainer's word, verbatim and untranslated, as the card quotes it: 「刚才你让我转帖的项目指令规则,为什么不定义在仓库中呢,我只要穿到具体的车道就行。」 ## The PM's mechanism assumptions, measured - **A1 (both blockers landed)** — holds. #25214 (`03de83bfe`) wrote the `mode:thread` backend, the effort field, the S/M split and 「项目的 coordinator 跨席位统一调度」; #25242 (`e58bd0e`) wrote a ruling-thread rule that #25348 (merged 2026-10-23) then revoked; item 5 now points at the rule #25348 left in `lanes/director.md` and the runbook's 「终报 `needs_decision` ⇒ 四维分析与推荐并入决裁批次呈维护者裁」 line. Items 2–5 of the new file point at those lines and restate none. - **A2 (SKILL.md 318/319; PR #25247 lowers to 317)** — holds. The `coordinator` row is paid by the director-summons deletion above; the file lands at 318 either way. PR #25247's diff is the 〈域车道〉 table, `lanes/*.md`, `check-half-states.mjs`, `ensure-pm-labels.sh` and the ratchet's SKILL.md / `lanes/server.md` rows — disjoint from every hunk here (the ratchet rows this PR adds sit beside `seat-lifecycle.md`, not beside the lane rows). Whichever lands second merges `main` and re-runs `check:pm-skill-ratchet`. Open PRs touching `.claude/skills/pm-dispatch/**` at claim time: #25247 only (MCP `search_pull_requests`, `is:open pm-dispatch`, 7 hits, one on the skill). - **A3 (new file needs its own ceiling row; id-lint)** — holds, done. `check:pm-skill-id-lint` is green (88 files clean); the new file names rules by file and section only. - **A4 (item 1 vs multiple seats per lane)** — **no contradiction, so no `needs_decision`.** `seat-lifecycle.md` 〈开轮互斥〉 is per seat number (读数三 「同席号」) and says nothing about projects; `seat-post-protocol.md` L9 admits several seat posts per lane. Item 1 adds a constraint one level up — one lane, one project — which several posts per lane can satisfy (one project may run several seats of its lane). What item 1 does contradict is today's **board state**: seat 1 (#7623, `os-bill`'s project) and seat 2 (#19287, this project) both sit `domain:skills`. Seat 1's handover (comment 6343601899) already declares that project leaves the lane once its in-flight cards land, so the double occupancy is the transition the rule converges to, not a second rule. The file spells the arbiter at lane level — a 🟢 post of another project on ANY seat of the lane means the lane is taken — and the release as seat-lifecycle already defines it (the sign-off brief). Read strictly, the rule would have told this project to wait for that brief before sitting seat 2; the contract review should read that sentence and say whether it stands as written. ## Gates Re-merge 2026-10-23: head `72bc519a` merges `main` `5e772c79` (carrying #25348) into the item-5 re-point `3e6e35eb`; on it the same 42 families all exit 0 (`--ran` 42/42), SKILL.md 319/319 (its row paid by the 项目总监席 deletion), dispatch-runbook.md 241/241, coordinator.md 49/49. First run, head `3788440`: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` over the four changed paths derived 42 families (23 pnpm, 19 direct node). Every one was run with its exit code captured before any pipe and recorded as `COMMAND :: exit CODE`; `--ran` reconciles 42/42, 0 NOT-MEASURED, 0 UNRUN. All 42 exit 0. One needed a second run: `pnpm --filter @objectstack/lint run check:doc-formula-expressions` first exited 3 (PREREQUISITE — `@objectstack/lint` unbuilt in a fresh worktree, the same reading PR #25214 recorded); after `pnpm --filter '@objectstack/lint...' build` it exits 0. `check:pm-skill-ratchet`: SKILL.md 318/319, dispatch-runbook.md 241/241, coordinator.md 49/49 (widest table row 0/0). `check:pm-skill-id-lint`: 88 files clean. `check:skill-frame-sync` green (the four-axis frame is untouched). CI's remaining families are the PR's check-runs. No published package moved (`.claude/**` and one `scripts/pm` ledger row), so `skip-changeset` rides this PR's create. ## 维护者速读(草稿) **改了什么:** pm-dispatch 技能新增 `references/coordinator.md`:项目协调者(在项目会话里开席位线程、开卡线程、跨车道调度的那一席)与席位线程之间的接口,按卡上七条写成七节,每节注明读者,只指向规则所在的文件、不复述。SKILL.md 入口表加一行 `coordinator`,用删掉一条已在 `lanes/director.md` 写明的总监召唤行抵账,行数不变;runbook 里「全项目上限 = 各席 batch 之和」改为「由维护者按项目定」。棘轮为新文件加封顶行,无上限抬高。 **为什么改:** 你 10-22 的话:「刚才你让我转帖的项目指令规则,为什么不定义在仓库中呢,我只要穿到具体的车道就行。」——规则进仓库,项目指令只写管哪几条车道。 **风险与代价(含回滚):** 纯规则文本,不碰代码与门禁;回滚即 revert 本 PR。一处值得你看:新文件写「一条车道恒归一个项目」(卡上第 1 条原话),而今天 skills 车道两个项目各坐一席(seat 1 的交接已说它收完在飞卡就退出)。按这条严格读,本项目本应等 seat 1 收班再坐席;契约复核会读这句并给意见。 **席位意见:** **你要做的:** 席位复核 PASS 后,在席位线程点名回一句「#25255 可以落地」。 ## Acceptance notes - The attribution block's first line is an HTML comment the session requires as the body's first line; `os-dev.md` 〈干净收尾〉 forbids HTML comments in GitHub text. Measured on PR #25214 (the same shape), the relay read-back keeps it byte for byte. Reported as a deviation, not hidden. - The claim's `Worktree:` line says 「the card thread's own checkout」; the repo's PreToolUse guards block edits in the primary checkout, so the work was done in a linked worktree (`../objectstack-issue-25219`) on the designated branch, the primary checkout left detached at `e58bd0e`. No deviation from the branch rule: the branch is the one the claim names. - The commit's co-author trailer is the model-free pair the pre-push hook (`check:commit-card-trailers`) requires; the harness's own trailer spelling was refused once and reworded before the first push — the session trailer is the attribution. --- _Generated by [Claude Code](https://claude.ai/code/session_01QbWZBrA43um6tADsbopAAA)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent b62ca78 commit 4e606ce

4 files changed

Lines changed: 63 additions & 2 deletions

File tree

‎.claude/skills/pm-dispatch/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
5454
| `<domain>`(如 `spec`、`skills`) | 以该 `domain:*` 车道的执行座位身份运行 | — |
5555
| `epic:#<n>` | 以父单 #n 的 epic PM 身份运行(见 `references/seat-lifecycle.md` 〈Epic 子树车道〉) | — |
5656
| `director` | 以项目总监席身份运行(人工召唤;三职与章程见 `references/lanes/director.md`) | — |
57+
| `coordinator` | 以项目协调者身份运行(项目会话:开席位线程与卡线程、跨车道调度;接口见 `references/coordinator.md`) | — |
5758
| `label:<name>` | backlog 过滤标签;`label:all` = 全部 open 未认领 | `pm:queue` |
5859
| `repo:<owner/name>` | 扫哪个仓的 backlog(单 issue 的落地仓看它自己的 `repo:*` 标签) | `objectstack-ai/objectstack` |
5960
| `batch:<n>` | 席位同时在飞的子代理总上限,按 `Agent` 调用、`create_session` 与卡线程计:dev、复核、普查皆计,⛔ 只读不豁免 | 默认 `3`;`n` 的维护者天花板 `5` |
@@ -271,7 +272,6 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
271272
- 每问必带推荐项,被 Skip 或长挂即转卡通道,⛔ 不重弹。
272273
- 推送维护者:受管 PR 待批合、决策卡待字、发版、仅其可解之阻 ⇒ 另发 `PushNotification`。
273274
- 一行 ≤200 字,先写动作与编号;每项恰一次,例行进展、刚问刚答与在场即见的不推。
274-
- 项目总监席:维护者在所在仓召唤 `/pm-dispatch director`;⛔ 无 Routine/cron;未回字 = 不在 = 停。
275275
- 总监席档位由维护者按项目人工定,每场记入摘要台账;⛔ 无档位硬门、无免档整理态。
276276
- 总监席是唯一呈裁席:决策箱只经本席呈维护者人工裁;⛔ 无代裁无自裁无子代理。
277277

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# 项目协调者(Project Coordinator)
2+
3+
项目会话里开席位线程与卡线程、跨车道调度的那一席读本文。
4+
它不是 `domain:*` 席:不坐座位贴、不认领卡;席位线程照 SKILL.md 与 `execution-duties.md` 跑循环。
5+
项目指令只写「按仓库规则执行;管 X、Y 车道」;规则住本仓,⛔ 不在项目指令里转贴。
6+
本文只写 coordinator 与席位线程之间的接口,七节各注明读者。
7+
8+
## 一、车道归属登记在座位贴(coordinator 开席位线程前读;席位线程坐席时读)
9+
10+
- 项目管哪些车道只由项目指令声明;每条车道开一个席位线程,坐该车道空着的座位贴。
11+
- 席位线程在贴的说明段写「由 X 账户的项目负责」;贴协议与互斥照 `seat-lifecycle.md`。
12+
- 一条车道恒归一个项目:车道任一座位贴 🟢 标着另一项目 ⇒ 车道已有主,⛔ 不坐别席。
13+
- 仲裁者是座位贴,⛔ 不是项目记忆;另一项目在飞卡由其席跟完,其收班简报在即可坐。
14+
15+
## 二、跨车道取卡(coordinator 每次唤醒读)
16+
17+
- 取卡面 = 本项目各车道 open 的 `priority:p1`/`priority:p2` 卡;候选判据照 `execution-duties.md`。
18+
- 每张卡交其车道的席位线程;车道无席位线程而座位贴空着 ⇒ 先开席位线程再交卡。
19+
- 维护者 ⛔ 不逐卡点名车道:车道读卡的 `domain:*`;S/M 分流见 `dispatch-runbook.md` 卡线程节。
20+
21+
## 三、全项目一个上限,p1 先(coordinator 调度读;席位交候选时读)
22+
23+
- 卡线程上限全项目一个数,由维护者按项目言明;未言明取各席 `batch` 之和。
24+
- 席位随时交候选:卡号、优先级、派发令文件、建议 effort;⛔ 不等自己的槽位。
25+
- coordinator 排队开线程:p1 先于 p2,同级先到先开;满即排队,线程交回或 PR 合入即释放。
26+
- 槽位只算在建的线程:等人(授权批准、决策卡)或等席位复核的卡线程不占槽。
27+
- S 卡的席内子代理只计该席 `batch`,不计本上限。
28+
29+
## 四、effort 与档位按难度(coordinator 开线程时读;席位请线程时读)
30+
31+
- 档位与 effort 的定法住 `execution-duties.md` 派发节:档位引 `dispatch-gates --tier`,effort 按卡难度。
32+
- 改技能(协议语义面)的卡恒契约复审档 `CONTRACT_REVIEW_TIER`;⛔ 不抄模型名。
33+
- 席位请线程附维护者原话,coordinator 开线程那一笔同设 model 与 effort(`dispatch-runbook.md`)。
34+
35+
## 五、卡线程的 `needs_decision`(coordinator 收到时读;席位写分析时读)
36+
37+
- 规则一处:`lanes/director.md` 与 `dispatch-runbook.md` 卡线程节;本文只指不抄。
38+
- 席位写四维分析加推荐,卡并入决裁批次由维护者人工裁;⛔ 无裁决线程、无代裁。
39+
- 等裁的卡线程不占槽(见第三节);裁决记录 = 卡上裁决评论,⛔ 不落项目文件或记忆。
40+
41+
## 六、额度压力(coordinator 每次开线程前读)
42+
43+
- 账号用量墙将近(墙信号与重置读法见 `seat-lifecycle.md`)⇒ 停开新卡线程,在飞的跑完。
44+
- 向维护者说一次即可,⛔ 不逐线程重复;墙过后照常。
45+
46+
## 七、语言与汇报(coordinator 与席位线程皆读)
47+
48+
- 项目内对维护者用维护者的语言;GitHub 内容英文,照 SKILL.md 全体座位不变量。
49+
- 只在结果、阻塞或待裁决时向维护者汇报,与席位同规;例行进展进线程清单。

‎.claude/skills/pm-dispatch/references/dispatch-runbook.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
- 披露纪律卡(私密细节不得离开席位会话)也留席内,认领写明;卡线程照计 `batch`。
134134
- 项目的 coordinator 跨席位统一调度卡线程;每席一个线程跑 PM 循环,卡线程即 dev。
135135
- 席位随时把候选卡交 coordinator,附优先级、派发令文件与建议 effort,⛔ 不等自己的槽位。
136-
- coordinator 按优先级开线程,p1 先;全项目上限 = 各席 `batch` 之和,满即排队。
136+
- coordinator 按优先级开线程,p1 先;全项目上限由维护者按项目定(`coordinator.md`),满即排队。
137137
- 卡线程交回或其 PR 合入,席位当即告知 coordinator 释放槽位。
138138
- 请 coordinator 开线程附维护者原话消息:它只凭维护者明言设线程的 model 与 effort。
139139
- 席位留认领文本、派发令、契约复核、ACCEPT 与落地;线程实施、开 draft PR、驱动 CI。

‎scripts/pm/check-skill-line-ratchet.mjs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,17 @@ export const CEILINGS = new Map([
12501250
// own counts (headroom 0, same convention as every entry above); added rows,
12511251
// paid for by the SKILL.md decrease — the map's total goes down.
12521252
['.claude/skills/pm-dispatch/references/seat-lifecycle.md', 96],
1253+
// The project coordinator's interface with the seat threads (maintainer's
1254+
// word, 2026-10-22, verbatim and untranslated: 「刚才你让我转帖的项目指令规则,为
1255+
// 什么不定义在仓库中呢,我只要穿到具体的车道就行。」): lane ownership on the seat
1256+
// post, cross-lane p1-first intake, one project-wide card-thread cap with
1257+
// waiting threads not counting, effort and tier by difficulty, ruling
1258+
// threads, quota pause, language and reporting — each section naming its
1259+
// reader and pointing at the rule's single source instead of restating it.
1260+
// It is beside seat-lifecycle.md because the coordinator is not a
1261+
// `domain:*` seat. A NEW file, so this is not a raise and funds nothing —
1262+
// set at the landed line count, headroom 0, same convention as above.
1263+
['.claude/skills/pm-dispatch/references/coordinator.md', 49],
12531264
['.claude/skills/pm-dispatch/references/reading-discipline.md', 37],
12541265
['.claude/skills/pm-dispatch/references/cross-repo-coordination.md', 51],
12551266
// Unchanged at 120 through the maintainer's revocation of every autonomous-
@@ -2116,6 +2127,7 @@ export const MAX_TABLE_ROW_BYTES = new Map([
21162127
// The five per-phase references of the principle-only cut carry no table
21172128
// row (their tables stayed in SKILL.md), so each pin is the measurement 0.
21182129
['.claude/skills/pm-dispatch/references/seat-lifecycle.md', 0],
2130+
['.claude/skills/pm-dispatch/references/coordinator.md', 0],
21192131
['.claude/skills/pm-dispatch/references/reading-discipline.md', 0],
21202132
['.claude/skills/pm-dispatch/references/cross-repo-coordination.md', 0],
21212133
['.claude/skills/pm-dispatch/references/triage-duties.md', 0],

0 commit comments

Comments
 (0)