roadmap — Live Feature-Set Roadmap Keeper
CodeOps Skills Version: 3.20.0
Resolve paths first (layout-aware)
Before any action, determine the layout via ../../_shared/layout-convention.md:
- Flat layout (no
codeops/.codeops.yml): a single roadmap at plans/00-roadmap.md. Behaves
exactly as flat layout always has — everything below that mentions "the roadmap" means this one file, and the
portfolio tier does not exist (its cascade steps are inert).
- Nested layout (marker present): two tiers — a per-feature roadmap at
codeops/features/<f>/00-roadmap.md and a portfolio roadmap at codeops/00-roadmap.md (one
row per feature, auto-cascaded). In nested layout the skill asks/confirms the target feature
before acting on a per-feature roadmap, and creates the feature folder lazily (never guesses).
The roadmap is a living document that tracks an entire feature at a higher altitude than any
individual execution plan. Where 99-execution-plan.md tracks the tasks within one feature, the
roadmap tracks every requirement (RD), plan, and task and the lifecycle stage each is in. It is
the user's cross-session lifeline: open it to see what is done, in flight, blocked, or in backlog.
It never replaces the execution plan; it indexes and summarizes across many of them.
Action dispatch
Detect the action from the user's phrasing or argument and branch:
| Trigger |
Action |
make_roadmap, "create the roadmap", "start a roadmap" |
make — create + seed |
update_roadmap, "sync the roadmap", "update the roadmap" |
update — re-infer + sync |
review_roadmap, "check the roadmap", "is the roadmap healthy" |
review — read-only health check |
show_roadmap, "show the roadmap", "roadmap status", "where do things stand", "what's the progress on " |
show — read-only status overview |
archive_roadmap, "archive the feature-set", "archive the roadmap" |
archive — move to _archive |
compact_roadmap, "compact the roadmap", "clean up / slim the roadmap" |
compact — strip the legacy Notes log + trim fat cells |
The lifecycle state machine
⬜ Backlog — RD identified but not yet drafted
✏️ RD Drafted — RD document written
🔎 RD Preflighted — RD passed preflight
📋 Plan Created — a plan was produced
🔬 Plan Preflighted — plan passed preflight
🔄 Executing — execution in progress
✅ Done — plan fully executed
⛔ Blocked — cannot proceed (waiting on a Deferred dependency)
⏸️ Deferred — a discovered dependency pulled out as its own tracked item
Linear happy path:
Backlog → RD Drafted → RD Preflighted → Plan Created → Plan Preflighted → Executing → Done.
Blocked and Deferred are orthogonal overlays on the linear path — a row in
any stage can become Blocked, and any discovered dependency can be pulled out as
a Deferred sub-row.
The full stage-transition map (which lifecycle events advance which rows, and which
skill fires each hook) is in stage-hooks.md — read it when wiring
or reasoning about transitions.
Task rows (nested layout)
A feature's roadmap also tracks lightweight tasks (T-NN) beside its RD rows. A task uses the
compact lifecycle ⬜ Backlog → 🔄 Executing → ✅ Done (with ⛔/⏸️ overlays) and never the
RD/Plan-Preflight stages. A trivial task is a row with no RD and no plan link; a non-trivial task
links a single mini-plan. T-NN and RD-NN are separate per-feature namespaces (no collisions).
Full task model + routing: ../../_shared/layout-convention.md.
Two governing rules (apply to every action)
Ask-if-missing / sync-if-exists — the roadmap is never auto-created silently:
- When MISSING: ask the user whether to create it. Never fabricate one without consent.
- When it EXISTS: always sync from disk state automatically — never ask, never prompt.
Stage hooks fire silently.
This keeps the roadmap opt-in to create, but always-fresh once it exists.
Real-time update mandate — the roadmap is updated immediately on each stage
transition, BEFORE verification, commit, or the next action. Update order:
complete the stage transition → update the resolved roadmap file → proceed (the resolved file
per the convention doc: plans/00-roadmap.md flat, the feature's 00-roadmap.md nested). On each
transition update the row's Stage, Status, and Last Updated, plus the header
Progress counter and Last Updated. Rationale — crash resilience: a session can
crash or hit context limits at any moment; if the roadmap is stale the user loses
their cross-session view. Keep it always reflecting reality, and never end a
session/task with a stale roadmap.
Stage-inference artifacts & the never-regress rule — stages must be re-inferable from disk:
RD Drafted ⇔ the RD file exists. Plan Created ⇔ a linked plan folder exists.
Executing/Done ⇔ the plan's 99-execution-plan.md checklist state (Done = all [x]).
RD Preflighted ⇔ a saved preflight report (00-preflight-report.md) exists in the resolved
requirements dir with a passing tier; Plan Preflighted ⇔ the same file in the plan folder.
(The preflight skill saves these reports — they ARE the stage's disk artifact.)
- Stages never regress on sync.
update may only advance or preserve a row's stage; if disk
suggests a LOWER stage than recorded, keep the recorded stage and report the discrepancy
(review_roadmap flags it). Regressing a row requires an explicit user instruction, recorded in
the git commit message that makes the regression (and, if it changes a dependent, noted terse in
that dependent's Depends-on / Blocker cell) — never in a running Notes log.
Portfolio cascade mandate (nested layout only) — the real-time update extends one altitude
up. After completing a per-feature stage transition, update that feature's row in
codeops/00-roadmap.md (re-roll Stage Summary / Progress / Status; bump the portfolio counts)
before verify/commit/next — but only on the integration branch. On a non-integration
branch (a parallel feature worktree) the portfolio write is deferred: update only the
isolated per-feature roadmap and leave codeops/00-roadmap.md untouched, so concurrent worktrees
never collide on it; roadmap update reconciles the portfolio from disk once the work lands on the
integration branch. In flat layout this step is inert. Full cascade rule, the integration-branch
deferral, and the status roll-up are in stage-hooks.md.
Deterministic linking (RD ↔ plan)
Plan folders are named by feature (e.g. plans/billing/) and carry no encoded RD
id, and the repo can hold multiple unrelated feature-sets at once, so "everything
under plans/" is not a valid membership rule. Link deterministically instead:
- Every plan declares the requirement it implements as a
> **Implements**: RD-NN
line in its 00-index.md (feature-qualified > **Implements**: <feature>/RD-NN in nested
layout — see the ID rules in the convention doc). The Plan Created hook reads this line and
links the plan to the matching RD row in that feature's roadmap.
- A plan with no declared RD is linked only when the user explicitly states which
RD (or
DEF-n) it belongs to. Unrelated plans are never silently swept in.
Deferred & Blocked handling
When a blocking dependency is discovered mid-preflight or mid-execution:
- Add a nested
↳ DEF-n sub-row directly beneath the affected parent row, visually tied to it.
- Set the parent row's Stage cell to
⛔ Blocked (was: <prior stage>) — the prior stage is
recorded IN the cell so recovery never depends on conversation memory — and name the DEF-n
it waits on in Depends-on / Blocker.
- Track the
DEF-n sub-row through its own lifecycle stages like any other item.
- When
DEF-n reaches Done, the parent leaves Blocked and resumes the stage recorded in
its (was: …) annotation.
Deferred work is never hidden in a separate section — it stays nested under the item
it blocks so the dependency is obvious at a glance.
make — create the roadmap
Create the roadmap using the template in template.md (header, legend, tracker
columns; and the portfolio template for nested layout). Path per the convention doc.
Flat layout → create plans/00-roadmap.md:
- Ask the user once for the feature-set name — used in the header and as the
archive folder slug.
- Auto-populate from disk (suggest, don't sweep):
- Seed one row per
requirements/RD-*.md found.
- For each
plans/*/99-execution-plan.md, suggest a link plus an inferred stage
(from checklist completion), but only write the plan into the roadmap after the
user confirms it belongs to this feature-set.
- If the roadmap already exists: do NOT ask — sync it from disk state instead
(the update action).
Nested layout → two tiers:
- Portfolio (
codeops/00-roadmap.md): create it if absent (a fresh-scaffolded or just-migrated
repo already has a seeded one). Seed one row per codeops/features/<f>/ present, each row
derived from that feature's roadmap.
- Per-feature roadmap (
codeops/features/<f>/00-roadmap.md): ask/confirm the target feature,
create the feature folder lazily if new, then seed it from that feature's requirements/ +
plans/ (same suggest-don't-sweep rule), and add T-NN task rows where tasks exist.
- After creating/seeding a feature roadmap, cascade its summary to the portfolio row.
update — re-infer stages and sync to disk
Advance stages and sync the roadmap to current disk state.
- Walk each row, re-infer its stage from disk per the stage-inference artifacts above (RD
present, preflight reports, plan present, checklist completion) and update
Stage, Status,
and Last Updated — honoring the never-regress rule (advance or preserve; report
discrepancies instead of downgrading).
- Delegate ALL counter arithmetic to the engine: run
scripts/codeops-roadmap-sync.sh (write
mode). It recomputes the header Progress counters, the portfolio Progress/Status cells,
and the Features count from disk — never re-derive these numbers in prose (the same
prose-vs-script division as the migration engine: the skill owns stage judgment, the script
owns arithmetic). Stage Summary phrasing remains yours. The engine counts only RD-* rows
(T-* tasks are excluded), is follow-on aware (a feature with all RDs Done but an open
## Open follow-ons row holds at 🔄), and preserves hand-maintained values — a
non-computed Progress such as n/a and any · … / (…) annotation are kept verbatim, and a
held row's Status is not re-rolled. See template.md → Open follow-ons and the
Progress/Features field notes for the authoring contract.
- Nested layout: stage re-inference is per-feature (your judgment); the script performs the
numeric cascade into
codeops/00-roadmap.md in the same run.
- Recommend compaction if the roadmap is bloated: run
scripts/codeops-roadmap-compact.sh --check; if it reports a legacy ## Notes section or an oversized cell, recommend the user run
compact. update itself never strips or trims — it only re-infers stages and delegates
counters (mirrors how it delegates arithmetic to the sync engine).
- Rows stay dependency-ordered: keep prerequisites above the rows that depend on them (see
template.md → Row ordering & discipline); a planned dependency is a terse
depends on RD-NN in the row's Depends-on / Blocker cell.
- If the roadmap is missing: fall back to make — ask whether to create it, then create it.
review — read-only health check
Run a health check and report findings; change nothing on disk.
- Counter/cascade drift is mechanical: run
scripts/codeops-roadmap-sync.sh --check — its
DRIFT lines and non-zero exit ARE that portion of the report (Progress counters, portfolio
Progress/Status cells, Features count). Do not re-derive the numbers in prose. Preserved
hand-maintained values are reported on informational HELD lines and do not fail the check —
an n/a sentinel or an annotated cell is healthy, not drift; surface HELD lines so a human can
eyeball the hand-maintained values.
- Bloat is mechanical too: run
scripts/codeops-roadmap-compact.sh --check — a reported legacy
## Notes section or oversized cell is that portion of the health report; recommend compact
to slim it (review itself changes nothing on disk).
- Every RD row references an existing
requirements/RD-*.md file.
- Every plan link references an existing plan folder.
- The recorded
Stage matches on-disk reality per the stage-inference artifacts (flag drift;
remember stages never regress — a lower-than-recorded disk state is a discrepancy to report,
not a downgrade to apply).
- Every
Blocked row has a live DEF-n sub-row and a (was: <stage>) annotation; if the
DEF-n is already Done, flag the parent as ready to unblock.
- Nested layout (both tiers): every portfolio row links an existing feature roadmap; Stage
Summary phrasing matches the feature's rolled-up state.
- If the roadmap is missing: return the error below.
show — present a status overview
Render a human-facing snapshot of where a feature (or the whole repo) stands: overall progress, the
per-item stage table, and the concrete next steps. Read-only — this action never writes to disk.
It is the presentation counterpart to review: review audits the roadmap for drift and broken
links, show simply displays it. Do not run the sync engine in write mode or edit any file here.
Resolve the target (layout-aware):
- Flat layout → present the single
plans/00-roadmap.md.
- Nested + a feature argument (
show_roadmap <feature>) → present that feature's
codeops/features/<f>/00-roadmap.md, including its T-NN task rows and any ## Open follow-ons.
- Nested + no argument → present the portfolio
codeops/00-roadmap.md (one row per feature)
as the overview, then offer to drill into a named feature. If the target feature is ambiguous, ask
— never guess (same rule as the other actions).
What to present (adapt the depth to the roadmap's size; keep it scannable):
- A one-line header — which roadmap you are reading (its resolved path) and its recorded
Last Updated.
- An overall progress line — the header
Progress fraction/percent (portfolio: the Features
count), plus a short phrase on what most recently landed and what is in flight. Report the
recorded counters as-is; do not silently recompute or mutate them. If a row's Stage or a
counter looks stale versus disk (apply the stage-inference artifacts read-only), note the
suspected drift in one line and suggest update_roadmap — never edit to "fix" it here.
- The tracker as a table — the roadmap's rows with their
ID, Title, Stage, Status
emoji, Plan (✔ / —), and Depends-on / Blocker, in dependency order, with the legend beneath.
Preserve ↳ DEF-n sub-rows nested under the row they block.
- "Where you stand right now" — a few grounded bullets: what just shipped, what is in flight,
anything
Blocked (name the DEF-n it waits on), and how much backlog remains.
- "Natural next steps" — 1–3 concrete, state-grounded suggestions (e.g. preflight the created
plan, execute it, unblock a
DEF-n, or draft the next backlog RD). Lead with the single most
obvious continuation; the user decides.
If the roadmap is missing: return the same error as review (below) — never fabricate one.
archive — archive a completed feature
Flat layout (membership is explicit — move only the rows listed in the roadmap):
- Read the feature-set slug from the roadmap header.
- Create
plans/_archive/<feature-set>/.
- Move into it: the roadmap itself, plus only the RD documents and plan folders
that appear as rows in the roadmap.
- Leave all other
requirements/ and plans/ content untouched. Never sweep every
folder under plans/.
- A fresh roadmap can then be created for the next feature-set.
- If the roadmap is missing: return the error below.
Nested layout (feature-level, whole-folder — FR-12 / AR #11):
- Confirm the feature to archive (its rolled-up Status should be ✅ Done; warn if not). Never
fragment a live feature — archive the whole folder, not individual plans.
git mv codeops/features/<f> codeops/_archive/<f> (preserves history; intra-feature links
survive because the whole folder shifts).
- In
codeops/00-roadmap.md, move the feature's row from ## Features to ## Archived
(mark 📦, update the Roadmap link to _archive/<f>/00-roadmap.md) — never delete it — and
refresh the Features count + Last Updated.
- If the portfolio is missing: return the error below.
compact — shrink an existing roadmap (both layouts)
Slim a roadmap that has bloated over time — a legacy ## Notes running log and/or verbose table
cells — back to a lean status table. The mechanical, safety-critical work is delegated to the
engine; the judgment (rewriting a fat cell down to a terse phrase) is yours.
- Resolve layout. compact operates on every roadmap in the repo — the portfolio, every
feature roadmap, and
_archive/ — not a single feature.
- Require a clean git tree. Deleting the Notes log is only reversible through git, so if the
tree is dirty, STOP and ask the user to commit or stash first (the engine also refuses — check
early so the user gets a clean message rather than a mid-run abort).
- Run the engine —
scripts/codeops-roadmap-compact.sh (apply). It strips every ## Notes
section in place and prints FLAG <file>:<row>:<column> (<n> chars) lines for oversized cells.
It never rewrites a cell.
- Trim each flagged cell to a terse status phrase, preserving the load-bearing tokens
verbatim —
waiting on DEF-n and Blocked (was: <stage>). The verbose original stays in git
history; never relocate it to another file on disk.
- Confirm, then re-sync. Run
scripts/codeops-roadmap-compact.sh --check — it must report no
## Notes section and no oversized cell. Then run scripts/codeops-roadmap-sync.sh so the
counter surfaces stay consistent.
- Report and stop. List the affected files and leave the change for the user to review and
commit (
git status / git diff); never auto-commit.
If no roadmap exists: report no roadmap found — nothing to compact; never create one.
Error handling
| Error case |
Handling |
| review / show / archive when roadmap missing |
Return **Error:** No roadmap found at <resolved roadmap path>. Run make_roadmap first. (path per the convention doc — plans/00-roadmap.md flat, codeops/00-roadmap.md or the feature roadmap nested) |
| update when roadmap missing |
Fall back to make (ask-if-missing, then create) |
| make when roadmap already exists |
Do NOT ask; sync from disk state (the update action) |
| Nested: per-feature transition but portfolio row stale |
Cascade is mandatory + immediate; review flags the drift (AR #8) |
| Nested: target feature ambiguous |
Ask the user; never guess (AR #26) |
| compact on a dirty or non-git tree |
STOP; ask the user to commit/stash first — the engine also refuses (exit 1) |
| compact when no roadmap exists |
Report no roadmap found — nothing to compact; never create one |
Project conventions
For project-specific settings (build/test/verify commands, package manager,
structure, conventions), read the project's CLAUDE.md (or detected project
conventions). If no CLAUDE.md exists, detect settings from manifest files and use
only facts you can read — do not invent settings.
Pointers & related skills
- template.md — the
plans/00-roadmap.md template, legend, tracker
columns, and a worked example. Read before make.
- stage-hooks.md — the full stage-transition map, which skill fires
which hook, and the source-of-truth rule. Read when reasoning about transitions.
scripts/codeops-roadmap-compact.sh — the compact engine driven by the compact action, and
by update/review's --check bloat detection (strips the legacy Notes log, flags fat cells).
- Related skills: requirements (
RD Drafted hook), preflight (RD/Plan Preflighted
hooks), make_plan (Plan Created hook + linking), exec_plan (Executing / Done /
Blocked hooks).
1---2name: roadmap3description: Tracks features across their lifecycle in a live, per-repo roadmap — every RD, plan, and task and the lifecycle stage each is in. Layout-aware: a single plans/00-roadmap.md in flat layout, or a two-tier per-feature + portfolio roadmap under codeops/ in nested layout. Use when the user says "roadmap", "make_roadmap", "update_roadmap", "review_roadmap", "show_roadmap", "archive_roadmap", or "compact_roadmap". Covers six actions: make_roadmap (create + seed rows from disk), update_roadmap (re-infer stages, sync to disk, cascade to the portfolio), review_roadmap (read-only health check for drift/broken links), show_roadmap (read-only status overview — progress, stages, and next steps), archive_roadmap (move a completed feature to the archive), and compact_roadmap (slim a bloated roadmap: strip the legacy Notes log and trim fat cells). Detects the action from the user's phrasing or arguments and branches. The roadmap is the cross-session source of truth at the RD/plan altitude, above any single execution plan.4---56# roadmap — Live Feature-Set Roadmap Keeper78> **CodeOps Skills Version**: 3.20.0910## Resolve paths first (layout-aware)1112Before any action, determine the layout via **[../../_shared/layout-convention.md](../../_shared/layout-convention.md)**:1314- **Flat layout** (no `codeops/.codeops.yml`): a single roadmap at `plans/00-roadmap.md`. Behaves15 **exactly as flat layout always has** — everything below that mentions "the roadmap" means this one file, and the16 portfolio tier does not exist (its cascade steps are inert).17- **Nested layout** (marker present): **two tiers** — a per-feature roadmap at18 `codeops/features/<f>/00-roadmap.md` and a **portfolio roadmap** at `codeops/00-roadmap.md` (one19 row per feature, auto-cascaded). In nested layout the skill asks/confirms the **target feature**20 before acting on a per-feature roadmap, and creates the feature folder lazily (never guesses).2122The roadmap is a living document that tracks an entire **feature** at a higher altitude than any23individual execution plan. Where `99-execution-plan.md` tracks the tasks *within one feature*, the24roadmap tracks *every requirement (RD), plan, and task* and the lifecycle stage each is in. It is25the user's cross-session lifeline: open it to see what is done, in flight, blocked, or in backlog.2627It never replaces the execution plan; it indexes and summarizes across many of them.2829## Action dispatch3031Detect the action from the user's phrasing or argument and branch:3233| Trigger | Action |34|---------|--------|35| `make_roadmap`, "create the roadmap", "start a roadmap" | **make** — create + seed |36| `update_roadmap`, "sync the roadmap", "update the roadmap" | **update** — re-infer + sync |37| `review_roadmap`, "check the roadmap", "is the roadmap healthy" | **review** — read-only health check |38| `show_roadmap`, "show the roadmap", "roadmap status", "where do things stand", "what's the progress on <feature>" | **show** — read-only status overview |39| `archive_roadmap`, "archive the feature-set", "archive the roadmap" | **archive** — move to `_archive` |40| `compact_roadmap`, "compact the roadmap", "clean up / slim the roadmap" | **compact** — strip the legacy Notes log + trim fat cells |4142## The lifecycle state machine4344```45⬜ Backlog — RD identified but not yet drafted46✏️ RD Drafted — RD document written47🔎 RD Preflighted — RD passed preflight48📋 Plan Created — a plan was produced49🔬 Plan Preflighted — plan passed preflight50🔄 Executing — execution in progress51✅ Done — plan fully executed52⛔ Blocked — cannot proceed (waiting on a Deferred dependency)53⏸️ Deferred — a discovered dependency pulled out as its own tracked item54```5556**Linear happy path:**57`Backlog → RD Drafted → RD Preflighted → Plan Created → Plan Preflighted → Executing → Done`.5859`Blocked` and `Deferred` are **orthogonal overlays** on the linear path — a row in60any stage can become `Blocked`, and any discovered dependency can be pulled out as61a `Deferred` sub-row.6263The full stage-transition map (which lifecycle events advance which rows, and which64skill fires each hook) is in [stage-hooks.md](stage-hooks.md) — read it when wiring65or reasoning about transitions.6667## Task rows (nested layout)6869A feature's roadmap also tracks **lightweight tasks** (`T-NN`) beside its RD rows. A task uses the70compact lifecycle `⬜ Backlog → 🔄 Executing → ✅ Done` (with `⛔`/`⏸️` overlays) and never the71RD/Plan-Preflight stages. A trivial task is a row with no RD and no plan link; a non-trivial task72links a single mini-plan. `T-NN` and `RD-NN` are separate per-feature namespaces (no collisions).73Full task model + routing: [../../_shared/layout-convention.md](../../_shared/layout-convention.md).7475## Two governing rules (apply to every action)7677**Ask-if-missing / sync-if-exists** — the roadmap is never auto-created silently:7879- **When MISSING:** ask the user whether to create it. Never fabricate one without consent.80- **When it EXISTS:** always sync from disk state automatically — never ask, never prompt.81 Stage hooks fire silently.8283This keeps the roadmap opt-in to create, but always-fresh once it exists.8485**Real-time update mandate** — the roadmap is updated **immediately** on each stage86transition, **BEFORE** verification, commit, or the next action. Update order:87`complete the stage transition → update the resolved roadmap file → proceed` (the resolved file88per the convention doc: `plans/00-roadmap.md` flat, the feature's `00-roadmap.md` nested). On each89transition update the row's `Stage`, `Status`, and `Last Updated`, plus the header90`Progress` counter and `Last Updated`. Rationale — crash resilience: a session can91crash or hit context limits at any moment; if the roadmap is stale the user loses92their cross-session view. Keep it always reflecting reality, and never end a93session/task with a stale roadmap.9495**Stage-inference artifacts & the never-regress rule** — stages must be re-inferable from disk:9697- `RD Drafted` ⇔ the RD file exists. `Plan Created` ⇔ a linked plan folder exists.98 `Executing`/`Done` ⇔ the plan's `99-execution-plan.md` checklist state (`Done` = all `[x]`).99- `RD Preflighted` ⇔ a saved preflight report (`00-preflight-report.md`) exists in the resolved100 requirements dir with a passing tier; `Plan Preflighted` ⇔ the same file in the plan folder.101 (The preflight skill saves these reports — they ARE the stage's disk artifact.)102- **Stages never regress on sync.** `update` may only advance or preserve a row's stage; if disk103 suggests a LOWER stage than recorded, keep the recorded stage and report the discrepancy104 (review_roadmap flags it). Regressing a row requires an explicit user instruction, recorded in105 the git commit message that makes the regression (and, if it changes a dependent, noted terse in106 that dependent's `Depends-on / Blocker` cell) — never in a running Notes log.107108**Portfolio cascade mandate (nested layout only)** — the real-time update extends one altitude109up. After completing a per-feature stage transition, update that feature's row in110`codeops/00-roadmap.md` (re-roll Stage Summary / Progress / Status; bump the portfolio counts)111**before** verify/commit/next — **but only on the integration branch**. On a **non-integration112branch** (a parallel feature worktree) the portfolio write is **deferred**: update only the113isolated per-feature roadmap and leave `codeops/00-roadmap.md` untouched, so concurrent worktrees114never collide on it; `roadmap update` reconciles the portfolio from disk once the work lands on the115integration branch. In flat layout this step is inert. Full cascade rule, the integration-branch116deferral, and the status roll-up are in [stage-hooks.md](stage-hooks.md).117118## Deterministic linking (RD ↔ plan)119120Plan folders are named by feature (e.g. `plans/billing/`) and carry **no encoded RD121id**, and the repo can hold multiple unrelated feature-sets at once, so "everything122under `plans/`" is **not** a valid membership rule. Link deterministically instead:123124- Every plan declares the requirement it implements as a `> **Implements**: RD-NN`125 line in its `00-index.md` (feature-qualified `> **Implements**: <feature>/RD-NN` in nested126 layout — see the ID rules in the convention doc). The `Plan Created` hook reads this line and127 links the plan to the matching RD row in that feature's roadmap.128- A plan with **no declared RD** is linked only when the user explicitly states which129 RD (or `DEF-n`) it belongs to. Unrelated plans are never silently swept in.130131## Deferred & Blocked handling132133When a blocking dependency is discovered mid-preflight or mid-execution:1341351. Add a **nested `↳ DEF-n` sub-row** directly beneath the affected parent row, visually tied to it.1362. Set the **parent row's Stage cell to `⛔ Blocked (was: <prior stage>)`** — the prior stage is137 recorded IN the cell so recovery never depends on conversation memory — and name the `DEF-n`138 it waits on in `Depends-on / Blocker`.1393. Track the `DEF-n` sub-row through its own lifecycle stages like any other item.1404. When `DEF-n` reaches `Done`, the parent **leaves `Blocked`** and resumes the stage recorded in141 its `(was: …)` annotation.142143Deferred work is never hidden in a separate section — it stays nested under the item144it blocks so the dependency is obvious at a glance.145146---147148## make — create the roadmap149150Create the roadmap using the template in [template.md](template.md) (header, legend, tracker151columns; and the **portfolio template** for nested layout). Path per the convention doc.152153**Flat layout** → create `plans/00-roadmap.md`:1541551. **Ask the user once for the feature-set name** — used in the header and as the156 archive folder slug.1572. **Auto-populate from disk (suggest, don't sweep):**158 - Seed one row per `requirements/RD-*.md` found.159 - For each `plans/*/99-execution-plan.md`, *suggest* a link plus an inferred stage160 (from checklist completion), but only write the plan into the roadmap **after the161 user confirms** it belongs to this feature-set.1623. **If the roadmap already exists:** do NOT ask — sync it from disk state instead163 (the update action).164165**Nested layout** → two tiers:1661671. **Portfolio** (`codeops/00-roadmap.md`): create it if absent (a fresh-scaffolded or just-migrated168 repo already has a seeded one). Seed one row per `codeops/features/<f>/` present, each row169 derived from that feature's roadmap.1702. **Per-feature roadmap** (`codeops/features/<f>/00-roadmap.md`): ask/confirm the target feature,171 create the feature folder lazily if new, then seed it from that feature's `requirements/` +172 `plans/` (same suggest-don't-sweep rule), and add `T-NN` task rows where tasks exist.1733. After creating/seeding a feature roadmap, **cascade** its summary to the portfolio row.174175## update — re-infer stages and sync to disk176177Advance stages and sync the roadmap to current disk state.178179- Walk each row, re-infer its stage from disk per the **stage-inference artifacts** above (RD180 present, preflight reports, plan present, checklist completion) and update `Stage`, `Status`,181 and `Last Updated` — honoring the **never-regress rule** (advance or preserve; report182 discrepancies instead of downgrading).183- **Delegate ALL counter arithmetic to the engine:** run `scripts/codeops-roadmap-sync.sh` (write184 mode). It recomputes the header `Progress` counters, the portfolio `Progress`/`Status` cells,185 and the `Features` count from disk — **never re-derive these numbers in prose** (the same186 prose-vs-script division as the migration engine: the skill owns stage judgment, the script187 owns arithmetic). Stage Summary phrasing remains yours. The engine counts only `RD-*` rows188 (`T-*` tasks are excluded), is **follow-on aware** (a feature with all RDs Done but an open189 `## Open follow-ons` row holds at `🔄`), and **preserves hand-maintained values** — a190 non-computed `Progress` such as `n/a` and any ` · …` / ` (…)` annotation are kept verbatim, and a191 held row's `Status` is not re-rolled. See [template.md](template.md) → *Open follow-ons* and the192 Progress/Features field notes for the authoring contract.193- **Nested layout:** stage re-inference is per-feature (your judgment); the script performs the194 numeric **cascade** into `codeops/00-roadmap.md` in the same run.195- **Recommend compaction if the roadmap is bloated:** run `scripts/codeops-roadmap-compact.sh196 --check`; if it reports a legacy `## Notes` section or an oversized cell, recommend the user run197 **compact**. `update` itself never strips or trims — it only re-infers stages and delegates198 counters (mirrors how it delegates arithmetic to the sync engine).199- **Rows stay dependency-ordered:** keep prerequisites above the rows that depend on them (see200 [template.md](template.md) → Row ordering & discipline); a planned dependency is a terse201 `depends on RD-NN` in the row's `Depends-on / Blocker` cell.202- **If the roadmap is missing:** fall back to **make** — ask whether to create it, then create it.203204## review — read-only health check205206Run a health check and report findings; change nothing on disk.207208- **Counter/cascade drift is mechanical:** run `scripts/codeops-roadmap-sync.sh --check` — its209 `DRIFT` lines and non-zero exit ARE that portion of the report (Progress counters, portfolio210 Progress/Status cells, Features count). Do not re-derive the numbers in prose. Preserved211 hand-maintained values are reported on informational `HELD` lines and do **not** fail the check —212 an `n/a` sentinel or an annotated cell is healthy, not drift; surface `HELD` lines so a human can213 eyeball the hand-maintained values.214- **Bloat is mechanical too:** run `scripts/codeops-roadmap-compact.sh --check` — a reported legacy215 `## Notes` section or oversized cell is that portion of the health report; recommend **compact**216 to slim it (review itself changes nothing on disk).217- Every RD row references an existing `requirements/RD-*.md` file.218- Every plan link references an existing plan folder.219- The recorded `Stage` matches on-disk reality per the stage-inference artifacts (flag drift;220 remember stages never regress — a lower-than-recorded disk state is a discrepancy to report,221 not a downgrade to apply).222- Every `Blocked` row has a live `DEF-n` sub-row and a `(was: <stage>)` annotation; if the223 `DEF-n` is already `Done`, flag the parent as ready to unblock.224- **Nested layout (both tiers):** every portfolio row links an existing feature roadmap; Stage225 Summary phrasing matches the feature's rolled-up state.226- **If the roadmap is missing:** return the error below.227228## show — present a status overview229230Render a human-facing snapshot of where a feature (or the whole repo) stands: overall progress, the231per-item stage table, and the concrete next steps. **Read-only — this action never writes to disk.**232It is the presentation counterpart to `review`: `review` audits the roadmap for drift and broken233links, `show` simply *displays* it. Do not run the sync engine in write mode or edit any file here.234235**Resolve the target (layout-aware):**236237- **Flat layout** → present the single `plans/00-roadmap.md`.238- **Nested + a feature argument** (`show_roadmap <feature>`) → present that feature's239 `codeops/features/<f>/00-roadmap.md`, including its `T-NN` task rows and any `## Open follow-ons`.240- **Nested + no argument** → present the **portfolio** `codeops/00-roadmap.md` (one row per feature)241 as the overview, then offer to drill into a named feature. If the target feature is ambiguous, ask242 — never guess (same rule as the other actions).243244**What to present** (adapt the depth to the roadmap's size; keep it scannable):2452461. **A one-line header** — which roadmap you are reading (its resolved path) and its recorded247 `Last Updated`.2482. **An overall progress line** — the header `Progress` fraction/percent (portfolio: the `Features`249 count), plus a short phrase on what most recently landed and what is in flight. **Report the250 recorded counters as-is; do not silently recompute or mutate them.** If a row's `Stage` or a251 counter looks stale versus disk (apply the stage-inference artifacts read-only), note the252 suspected drift in one line and suggest `update_roadmap` — never edit to "fix" it here.2533. **The tracker as a table** — the roadmap's rows with their `ID`, `Title`, `Stage`, `Status`254 emoji, `Plan` (✔ / —), and `Depends-on / Blocker`, in dependency order, with the legend beneath.255 Preserve `↳ DEF-n` sub-rows nested under the row they block.2564. **"Where you stand right now"** — a few grounded bullets: what just shipped, what is in flight,257 anything `Blocked` (name the `DEF-n` it waits on), and how much backlog remains.2585. **"Natural next steps"** — 1–3 concrete, state-grounded suggestions (e.g. preflight the created259 plan, execute it, unblock a `DEF-n`, or draft the next backlog RD). Lead with the single most260 obvious continuation; the user decides.261262**If the roadmap is missing:** return the same error as `review` (below) — never fabricate one.263264## archive — archive a completed feature265266**Flat layout** (membership is **explicit** — move only the rows listed in the roadmap):2672681. Read the feature-set slug from the roadmap header.2692. Create `plans/_archive/<feature-set>/`.2703. Move into it: the roadmap itself, plus **only** the RD documents and plan folders271 that appear as rows in the roadmap.2724. Leave all other `requirements/` and `plans/` content untouched. Never sweep every273 folder under `plans/`.2745. A fresh roadmap can then be created for the next feature-set.2756. **If the roadmap is missing:** return the error below.276277**Nested layout** (feature-level, whole-folder — FR-12 / AR #11):2782791. Confirm the feature to archive (its rolled-up Status should be ✅ Done; warn if not). Never280 fragment a live feature — archive the whole folder, not individual plans.2812. `git mv codeops/features/<f> codeops/_archive/<f>` (preserves history; intra-feature links282 survive because the whole folder shifts).2833. In `codeops/00-roadmap.md`, **move** the feature's row from `## Features` to `## Archived`284 (mark 📦, update the Roadmap link to `_archive/<f>/00-roadmap.md`) — **never delete it** — and285 refresh the `Features` count + `Last Updated`.2864. **If the portfolio is missing:** return the error below.287288---289290## compact — shrink an existing roadmap (both layouts)291292Slim a roadmap that has bloated over time — a legacy `## Notes` running log and/or verbose table293cells — back to a lean status table. The mechanical, safety-critical work is delegated to the294engine; the judgment (rewriting a fat cell down to a terse phrase) is yours.2952961. **Resolve layout.** compact operates on **every** roadmap in the repo — the portfolio, every297 feature roadmap, and `_archive/` — not a single feature.2982. **Require a clean git tree.** Deleting the Notes log is only reversible through git, so if the299 tree is dirty, STOP and ask the user to commit or stash first (the engine also refuses — check300 early so the user gets a clean message rather than a mid-run abort).3013. **Run the engine** — `scripts/codeops-roadmap-compact.sh` (apply). It strips every `## Notes`302 section in place and prints `FLAG <file>:<row>:<column> (<n> chars)` lines for oversized cells.303 It never rewrites a cell.3044. **Trim each flagged cell** to a terse status phrase, **preserving the load-bearing tokens305 verbatim** — `waiting on DEF-n` and `Blocked (was: <stage>)`. The verbose original stays in git306 history; never relocate it to another file on disk.3075. **Confirm, then re-sync.** Run `scripts/codeops-roadmap-compact.sh --check` — it must report no308 `## Notes` section and no oversized cell. Then run `scripts/codeops-roadmap-sync.sh` so the309 counter surfaces stay consistent.3106. **Report and stop.** List the affected files and leave the change for the user to review and311 commit (`git status` / `git diff`); never auto-commit.312313**If no roadmap exists:** report `no roadmap found — nothing to compact`; never create one.314315---316317## Error handling318319| Error case | Handling |320|------------|----------|321| **review** / **show** / **archive** when roadmap missing | Return `**Error:** No roadmap found at <resolved roadmap path>. Run make_roadmap first.` (path per the convention doc — `plans/00-roadmap.md` flat, `codeops/00-roadmap.md` or the feature roadmap nested) |322| **update** when roadmap missing | Fall back to **make** (ask-if-missing, then create) |323| **make** when roadmap already exists | Do NOT ask; sync from disk state (the update action) |324| Nested: per-feature transition but portfolio row stale | Cascade is mandatory + immediate; `review` flags the drift (AR #8) |325| Nested: target feature ambiguous | Ask the user; never guess (AR #26) |326| **compact** on a dirty or non-git tree | STOP; ask the user to commit/stash first — the engine also refuses (exit 1) |327| **compact** when no roadmap exists | Report `no roadmap found — nothing to compact`; never create one |328329## Project conventions330331For project-specific settings (build/test/verify commands, package manager,332structure, conventions), read the project's CLAUDE.md (or detected project333conventions). If no CLAUDE.md exists, detect settings from manifest files and use334only facts you can read — do not invent settings.335336## Pointers & related skills337338- [template.md](template.md) — the `plans/00-roadmap.md` template, legend, tracker339 columns, and a worked example. Read before **make**.340- [stage-hooks.md](stage-hooks.md) — the full stage-transition map, which skill fires341 which hook, and the source-of-truth rule. Read when reasoning about transitions.342- `scripts/codeops-roadmap-compact.sh` — the compact engine driven by the **compact** action, and343 by `update`/`review`'s `--check` bloat detection (strips the legacy Notes log, flags fat cells).344- Related skills: requirements (`RD Drafted` hook), preflight (`RD/Plan Preflighted`345 hooks), make_plan (`Plan Created` hook + linking), exec_plan (`Executing` / `Done` /346 `Blocked` hooks).