plugin/skills/control-session-orchestrator/SKILL.md
Control-plane workflow for coordinating multi-agent, multi-session project work from a single Codex, GitHub Copilot, or agent-app control session. Use this skill whenever the user asks to orchestrate agents, create or steer worker sessions, run a workflow-like effort, fan out audits/research/migrations, coordinate parallel implementation streams, monitor other project sessions, or compare this control-session pattern to Claude Code dynamic workflows. This skill is especially relevant when the current session can spawn persistent project sessions and those sessions can spawn their own subagents, creating a two-level orchestration hierarchy.
npx skillsauth add pskoett/pskoett-ai-skills control-session-orchestratorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use the current session as the control plane for project work that is too broad, risky, or stateful for one conversation. The control session owns intent, decomposition, routing, status, verification, and consolidation. Worker sessions own scoped execution. Worker subagents are local implementation/research/audit helpers inside each worker session.
User
-> Control session (strategy, dispatch, tracking, integration)
-> Worker project session A (persistent branch/workstream)
-> Subagents for research, implementation, review, tests
-> Worker project session B (persistent branch/workstream)
-> Subagents for local fan-out
-> Verifier/reviewer session (optional independent gate)
This is similar to dynamic workflows, but the orchestration is human-readable and session-native instead of a runtime script. Use it when persistence, branches, PRs, human steering, or cross-session continuity matter more than fully automated fan-out.
A code runtime gets reliability for free (validated results, barriers, budgets, dedup, resume). A prompt-driven control plane only gets it if you make state machine-checkable. Two contracts do that without a runtime: a required worker result block and a durable control-state manifest (see Machine-checkable contracts). Everything else in this skill keys off those two artifacts — without them, "is this worker done and passing?" is a guess, not a field read.
This skill is app-agnostic. First discover which orchestration tools are available in the current session, then adapt the same control workflow to that surface.
| Capability | Codex app | GitHub Copilot app | Fallback | |---|---|---|---| | Find worker sessions | List/search project threads | List/search app sessions | Ask user for target session links/IDs | | Create persistent workstreams | Create or reuse Codex threads/worktrees when available | Create or reuse Copilot app sessions/workspaces when available | Use local subagents only | | Steer an existing workstream | Send a follow-up prompt to the thread | Send a follow-up prompt to the session | Ask user to paste the prompt into the worker | | Local fan-out | Spawn subagents from this session or ask workers to spawn their own | Use Copilot's available agent/session tools | Keep work local | | Tracking | Thread titles, pins, branches, PRs, canvas nodes, compact status tables | Session names, branches, PRs, issues, canvas nodes, compact status tables | Markdown status table |
Do not assume the GitHub Copilot or Codex tool names. Use the tools exposed in the current environment, and say which control surface is active before dispatching workers.
Use this skill for:
Do not use it for a simple one-file fix, a quick answer, or a task where a single local subagent is enough. Orchestration has overhead; spend it only when coordination reduces risk or increases throughput.
These are the session-native analog of a runtime's typed results and durable run state. They stay human-readable, but they are required, not advisory — the control session parses them instead of re-reading prose.
Every worker MUST end its report with a fenced ```json block tagged control-result. The control
session reads this block (never the surrounding prose) to update state, dedup, and decide routing.
{
"worker_id": "auth-api",
"wave_id": "w1",
"unit_key": "service/auth",
"scope": "src/auth/** — refresh-token rotation",
"status": "complete",
"files_changed": ["src/auth/rotate.ts"],
"verification": { "command": "pnpm test auth", "result": "pass", "evidence": "42 passed" },
"subagents_used": "2 — one research, one test author",
"risks": ["rotation interacts with logout; covered by test"],
"next_step": "ready for review session",
"report_ref": "thread/PR/path to the full report"
}
The block must be strict JSON (no comments/trailing commas) so it parses. status is one of
complete | blocked | needs-decision | failed; verification.result is one of pass | fail | not-run.
One durable artifact that is the source of truth for the mission — a pinned control thread, a
tracking-issue body, a canvas node, or a committed control/state.json. Re-read and update it every
turn; keep the conversation for decisions, not state. One row per unit (unit-keyed, so the same
unit is never dispatched twice — this is the dedup ledger).
{
"mission": "MCP tool parity audit",
"non_goals": ["no behavior changes"],
"success_criteria": ["every tool present in server, HTTP, SDK, docs or flagged"],
"budget": { "max_concurrent_workers": 5, "max_total_workers": 25, "spawned": 0, "in_flight": 0 },
"convergence": { "rule": "single-pass", "k_empty": 2, "empty_streak": 0, "target": null, "current": 0 },
"workers": [
{
"unit_key": "surface/http",
"worker_id": "http-audit",
"session_ref": "thread-or-session id/link",
"scope": "HTTP API surface",
"branch_or_pr": "—",
"status": "pending",
"wave_id": "w1",
"last_update": "ISO-8601",
"evidence_ref": "report_ref from the result block",
"verification": "not-run",
"blocker": null
}
],
"decisions": [],
"open_followups": []
}
Rules:
complete | blocked | needs-decision | failed.pending | dispatched | needs-decision | blocked | stalled | complete | failed | dropped. Worker-reported values are a
subset of these, so setting a unit's status from a worker block (Step 5) is always valid.complete | failed | dropped. Everything else is
non-terminal and must be resolved, or explicitly converted to dropped with a reason, before the
mission closes (Step 8).budget.in_flight is the number of rows currently dispatched. Increment spawned and in_flight
on dispatch; decrement in_flight when a unit leaves dispatched; recompute it from the rows on
rehydrate.convergence.rule is one of single-pass | loop-until-dry | loop-until-budget | accumulate-to-target. k_empty/empty_streak are used only by loop-until-dry; target/current
only by accumulate-to-target (target = the count or coverage goal, current = progress so far).open_followups.This manifest is what a fresh control session rehydrates from (Step 0).
On session start, look for an existing control-state manifest for this mission. If one exists:
session_ref and reconcile each worker's real status (read the thread/PR)
before any new dispatch.budget.in_flight from the rows still marked dispatched.dispatched or complete — route a follow-up instead.If no manifest exists, this is a new mission — create one during Step 1.
Before spawning anything, capture (and write into the manifest):
Also set explicit limits up front (manifest budget and convergence):
max_concurrent_workers (default ~4–6) — never more in flight at oncemax_total_workers — a lifetime backstop for the whole mission (e.g. 25)single-pass for bounded missions; loop-until-dry, loop-until-budget,
or accumulate-to-target for open-ended audits/migrations/parity sweepsIf any boundary is ambiguous and could cause conflicting edits, ask before dispatch.
Before dispatch, identify the available app tools:
If no persistent-session tools are available, downgrade to a local multi-agent plan and explain the limitation. Do not invent a backend.
Pick the smallest useful topology:
Prefer separate sessions when workers may edit overlapping history, need different branches, or need long-running context. Prefer local subagents inside one session when the task is exploratory and does not need persistent branch state.
Respect the budget: never dispatch while in_flight >= max_concurrent_workers — queue the unit
(status: pending) and log it. On reaching max_total_workers or a token/cost ceiling, STOP
dispatching and surface a Decision needed rather than spawning more. Dispatch is an atomic
manifest update: set the unit's row to status: dispatched (with session_ref, worker_id,
wave_id, last_update) and increment spawned and in_flight together; if the dispatch fails to
start, leave the row pending and advance neither counter. Decrement in_flight when a unit leaves
dispatched (it reaches a terminal state, or returns to needs-decision/blocked/stalled) so
queued units can start. This keeps in_flight equal to the count of dispatched rows that Step 0
recomputes.
Each worker prompt should be self-contained. Include:
unit_key)Worker prompt template:
You are worker <name> for <project>.
Mission: <specific outcome>
unit_key / wave_id: <key> / <wave>
Scope: <files/subsystems/issue/PR>
Do not touch: <boundaries>
Approach: <expected plan or constraints>
Verification: <commands/checks/evidence>
You MAY use your own subagents for local research, implementation, and review, but you remain
accountable for this scope and the final report. Do NOT create or steer further persistent project
sessions — if the work needs another full workstream, say so in next_step.
End your report with a fenced ```json control-result block (see the contract). Populate every field;
record subagents you used in subagents_used. The control session reads only that block.
When using Codex app controls, prefer to rename and pin important worker/control threads so the session graph stays legible. When using GitHub Copilot app controls, use the corresponding session or workspace labels if exposed.
The control-state manifest is the single source of truth — update it every turn, not the
conversation. From each worker's result block, set the unit's status, evidence_ref (= the block's
report_ref), verification (= the block's verification.result), and — when status is blocked
or needs-decision — blocker (the block's blocking reason; otherwise null). The control session
records the remaining fields itself: stamp last_update from its own clock, and set branch_or_pr
from the worker's session/PR metadata when known (workers don't self-report it in the block). Keep the
control session's context focused on summaries and decisions, not full transcripts; the full report
lives at report_ref.
Track at least, per unit: unit_key, worker_id, session_ref, scope, status, branch/PR, last
update, blocker, and verification state — matching the row schema above. Canvas nodes or a SQL/todo
table are good backends for the manifest when the app exposes them.
When a worker reports, first run the result-gate:
control-result block. If a required field is missing or malformed, or the status is
inconsistent with evidence (e.g. status: complete with verification.result != pass), do NOT
accept it — send exactly one standardized re-prompt asking only for the corrected block. Cap at 2
retries, then escalate to the user.Then route:
For multi-wave missions, after routing a wave's follow-ups, apply the declared convergence.rule
before consolidating:
k_empty consecutive waves produce zero new
(deduped) units; maintain empty_streak in the manifest."New" and "dry" are measured against the manifest's set of unit_keys, not memory. Never stop
silently — write why iteration ended (open_followups / decisions).
Before declaring the mission done:
Wave-join / completeness gate: the mission is complete only when every manifest worker row is
in a terminal state — complete, failed, or dropped. Non-terminal rows (pending,
dispatched, needs-decision, blocked, stalled) must first be resolved; a unit that cannot be —
e.g. a worker that never reported by its checkpoint, marked stalled — must be explicitly converted
to dropped with a reason. Only then may the mission be declared "complete with N dropped: <ids +
reasons>". Never close with a non-terminal row, and never drop silently. Enumerate every dispatched
unit in the final summary.
Pull cadence (no push signal): a session-native control plane has no "worker done" event to wake it. After dispatching a wave, define the next checkpoint trigger — a follow-up turn, a status-table poll, or a user ping — and never leave a wave un-joined.
For PR-bound work, keep the control session responsible for final PR readiness and review routing.
Use a compact control-plane update (rows derived from the manifest):
**Status:** <on track | blocked | needs decision | complete>
**Budget:** in-flight <X/Y> · spawned <A/B> · wave <N> (empty-streak <E>)
| Workstream | Session | Scope | State | Evidence |
|---|---|---|---|---|
| <name> | <id/name> | <scope> | <state> | <test/report/PR> |
**Decision needed:** <only if blocked>
Keep user-facing updates concise. The control session should make coordination legible, not flood the user with every worker's transcript.
tools
Active runtime recovery for coding agents: when something breaks mid-task, diagnose the root cause, write a fix, VERIFY by re-running the broken thing, then file a `HEAL-` entry to `.learnings/HEALS.md` with proof. Use whenever a command, test, build, or lint fails or exits non-zero; on missing tooling, dependency/lockfile mismatch, wrong runtime version, venv or permission errors, port conflicts, dirty git state, or a missing `.env`; when the agent needs a helper or one-off script that doesn't exist yet; when an external API, tool, or MCP errors or rate-limits; or when a test flakes. Search `HEALS.md` by `Pattern-Key` first — most heals are recurrences, so increment `Recurrence-Count` instead of duplicating. Verify is mandatory: mark `pending-verify` honestly if sandboxed, `abandoned` if the fix can't be made to work. Pairs with `self-improvement` (which promotes recurring heals to durable memory) but owns the verify-before-persist discipline self-improvement doesn't.
development
Control-plane workflow for coordinating multi-agent, multi-session project work from a single Codex, GitHub Copilot, or agent-app control session. Use this skill whenever the user asks to orchestrate agents, create or steer worker sessions, run a workflow-like effort, fan out audits/research/migrations, coordinate parallel implementation streams, monitor other project sessions, or compare this control-session pattern to Claude Code dynamic workflows. This skill is especially relevant when the current session can spawn persistent project sessions and those sessions can spawn their own subagents, creating a two-level orchestration hierarchy.
tools
Active runtime recovery for coding agents: when something breaks mid-task, diagnose the root cause, write a fix, VERIFY by re-running the broken thing, then file a `HEAL-` entry to `.learnings/HEALS.md` with proof. Use whenever a command, test, build, or lint fails or exits non-zero; on missing tooling, dependency/lockfile mismatch, wrong runtime version, venv or permission errors, port conflicts, dirty git state, or a missing `.env`; when the agent needs a helper or one-off script that doesn't exist yet; when an external API, tool, or MCP errors or rate-limits; or when a test flakes. Search `HEALS.md` by `Pattern-Key` first — most heals are recurrences, so increment `Recurrence-Count` instead of duplicating. Verify is mandatory: mark `pending-verify` honestly if sandboxed, `abandoned` if the fix can't be made to work. Pairs with `self-improvement` (which promotes recurring heals to durable memory) but owns the verify-before-persist discipline self-improvement doesn't.
tools
CI-only self-healing workflow using gh-aw (GitHub Agentic Workflows) for active runtime recovery on pull requests and scheduled runs. When a CI check fails (test, build, lint, deploy, scan), this skill diagnoses the failure from CI logs, proposes a verified patch as a PR comment or follow-up commit, and commits a HEAL entry to `.learnings/HEALS.md`. Verify-before-persist discipline preserved: a HEAL is only `verified` if a re-run check passes in the same workflow; otherwise it ships as `pending-verify` for human follow-up. Recurrent heal patterns across PRs accumulate `Recurrence-Count` and append a `Handoff` block at ≥3 to flag promotion via self-improvement-ci. Use this skill when: you want headless heal-loop execution in CI/scheduled pipelines, you want recurring failure patterns captured automatically, or you want PRs that surface non-obvious environmental / tooling fixes without human triage. For interactive/local sessions, use `self-healing` instead.