# Planning
> The SPDD cycle and the identifiers that hold it together — R-*, N-* and OP-* ids, what declares each one, and the exact shape the execution graph is parsed from.
Source: https://ivar.run/docs/guide/planning

import { Callout } from 'fumadocs-ui/components/callout';
import { File, Files, Folder } from 'fumadocs-ui/components/files';

```text
/ivar-plan <feature-name>
```

Planning turns a discovery brief into artifacts an execution run can be held
against. It needs a feature session — `IVAR_FEATURE` set — and a feature that
already exists. Start a fresh cycle with `ivar plan create <feature>`.

## Four artifacts, four gates

```
Requirements → [approve] → Analysis → [approve] → Plan → [approve] → Graph → [approve] → Execution
```

Each phase stops and waits. The agent writes the artifact, shows it to you, and
records the approval only after you have said yes.

<Files>
  <Folder name="plans" defaultOpen>
    <Folder name="billing-currency" defaultOpen>
      <File name="requirements.md" />
      <File name="analysis.md" />
      <File name="plan.md" />
      <File name="execution-graph.json" />
    </Folder>
  </Folder>
</Files>

They live committed under the hall and are projected into the view directory at
`plans/<feature>/`, so edits there land in the hall's committed copy.

## The reference system

Four namespaces. Each is **declared** in exactly one place and **cited**
everywhere else — that is what makes an approved plan checkable rather than
merely agreed.

| Id | Declared in | Cited by | Means |
| --- | --- | --- | --- |
| `R-*` | `requirements.md` | analysis, plan, code comments | a functional requirement |
| `N-*` | `requirements.md` | plan `## Norms`, code comments | a norm — a convention the work must hold to |
| `OP-*` | `plan.md` `## Operation details` | plan `## Operations`, `execution-graph.json` | one unit of implementation |
| workstream id | `plan.md` `### <id>` | `execution-graph.json` `id` | a unit of parallel work |

Real examples from this site's own feature: `R-QUICKSTART-PAGE`,
`R-SHARED-COMPONENT`, `N-VOICE`, `N-MOBILE`, `OP-DOCS-CONFIG`, workstream
`docs-route`.

<Callout title="Why the ids earn their keep">
  A norm cited as `N-MOTION` in a stylesheet comment points back at the
  requirement that asked for it. Six months later the comment still explains
  *why*, and the requirement is still findable — which is the part prose alone
  never survives.
</Callout>

## Phase 1 — Requirements

Functional requirements with stable `R-*` ids, non-functional requirements and
norms as `N-*`, plus constraints. The ids are the contract: everything
downstream cites them, and renaming one silently orphans every citation.

## Phase 2 — Analysis

Read the relations in `HALL.md` first — select the ones involving potentially
affected repos, follow only the linked topics, and record what is relevant in
`analysis.md`. This checkpoint never edits `HALL.md`;
[`/ivar-relations`](/docs/guide/features) is the only writer of that region.

Then, with approved requirements as context: affected modules (repo, path,
impact level), trade-offs between approaches, risks and mitigations, and a
recommendation.

## Phase 3 — Plan

The plan is the REASONS canvas:

| Section | Holds |
| --- | --- |
| Requirements | a reference to the approved artifact |
| Entities | the domain model, delta only |
| Approach | the chosen design |
| Structure | file and module organisation |
| Operations | which workstream owns which `OP-*` ids |
| Operation details | what each `OP-*` id means |
| Norms | the `N-*` conventions to follow |
| Safeguards | what to watch out for |

### Two sections are parsed, not read

Every other section is prose for a human. `## Operations` and
`## Operation details` are the input `ivar feature execute tick` parses to build
each executor's prompt: the graph names the `OP-*` ids a workstream owns, and
the plan is where the executor is told what those ids mean.

````markdown title="plan.md"
## Operations

### checkout-api
- OP-API-CONTRACT
- OP-API-HANDLER
write_contract:
- src/api/checkout.rs
- src/api/checkout_test.rs

## Operation details

**OP-API-CONTRACT** — Define the request and response types for `POST
/checkout`, including the `410` a closed cart answers with.

- `touches`: src/api/checkout.rs
- `tests`: a closed cart answers `410`; an open one answers `200`
- `doneWhen`: the contract compiles and both tests pass

**OP-API-HANDLER** — Implement the handler against that contract, rejecting a
cart the session does not own before any pricing runs.

- `dependsOn`: OP-API-CONTRACT
- `tests`: a foreign cart is rejected before pricing; an owned cart prices once
- `doneWhen`: a foreign cart can no longer reach the pricer
````

The rules behind that shape:

- **`### <id>` is a workstream id**, matching the execution graph byte for byte.
  Not a phase, not a cluster, not a title. `### Fase 1` or `### Cluster 2 —
  Report` produces workstreams no graph refers to, and every operation the graph
  claims is then missing from the plan.
- **The bullets under it are operation ids and nothing else** — `- OP-SLUG`, one
  per line, following `OP-<SLUG>`.
- **`write_contract:` switches** the bullets that follow to the paths that
  workstream may write. `execute replan` compares this list to decide which
  workstreams a revision affects, so it is load-bearing.
- **Every id needs a `**OP-SLUG**` entry** under `## Operation details`. The
  entry's text reaches the executor verbatim and runs until the next declared
  `**OP-***` marker or the next heading — a blank line is a paragraph break
  inside the entry, not its end.
- **`## Operations` is parsed to the end of the file**: every later heading
  opens another workstream named after it. Harmless for `## Norms` and
  `## Safeguards`, but a workstream id must never collide with a section
  heading.

<Callout type="warn" title="Getting the shape wrong fails late">
  A mis-shaped `## Operations` section is not caught at approval. The tick
  refuses with `execute.operation_missing_from_plan` — after the graph has been
  approved, with nothing launched.
</Callout>

## Phase 4 — Execution graph

The graph is approved separately from the plan:

```sh
ivar feature execute prepare <feature> --graph-json <path>
ivar feature execute approve <feature>
```

`prepare` persists the resolved targeting into `plan.md`, computes the plan
fingerprint over that persisted form, and validates the graph. Between the two
commands the board sits at `AwaitingApproval` for you to read.

## Where a feature actually is

```sh
ivar plan status plans/<feature>/plan.md
```

Reports each gate as approved, pending or needs-revision. At the start of a
session this is how you re-derive the state: continue from the first gate that
is not approved.

## Changing an approved artifact

Approval is not a freeze — it is a record of what was agreed, and changing an
upstream artifact marks the downstream gates `needs_revision` automatically.
Behaviour-changing plan edits — anything in Operations or Approach — require
re-approval of the affected gates.

<Callout type="warn" title="Never hand-edit approvals">
  The records under `.ivar/features/<feature>/planning/` are written by
  `ivar plan approve`. Editing them by hand desynchronises the gates from the
  artifacts they were computed against.
</Callout>

Once execution is in flight, revisions go through the board instead — see
[Execution](/docs/guide/execution#when-reality-diverges).
