Repository navigation
Commit 19f49ef
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
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
117 | 114 | | |
118 | | - | |
119 | 115 | | |
120 | | - | |
121 | | - | |
122 | | - | |
| 116 | + | |
| 117 | + | |
123 | 118 | | |
124 | 119 | | |
125 | | - | |
126 | | - | |
127 | | - | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
128 | 128 | | |
129 | 129 | | |
130 | 130 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
143 | 143 | | |
144 | 144 | | |
145 | 145 | | |
146 | | - | |
147 | | - | |
| 146 | + | |
148 | 147 | | |
| 148 | + | |
149 | 149 | | |
150 | 150 | | |
151 | 151 | | |
| |||
0 commit comments