Repository navigation
pm-dispatch runbook: the desktop-launched cloud os-dev path — base branch, model, relay, CI trigger, hand-back and archive, as measured on the first two cloud cards #27214
Description
Observed (epic #26676, 2026-10-28, the first two cloud-dispatched cards #27052 → PR #27120 and #27054 → PR #27163)
The runbook's 「云卡(mode:cloud)四课」 (.claude/skills/pm-dispatch/references/dispatch-runbook.md) describes the claude.ai cloud API path: create_session with source_url / outcome_branch, poke triggers, subscribe_pr_activity. A PM seat running in the Claude desktop app has a second path — start_session with target: cloud — and it behaves differently on six points, each measured this round:
- Base branch. The cloud session clones the branch the app recorded for the launching session, not the current checkout and not
main. That record goes stale (this seat's was a branch deleted after its PR merged two weeks earlier); the session then dies at start withThe requested branch or commit was not found in the repository(upstream: Desktop: a cloud session launched from a local worktree with an unpushed branch dies at start with "branch or commit was not found", and the session can't be recovered anthropics/claude-code#104412, open). Three launches failed before the seat pushed a pointer branch of that exact name atorigin/main. The dispatch order must say the base branch is a pointer, never a place to commit. - Model.
start_session'smodel/effortare ignored fortarget: cloud; the session inherits the launching seat's model. Both cards started on the seat's tier until the maintainer switched them to the claim'sTIER_DEFAULTby hand. A claim for a cloud card must say so, or the seat must launch from a session already on the card's tier. - Relay. In the cloud container the fleet relay (
scripts/pm/fleet-write/dispatch.mjs) auto-selects the dispatch transport with the container's session id — no--session, nofleet.env. Both cards'pr_createand report comments went through it asobjectstack-fleet[bot](2 relay strokes each). - CI. The cloud session's git credential is the Claude GitHub App. Its pushes after the PR exists fire no PR workflow on this repository (
b36136e279on feat(app-shell,plugin-detail,components,i18n): the record page's timeline and related columns are each reader's per-object switches, toggled from the crumb row #27120: five third-party check suites queued, nogithub-actionssuite, whilepr-body-guardslistens tosynchronize); only the fleet bot's PR-open event ran CI. The final head therefore needs one push from a user token — this round that was the seat's local patch round. Either the dispatch order says "open the PR after the last push", or the seat plans a local re-push. - Hand-back. The cloud session cannot message the seat and receives no poke; the PR and the
os-dev-reportcomment on the card are the only hand-back. A REWORK cannot be delivered to it: the patch round runs as a local os-dev agent on the same branch under the same claim (both cards this round). - Archive. The failed and the finished cloud sessions are not visible to the desktop seat's session tools (
list_sessionslists local sessions only); the archive duty (execution-duties.md「归档义务只落在云卡」) falls to the maintainer in claude.ai/code until the seat has a handle.
Positive reading, worth keeping: the cloud session on #27052 read its own CI red (an a11y name collision caught by a #26678 pin outside its touched families) and fixed it before reporting, without a poke.
Target
One addition to dispatch-runbook.md beside the existing four lessons — 「桌面起云会话」, the six points above as six lines, each with its re-check command (get_session self → branch; git ls-remote --heads origin <branch>; the check-suites read on a post-PR push) — and one line in execution-duties.md's cloud rows pointing at it. No new gate (「新增门禁默认否」). Line budget for .claude/skills/**: net +8 lines, paid by tightening the existing cloud lesson wording where it repeats.
Governing text: .claude/skills/pm-dispatch/references/dispatch-runbook.md 〈云卡(mode:cloud)四课〉; references/execution-duties.md the mode:cloud rows; .claude/agents/os-dev.md (each dispatch mode's hand-back is GitHub).
Acceptance
- The six lines are present with their re-check commands;
pnpm check:pm-skill-ratchet(the SKILL.md line ratchet) is unaffected (references only);check:skill-frame-sync/-freshnessgreen. - A seat following the new lesson launches a cloud card without the three failures above.
Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff on 2026-10-28 from the two cloud trials of epic #26676, on the maintainer's instruction (verbatim: 「好,失败的云会话我自己归档,skills 卡等云试派回报后你再立。」). Evidence: PR #27120 comments 6464903026 / 6466520937, PR #27163 comment 6465393909, the epic parent's round-3 checklist, and the seat's reading of check-suites on b36136e279.
Activity
objectstack-fleet commentedon Oct 28, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Triage: p2 ·
domain:skills·area:devpath· 2026-10-28T12:03Z⛔ Not a claim.
mode:cloudlessons describe the API path, while seats now launch cloud os-devs from the desktop app. Base branch, model, relay, CI trigger, hand-back and archive differ, as measured on console: one workspace-preference module (record open mode, drawer width, timeline / related column toggles) read per user × object, with a shared panel-toggle toolbar on the record page — defaults derived from the object, never metadata #27052 and Studio: the object and field inspectors author what the v3 record page reads —relatedList(show / hide / primary), related-list columns / filter / limit on the block, and a new record page starts empty instead of a copy of the synthesized regions #27054. p2: a seat following the runbook launches on a stale base.Generated by Claude Code
objectstack-fleet commentedon Oct 28, 2026
domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1
Claim: PM loop round 1
Session:
session_017xRBcUi2qhP1eKRbZJ1Ze1Account:
sunhaolin(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-27214-desktop-cloud-lessonWorktree:
objectstack-issue-27214Domain:
domain:skillsSeat:
domain:skills#1File surface:
.claude/skills/pm-dispatch/references/dispatch-runbook.md(the 〈云卡(mode:cloud)四课〉 section only; line ceiling 245 / 245, so net 0 lines, paid inside the section) and.claude/skills/pm-dispatch/references/execution-duties.md(themode:cloudrows only; ceiling 188 / 188, net 0) (stop on breach; explain in the report)Container & model:
S(prose judgment, treated as M),mode:subagent,model: TIER_DEFAULT(dispatch-gates --tierthis fire: no path-derived mandate, the surface hits none of the 4 declared globs; PM's per-card call = default),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
n/a — not a defect cardThread-read: 6468481290
Premise: holds (re-checked at
origin/main5b5cff15, 2026-10-28T15:22Z:## 云卡(\mode:cloud`)四课is atdispatch-runbook.md:108; themode:cloudrows stand inexecution-duties.md〈派发〉; the two files were touched today by3af6022(#27266) andd63f24a(#27143), so the dev works from the merged text) Serial constraints cleared: PR #27292 (seat 2, #27117) touchesdispatch-runbook.md:137(the 卡线程 row) andexecution-duties.md:12, 21–22(候选与批次) — region-disjoint from this card's section and rows; this card mergesorigin/mainbefore opening its PR and again once #27292 lands, and the queue arbitrates. PR #27295 (#27062:contract-review.md,triage-duties.md) and seat 2's queued #27061 (SKILL.md,triage-duties.md`) are disjoint.objectstack-fleet commentedon Oct 28, 2026
domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1
os-dev-report
{ "issue": 27214, "status": "done", "branch": "claude/issue-27214-desktop-cloud-lesson", "pr": "https://github.com/objectstack-ai/objectstack/pull/27308", "session": "session_017xRBcUi2qhP1eKRbZJ1Ze1 (mode:subagent; the parent seat's harness id)", "premise_still_valid": true, "summary": "dispatch-runbook.md's cloud section becomes 云卡五课: a new lesson 五 (desktop start_session with target: cloud) carries the six measured points in six lines (L122-L127) — pointer base branch with its re-check (get_session → branch, ls-remote --heads), model/effort inherited from the launching seat, relay self-selects dispatch with no --session, the seat's list_sessions does not see the session, Claude GitHub App pushes after the PR fire no workflow with its re-check (check-suites of that push), hand-back only via PR + report and REWORK as a local os-dev on the same branch and claim. Paid net 0 inside the section by merging six pairs of lines that restated each other (L110-L121; per-line before/after in the PR body). execution-duties.md gains one pointer row (L148) carrying the archive duty for desktop-launched sessions, paid by merging the closure / fixed-overhead rows (L146). Premise held at fa5e7825: no desktop/start_session text existed anywhere under .claude/skills/pm-dispatch or os-dev.md (grep for start_session, target: cloud, 桌面, GitHub App, 指针分支: 0 operational hits).", "line_budget": { ".claude/skills/pm-dispatch/references/dispatch-runbook.md": { "before": 245, "after": 245, "ceiling": 245, "section_content_lines_before": 18, "section_content_lines_after": 18, "widest_new_line_bytes": 120 }, ".claude/skills/pm-dispatch/references/execution-duties.md": { "before": 188, "after": 188, "ceiling": 188, "widest_new_line_bytes": 120 } }, "files_changed": [ ".claude/skills/pm-dispatch/references/dispatch-runbook.md (L108-L127, the cloud-lesson section only)", ".claude/skills/pm-dispatch/references/execution-duties.md (L146-L148, the mode:cloud rows of 派发 only)" ], "tests": "No package touched (.claude/** only): no build closure, no package test/typecheck, no changeset, no ablation (protocol text, no tested behaviour). Byte widths measured per line with Buffer.byteLength before writing: every new/changed line 101-120 bytes. The only build: OS_VERIFY_LOCK_SLOT=issue-27214 bash scripts/pm/os-verify-lock.sh -c 'pnpm exec turbo run build --concurrency=2 --filter=@objectstack/formula --filter=@objectstack/lint' → 'Tasks: 4 successful, 4 total', 'VERDICT command-exit 0 · held the lock 111s', the declared prerequisite of check:doc-formula-expressions. Control-byte self-scan grep -naP over both files: exit 1 (no hit).", "gates": "Derived on head 375a0618 (after merging origin/main 65b49208): node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack → 17 commands, identical to the dispatch's list. Each run with exit captured before any pipe: check-closing-keyword-parity :: 0; check-closing-keyword-parity --self-test :: 0; check-comment-mask-corpus :: 0; pm/check-harness-current --self-test :: 0; @objectstack/lint check:doc-formula-expressions :: 0 (on pre-merge head 593fa8ec it first exited 3, PREREQUISITE NOT MET — formula/lint unbuilt, nothing measured; after the build 0); check:agent-test-spelling :: 0; check:cross-package-test-inputs :: 0; check:doc-authoring :: 0; check:driver-memory-census :: 0; check:gitlink-declared :: 0; check:nul-bytes :: 0; check:pm-governed-merges :: 0; check:pm-skill-id-lint :: 0 ('104 file(s) clean'); check:pm-skill-ratchet :: 0 ('dispatch-runbook.md is 245 lines (ceiling 245; headroom 0)', 'execution-duties.md is 188 lines (ceiling 188; headroom 0)', no length verdict red); check:refd-timer-probe :: 0; check:skill-frame-sync :: 0; check:watch-hint-literal :: 0. Beyond the derivation: check:skill-frame-freshness :: 0 ('current with origin/main'), check:pm-settings-deny-roster :: 0 (roster under .claude). --ran: 'Run reconciliation — 17 derived, 17 run, 0 NOT-MEASURED, 0 UNRUN' / '✓ … 0 NOT-MEASURED (a DERIVED zero — all 17 recorded an exit code and none of them is 3)'. CI on PR 27308 at report time (head 375a0618): Governed Surface Queue Guard success, Check Changeset success; Lint · *, Type Check · *, PR-body guards, Check PR Size in_progress — not waited on per os-dev.md.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0 — no MCP GitHub tool called (reads went through gh api GET: issue 27214 + its comments, comments 6464903026 / 6466520937 / 6465393909, PR 27292, PR 27308 read-back, check-runs of 375a0618)", "api_writes": "3 — (1) relay repository_dispatch fw-20261028T155820Z-cd17de, run 40721321630 success: pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /issues/27308/assignees [sunhaolin] + POST /issues/27308/labels [skip-changeset]; read-back '10629 byte(s) sent, 10629 stored — identical', assignees sunhaolin, labels read back skip-changeset, draft true. (2) this os-dev-report comment via node scripts/pm/post-stamped.mjs --comment=27214. git push ×2 (not REST): empty-branch probe fa5e7825, final 375a0618.", "deviations": [ "Card wish 'net +8 lines' overridden by the ratchet reading per the dispatch's 裁决: net 0 per file, paid in place; no ceiling moved.", "One prohibition was dropped as a restatement, not a rule: 「⛔ 不为提问或中报结束回合」 (old L115) — the same section's 「合法终点仅推送加终报、硬阻塞详报」 (L112) already excludes ending a turn for a question or mid-report. Flagged in open_questions.", "One detail narrowed in execution-duties L146: the parenthetical 「(安装 + 拉缓存)」 defining the fixed overhead is gone; the line still names the cache pull, not the install.", "Card numbering changed: its point 6 (visibility) is ④ and its point 5 (hand-back) is ⑥; the archive half of point 6 lives in execution-duties L148 beside 「归档义务只落在云卡」. 「不为提问」 aside, the API-path rules were compressed in wording only (授权面→授权, 只读勘察→只读, 以车道名开头 shown by the title form, 跨账号接班活性→活性 widened to cover desktop sessions).", "Re-check commands: only ① and ⑤ carry them (the three the card names); ② ③ ④ ⑥ carry none because the card names none.", "Commit trailers: the commit carries the model-free pair (Claude-Session + Co-authored-by: Claude) per AGENTS.md, not the harness reminder's model-named Co-Authored-By; the merge commit 375a0618 carries git's default message with no trailer pair. PR footer: AGENTS.md session-URL form, not the reminder's form.", "Two gates run beyond the derivation (skill-frame-freshness, pm-settings-deny-roster); both exit 0.", "PM hypothesis 2: PR 27292 had already landed (fa5e7825) when the worktree was cut, so no reconciliation was needed; origin/main merged again at 65b49208 before pr_create (neither file changed there). Hypothesis 1 held: the six readings are in the card body and the three fleet-written comments (base branch, relay and archive in the card body only). Hypothesis 4 held: skill-frame-sync / -freshness exit 0." ], "open_questions": [ { "question": "Is dropping 「⛔ 不为提问或中报结束回合」 (old dispatch-runbook L115) acceptable as the negative restatement of 「合法终点仅推送加终报、硬阻塞详报」, or must it be restored?", "options": [ "A keep it dropped — the two-endpoint rule excludes both cases; os-dev.md 干净收尾 ④ carries the same ban for the dev itself (0 lines)", "B restore it — no byte room remains in the section at headroom 0, so it needs a ruled ceiling raise of +1 on dispatch-runbook.md or another in-section merge" ], "recommendation": "A. 实际业务需求: the dispatch words already carry the clause and os-dev.md binds the dev to the two endpoints, so no reader loses the ban; 项目长远合理性: one statement of one rule is the ratchet's intent; 防 AI 写错: the positive closed set (two endpoints) is the stricter spelling — a negative list invites 'but this case is not listed'; 创业阶段不扩散: B spends a ceiling raise on restated text." } ], "out_of_scope_findings": [ "carrier: none · noted, not filed — the relay's auto-selection (lesson ③) is already stated in full in the headers of scripts/pm/with-fleet.sh and scripts/pm/fleet-write/dispatch.mjs; the lesson states only what the seat must not pass (agent-read protocol text, outside the three filing classes)." ] }objectstack-fleet commentedon Oct 28, 2026
domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1
os-dev-report
{ "issue": 27214, "round": "REWORK round 1 (contract-review must-fix)", "status": "done", "branch": "claude/issue-27214-desktop-cloud-lesson", "pr": "https://github.com/objectstack-ai/objectstack/pull/27308", "head": "3809c88b2cbf539f6e7a22ac1f7c203f2ed4d109", "previous_head": "375a0618167b0ab1f4651529d87cfe0aa7542ff1", "session": "session_017xRBcUi2qhP1eKRbZJ1Ze1 (mode:subagent; the parent seat's harness id)", "summary": "dispatch-runbook.md L123 replaced with exactly the line from the review record: 「推…到 `origin/main`」 becomes 「先推同名指针分支(= `origin/main`)」, so it names what the pointer points at, not where to push. Nothing else changed. Occurrence counts on disk: new spelling 1, old spelling 0.", "files_changed": [ ".claude/skills/pm-dispatch/references/dispatch-runbook.md (L123 only; +1 / -1)" ], "line_budget": { ".claude/skills/pm-dispatch/references/dispatch-runbook.md": { "before": 245, "after": 245, "ceiling": 245, "changed_line_bytes": 120, "widest_line_bytes": 120 }, ".claude/skills/pm-dispatch/references/execution-duties.md": { "before": 188, "after": 188, "ceiling": 188, "note": "untouched this round" } }, "gates": "Run on the edited tree before commit, exit captured before any pipe: pnpm check:pm-skill-ratchet :: exit 0 ('dispatch-runbook.md is 245 lines (ceiling 245; headroom 0)', 'execution-duties.md is 188 lines (ceiling 188; headroom 0)'); pnpm check:pm-skill-id-lint :: exit 0 ('104 file(s) clean'); pnpm check:skill-frame-sync :: exit 0; pnpm check:nul-bytes :: exit 0 ('scanned 22095 text file(s) … no raw ASCII control bytes'). Line width: python3 len(line.encode()) = 120.", "api_writes": "1 — this os-dev-report comment via node scripts/pm/post-stamped.mjs --comment=27214 (relay). git push x1 (not REST): 375a0618..3809c88b. No PR body patch, no ready flip, no label write.", "mcp_calls": "0", "deviations": [ "The worktree had been removed after round 0, so it was re-added from the local branch, which matched origin at 375a0618, and pnpm install was run again. The new commit sits on top of the pushed history (no amend, no force)." ] }objectstack-fleet commentedon Oct 28, 2026
domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1
ACCEPT → PR #27308 comment 6474466660 · 2026-10-28T16:21Z. Contract review at
CONTRACT_REVIEW_TIER: FAIL 6474334819 on375a0618(one line read as a push destination), rework round 1 on the same branch, delta PASS 6474438296 on3809c88b. Tier S (.claude/**): the seat lands it (ready + auto-merge) once every check on the head is green; card stayspm:dispatcheduntil MERGED.objectstack-fleet commentedon Oct 28, 2026
domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1
Landed · 2026-10-28T16:51Z · PR #27308 MERGED through the merge queue as
19f49ef35onmain(Tier S, on the in-seat contract-review PASS 6474438296 for head3809c88b; every check green at the landing stroke, governed pre-check Tier S). Card closed byFixes;pm:dispatchedstripped in this act. Readings: ready_for_review 16:34:49Z → added_to_merge_queue 16:34:53Z → merged (timeline, fleet bot).