Skip to content

Planning Graph & Todo Routing

The migration to cordanaLLM/imago is tracked as a typed dependency graph under planning/, compiled with praetor's planning compiler and routed by the imago CLI. Recurring, cadence-driven work stays in .github/epics.json; one-off work with dependencies lives in the graph.

Status: frozen migration record

Since 2026-10-11 the forge is the record of open work: issues under milestones (ADR-0025). The graph under planning/ stays as the record of the migration and receives no new step. imago plan validate and imago plan route keep working on it.

Twenty of the 22 steps are done. The two open steps are carried by issues:

Step Carried by Closes when
step-aegis-pair #46 the executor returns a real result for an accepted Aegis request
step-nucleus-contract #47 a nucleus release crosses the contract and imago verifies it

The overlay names the issue in the evidence field of each open step. When an issue closes, its step is marked done there with the pull request as evidence. A step marked done whose acceptance turns out unmet is reopened with the issue that carries it (ADR-0029); tests/test_planning_overlay.py fails when this table and the overlay name different open steps.

Files

File Authority Contents
planning/plan.json Canonical draft (praetor planning schema version 1) Sources with SHA-256, cited requirements, milestones, steps with depends_on, actions, expected outputs, and positive/negative/boundary acceptance proposals.
planning/TODO.md, ROADMAP.md, MILESTONES.md Generated projections Rendered by praetorctl planning prepare; cross-linked by stable IDs and the plan digest. Never edited by hand, except the frozen-record marker on the first line of TODO.md and the note under its title (ADR-0025): the marker <!-- praetor: frozen-record; open-work: forge; adr: 0025 --> tells the Praetor plan-doc scan that its unchecked boxes are not open work.
planning/routing.json Routing overlay Per-step cost class, completion, owner, and the flags that push work behind local steps (needs_external_contract, needs_hardware).
planning/DECISIONS.md Planning source Operator decisions the plan cites by hash; changing a decision invalidates the dependent draft.
planning/archetypes/os-image.yaml Recorded draft The archetype proposed upstream and accepted in praetor#54. Retained as the output of step-archetype-draft; the authoritative copy is the vendored .config/archetypes/os-image.yaml.
flowchart LR
    classDef src fill:#7c3aed,stroke:#6d28d9,stroke-width:2px,color:#ffffff
    classDef gen fill:#0284c7,stroke:#0369a1,stroke-width:2px,color:#ffffff
    classDef route fill:#059669,stroke:#047857,stroke-width:2px,color:#ffffff

    PLAN["planning/plan.json<br/><small>typed draft, DAG</small>"]:::src
    ROUTING["planning/routing.json<br/><small>cost, done, flags</small>"]:::src
    PRAETOR["praetorctl planning prepare"]:::gen
    PROJ["TODO.md · ROADMAP.md · MILESTONES.md"]:::gen
    ROUTER["imago plan route<br/>route_plan (MCP)"]:::route
    READY["Ranked ready set"]:::route

    PLAN --> PRAETOR --> PROJ
    PLAN --> ROUTER
    ROUTING --> ROUTER --> READY

Routing policy

imago plan route validates both files, derives each step's state, and ranks the graph:

  1. State: done when the overlay marks it complete; ready when every direct dependency is done; otherwise blocked.
  2. Order: ready steps first, then blocked, then done.
  3. Local before external: among ready steps, work that needs no external contract and no hardware ranks ahead of flagged work, whatever its score.
  4. Score: (1 + transitive unblocks) / cost, with cost weights trivial=1, small=2, medium=4, large=8 (the Aegis-OS scale).
  5. Ties: more transitive unblocks first, then the lexicographically smaller step ID, so the output is deterministic.
imago plan validate                 # schema, references, cycle check, overlay coverage
imago plan route                    # full ranked table
imago plan route --ready --json     # ready set for agents and dashboards

The route_plan MCP tool returns the same JSON. Paths are repository-relative; absolute paths and .. are rejected.

Recompiling the projections

plan.json is the input and the canonical output of praetor's compiler. After editing it, recompile into a new directory and copy the four artifacts back; the digest in every projection must match.

praetorctl planning prepare --input planning/plan.json --output-dir .workingdir/planning-next
cp .workingdir/planning-next/{plan.json,TODO.md,ROADMAP.md,MILESTONES.md} planning/
imago plan validate

The compiler rejects incomplete steps, unknown references, uncovered requirements, and dependency cycles. It does not verify source bytes, execute actions, or record completion; completion lives in routing.json and is proven by the evidence each step names.