Skip to content

Commit 19f49ef

Browse files
pm-dispatch(runbook): the desktop-launched cloud os-dev path as a fifth cloud lesson — pointer base branch, inherited tier, relay, post-PR pushes that fire no CI, hand-back, visibility (#27308)
Fixes #27214 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:pm-dispatch 运行细则的云卡一节由「四课」变「五课」,新增「五、桌面 `start_session`(`target: cloud`)」六条实测差异(基底指针分支、模型继承发起席位、中继自选、席位看不见会话、PR 后推送不触发 CI、交回只经 GitHub);执行职责云卡行加一条指针,并写明桌面起的云会话归档落维护者。 - 为什么改:首两张桌面起的云卡在这六处踩坑(三次开局即死、档位跑错、最终 head 没进 CI),旧文本只描述 API 路径,席位照做会重犯。 - 风险与回滚:纯协议文本,两文件行数不变(245 / 188,均顶格),每行不超 120 字节,无脚本、无门禁、无标签;风险是压缩措辞后某条旧规则读得更省略(逐行对照见下);回滚 = revert 本 PR。 - 先看:`.claude/skills/pm-dispatch/references/dispatch-runbook.md` L122–L127(新增五课六行)与 L110–L121(付账压缩的旧四课);`references/execution-duties.md` L146、L148。 - 两分钟验证:`pnpm check:pm-skill-ratchet` —— 两文件各印 `245 lines (ceiling 245; headroom 0)` 与 `188 lines (ceiling 188; headroom 0)`;`sed -n 122,127p .claude/skills/pm-dispatch/references/dispatch-runbook.md` 看到 ①–⑥。 - 需要你做的:无,席位落地(Tier S:达档契约复核 PASS 后由席位入队)。 ## What changes Two protocol files, every edit inside the claimed surface (the cloud-lesson section of `dispatch-runbook.md`, the `mode:cloud` rows of `execution-duties.md` 〈派发〉). Neither file gains or loses a line; every prose line is at most 120 bytes; no re-wrap is used as currency: each freed line comes from merging two rules that restated each other, never from re-flowing the same text. Base `fa5e7825`, head `375a0618`. Bytes are UTF-8 without the newline. In the quotes below the angle-bracket placeholders of the source lines are spelled LANE / NUM / PHRASE / N, because the body sanitizer eats bracket-shaped fragments; the file keeps its original spelling. ### `dispatch-runbook.md` — the section heading becomes 「云卡(`mode:cloud`)五课」; 18 content lines before, 18 after | Old line(s) | New line · bytes | What was compressed, and where each rule now lives | |:--|:--|:--| | L110 + L111 (95 + 63) | L110 · 120 | 「授权随 source 不随环境」 stays; trigger sessions: no repo authorization, read-only; `create_session` with `source_url` can push. Dropped words only: 拉起的, 勘察, 出生即持…授权 → 可推送. | | L112 + L113 (102 + 90) | L111 · 119 | `outcome_branch` (claim branch), explicit `model`, `title` in the form `⚡ LANE #NUM PHRASE`, ⛔ not named os-dev. 「以车道名开头」 is what the form itself shows (LANE leads), so it is a restatement. 「trigger 流不可指模型」 moves to L124 ②, where it merges with the desktop half of the same fact. | | L114 + L116 (80 + 76) | L112 · 118 | Self-drive clause; the session stops when its turn ends; the only legal endpoints are push + final report or a detailed hard-blocked report. 「等 poke」 is L117's remedy line, kept there. | | L115 + L118 (115 + 66) | L113 · 118 | Implementation choices into `open_questions`, product behaviour / contract → fork; unattached sister repos unreachable, the PM files the cross-repo follow-up. 「⛔ 不为提问或中报结束回合」 is the negative restatement of L112's two-endpoint rule (a question or mid-report is neither endpoint), so it is the line's payment. | | L117, L119 | L114, L115 · unchanged | — | | L120 + L121 (82 + 91) | L116 · 118 | Subscribe the moment the draft PR exists (hard step); `get_session` reads state, IDLE with nothing pushed = stalled. 「停摆待 poke」 restated L114's stall. | | L122 (118) | L117 · 105 | 「投递消息用绑会话 poke 触发器」 → 「poke 用绑会话触发器」; the recipe is byte-identical. | | L123, L124 | L118, L119 · unchanged | — | | L125 (105) | L120 · 102 | 「是账号作用域的」 → 「按账号作用域」. | | L126 + L127 (70 + 89) | L121 · 116 | Indistinguishable from never-existed, ⛔ never read as a death signal; liveness only from GitHub output, which is why the report is delivered at draft-PR time. 「跨账号接班」 is widened to plain 「活性」 because ④ below needs the same reading for desktop-launched sessions. | | — | L122–L127 · 116 / 120 / 116 / 118 / 120 / 120 | 五、the desktop path, six measured points: ① the session clones the branch recorded for the launching session, a deleted one kills it at start; push a same-name pointer branch at `origin/main` first, ⛔ never commit to it; re-check `get_session` → `branch` and `ls-remote --heads`. ② `model` / `effort` cannot be set (as on the trigger flow); the session inherits the launching seat's tier, so the claim says so or the seat launches from a session already on the card's tier. ③ the relay picks `dispatch` from the container session id, ⛔ no `--session`. ④ the seat's `list_sessions` lists local sessions only and does not see it. ⑤ pushes by the Claude GitHub App after the PR exists fire no workflow (re-check: the check-suites of that push): open the PR after the last push, or plan a user-token re-push. ⑥ it receives no poke and cannot message the seat; the PR and the report comment are the only hand-back; a REWORK runs as a local os-dev on the same branch under the same claim. | ### `execution-duties.md` — 188 lines before and after | Old line(s) | New line · bytes | What | |:--|:--|:--| | L146 + L147 (95 + 79) | L146 · 120 | One build-heavy subagent per container at a time; the cloud session builds its closure from the turbo remote cache; the first such dispatch records its measured fixed overhead on its card. The parenthetical (install + cache pull) is the one detail narrowed: the line names the cache pull, not the install. | | — | L148 · 116 | A cloud card launched by desktop `start_session` follows lesson 五 of the runbook's cloud section; the seat cannot see its session, so its archive falls to the maintainer. Placed right after 「归档义务只落在云卡」, which it qualifies. | ## Tests No package is touched (`.claude/**` only): no build closure, no package test or typecheck, no changeset (`skip-changeset` declared at `pr_create`), no ablation (protocol text, not tested behaviour). The gates are the test; see Verification. The only build run was `@objectstack/formula` + `@objectstack/lint`, the declared prerequisite of `check:doc-formula-expressions`. ## Acceptance notes - The card asked for net +8 lines; the line ratchet holds both files at headroom 0 and no ruling raises a ceiling, so every added line is paid inside the same section or rows (net 0 per file). - The card's numbering is changed: its point 6 (visibility) is ④ here and its point 5 (hand-back) is ⑥; its archive half lives in `execution-duties.md` L148, beside the archive duty it qualifies. - Re-check commands: the card names three (`get_session` → `branch`, `git ls-remote --heads origin BRANCH`, the check-suites of a post-PR push); all three are on ① and ⑤. ② ③ ④ ⑥ carry none because the card names none, and the desktop seat cannot read a cloud session's state (④). - The readings are carried as measured on the first two desktop-launched cloud cards, from the card body and the fleet-written review comments on the two PRs it cites; no cloud session was re-run. - PR #27292 (the slot-definition card on the same two files) had already landed at `fa5e7825` when this branch was cut, so there was nothing to reconcile; `origin/main` was merged again at `65b49208` before opening (neither file changed there). - Observation, not filed (agent-read protocol text, outside the three filing classes; carrier: none): the relay's auto-selection (③) is already stated with full detail in the headers of `scripts/pm/with-fleet.sh` and `scripts/pm/fleet-write/dispatch.mjs`; the lesson line states only what the seat must not pass. ## Verification <details><summary>Derived gates on head 375a061 — 17 derived, 17 run, every exit 0; reconciliation by --ran</summary> `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (change set from the merge base, 2 paths, +18 / -18), each run with its exit code captured before any pipe: ``` 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 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 pnpm check:skill-frame-freshness :: exit 0 (local-only, outside the derivation) pnpm check:pm-settings-deny-roster :: exit 0 (roster under .claude, outside the derivation) ``` `--ran`: `Run reconciliation — 17 derived, 17 run, 0 NOT-MEASURED, 0 UNRUN.` · `✓ dispatch-gates --ran: 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).` On the pre-merge head `593fa8ec` the same 17 were run first; `check:doc-formula-expressions` exited 3 (PREREQUISITE NOT MET: `@objectstack/formula` and `@objectstack/lint` not built — nothing measured), and after the build it exited 0. </details> <details><summary>Ratchet readings for the two files</summary> ``` ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 245 lines (ceiling 245; headroom 0). ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/execution-duties.md is 188 lines (ceiling 188; headroom 0). ✓ check-skill-id-lint: 104 file(s) clean (pattern /#[0-9]{3,}/g). ✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent ✓ check-skill-frame-freshness: the decision frame in this tree is current with origin/main (fetched just now). ``` A line over 120 bytes would have printed a red length verdict; none did. </details> --- _Generated by [Claude Code](https://claude.ai/code/session_017xRBcUi2qhP1eKRbZJ1Ze1)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 02a891e commit 19f49ef

2 files changed

Lines changed: 18 additions & 18 deletions

File tree

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,26 +105,26 @@
105105
- 无权执行 ⇒ 点名有权者,并当轮换标把状态搬进对方的收件箱视图或决策箱。
106106
- ⛔ 不许只留一条评论等人路过:评论不是任何人的收件箱,标签才是。
107107

108-
## 云卡(`mode:cloud`)四课
109-
110-
- 一、授权面随 source 不随环境:trigger 拉起的会话无仓库授权,只读勘察。
111-
- `create_session` 带 `source_url` 出生即持推送授权。
112-
- 同时带 `outcome_branch`(= 认领分支)、显式 `model`(trigger 流不可指模型)、`title`。
113-
- `title` 以车道名开头,⛔ 不叫 os-dev,形如 `⚡ <车道> #<单号> <短语>`。
114-
- 二、派发词必带自驱条款:云会话回合一结束即停摆等 poke。
115-
- ⛔ 不为提问或中报结束回合;实现取舍自定记入 `open_questions`;碰产品行为/契约报 fork。
116-
- 合法回合终点只有两个:推送完成加终报,或硬阻塞详报。
108+
## 云卡(`mode:cloud`)五课
109+
110+
- 一、授权随 source 不随环境:trigger 会话无仓库授权只读,`create_session` 带 `source_url` 可推送。
111+
- 带 `outcome_branch`(认领分支)、显式 `model`、`title`(`⚡ <车道> #<单号> <短语>`,⛔ 不叫 os-dev)。
112+
- 二、派发词必带自驱条款:云会话回合一完即停摆,合法终点仅推送加终报、硬阻塞详报。
113+
- 取舍自记 `open_questions`,产品行为/契约报 fork;姊妹仓未 attach 够不着,跨仓跟进卡 PM 代立。
117114
- 三、交付通道:dev 自开 draft PR(`Fixes #<n>` 只写正文,`partof-closing-keyword` RULE 2,含验证记录)。
118-
- 未 attach 的姊妹仓够不着,跨仓跟进卡由 PM 代立。
119115
- trigger 定时会话维持降级通道:推送 outcome branch,终报走最后一条会话消息,PM 代开 draft PR。
120-
- 四、云卡 draft PR 一存在立即 `subscribe_pr_activity`,这是硬步骤。
121-
- 监控与转向:`get_session` 读实时状态,IDLE 加分支未推送 = 停摆待 poke。
122-
- 投递消息用绑会话 poke 触发器:`create_trigger` 带 `persistent_session_id` 加 `fire_trigger`,用后删。
116+
- 四、draft PR 一存在即 `subscribe_pr_activity`(硬步骤);`get_session` 读状态,IDLE 且未推送即停摆。
117+
- poke 用绑会话触发器:`create_trigger` 带 `persistent_session_id` 加 `fire_trigger`,用后删。
123118
- 巡检退为兜底心跳,只补订阅盲区:会话停摆、未开 PR 的分支、姊妹仓动静。
124119
- roster 不可达与 `SendMessage` 同裁,`ListAgents` 同列不到,⛔ 不复测。
125-
- 会话句柄是账号作用域的:三个会话工具对另一账号建的会话一律答 `not found`。
126-
- 该答案与从不存在不可区分,⛔ 永不读作死亡信号。
127-
- 跨账号接班活性只认 GitHub 产出读数,draft-PR 时点交报正为此存在。
120+
- 会话句柄按账号作用域:三个会话工具对另一账号建的会话一律答 `not found`。
121+
- 该答案与不存在不可区分,⛔ 不读作死亡信号;活性只认 GitHub 产出,draft-PR 即交报为此。
122+
- 五、桌面 `start_session`(`target: cloud`)实测六异。① 克隆发起会话所记分支,已删即开局死:
123+
- 先推同名指针分支(= `origin/main`),⛔ 不提交其上;复核 `get_session`→`branch`、`ls-remote --heads`。
124+
- ② `model`/`effort` 同 trigger 流不可指:继承发起席位档,认领写明,或从卡档位的会话发起。
125+
- ③ 中继凭会话 id 自选 `dispatch`,⛔ 不传 `--session`;④ 席位 `list_sessions` 只列本地,不见它。
126+
- ⑤ Claude GitHub App 的 PR 后推送不触发工作流(复核 check-suites):末推后开 PR 或用户令牌重推。
127+
- ⑥ 收不到 poke 也发不了消息,只经 PR 与报告评论交回;REWORK 由本地 os-dev 同分支同认领接。
128128

129129
## 卡线程(`mode:thread`)
130130

‎.claude/skills/pm-dispatch/references/execution-duties.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@
143143
- 资源与后端:S 级机械 + M ⇒ `mode:subagent`;S 级但不机械(判断面在设计不在门禁)按 M 待遇。
144144
- `mode:cloud` 只保留给 L/XL、活过 PM 会话的工作、浏览器/dogfood 验证;build 重的 M 卡逐卡判。
145145
- 申报文件面写 `packages/spec/src/**` 且至少另一包 ⇒ build 重,派 `mode:cloud`,一卡一容器。
146-
- 一容器同时至多跑一个 build 重子代理;云会话建闭包拉 turbo 远程缓存。
147-
- 首张这类派发实测固定开销(安装 + 拉缓存)并记在其卡上。
146+
- 一容器同时仅一个 build 重子代理;云会话建闭包拉 turbo 远程缓存,首张实测固定开销记卡。
148147
- 归档义务只落在云卡;OOM 死的单独重派;判定连同档位写进认领评论。
148+
- 桌面 `start_session` 起的云卡照 runbook〈云卡五课〉五;席位看不见其会话,归档落维护者。
149149
- 一次性云卡用 `create_session`,⛔ 不用 create_trigger+fire;trigger 流只留给定时/重复型。
150150
- 接手中断的 dev:先试 SendMessage 复活,不可用才走接手协议,⛔ 不重跑原派发词。
151151

0 commit comments

Comments
 (0)