| name | plan |
| description | Create durable Infiquetra implementation plans with issue, review, test, and deploy gates. Interrogates HOW work gets built, writes an agent-consumable plan artifact, records a plan saga, and routes to doc-review and /work. Triggers on "plan this", "how should we build this", "create a plan", "break this down", or a handoff issue ready for planning. |
Plan
/plan answers "How should it be built?" It takes a settled WHAT โ from /brainstorm's
requirements doc, a handoff issue, or a clear ad-hoc request โ and interrogates it into a durable,
agent-consumable implementation plan. It does not invent product behavior (that came from
/brainstorm or the issue), it does not implement code, and it does not run the review
gauntlet. It plans, self-reviews, records a plan saga, and routes.
Position in the lifecycle
/plan sits between requirements and execution:
/office-hours answers: "What is even the right frame?"
/ideate answers: "What are the strongest ideas worth exploring?"
/brainstorm answers: "What exactly should one chosen idea mean?" (the WHAT)
/plan answers: "How should it be built?" (the HOW โ this engine)
- the
review phase (/doc-review) answers: "Is this plan ready to execute?"
/work answers: "Build it." (consumes the plan + saga)
The handshake is deliberate. When the WHAT is unsettled, /plan recommends the operator step back to
/brainstorm first (a one-way forward route โ /plan points there; it does not claim /brainstorm
"accepts" a handoff). When the plan is written, /plan recommends /doc-review (the review phase)
before /work.
Core principles
- Decisions, not code. Capture approach, boundaries, files, dependencies, risks, and per-unit
test scenarios. Do not pre-write implementation code or shell-command choreography. Pseudo-code and
DSL grammars are allowed only as explicitly directional high-level design, never as implementation
specification.
- Ground before asking. Read the code before you ask a question its answer is already in. Cite
path:line. Quantify everything โ "several files" is a bug; find the exact count. Never guess about
the codebase; go read it.
- Agent-consumable plans. The plan must let an unfamiliar implementer (human or
/work) start
confidently without re-asking the operator. Stable IDs (R-IDs, KTDs, U-IDs), per-unit test
scenarios with repo-relative test-file paths, dependency-ordered units.
- Right-size via the warranted-gate. Not every invocation produces a plan doc. Genuinely atomic
work skips the artifact. But stress-test the "looks atomic" case โ most requests hide KTDs.
- HOW-only. Assume the WHAT arrived from
/brainstorm or the issue. Do not re-litigate product
scope, actors, or success criteria here โ carry them forward as constraints.
Interaction method
Use AskUserQuestion for choices from a known set (destination, execution backend, scope class,
resume-vs-mint). Call ToolSearch with select:AskUserQuestion first if its schema is not loaded.
Ask one question per turn; prefer a concise single-select when natural options exist. For open-ended
interrogation, ask inline in chat. Never silently skip a question.
In a channel session (redis-channel active), AskUserQuestion cannot be called โ inline the choices
in your reply text instead. Follow the canonical channel-inline convention in
saga/skills/brainstorm/SKILL.md (do not duplicate its wording here).
Use repo-relative paths in every generated document. Absolute paths break portability across machines
and worktrees.
Phase 0 โ Enter and warranted-gate
Capture the input and decide whether a plan doc is even warranted before spending interrogation effort.
0.1 Capture input
The input is an issue reference, a requirements doc path, or an ad-hoc request. Take it from command
arguments or the active artifact. If empty, ask: "What would you like to plan? Point me at the
requirements doc, the issue, or describe the work." Do not proceed without one.
0.2 Issue handoff routing
If the input is a GitHub issue, run scripts/parse_issue.py and inspect the handoff object.
- For
idea-ready or requirements-ready handoff issues, create or update a durable plan from the
issue and its Source context / linked source. These are the maturities /plan consumes.
- For
plan-ready or resume-ready handoff issues, tell the operator /work <issue> is the more
direct consumer unless they explicitly want to re-plan. A plan already exists for these.
Use the issue's Handoff maturity and Source context sections as authoritative input.
0.3 Saga scan โ offer resume before minting
Before minting a new plan saga, run scan to offer resuming an existing one (slug-instability
mitigation โ a drifting task description would otherwise fork a second saga for the same work):
python3 plugins/saga/scripts/saga.py scan
If a candidate matches this thread (same issue_ref, or the operator confirms "resume this"), reuse
it โ Phase 5 appends a tick rather than minting. For an issue whose issue-<N> directory is absent,
resolve via state.json.sagas[*].issue_ref ending in #N (the id is sticky; never rename the
directory). See references/saga-spec.md ยง2.3 and ยง2.1.
0.4 Warranted-gate โ decide whether a plan doc is warranted
Bias toward producing a plan; the risk asymmetry favors writing one. Skip the plan doc only when ALL
hold: the work is atomic (fits one commit, no unit boundaries), there are no Key Technical Decisions
worth recording, no scope boundaries worth pinning, and no upstream artifact needs traceability.
Stress-test the "looks atomic" case โ many requests look atomic but hide KTDs ("add caching" โ
TTL / invalidation / key shape; "migrate A to B" โ semantic-difference KTDs; "add rate limiting" โ
algorithm / scope / configurability). See references/plan-sections.md ("Decide whether a plan doc is
warranted") for the full skip-vs-write rubric. When skipping, route directly to /work and let
decisions land in the commit message; otherwise continue.
0.5 Scope classification
Classify the work into one depth, which sizes the plan (Phase 3) and gates the deepening pass (Phase 4):
- Lightweight โ small, well-bounded, low ambiguity. ~2-4 units. Omit optional sections.
- Standard โ normal feature or bounded refactor with technical decisions to document. ~3-6 units.
- Deep โ cross-cutting, strategic, high-risk, or highly ambiguous. ~4-8 units; optional analysis
sections warranted.
If depth is unclear, ask one targeted question, then continue.
Phase 1 โ Ground (HOW)
Read code before asking. This is the moment the operator sees you grounded in their actual repo, not a
generic checklist.
- Read the upstream artifact first. If a
/brainstorm requirements doc (docs/brainstorms/*-requirements.md),
the handoff issue, or a linked source exists, read it thoroughly and carry forward its problem frame,
requirements, scope boundaries, KTDs, and open questions as constraints the plan must honor.
- Read
STRATEGY.md if present and anchor plan decisions to the active tracks; flag any decision
that pulls away from the stated approach.
- Read the engineering journal (
docs/engineering-journal/) for relevant prior LEARNINGS and
DECISIONS so the plan follows established patterns instead of reinventing them.
- Quantify. Find exact counts (files, call sites, tables). Cite
path:line in your prose.
- Dispatch generic
Explore agents in parallel for grounding โ repo patterns, relevant files,
existing test conventions, adjacent implementations. Use the generic Explore agent; the ce-*
research agents do not exist in this plugin.
Cold-start (no upstream WHAT). If there is no brainstorm doc, no issue, and the request is bare:
run a light Why-check (problem frame, intended behavior, obvious non-goals, success signal โ keep it
brief; see references/interrogation.md). If the WHAT itself is unsettled โ product framing, user
behavior, or scope is genuinely open โ recommend the operator run /brainstorm first to settle
the WHAT, then return to /plan. This is a one-way forward route: point them there, offer to continue
planning with explicit assumptions if they decline, and do not claim /brainstorm "accepts" a handoff.
Phase 2 โ Interrogate (HOW)
Load references/interrogation.md and run the HOW-interrogation register against the grounded
evidence. Ambiguity is a bug; find it. The register covers:
- Failure-mode enumeration โ for each unit, what happens when the input is empty, null, huge,
duplicated, called by the wrong role, or called twice. Unenumerated failure modes are unwritten test
scenarios.
- Scope-lock โ lock what is explicitly out of scope early. When the operator opens a new front
mid-plan, name it: "That's a separate issue โ let's finish this one."
- KTD-forcing โ surface the load-bearing technical decisions and force a choice with rationale.
An open design fork the plan never resolves is a gap, not a decision.
- Anti-premature-solution โ do not jump to implementation detail before the approach, boundaries,
and failure modes are pinned.
Push on vagueness and ungrounded assumptions (not the operator's judgment): an undefined term,
a "several files" that should be a count, a behavioral assumption you have not verified in the code.
Push twice, then respect the answer. Escape hatches are in references/interrogation.md.
Phase 3 โ Synthesize the plan artifact
Write the plan to docs/plans/YYYY-MM-DD-<topic>-plan.md per references/plan-sections.md. Right-size
by the Phase-0.5 scope class. Never code during this phase โ research, decide, and write the plan.
Follow the shared formatting contract in saga/references/formatting-style.md for the plan's visual
structure: lead each unit and major section with a one-line summary, keep narrative fields as short
(โค3-sentence) blank-line-separated prose, render comparative/scored data as a table, and never stack
bold labels without a blank line between them. Per-unit fields stay as blank-line-separated
**label:** lines under each ### U<N>. heading (the contract's prose-heavy per-unit branch) โ not a
table.
Hard floor (every warranted plan carries these):
- Summary โ what the plan proposes, in 1-3 lines.
- Problem Frame โ why the work is being done (may merge into Summary for compact plans).
- Requirements โ with stable R-IDs (
R1., R2.); the reviewer's and /work's checklist.
- Key Technical Decisions โ the KTDs, each
<decision>: <rationale>; the load-bearing choices
that constrain implementation.
- Implementation Units โ with stable U-IDs (
U1., U2.), each independently landable, with
per-unit test scenarios and repo-relative test-file paths. Feature-bearing units require real test
scenarios; only non-feature units (config, scaffolding) may use Test expectation: none -- [reason].
- Scope Boundaries โ what is explicitly out of scope, with
Deferred to Follow-Up Work kept
distinct from true non-goals.
Deep adds (warranted only, never boilerplate): High-Level Technical Design (HTD), Risk Analysis &
Mitigation, Alternatives Considered, Success Metrics. Include only when the content earns the section.
The plan must serve three audiences: the implementing agent (informed starting baseline), the
reviewer (load-bearing decisions in one pass), the future reader (why the work was done).
Plan-doc frontmatter (NOT the saga fields โ those land in Phase 5):
---
title: <verbatim plan title, matches the H1>
type: <feat|fix|refactor|chore|docs|perf|test>
status: active
date: YYYY-MM-DD
origin: <repo-relative path to the upstream brainstorm/requirements doc, when planning from one>
---
origin: MUST be emitted so the review phase can trace the plan back to its source. The body MUST use
the exact section markers Implementation Units, Key Technical Decisions, and the U1 U-ID prefix โ
/doc-review parses these to recognize the document as a plan.
Record the KTDs to the engineering journal (docs/engineering-journal/DECISIONS.md) โ the journal
is the canonical decision record; the saga's ## Decisions mirrors it.
Phase 4 โ Deepen (condensed confidence pass, conditional)
After writing the plan, evaluate whether it needs strengthening. The condensed confidence-pass rubric
lives in the Confidence pass (deepening) section of references/plan-sections.md โ per-section gap
checklist, risk-weighted "is this plan thin?" scoring, and the top-N section cap.
- Auto-run for Deep plans, high-risk topics (auth, payments, data migration, external APIs,
privacy), or thin grounding (Phase 1 found fewer than ~3 local patterns for what the plan needs).
- Skip for Lightweight, well-grounded plans โ report "Confidence check passed" and continue.
When deepening, dispatch generic Explore / Task agents (not ce-* agents) at the top-scoring
sections only. Strengthen rationale, sequencing, test scenarios, and risk treatment in place. Never
renumber existing U-IDs when reordering or splitting units (the most likely accidental-renumber
vector). Add deepened: YYYY-MM-DD to frontmatter when the plan was substantively improved.
Phase 5 โ Saga, route, and operator-choice
5.1 Ask the destination
Ask the routing intent (AskUserQuestion, or channel-inline): plan-only / pr / merge /
nonprod-deploy. This becomes the saga --destination.
Deploy-autonomy follow-up (only when destination is nonprod-deploy). When โ and only when โ
the operator picks nonprod-deploy, ask one more question (AskUserQuestion, or channel-inline) to
capture the gate-or-auto posture at the sagaโdeploy edge (issue #395, KTD3). Skip this question for
every other destination.
When a merged item reaches deploy, should nonprod promotion happen automatically, or wait for
your explicit confirmation each time?
A) Gate (default, pre-select) โ deploy asks for explicit confirmation before promoting.
B) Auto โ deploy may auto-promote to nonprod only (staging/production always confirm).
This becomes the saga --deploy-autonomy <gate|auto>. It is authored once here and read โ never
re-asked โ by deploy_handoff.offer at handoff time; there is deliberately no way to widen it to
auto at deploy time. Pre-select Gate: a missing or gate posture can never auto-fire, which is
the safe failure direction (R5). Omit --deploy-autonomy entirely for any non-deploy destination โ
deploy_handoff reads an absent posture as gate.
5.2 Offer the execution backend
Offer the execution backend per references/operator-choice.md (the decision contract). There are
exactly three backends โ inline ("inline") | team-execution ("team execution") |
cc-workflows-ultracode ("dynamic workflows"). Read the work shape, recommend the cheapest-correct
backend and pre-select it, but always render the offer from the full backends enumeration
(lifecycle_state.recommend_execution_backend's backends key โ all three, each with a
{backend, status, note} entry) so every offer names all three and escalation is one step.
Before offering, probe Workflow-tool availability with ToolSearch (not an assumption) and pass
the result as --workflow-availability-source probed; only fall back to the asserted default when a
live probe is not possible on this host (e.g. a non-Claude-Code runner). The recommender echoes the
source back in workflow_availability so the offer can say whether availability was verified or merely
assumed.
Dynamic workflows serve the five workflow shapes (per references/operator-choice.md ยง3.2) โ
escalate to cc-workflows-ultracode ("dynamic workflows"), without elevated risk, when the work matches
any of the frozen WORKFLOW_SHAPES โ understand / design / research / review / migrate โ or either
of the two legacy triggers still recognized beside them:
- Breadth / scale (
broad_independent_fanout) โ broad independent fan-out, the same operation
across many enumerated targets, or an exhaustive probe-all sweep where missing a target is the
failure mode.
- Adversarial confidence (
adversarial_confidence) โ a judge panel over N independent attempts,
prove-by-refutation (refute-N), or perspective-diverse verifiers each applying a distinct lens. This
is real review depth; the Workflow tool names confidence as a first-class purpose. Set it only on an
explicit request for many-independent-attempt verification, not on a generic "be more sure." (The
review shape covers a multi-lens review sweep requested as a workflow; the explicit refute-N /
judge-panel form stays adversarial_confidence โ the two may co-fire, no precedence between them.)
Pass any matching shape(s) via repeatable --workflow-shape; an unrecognized shape is rejected loud
(ValueError), never silently downgraded to inline.
The teamโworkflow fork is GOVERNANCE, not "review depth" (both have review depth). The question is:
does the verdict need to stick? Escalate to team-execution ("team execution") when the work needs
gated consensus โ a verdict that blocks a merge/deploy and persists as standing evidence (a reviewer-
CONSENSUS gate, named scanners, a guarded deploy), or the size/risk signals fire (โฅ8 functional files,
โฅ4 phases, security, infra, cross-repo, deployment-sensitive). When the consensus signal is advisory
โ N throwaway in-session votes you act on yourself, nothing recorded or blocking โ it is a
dynamic-workflow judge-panel, not a team-execution job. Never omit cc-workflows-ultracode ("dynamic
workflows") from the offer โ when the Workflow tool is observably absent in this session (or only
asserted, unprobed), still name it in the enumeration with status: unavailable and its provenance note,
so the operator sees the full map even on a host that cannot run it. Confirm with the operator and record
what they picked via --orchestration-mode.
KTD4 โ the gated-vs-advisory interrogation (R7). When a consensus / multi-reviewer / many-attempt
signal is present, do not silently force team-execution. Ask the operator (AskUserQuestion, or
channel-inline) one question, with the work-shape default pre-selected:
Does this verdict need to BLOCK a merge/deploy or PERSIST as evidence โ or are these throwaway
in-session votes you act on yourself?
A) Gated โ block/persist (a reviewer-CONSENSUS gate, named scanners, a guarded deploy) โ team-execution.
B) Advisory โ N throwaway votes, nothing recorded/blocking โ cc-workflows-ultracode (a judge-panel).
Work-shape default: pre-select Gated when any deploy / security / persist signal is present
(--destination merge|nonprod-deploy, security/infra work, or a verdict that must be recorded); pre-select
Advisory otherwise. Pass the answer into the recommender as --advisory-consensus (set for B; omit for
A โ gated is the default). The advisory path feeds the existing adversarial_confidence ultracode trigger,
so a contested-but-not-gated job reaches the judge-panel and never regresses to inline. If the work is
both gated and broadly parallel, list both backends (per references/operator-choice.md ยง3.3).
5.2a Author the ExecutionSpec (cc-workflows-ultracode only)
When the operator chooses cc-workflows-ultracode, author a structured ExecutionSpec before writing
the saga tick. This is the canonical artifact /work re-emits from; the spec JSON โ not the prose plan
โ is the single source of truth (KTD1, references/operator-choice.md ยง6).
Step 1 โ Derive per-unit tiers. For each Implementation Unit in the plan, assign a {model, effort}
tier from the work-shape heuristic (R10). Surface the tier table for operator override before locking:
| Work shape | Default tier | Rationale |
|---|
| Judgment, design, adversarial review, architectural decisions | opus / high | Judgment, design, adversarial review, architectural decisions โ deep reasoning needed; cost-justified. |
| Mechanical, deterministic, scripted transforms, scaffolding | sonnet / medium (or haiku / low for purely mechanical) | Mechanical, deterministic, scripted transforms, scaffolding โ bounded output, predictable steps.; Purely mechanical work within the mechanical work-shape โ cheapest tier still safe for bounded, predictable steps. |
| Read-only survey, search, grep, sampling, census | sonnet / low | Read-only survey, search, grep, sampling, census โ low-effort read, no write risk. |
External-engine delegation, intent=offload, verifiability=test-gated (ratify-only) | haiku / low | External-engine delegation, intent=offload, verifiability=test-gated โ chaperone ratifies the declared test oracle and provenance; keep the chaperone cheap unless evidence size escalates. |
External-engine delegation, intent=offload, verifiability=unverifiable or absent | sonnet / medium | External-engine delegation, intent=offload, verifiability=unverifiable or absent โ chaperone performs full review; a heavier default would erase the token savings that motivated delegation (KTD2). |
External-engine delegation, intent=second-opinion (U12) | opus / high | External-engine delegation, intent=second-opinion โ adversarial verification IS the product; extra spend assumed; fable/xhigh available as a per-unit override, never a default (KTD2). |
External-engine delegation, intent=divergence (adversarial review) | opus / high | External-engine delegation, intent=divergence โ agreement and disagreement are both explicit adversarial-review outcomes; use the high-tier chaperone posture. |
Apply the heuristic per unit, then present the full tier table (U-ID, label, proposed tier, rationale)
and ask the operator to confirm or override before proceeding. Do not lock tiers silently.
Run-start posture seeds the defaults (#380). When the run carries a committed intent envelope
(ExecutionSpec.intent, or the parent outcome's OutcomeSpec.intent โ see
plugins/saga/references/intent-envelope.md), derive each unit's PROPOSED tier through
intent_envelope.seeded_tier(spec, work_shape) (equivalently intent_envelope.py recommend --work-shape <shape> --run-mode <mode>): the posture was asked ONCE at run start, and an
unattended posture proposes one rung cheaper than the attended default for the same work shape.
This changes only the table's proposed defaults โ the table itself, the operator-override flow,
and the VERIFY_N_CAP mechanics are unchanged, and no per-unit posture question is ever asked
(the fleet drift guard fails on one).
Estimate column (#402). Add a fourth Estimate column to this per-plan table (the U-ID/label/
tier/rationale table above, never the GENERATED work-shape registry table) โ the ordinal, index-weighted
spend the assigned tier costs (never a dollar amount). Once the per-unit tiers are locked into a draft
ExecutionSpec, run
python3 plugins/saga/scripts/spend_estimate.py estimate --spec <spec.json>
and fold its per-unit figures into the Estimate column so the operator sees relative cost alongside the
tier they are confirming, not as a separate lookup. The estimator is read-only (it renders a table; it
writes nothing to the ledger or the spec) โ see spend_estimate.py's own module docstring for the
reconcile-side (post-run) companion this authoring-time render feeds into.
The /plan-authored tier table is not the only lever (#365). The operator can adjust tier
mid-run without aborting and re-planning via /tier: a run-scoped ceiling
(.claude/saga/tier-session-override.json) that the emitters clamp every unit down to, or a mid-run
patch of a not-yet-run unit's tier that re-validates and re-emits the spec. The authored table is the
starting point; /tier is the live adjustment. A ceiling only ever clamps down, and an up-ladder
mid-run change is gated (asks) before it re-emits.
Persisted tier preferences (#368). Before deriving cold from the registry table above, resolve
each work-shape through scripts/tier_defaults.py โ precedence is repo overlay > issue band >
shared registry:
- Repo overlay โ a committed
.saga/tier-defaults.json ({"<work-shape>": {"model", "effort"}})
pins repo-tuned defaults. resolve_tier_with_overlay(work_shape) returns the pinned tier when
present. Missing file โ clean registry fallback; malformed (bad JSON, unknown shape, off-palette or
unrunnable tier) โ TierDefaultsError, halt and surface (never degrade silently).
- Issue band โ when the driving issue carries a
### Recommended Tier Band section
(auto-stamped by mission-control:issue at creation), parse it with parse_tier_band(body) and
pass it to resolve_tier_for_plan(work_shape, issue_band=band). The band seeds the proposed tier
only where no repo override exists; an absent band is normal (None), a present-but-invalid one
fails loud.
- Write-back โ when the operator confirms a tier override in the Step 1 table, persist it with
write_tier_default(work_shape, model, effort) so the next /plan proposes the accreted
preference. Read-merge-write: never clobbers other keys. The file is tracked โ commit the
dirtied overlay with the run's changes (the repo accretes tier judgment). Every persisted override
originates from an explicit operator confirmation; never auto-promote silently.
For a unit carrying engine/capability (U12 chaperone-worker units), the recommendation row also
carries the unit's intent and a plan-time resolution preview: for a capability-routed unit, call
engine_resolver.resolve({"role_kind": "worker", "capability": <value>}, mode="advisory", registry=โฆ)
(mode="advisory" โ R7 โ since this is a non-binding preview, not the run-time dispatch) and surface
"resolves today to <engine_id>/<variant>" alongside the tier row; an explicit-engine unit has no
preview to show (naming the engine already fixes it โ R26 halts rather than substitutes if it becomes
unavailable). This preview is the baseline the chaperone's substituted-engine disposition compares
the run-time resolution against (KTD4, references/external-engine-workers.md ยง4 in team-execution) โ
record it in the saga tick / emitted plan alongside the tier so it survives to /work.
Step 1b โ Price the plan and set the spend guards (#366). Once tiers are locked the plan has a
price: surface it and set the run-scoped guards before authoring prompts.
- Run
python3 plugins/saga/scripts/execution_spec.py spend <spec.json> to print per-unit spend, the
multiplicity-aware total (fan-out targets and verify panels counted, not one weight per unit), any
cost_budget headroom, and the spend_envelope. Show the operator the priced plan.
- Set an optional
cost_budget on the spec when the operator wants a hard ceiling โ validate/emit
HALT (never a silent over-spend, per HALT-not-degrade) if the summed spend exceeds it, mirroring
VERIFY_N_CAP.
- Set an optional
spend_envelope when the operator wants "ask once, at the crossing" rather than a
prompt per expensive choice; /work's #364 between-rounds escalation consults it before proposing a
climb (SpendEnvelope.consider).
- Author per-unit effort allocations with
python3 plugins/saga/scripts/effort_ledger.py allocate --unit <U-ID> --amount <to_spend> (ordinal
spend units, so escrow and the budget speak one currency). /work records actuals and refunds unused
budget; a unit that would exceed its allocation surfaces an escalation-request before it runs.
Weights are ordinal/relative, not dollar prices โ the cost-weighted spend-delta classifier is #367.
Step 1c โ Spend-delta levers: relative override, worth-it receipts, spend authority (#367).
- Relative override โ when the operator wants to adjust a proposed tier, offer the three-way
relative choice
cheaper / as-proposed / dearer (computed by execution_spec.adjacent_tier)
instead of forcing an absolute re-pick from the full MODELS ร EFFORTS enum. cheaper/dearer step
exactly one rung; at a ladder boundary the lever raises (no silent clamp). spend_delta(old, new)
classifies any change as cheapen / escalate / lateral โ a lateral (sideways axis trade) or a
cheapen proceeds quietly; an escalate is the one that asks.
- Worth-it receipts โ a premium tier (opus/fable model or xhigh effort โ above the
sonnet/high
baseline) must carry a one-line worth_it_because and a named cheaper_fallback (an adjacent
strictly-cheaper tier, default adjacent_tier(tier, "cheaper")). Enforce it at authoring by validating
with receipts required:
python3 plugins/saga/scripts/execution_spec.py validate <spec.json> --require-receipts. Plain
validate/emit do NOT require receipts, so existing specs are never retroactively broken.
- Spend authority โ resolve each unit's silent/ask disposition via
spend_authority.resolve_spend_authority(tier): a .saga/spend-authority.json silent_ceiling
(absent โ sonnet/high) makes any premium tier ask and everything at/below silent โ the
configurable home for the cheap-silent/expensive-asks rule.
Step 2 โ Author thin per-unit prompts (KTD2). Each unit's prompt is a thin pointer, not a prose
transcription of the plan:
<unit-id>: <one-line goal>. Read the plan at <repo-relative plan path> as your authoritative spec.
The emitter appends fan-out reconciliation, budget riders, and return contracts automatically โ do not
duplicate them in the prompt. Depth comes from the agent reading the plan; the prompt is control flow.
Step 3 โ Wire depends_on barriers and optional verify panels. Set depends_on from the plan's
dependency order. For units with an explicit adversarial-confidence request, add a verify panel:
default n=3, pass_rule=majority (KTD3 โ a finding survives unless โฅโ3/2โ=2 of 3 verifiers refute
it). Override N per-unit when the operator requests a different panel size; N is capped at 7
(VERIFY_N_CAP) โ above the cap, validate will hard-block.
Step 4 โ Validate the spec (HARD BLOCK on failure). Run the validator:
python3 plugins/saga/scripts/execution_spec.py validate docs/plans/<name>-spec.json
A non-zero exit means the spec is malformed. Do NOT proceed to emit or persist an invalid spec โ fix
the SpecError and re-validate. Common failures: depends_on cycle, fan-out unit with no targets,
pilot tier mismatch (R3), N above VERIFY_N_CAP.
Step 5 โ Emit the workflow script and surface for operator confirmation. Once validate exits 0:
python3 plugins/saga/scripts/execution_spec.py emit docs/plans/<name>-spec.json \
-o docs/plans/<name>.workflow.js
Then render the approval table โ this is the artifact the operator approves, not the JSON:
python3 plugins/saga/scripts/spec_table.py docs/plans/<name>-spec.json --backend <backend>
Paste that table into your reply verbatim. It reports every unit's tier, the dependency waves
(what actually runs in parallel), spend against budget, and โ the decision-relevant part โ what
the chosen backend can and cannot enforce. A spec declaring a restrictive sandbox axis the
backend cannot enforce will HALT at emit rather than silently downgrade, and the table says so
before the operator approves rather than after the run fails.
Do not hand-build this table, and do not dump the spec JSON instead. Never ask an operator
to approve a backend without showing its enforceability rows: cc-workflows-ultracode enforces
read-only and disposable-worktree and reaches every model; team-execution enforces neither axis
and cannot reach fable. That asymmetry is invisible in the spec itself.
Split the work so concurrent units never share a file (#671). The table's
Concurrent-writer safety section reports any two units that would run in the same wave while
declaring the same path, and emit HALTs on one โ no backend can enforce its way out of a
collision, because concurrent agents share one working tree and Claude Code has no cross-agent file
lock. Get this right while authoring the units, not at emit:
- Different repositories, or disjoint files โ safe to run in parallel.
- Same file โ one unit, not two. Merging beats sequencing: a single agent making both edits
keeps the file's context warm and reuses the prompt cache, where splitting pays to load the same
file into two agents and then risks losing one of their writes.
- Only reach for
depends_on when the two really are separate pieces of work that happen to touch
a shared path.
Bias toward fewer, longer-lived units generally. Parallel width is not free โ it costs cache
reuse, and the fleet's own history is 88 of 92 waves running a single unit.
The operator must explicitly confirm the tier assignments and the control-flow structure before
/work runs it (R8 "approved"). A rejection means revising the spec and re-running validate +
emit + table.
Spec naming convention: docs/plans/<YYYY-MM-DD>-<topic>-spec.json beside the plan doc. The
.workflow.js shares the same stem: docs/plans/<YYYY-MM-DD>-<topic>.workflow.js.
5.3 Write the saga tick
Emit a runnable saga save command โ never prose like "write a saga", and never git add the
tick (saga state is git-ignored, machine-local). Use the real flags:
python3 plugins/saga/scripts/saga.py save \
--kind <issue|task> \
--id <issue-number-or-task-slug> \
--lifecycle-phase plan \
--plan-path docs/plans/YYYY-MM-DD-<topic>-plan.md \
--destination <plan-only|pr|merge|nonprod-deploy> \
--deploy-autonomy <gate|auto>
--adr-refs "ADR-NNNN|ADR-MMMM" \
--decisions "KTD1: rationale. KTD2: rationale." \
--orchestration-mode <inline|team-execution|cc-workflows-ultracode> \
--orchestration-recommended <recommend_execution_backend() output>
For cc-workflows-ultracode: also pass --orchestration-ref pointing at the spec JSON (the
canonical artifact, per KTD1/KD3 โ regenerable, so the ref is the spec not the .workflow.js):
python3 plugins/saga/scripts/saga.py save \
--kind <issue|task> \
--id <issue-number-or-task-slug> \
--lifecycle-phase plan \
--plan-path docs/plans/YYYY-MM-DD-<topic>-plan.md \
--destination <plan-only|pr|merge|nonprod-deploy> \
--adr-refs "ADR-NNNN|ADR-MMMM" \
--decisions "KTD1: rationale. KTD2: rationale." \
--orchestration-mode cc-workflows-ultracode \
--orchestration-recommended <recommend_execution_backend() output> \
--orchestration-ref docs/plans/YYYY-MM-DD-<topic>-spec.json
The .workflow.js is regenerable at any time from the spec (execution_spec.py emit); the spec JSON is
the durable canonical artifact. orchestration_ref is the repo-relative path to the spec JSON, so
/work can re-emit fresh without any prose-parsing.
Also pass --orchestration-recommended <the backend the recommender suggested> so the tick records
recommended-vs-chosen on this decision (R12 override-rate telemetry); orchestration_operator_choice
auto-derives from --orchestration-mode, so the only added burden is naming the recommendation.
--id is the only strictly required flag (--kind defaults to issue); for ad-hoc work pass
--kind task --id <slug>. --lifecycle-phase plan, --plan-path, --destination,
--deploy-autonomy (only when --destination nonprod-deploy โ Phase 5.1), --adr-refs,
--decisions (the KTD mirror), --orchestration-mode, --orchestration-recommended, and (for
ultracode) --orchestration-ref carry the /plan consumer row from references/saga-spec.md ยง11.
When resuming (Phase 0.3 matched), this appends a tick to the existing saga directory rather than
minting a new one.
5.4 Route
Recommend the next command with plural clean exits:
/doc-review (recommended next) โ the review phase. /work gates on doc-review and blocks on
unresolved P0/P1 findings, so run the review before execution.
/work โ execute the plan (after doc-review).
/handoff โ hand the plan to an SDLC issue through mission-control.
/brainstorm โ step back if interrogation revealed the WHAT was not actually settled.
5.5 Hard boundary
/plan authors a plan artifact and self-reviews it. It does NOT implement code, does NOT file
SDLC issues (mission-control owns issue creation), and does NOT run the full review gauntlet
(/doc-review owns that). Plan, write the saga, route โ then stop.