| name | session-orchestration |
| description | Protocol for running work through parent/child agent sessions (e.g., a Claude Code orchestrator session spawning worktree-isolated child sessions or subagents, or any orchestrator dispatching cloud-agent runs). Use this whenever a session spawns or reports to another session, when starting work on a Task issue in a new session, when writing a completion/blocked/failed report, or when deciding what belongs in plan.md versus GitHub. |
Session Orchestration
Session trees and inter-session messages are powerful but app-local: a
cloud agent, a teammate, another machine, or you-next-week cannot see them.
GitHub is the only shared memory. Every rule below exists to keep the durable
record on GitHub while using sessions for speed.
Mapping (the 1:1:1:1 rule)
| Plan object | Session object | Workspace object |
|---|
| Epic issue | Parent (orchestrator) session | — |
| Task issue | One child session | One worktree + branch task/<n>-<slug> (or accepted tool-prefixed variant) + one PR |
One Task issue per child session — never batch several issues into one
session (reports become unattributable) and never split one issue across
sessions without replanning first. Use a separate worktree per concurrent
child so parallel sessions cannot write to the same checkout.
Child session protocol
Start ritual (do this before touching any file):
-
gh issue view <n> — read the full brief: Objective, Context &
references, Origin, Acceptance criteria, Out of scope, File ownership,
Verification, Risk gate, Routing, Handoff notes.
-
Open every referenced agreement (REQ-###, ADR links). If a reference is
missing or contradicts the issue, stop and apply the Ambiguity rule
(AGENTS.md §6) — do not fill gaps with guesses.
-
Write plan.md in the worktree root: restate the acceptance criteria, the
ownership paths, the verification commands, and your step plan. plan.md
is a session cache — convenient, disposable, never authoritative, and
never a substitute for updating the issue. Do not commit it
(add to .gitignore if needed).
-
Comment one line on the issue: Starting in session <name/link>, branch task/<n>-<slug> (or the accepted tool-prefixed variant, AGENTS.md §4).
Now the world knows this task is taken.
-
Post the plan as a comment on the Task issue before your first
commit: goal restated, intended approach, files you expect to touch,
verification you will run. This comment — not plan.md, not the PR
description — is the plan of record. The timeline then reads work order
(body) → start → plan → outcome, which is what makes deviations
diagnosable from one page.
-
Risk gate: if the Task issue carries the risk:high label, stop
after posting the plan comment and wait for a human approval comment
that quotes the exact URL of that plan comment before the first file
change — approval of a different plan, or an agent-authored approval,
does not open the gate, and a revised plan needs fresh approval
(ADR-0002 item 7). The default for unlabeled tasks is pass-through —
the gate exists only for labeled exceptions (plan-management skill,
Intervening).
Surfaces that write a plan into the PR description automatically (e.g. the
cloud agent) produce a convenient copy: link the plan comment from the PR
description and treat the issue timeline as authoritative.
Work loop: stay inside the ownership paths; commit early and often;
update plan.md freely — and when the plan changes materially, post a
fresh plan comment on the issue (never edit the old one; the sequence of
plan comments is the plan's history). If scope drifts, stop and follow the
Ambiguity rule rather than quietly expanding.
Verify (before any completion claim): run every command in the issue's
Verification section; then confirm external state with commands, e.g.
gh pr view <pr> --json state,statusCheckRollup, gh pr checks <pr>,
git status --short (must be clean), and, when the task tracked Project
items, gh project item-list. Evidence = command + observed result.
Record before report — post this comment on the Task issue, then (and
only then) message the parent:
## Outcome: <completed | blocked | failed | needs-replan>
**PR:** #<pr-number>
**Evidence:**
| Criterion | Evidence (command / link) | Result |
|---|---|---|
| AC1 ... | `pio test -e native` -> 12 passed | pass |
**Deviations:** <none, or what differs from the brief and why>
**Follow-ups:** <suggested downstream issue changes, or none>
**Scaffold friction:** <none | retro:candidate issue link>
The Scaffold friction line is optional: fill it when you filed or +1'd a
retro:candidate issue during the task (retro skill, §Candidate ledger).
The message to the parent is a pointer, not a payload: outcome word + issue
and PR links. If the parent session is gone, the record still stands — that
is the point.
Parent session protocol
- Dispatch only from the frontier (
plan-management skill), after checking
that concurrently dispatched tasks have disjoint File-ownership paths.
- Issue-first, dedicated-session — no exceptions for infra/ops. Ad-hoc
requests (e.g. a human asking "can you deploy this?"), and cloud/deploy/
infra work in general (provisioning, secrets, deploy unblocking), get a
Task issue created before any work begins, and run in a dedicated child
session like any other task — never inline in the parent. No issue, no
work: evidence recorded after the fact on a closed issue does not count.
- When delegating, pass the issue number only — the issue is the brief. If
you feel the need to add substantial instructions in the dispatch message,
the brief is incomplete: fix the issue first.
- Steer with short course-correction messages when session logs show drift;
prefer steering over restarting.
- On receiving a report: verify the record exists on the issue and spot-check
the evidence with your own
gh calls before updating labels/Project state
or dispatching dependents. An unrecorded report is returned to the child
with one instruction: record first.
- Route
needs-replan outcomes to the planner procedure
(plan-management §Replanning) and post the rationale on the Epic.
Resume protocol (crash-only)
There is no dedicated resume machinery — by design. Sessions are
crash-only: any session may vanish at any point, and recovery is always
the same procedure, because the ledger (issue timelines) plus the
artifacts (branches, PRs, checks) already hold the current position.
- Resume = start ritual + derivation. A successor re-runs the start
ritual (AGENTS.md §9), then derives where things stand from the Task
issue timeline (work order → start → plan → latest comment) and the
artifacts (
git log, gh pr view, gh pr checks) — never from a
predecessor's memory or session messages.
- Orphan detection is the parent's duty. An orphaned task's signature:
start comment present, no Outcome comment, session gone. Parents scan
their dispatched tasks for that signature; nobody else will.
- Ownership transfers by resume comment. Before touching files, the
successor posts a resume comment on the Task issue ("Resuming from
; position derived from "). One task, one
live session — the resume comment is what makes the swap visible and
prevents double-driving.
- Same failure twice across sessions → human. If a successor dies the
same way its predecessor did, escalate per AGENTS.md §6 instead of
burning a third session. (Distinct from the in-loop three-strikes rule
(verification skill), which counts retries against the wall within one
session.)
Escalation to humans
Escalate (label needs:human, stop the affected line of work) when: an
agreement in docs/agreements/ turns out wrong; credentials/security issues
appear; the same task fails twice with different approaches; or two sessions
claim the same ownership paths. These are judgment or trust failures, not
execution failures — humans own those.