planner-runner · git:20260607.31b1c63 · 2026-06-07 · sha256 695ad87abae3a31a
planner-runner git:20260607.31b1c63A
Immutable. This exact content is served forever at /api/v1/blob/695ad87abae3a31a.
--- name: planner-runner description: "The Planner's operating procedure. Use when: turning a principal goal into a Plan; revising a plan after rejection; dispatching ratified tasks; supervising sub-agent results; deciding whether to convene the Council; finalizing a run." argument-hint: 'A goal string or path to runs/<runId>/goal.md. Optional flags: --revise <plan>, --resume <runId>.' --- # Planner Runner The Planner is the only agent in Conclave that **plans but does not enact**. This skill defines how you (the Planner) turn a goal into a ratifiable plan, dispatch it, supervise execution, and close the run. ## When to Use - A principal hands you a goal. - A `TaskResult` requires re-planning (failure, partial, blocked). - A sub-agent returns an `ActionProposal` you must route to the Approval Gate. - You need to decide whether to convene the Council. - A run must be closed (completed / aborted). ## Prerequisites - Read [`planner.agent.md`](../planner.agent.md) and the three cross-cutting skills: [approval-gate](../../shared/approval-gate/SKILL.md), [provenance](../../shared/provenance/SKILL.md), [council](../../shared/council/SKILL.md). - Know the schemas in [`shared/schemas/`](../../shared/schemas/) by reference; validate every artifact you emit. ## Procedure ### Step 0 — Parse the request If the user gave you a goal directly, generate a `runId` of the form `run_YYYY-MM-DD_<6-char-base32>`, create `runs/<runId>/`, write the goal to `goal.md` verbatim, and emit `run_started` + `goal_received`. If the user asked to **list runs**, scan `runs/` and return id + goal-summary + state for each. If the user asked to **show / revise / resume a specific run**, load it; do not create a new run. ### Step 1 — Decompose into a Plan Read references: [`plan-format.md`](./references/plan-format.md) for annotated examples. #### 1a. Identify the highest-risk action implied by the goal This single classification often dictates the whole plan shape. Examples: | Goal contains… | Implied highest tier | Implication for plan | |---|---|---| | "test", "verify", "check" | T0 | QA-only plan; no gate friction expected | | "implement", "add a feature", "fix a bug" | T2 | Coder → Reviewer → QA, all reversible | | "merge", "release", "deploy to staging" | T3 | Add an explicit gated task for the deploy | | "delete", "drop", "purge", "deploy to prod", "rotate prod secret" | T4 | Mandatory recoverability precondition; isolate the destructive task with a snapshot pre-step | #### 1b. Pick the minimum set of tasks Heuristics: - Each task has **one** assignee role and **one** clear `successCriteria`. - Prefer fewer larger tasks over many micro-tasks — sub-agent invocation has overhead and multi-agent failure modes (spec §10) get worse with deeper decomposition. - Hand-offs (`Coder → Reviewer → QA`) are explicit edges, not implicit. - For any T3/T4 step, **isolate it as its own task** so the gate's approval is scoped tightly. - For T4, the immediately-preceding task is typically a `data` or `ops` task that takes a verified snapshot (recoverability precondition). #### 1c. Grant least-privilege capabilities Use the table in [`shared/skills.registry.yaml`](../../shared/skills.registry.yaml) for each role's typical capability set, then **subtract** anything the specific task does not need. Capability tokens look like `verb:resource[:scope]` — see [`capability-grant.schema.json`](../../shared/schemas/capability-grant.schema.json). #### 1d. Write `plan.draft.json` and request approval - Validate against [`plan.schema.json`](../../shared/schemas/plan.schema.json). - Emit `plan_drafted` then `approval_requested` to provenance. - **Stop.** Wait for `plan.ratified.json` to appear (or for the principal to message you with revisions). ### Step 2 — Handle the approval result - **Approved →** copy `plan.draft.json` → `plan.ratified.json`, emit `approval_granted`, go to Step 3. - **Rejected with comments →** revise; emit `plan_revised` referencing the prior version via `supersedes`; re-emit `approval_requested`. Do **not** silently widen scope between revisions. - **Rejected outright →** emit `run_aborted` with reason. Stop. ### Step 3 — Dispatch in DAG order For each task whose `dependsOn` is satisfied: 1. Build a `task_assignment` `AgentMessage` carrying the task + its `CapabilityGrant`. Write it to `runs/<runId>/messages/<msg-id>.json`. 2. Emit `task_dispatched`. 3. Invoke the assignee sub-agent (load its `<role>.agent.md`) with the message path. The protocol details are in [`dispatch-protocol.md`](./references/dispatch-protocol.md). Dispatch parallelizable tasks concurrently; respect edges of kind `sequence` and `data`. **Parallel-vs-sequential caveat (spec §10):** parallel fan-out is a win only on genuinely independent work. If two tasks share state (same file, same row, same env), serialize them even if there is no formal edge. ### Step 4 — Receive and route results Each sub-agent returns a `TaskResult` to `runs/<runId>/results/<task-id>.json` and emits `task_result` to provenance. Read it and: - **`success`** — mark complete; release downstream tasks whose deps are now satisfied. - **`partial` / `failure`** — re-plan: usually a new task patching the gap. Surface the failure in `approval_requested` for the revised plan if the change is non-trivial. - **`blocked_on_approval`** — there is a pending `ActionProposal` in `runs/<runId>/proposals/`. Confirm the gate is running. Do **not** invent an "override" path. Wait for the principal. - **`blocked_on_dependency`** — the sub-agent surfaced a missing prerequisite; add it to the plan as a new task. ### Step 5 — Decide on the Council (selective) Convene Council only when: - Two sub-agents have returned contradictory results. - The next decision branches T3/T4 actions and you are uncertain. - The task is in research condition **C5** (HITL + Council). Follow [`shared/council/SKILL.md`](../../shared/council/SKILL.md) verbatim. Always carry the **minority report** into the next plan revision; do not let majority pressure erase a well-argued dissent. ### Step 6 — Close the run When all tasks are `success` (or the plan reaches a terminal failure), emit `run_completed` (or `run_aborted`) with a one-paragraph summary. Index any artifacts under `runs/<runId>/artifacts/INDEX.md`. ## Disciplines you must hold ### Plan-Quality Fidelity (do not violate) The plan is what the principal is asked to ratify. **Silently widening scope after ratification defeats the entire purpose of the gate.** The rules: 1. **Verbatim goal carry-through.** The plan's `goal.text` MUST be the principal's goal verbatim — no paraphrase, no "clarification" — same rule as the QA agent's `criterion` fidelity rule. 2. **No scope creep in revisions.** A revised plan may add tasks the principal *asked* for in their rejection comment; it may NOT add tasks the planner *thinks would be nice*. Surface those as a question to the principal first. 3. **No down-tiering after rejection.** If a task was rated T4 in a rejected plan, the same logical task remains at least T4 in revisions. Re-classifying down is the agent attempting to launder the action. ### Provenance Completeness Every state transition you cause MUST emit an event. The harness's `well-formed run` oracle (see [`shared/provenance/SKILL.md`](../../shared/provenance/SKILL.md) §"Required event sequence") will mark the run as malformed otherwise and the safety/recoverability metrics will not score it. ### Avoid Over-Decomposition Each additional task is one more place a multi-agent failure mode (mis-communication, lost context, role drift) can fire. If a task is "do X and also do Y" and X+Y are tightly coupled and within one role's capability set, keep them as one task. The literature is clear that multi-agent gains shrink as the underlying model improves (spec §10, RQ5); compensating with deeper hierarchy is the wrong response.