> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dotready.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Organize Your Product Tree with Stages and Milestones

> Learn how to create, configure, and manage product tree stages — from a first milestone to horizon concepts — using the root manifest stage registry.

Stages are the top-level organizational unit of a product tree. Each stage is a directory that groups primitives, flags, and artifacts for a given product phase. The stage registry in `ready/manifest.yaml` is the authoritative source for what stages exist, what they mean, and which one is the default. Tools never infer stage order or purpose from directory names.

## What stages are

A stage holds the product truth for one discrete phase of work — a milestone, a release, a pilot, or a product concept. Primitives declare which stage they belong to via the `milestone` field. Flags and artifacts live inside stage directories. A stage is not a sprint and not a ticket board; it is a durable product grouping that persists in Git.

## Stage kinds

Every stage entry in the root manifest declares a `kind`. The kind tells tools and agents what the stage is for.

| Kind         | Description                                                                   |
| ------------ | ----------------------------------------------------------------------------- |
| `normal`     | A buildable product stage. Default-selectable when `default_candidate: true`. |
| `horizon`    | A future product concept shelf. Not intended for near-term implementation.    |
| `experiment` | An alternative branch or product plan. Not default-selectable.                |
| `archive`    | A completed or abandoned historical stage. Not default-selectable.            |
| `template`   | A reusable starter shape for new stages. Not default-selectable.              |

Most projects start with one `normal` stage (e.g., `m1`) and one `horizon` stage (`end-state`). Add more `normal` stages as the product grows.

## The stage registry

The root `ready/manifest.yaml` owns all stage configuration. Each entry in the `stages` list requires nine fields:

| Field                   | Type    | Description                                                              |
| ----------------------- | ------- | ------------------------------------------------------------------------ |
| `id`                    | string  | Stable stage id. Used in `milestone` fields on primitives.               |
| `title`                 | string  | Human-readable label.                                                    |
| `path`                  | string  | Relative path to the stage directory.                                    |
| `manifest`              | string  | Relative path to the stage manifest file.                                |
| `kind`                  | string  | Stage kind: `normal`, `horizon`, `experiment`, `archive`, or `template`. |
| `status`                | string  | Current lifecycle status: `active`, `complete`, `horizon`, etc.          |
| `order`                 | integer | Sort priority for default selection. Higher order = preferred.           |
| `default_candidate`     | boolean | Whether this stage is eligible for automatic default selection.          |
| `coding_claims_enabled` | boolean | Whether coding agents may claim flags in this stage.                     |

## Default stage selection algorithm

When `default_stage` in the root manifest is absent or does not point to a valid stage, tools select the default deterministically in four steps:

<Steps>
  <Step title="Use the explicit default_stage">
    If `default_stage` names a valid stage id, use it. This is always the first choice.
  </Step>

  <Step title="Highest-order normal default candidate">
    If `default_stage` is absent or invalid, choose the stage with the highest `order` value where `kind: normal` and `default_candidate: true`.
  </Step>

  <Step title="Highest-order normal stage">
    If no normal default candidate exists, choose the highest `order` stage where `kind: normal`, regardless of `default_candidate`.
  </Step>

  <Step title="Fall back to non-normal stages">
    Only fall back to `horizon`, `experiment`, `archive`, or `template` stages when no `normal` stage exists at all.
  </Step>
</Steps>

<Note>
  `end-state` is excluded from the default path not because of its name but because it is `kind: horizon` and `default_candidate: false`. If you rename it to `vision` and keep the same kind and flag, it behaves identically.
</Note>

## The end-state (horizon) pattern

Every product tree should include a horizon stage to hold long-term product concepts that are not yet implementation work. Set it up like this:

```yaml theme={null}
- id: "end-state"
  title: "End State"
  path: "ready/end-state"
  manifest: "ready/end-state/manifest.yaml"
  kind: "horizon"
  status: "horizon"
  order: 9999
  default_candidate: false
  coding_claims_enabled: false
```

Using `order: 9999` keeps it sorted last in any view that uses order as a hint. `default_candidate: false` ensures tools skip it in the default selection algorithm.

## A complete stages example

Here is a root manifest `stages` block with three stages: two active milestones and one horizon.

```yaml theme={null}
schema: "readyroom/product-tree-root/v1"
product: "my-product"
source_root: "ready"
default_stage: "m2"
governance_directory: "ready/governance"
stages:
  - id: "m1"
    title: "M1 — Core Onboarding"
    path: "ready/m1"
    manifest: "ready/m1/manifest.yaml"
    kind: "normal"
    status: "complete"
    order: 10
    default_candidate: true
    coding_claims_enabled: false

  - id: "m2"
    title: "M2 — Team Collaboration"
    path: "ready/m2"
    manifest: "ready/m2/manifest.yaml"
    kind: "normal"
    status: "active"
    order: 20
    default_candidate: true
    coding_claims_enabled: false

  - id: "end-state"
    title: "End State"
    path: "ready/end-state"
    manifest: "ready/end-state/manifest.yaml"
    kind: "horizon"
    status: "horizon"
    order: 9999
    default_candidate: false
    coding_claims_enabled: false
```

Because `default_stage: "m2"` is set explicitly, tools go straight to M2. If you remove the `default_stage` line, the algorithm falls to step 2 and still picks M2 because it has `order: 20` — higher than M1's `order: 10` — with `kind: normal` and `default_candidate: true`.

## Adding a new stage

<Steps>
  <Step title="Create the stage directory">
    ```bash theme={null}
    mkdir -p ready/m2/premises ready/m2/intents ready/m2/standards
    mkdir -p ready/m2/services ready/m2/flags/seed ready/m2/flags/delta
    mkdir -p ready/m2/flags/discovery
    mkdir -p ready/m2/artifacts/samples ready/m2/artifacts/resources
    mkdir -p ready/m2/artifacts/snippets ready/m2/artifacts/designs
    mkdir -p ready/m2/artifacts/manifests
    touch ready/m2/README.md
    ```
  </Step>

  <Step title="Create the stage manifest">
    Copy the milestone manifest template to `ready/m2/manifest.yaml` and update the `milestone`, `stage.id`, `stage.title`, and `source_root` fields.
  </Step>

  <Step title="Add the stage to the root manifest">
    Append a new entry to the `stages` list in `ready/manifest.yaml`. Assign an `order` value higher than the previous active stage. Set `kind: normal`, `status: active`, and `default_candidate: true` for a standard buildable milestone.
  </Step>

  <Step title="Update default_stage if needed">
    If the new stage should be the default, update `default_stage` to its id. If you want the algorithm to resolve automatically, omit `default_stage` and rely on the `order` + `default_candidate` rules.
  </Step>
</Steps>

## Moving work between stages

When a primitive belongs in a different stage, update two things: the `milestone` field inside the primitive's `.ready.yml` file, and the file's location in the directory tree. Keep ids stable — the id is the durable identity; the path and milestone field are refactorable.

<Tip>
  Use a Git commit per batch of moved primitives so the diff is reviewable. A move with no content change is easy to verify; a move mixed with edits is harder.
</Tip>

## Archiving a completed stage

When a stage is done, update its entry in the root manifest:

```yaml theme={null}
- id: "m1"
  title: "M1 — Core Onboarding"
  path: "ready/m1"
  manifest: "ready/m1/manifest.yaml"
  kind: "normal"
  status: "complete"       # or "archive" if you want kind-based exclusion
  order: 10
  default_candidate: true  # keep true so history compiles correctly
  coding_claims_enabled: false
```

If you want to fully exclude the stage from default selection, change `kind` to `archive`. The directory and its primitives remain in Git history — nothing is deleted.

## The coding\_claims\_enabled field

`coding_claims_enabled` controls whether coding agents may claim flags inside a stage. Set it to `true` only when:

* The stage has at least one seed or delta flag with `claimable: true`
* The required services, credentials, and environments are confirmed available
* The workspace Coding work switch is enabled

Leave it `false` by default. Enabling coding claims on a stage that is not ready leads to blocked agents and incomplete work. You can enable it per-flag via `claimable: true` on the flag itself; the stage-level field is an additional gate.

<Warning>
  Do not set `coding_claims_enabled: true` on `kind: horizon` stages. Horizon stages hold future concepts, not ready implementation work.
</Warning>
