| name | orc-planner |
| description | Requirement Planner for ORC (Opus 5 medium). Turns a detailed request OR a System Analyst requirement-spec into orc's planning-output: right-sized tasks, each with grounded declared_files (incl. tests), explicit depends_on, owns_area, and spec_ref — self-checked for dependency cycles and same-file collisions. A planner OPTION in orc Phase 1 and available standalone via /orc-plan (fires on "plan this", "break this into tasks", "turn this spec into a task plan"). Distinct from the fast orc-planner-mini (Sonnet 5, single-pass): full grounding and deep dependency tracing. The orchestrator dispatches this to a subagent — it never plans itself.
|
orc-planner (Requirement Planner)
The orchestrator stays on top and dispatches a planner subagent (Opus 5,
medium) to produce the plan. Strictly planning: it does not implement, review,
or verify. Output contract is orc's schemas/planning-output.md (single-source;
do not redefine it here).
Input (accepts either)
- A detailed typed request. "Too thin to plan" has a definition: plannable ⇔
the request states (a) an observable outcome AND (b) an identifiable area of
the repo it lands in. Failing either → do NOT plan; recommend routing through
orc-analyze (requirement mode) instead — the same escalation valve intake
has, now covering the /orc-plan side door. A vague request planned anyway
yields a confidently vague plan.
- A System Analyst requirement-spec (
orc/analyzer/{name}/requirement-spec.md).
Already scope-bounded and code-grounded. If its git_head ≠ current HEAD,
the orchestrator re-runs the evidence spot-check before dispatching you —
never plan against a spec flagged stale without the user's go-ahead.
- An orc-poly
poly-spec.md (first line marker orc-poly:spec, from
/orc-poly). Switch to Poly-repo split mode below.
Poly-repo split mode (only on the orc-poly:spec marker)
The spec has a repos[] block (each: name, role, absolute path,
in_scope[], requirements[]) and points at a frozen interface-contract.md.
Produce one planning-output per repos[] entry — never a merged plan:
- Scope each plan to that repo's
in_scope[] and ground those paths against
THAT repo's files (a peer lives outside CWD — Glob/read via absolute paths).
- Embed the frozen
interface-contract.md verbatim as a Frozen contract
section in every plan and copy each requirement's contract_ref into the
guarded task's spec_invariants[], so the later per-repo /orc build cannot
drift from the boundary. Never paraphrase the contract — it is immutable.
- Write the HOST plan to
poly-repo-implementation/<slug>/<host>-implementation-plan.md in the HOST
repo; write each PEER plan into that peer repo at the same relative path
(Write to the absolute peer path — a plan file only, never peer source).
- Run coverage/grounding/cycle self-checks PER plan; carry the spec's
git_head staleness stamp into each. Scope and the contract are settled
upstream by orc-poly — never re-litigate them.
- This is a split-and-STOP branch — present the per-repo plans + the
per-repo build handoff and stop. A poly-spec NEVER takes into build here (the
build runs later, per repo, in its own session). See "Branch" below.
Grounding (conditional — the token-saving rule)
- Standalone (not chained from SA): read the repo and, if present and
non-empty, the
wiki/ overviews, to ground declared_files in real paths and
detect what already exists. Select pages via wiki/INDEX.md (lines carry doc
type, status, keywords); on v2 wikis pull each doc's Contracts & shapes
(file-anchored routes/tables/config) and Testing map (where the area's
tests live — feeds declared test files), plus the cross-cutting reference
maps (API surface / data model / glossary / config-env) when the plan
touches their domain. Wiki claims never outrank the code — on conflict,
ground in the file and treat the doc as stale. Record grounding
provenance in the plan (grounding: repo-read, plus what was consulted).
- From System Analyst: DO NOT re-read the repo to re-verify the spec's
claims. Trust the requirement-spec's
files mappings as the grounding source
(SA already verified them). COPY the spec's file:line evidence into each
task's grounding[] entries — never drop it on the way through. NEW paths
the plan adds beyond the spec (tests, new modules) still need their own
grounding: Glob the parent dir — "trust the spec" never covers paths the spec
doesn't mention.
Per-file attestation (hard gate — never prose). Every declared_files path
gets a grounding[] entry: {path, disposition: exists|new, evidence}.
exists means YOU confirmed the path this session (globbed/read it — evidence
says which; from-SA, the spec's file:line is the evidence). new means a file
to be created — the evidence is the parent dir you confirmed exists. Never mark
exists on a path you did not confirm: the orchestrator Globs every exists
path at Phase 1 exit and bounces a plan with misses back to you (one retry,
then it escalates to the user). An ungrounded path is a malformed plan.
Context & invariants (non-actionable — carry, never build)
If the requirement-spec carries a Context & invariants (do not build) block,
it is anchored adjacent-scope context the Analyst gathered so the build respects
it. NEVER turn a context item into a task or a declared_files entry — the scope
perimeter is unchanged, only in-scope requirements become tasks. Where a listed
invariant is load-bearing for a specific task, copy it VERBATIM into that
task's spec_invariants[] (schema field) — the orchestrator appends
spec_invariants to the executor slice's constraints[], so an invariant that
reaches the field demonstrably reaches the executor (hard rules to respect,
not to reimplement). The full block still travels with the spec via spec_ref.
Config
Resolve max_wave_tasks and batch_pause_every the standard way — config.md
defaults with the user override .claude/orc.config.yaml merged on top per key
(see config.md's "Resolution" rule). You don't apply them (the
orchestrator does, after hand-back) — you read them only so the plan fits the
wave cap (e.g. with max_wave_tasks: 3, don't design 8 independent tasks
expecting all 8 to run at once).
Procedure (defend against bad plans)
-
Draft tasks from the input, each a coherent unit one subagent can own,
tagging each with requirements[] — the R# ids (from-SA) or DoD line ids
(direct) it implements. [] only for pure-infra tasks WITH a stated reason.
-
Ground declared_files per the rule above (incl. test files), filling
each task's grounding[] attestation as you go. Copy load-bearing spec
invariants into spec_invariants[] per the Context & invariants rule.
Fill each task's facets block in the same pass (you are already reading
every declared file — zero extra passes): breadth = len(declared_files),
plus novelty / logic / test_surface / uncertainty, and any risk
entries — each risk entry MUST cite the file/requirement that makes it so
(an uncited risk bounces at the orchestrator's Phase 2 facet gate). You do
NOT emit fan_in/fan_out (the orchestrator computes them from depends_on)
and you do NOT compute the score — the orchestrator does, arithmetically, from
your facets. See ../../references/effort-and-mode.md.
-
Slice per-task acceptance: give each task an acceptance[] — the
intent-spec/requirement-spec definition-of-done lines that THIS task must
satisfy (executors self-check against them; review/verify localize failures
to a task). Each line CITES its source (R3 / DoD#2) — a line with no
source is invented by definition. Never invent criteria the spec lacks.
3b. Author the tdd_spec (v0.33.0 — when the run's TDD policy is on; full
orc/ultra AND standalone /orc-plan always — a saved plan's only consumers
are the TDD-always build lanes). TDD IS SCOPED TO WHAT CAN ACTUALLY FAIL
(v0.41.0): every entry carries a disposition from the closed set, DERIVED
from the facets you already produced — you are not judging this fresh:
| facets | disposition | test? |
|---|
test_surface: none + novelty: mechanical | no-behavior (+reason) |
Return echo (attestation the orchestrator recomputes)
Alongside the planning-output, return coverage: {requirements: N, tasks: M, orphans: []} — self-attested, then independently recomputed by the
orchestrator's Phase 1 exit gate (spec R# set vs union of task
requirements[]), the same attestation + spot-check pairing as grounding[].
The planning-output also carries, per task, the facets block (breadth =
len(declared_files), novelty/logic/test_surface/uncertainty, cited risk[])
the orchestrator scores from and re-validates (breadth + fan recompute, risk
citation); and at the top level plan_confidence + open_questions[] (Part E),
which the orchestrator relays in one batch. Record the plan's plan_head (HEAD
at plan time) so the executing session can detect cross-session drift.
Behavior trace (PERMANENT — every ORC entry point traces; always on)
../../../_shared/phases/trace.md (core, at run start; orc lane phases names
the file and the layers). Lane token plan, tier Single-dispatch —
exactly ONE end-of-run packet, dispatched solo before .current is deleted.
At run start write log_dir/.current = run-plan-<slug>-<DDMMYY>-<HHMMSS>.txt AND
touch the trace file of that name in the SAME step.
Nothing else about the protocol is restated here; a phase that ends with
zero new trace lines is a protocol violation.
Checkpoint before branching
Before the branch, WRITE A CHECKPOINT of the planning-output into
orc/planner/{name}/ (internal): the plan md + a checkpoint.json snapshot via
the orchestrator's orc-checkpoint. This means a plan is never lost if the session
stops between planning and building, and a plan run can resume. Do NOT write
straight to a loose plan-{name}.md with no checkpoint.
Branch (plain-language choice)
- Take into build → hand the approved planning-output BACK to the
orchestrator. Control returns to orc, which then runs the FULL pipeline:
Phase 2 (score every task → show the effort/model table → dispatch style →
ask batch-pause frequency), Phase 3 (wave-grouping capped at
config.max_wave_tasks, checkpoints, pauses), through review/verify/ship. The
planner NEVER starts implementation itself. "Here's the plan — {N} tasks
grounded in your files. Approve and I'll take it through scoring and the full
build?"
- Save & stop → the plan is already checkpointed in
orc/planner/{name}/;
also copy the readable plan-{name}.md out to the project root if the user
wants it. "Saved the plan (checkpointed) — stopping here." Then ask ONE extra
question — only on this branch: "Want a lane recommendation for building
this? [yes / no]". Yes → run ../../../orc-route/SKILL.md on this plan
(it is already a valid plan input) and print the forecast: block from
../../references/preflight-report.md alongside it, so price and lane land
together. No → stop. Take into build never asks (the lane is chosen and
running); Poly split & stop never asks (it has its own per-repo handoff).
- Poly split & stop (poly-spec input only) → the per-repo plans are written
(HOST here, each PEER into its repo). Present them and the handoff — "open
each repo in its own session and run
/orc on its plan; every plan pins the
same frozen contract, so nothing drifts" — then STOP. Never take a poly-spec
into build; there is no scoring/wave phase for it here.
Mini
The fast lane uses orc-planner-mini (Sonnet 5 high), dispatched by orc-mini.
Same output contract; trimmed procedure. See that subskill.