Skip to content

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

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-27214-desktop-cloud-lesson
Oct 28, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-27214-desktop-cloud-lesson

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

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 pm-dispatch(batch): a slot is a RUNNING subagent or card thread — waiting PRs occupy none; the round report counts running and un-landed separately; a soft ceiling of 5 accepted Tier H PRs awaiting a human #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

Derived gates on head 375a061 — 17 derived, 17 run, every exit 0; reconciliation by --ran

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.

Ratchet readings for the two files
✓ 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.


Generated by Claude Code

…th cloud lesson — pointer base branch, inherited tier, relay, post-PR pushes that fire no CI, hand-back and visibility

The 云卡 section gains 五、桌面 start_session (target: cloud): six measured
differences from the API path, each with its re-check where one exists.
Paid line-for-line inside the section by merging restatements (the lane-first
title rule shown by its own form, the turn-end ban stated twice, the poke
stall stated twice, the account-scoped not-found reading over three lines).
execution-duties' cloud rows gain one pointer carrying the archive duty for
desktop-launched sessions, paid by merging the closure / fixed-overhead rows.
Both files stay at their ceilings (245, 188).

Claude-Session: https://claude.ai/code/session_017xRBcUi2qhP1eKRbZJ1Ze1
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 28, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Oct 28, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 375a0618167b0ab1f4651529d87cfe0aa7542ff1
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/dispatch-runbook.md, .claude/skills/pm-dispatch/references/execution-duties.md + .claude/agents/os-dev.md, scripts/pm/with-fleet.sh, scripts/pm/fleet-write/dispatch.mjs, .claude/skills/pm-dispatch/references/lanes/skills.md

① Derived judgments

Diff read against merge base 65b4920 (main a0aa8a1 touched neither file): +18/−18, 245/188 lines kept.

  • Old L110+L111: SURVIVES at L110 「trigger 会话无仓库授权只读,create_session 带 source_url 可推送」.
  • Old L112+L113: SURVIVES at L111 (lane leads the form); 「trigger 流不可指模型」 SURVIVES at L124.
  • Old L114+L116 (停摆等 poke, 两个终点): SURVIVES at L112 「合法终点仅推送加终报、硬阻塞详报」; poke remedy = L117's recipe beside L116's stall read.
  • Old L115 「⛔ 不为提问或中报结束回合」: no literal home on main (grep: 0). SURVIVES in substance: L112's 「仅」 closes the list (a question or mid-report is neither endpoint), L113 keeps the open_questions/fork routing, and os-dev.md L336 「报告只有两种」 + L344 「终消息只能是报告 JSON 或 blocked 报告」 bind the dev to the same set (true in substance, not in those words).
  • Old L118: SURVIVES at L113. Old L120+L121: SURVIVES at L116. L122/L125: wording only.
  • Old L126+L127 「跨账号接班活性只认 GitHub 产出读数」: SURVIVES widened at L121; its own not found clause scopes it to unseen sessions, no clash with L116's get_session read.
  • Exec-duties L146+L147: the rule SURVIVES at L146; the gloss 「(安装 + 拉缓存)」 is LOST, no other home (grep 固定开销: 0), no ≤120-byte spelling restores it — disclosed narrowing, not must-fix.
  • New ① holds (card 1; wording, see ④). ② holds (card 2; both evidence comments). ③ holds (card 3). ④ holds (card 6 visibility half). ⑤ holds (card 4; 6464903026 「no workflow run … no github-actions suite」, both remedies kept). ⑥ holds (card 5). 「实测六异」 = the card's 「six points, each measured」; no line teaches a capability the platform lacks. Archive half: exec-duties L148.
  • Heading reader: git grep -n 四课 origin/main → only the heading itself.

② Semver level

None: .claude/** only, no package publishes it; skip-changeset on the PR, Check Changeset success; Clause-②: no / Metadata-protocol: none consistent.

③ Boundary flags

  • Open question: A, agreed — 「仅」 makes the endpoints a closed list, L113 keeps the routing, os-dev.md L336/L344 carry the same set; B spends a ceiling raise on restated text.
  • net +8 → 0: accepted (headroom 0). Parenthetical: accepted as disclosed. Numbering ④/⑥ vs card 6/5: accepted. Re-checks only on ①/⑤: accepted, the card names exactly three. Trailers: AGENTS.md L444 pair on 593fa8e; bare merge commit moot under squash. Extra gates / hypotheses: noted.
  • Bytes via len(line.encode()): widest new line 120 (runbook L110/L123/L126/L127, exec-duties L146); file-wide max 120 in both.
  • Head CI at read: 45 check-runs, 23 success, 22 skipped, 0 failed / in progress.

④ Design judgment

Scenario: a seat reading 五 pushes the pointer first (①), knows the tier inherits (②), passes no --session (③), reads no death in its unseen session (④, L121), plans the re-push or late PR-open (⑤), knows REWORK (⑥) and archive (L148). Lesson ③ vs headers: with-fleet.sh 「dispatch only when the cloud discriminator, the seat's session (read from CLAUDE_CODE_REMOTE_SESSION_ID) and a live relay all hold」 + dispatch.mjs condition ②: the line names one of three conditions and the right prohibition — understated, not contradicted. Self-contained: no issue numbers in added lines. No anchor checker reads 「云卡五课」.
must-fix: runbook L123 「先推同名指针分支到 origin/main」 parses as a push destination — the one wrong reading on the line that prevents the three start failures. Replace L123 with (120 bytes; house style of old L112 「(= 认领分支)」):
「- 先推同名指针分支(= origin/main),⛔ 不提交其上;复核 get_session→branch、ls-remote --heads。」
Paid in place: same line, same width.

Implemented-by: claude/issue-27214-desktop-cloud-lesson
Reviewed-by: session_017xRBcUi2qhP1eKRbZJ1Ze1

VERDICT: FAIL

Seat note: review run by an isolated at-tier reviewer agent, adopted by the seat (domain:skills#1) at 2026-10-28T16:15Z; the patch round goes back to the original dev on the same branch and claim; a delta review of the fixing commit follows.

…oints at, not where to push

「推…到 `origin/main`」 read as a push destination; 「(= `origin/main`)」 states
the pointer's target. Same width (120 bytes), paid in place.

Claude-Session: https://claude.ai/code/session_017xRBcUi2qhP1eKRbZJ1Ze1
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 3809c88b2cbf539f6e7a22ac1f7c203f2ed4d109
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/dispatch-runbook.md, .claude/skills/pm-dispatch/references/execution-duties.md + .claude/agents/os-dev.md, scripts/pm/with-fleet.sh, scripts/pm/fleet-write/dispatch.mjs, .claude/skills/pm-dispatch/references/lanes/skills.md

① Derived judgments

Delta since 6474334819: git diff 375a0618..3809c88b = one file, one line (dispatch-runbook.md L123), 1+/1−; execution-duties.md untouched. New L123 is byte-for-byte the must-fix line 「- 先推同名指针分支(= origin/main),⛔ 不提交其上;复核 get_session→branch、ls-remote --heads。」 at 120 bytes (len(line.encode())). Every SURVIVES / LOST reading and the six lesson-line readings of 6474334819 are unchanged: no other old or new line moved. Heading reader: unchanged from 6474334819.

② Semver level

Unchanged from 6474334819: .claude/** only, skip-changeset still on the PR, Clause-②: no / Metadata-protocol: none consistent.

③ Boundary flags

  • Open question A and every deviation: unchanged from 6474334819; no new deviation in the delta.
  • Trailers: fixing commit 3809c88 carries the model-free pair (AGENTS.md L444); its sole parent is 375a061 (merge-base --is-ancestor YES), so no pushed history was rewritten.
  • Bytes: widest line 120 in both files (runbook L110/L123/L126/L127, exec-duties L146); runbook 245 lines, exec-duties 188; whole-branch diff vs merge base 65b4920 still 2 files, +18/−18. PR head on GitHub = 3809c88, draft, labels documentation / size/s / skip-changeset.
  • Head CI at the reviewer's read (3809c88): 38 check-runs, 11 success, 18 skipped, 9 in_progress, 0 failed — conclusions NOT MEASURED there; the seat re-reads before landing (reading in the seat record below).

④ Design judgment

Scenario and lesson ③ vs the script headers: unchanged from 6474334819. L123 now names what the pointer branch points at rather than a push destination; the three-start-failure remedy reads one way only. Self-contained: no issue numbers in the changed line.
must-fix: none (the 6474334819 must-fix is closed by 3809c88).

Implemented-by: claude/issue-27214-desktop-cloud-lesson
Reviewed-by: session_017xRBcUi2qhP1eKRbZJ1Ze1

VERDICT: PASS

Seat note: delta review by the same isolated at-tier reviewer agent as 6474334819, adopted by the seat (domain:skills#1) at 2026-10-28T16:19Z.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1

维护者速读(席位终稿,钉 head 3809c88b)

  • 改了什么:pm-dispatch 运行细则的云卡一节由「四课」变「五课」,新增「五、桌面 start_session(target: cloud)」六条实测差异(基底指针分支、模型继承发起席位、中继自选、席位看不见会话、PR 后推送不触发 CI、交回只经 GitHub);执行职责云卡行加一条指针,并写明桌面起的云会话归档落维护者。
  • 为什么改:首两张桌面起的云卡在这六处踩坑(三次开局即死、档位跑错、最终 head 没进 CI),旧文本只描述 API 路径,席位照做会重犯。
  • 风险与回滚:纯协议文本,两文件行数不变(245 / 188,均顶格),每行 ≤120 字节,无脚本、无门禁、无标签;风险是压缩后一条旧规则读得更省略(逐行对照见 PR 正文表格与契约复核 ①);回滚 = revert。
  • 先看:dispatch-runbook.md L122–L127(新五课)与 L110–L121(付账压缩的旧四课);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(.claude/**):达档契约复核 PASS 在案,席位落地(ready + auto-merge)。
  • 席位意见:ACCEPT。砍点逐条核幸存(复核 ①):唯一字面丢失的是「⛔ 不为提问或中报结束回合」,其实质由同节「合法终点仅…」的闭合列表与 os-dev.md 干净收尾 ④ 承载;「(安装 + 拉缓存)」注释为已申报收窄。首版 L123 「推…到 origin/main」读作推送目的地,复核 FAIL 后同分支一轮补丁改为「(= origin/main)」,delta PASS。

席位核对

  • 形态:draft PR,目标 main,正文首行 Fixes #27214,Clause-②: no / Metadata-protocol: none 在正文;skip-changeset(.claude/** 无包发布);assignee sunhaolin;两文件 +18/−18,三个 commit(593fa8ec 任务、375a0618 合 main、3809c88b 补丁)。
  • 前提实测:origin/main 上旧节「云卡(mode:cloud)四课」在 L108;git grep 四课 origin/main 只命中该标题本身,无脚本或他文锚定;PR pm-dispatch(batch): a slot is a RUNNING subagent or card thread — waiting PRs occupy none; the round report counts running and un-landed separately; a soft ceiling of 5 accepted Tier H PRs awaiting a human #27292(席位 2)已在分支切出前落地,无需调和。
  • 门禁 check-runs(钉 head 3809c88b,本席读数时刻见戳):38 check-runs: success 14, skipped 18, in_progress 6; not yet green: Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, Type Check · consumer gates
  • 接受的偏差:① 卡上「净 +8 行」被行棘轮(两文件余量 0)取代为净 0,已申报;② 编号与卡不同(卡 6 → ④,卡 5 → ⑥),归档半边落 execution-duties L148;③ 只有 ①⑤ 带复核命令(卡只点名三条);④ dev 两次 worktree 重建与 check:doc-formula-expressions 先 exit 3 后建包 exit 0,皆如实记录。
  • 范围外去向:中继自选的完整条件住 with-fleet.sh / fleet-write/dispatch.mjs 头注,课文只写席位不得传的参数 —— Acceptance notes,不立卡。
  • 落地条款:Tier S,落地前检 = check-governed-merges.mjs --pr 27308 + 全 check 绿或预期 skip;过则中继 pr_ready + automerge_enable。契约复核记录:FAIL 6474334819(head 375a0618)→ delta PASS 6474438296(head 3809c88b)。

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 28, 2026 16:34
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 19f49ef Oct 28, 2026
41 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-27214-desktop-cloud-lesson branch October 28, 2026 16:50
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/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants