Skip to main content
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. 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:

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:
1

Use the explicit default_stage

If default_stage names a valid stage id, use it. This is always the first choice.
2

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.
3

Highest-order normal stage

If no normal default candidate exists, choose the highest order stage where kind: normal, regardless of default_candidate.
4

Fall back to non-normal stages

Only fall back to horizon, experiment, archive, or template stages when no normal stage exists at all.
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.

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:
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.
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

1

Create the stage directory

2

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.
3

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.
4

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.

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.
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.

Archiving a completed stage

When a stage is done, update its entry in the root manifest:
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.
Do not set coding_claims_enabled: true on kind: horizon stages. Horizon stages hold future concepts, not ready implementation work.