Skip to content

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

Closed

Description

@objectstack-fleet

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:

  1. 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 with The 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 at origin/main. The dispatch order must say the base branch is a pointer, never a place to commit.
  2. Model. start_session's model / effort are ignored for target: 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's TIER_DEFAULT by hand. A claim for a cloud card must say so, or the seat must launch from a session already on the card's tier.
  3. 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, no fleet.env. Both cards' pr_create and report comments went through it as objectstack-fleet[bot] (2 relay strokes each).
  4. 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 (b36136e279 on 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, no github-actions suite, while pr-body-guards listens to synchronize); 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.
  5. Hand-back. The cloud session cannot message the seat and receives no poke; the PR and the os-dev-report comment 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).
  6. Archive. The failed and the finished cloud sessions are not visible to the desktop seat's session tools (list_sessions lists 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 / -freshness green.
  • 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

  1. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Triage: p2 · domain:skills · area:devpath · 2026-10-28T12:03Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    and removed on Oct 28, 2026
  3. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1

    Claim: PM loop round 1
    Session: session_017xRBcUi2qhP1eKRbZJ1Ze1
    Account: sunhaolin (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-27214-desktop-cloud-lesson
    Worktree: objectstack-issue-27214
    Domain: domain:skills
    Seat: domain:skills#1
    File 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 (the mode:cloud rows 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 --tier this fire: no path-derived mandate, the surface hits none of the 4 declared globs; PM's per-card call = default), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6468481290
    Premise: holds (re-checked at origin/main 5b5cff15, 2026-10-28T15:22Z: ## 云卡(\mode:cloud`)四课is atdispatch-runbook.md:108; the mode: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.

  4. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    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)."
      ]
    }
  5. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    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)."
      ]
    }
  6. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1

    ACCEPT → PR #27308 comment 6474466660 · 2026-10-28T16:21Z. Contract review at CONTRACT_REVIEW_TIER: FAIL 6474334819 on 375a0618 (one line read as a push destination), rework round 1 on the same branch, delta PASS 6474438296 on 3809c88b. Tier S (.claude/**): the seat lands it (ready + auto-merge) once every check on the head is green; card stays pm:dispatched until MERGED.

  7. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1

    Landed · 2026-10-28T16:51Z · PR #27308 MERGED through the merge queue as 19f49ef35 on main (Tier S, on the in-seat contract-review PASS 6474438296 for head 3809c88b; every check green at the landing stroke, governed pre-check Tier S). Card closed by Fixes; pm:dispatched stripped in this act. Readings: ready_for_review 16:34:49Z → added_to_merge_queue 16:34:53Z → merged (timeline, fleet bot).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:skillspriority:p2Medium: important, M3tooling

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions