Tracking a roadmap with ctxgrd

Lint a Now-Next-Later product roadmap as one file per initiative, with the horizon, the owner, and cross-initiative blocking all enforced.

What ctxgrd checks – and what it does not

ctxgrd checks that every initiative carries the required headings and metadata, that its status is one of the five allowed horizons, and that any depends_on reference resolves and does not cycle. It does not check whether an initiative belongs in now rather than later, whether the outcome is realistic, or whether the idea is any good. Sequencing is a planning call, not a structural one.

Prerequisites

  • ctxgrd 0.56.0 or later.
  • A ctxgrd.toml in the repository root. If none exists, run ctxgrd pack add project-docs to create a baseline.

1. Add the namespace

ctxgrd pack add project-docs

This writes [ROADMAP] into ctxgrd.toml alongside [ADR], [PRD], [RFC], [BUG], [TODO], and [README], path-claimed at docs/roadmap/**. To preview the block without touching your config:

ctxgrd pack add project-docs --dry-run

Run the linter right after adding the pack and you get a diagnostic, not a clean run:

error[core.min-docs]: namespace `ROADMAP` requires at least one document but the run found none

That is the pack telling you what to do next. ROADMAP is mandatory once claimed – a repo that opts in but never writes an initiative is a worse signal than a repo that never opted in at all. Write your first initiative (step 2) and the diagnostic clears. If your project genuinely carries no roadmap, drop the [ROADMAP] block instead of leaving it empty.

2. Write your first initiative

Each initiative is its own file under docs/roadmap/, id-claimed ROADMAP-<n> – there is no single ROADMAP.md. It requires five frontmatter fields (id, title, status, date, owner) and four H2 headings, in order: Problem, Outcome, Ideas, Success Metrics.

---
id: ROADMAP-1
title: Self-serve onboarding
status: now
date: 2026-07-09
owner: Growth
---

# Self-serve onboarding

## Problem

New teams need a human on the call to get their first config working.

## Outcome

A team goes from install to a clean first lint with no human involved.

## Ideas

- Guided `ctxgrd init` wizard.
- Starter pack recommendations by repo shape.

## Success Metrics

Time to first clean lint drops from a scheduled call to under 10 minutes.

owner is required because an unowned roadmap item is the first one to rot. date records when it was last triaged – a roadmap is a living document, not a plan you write once.

3. Set the horizon with status

status carries the Now-Next-Later horizon directly – there is no separate horizon field. The allowed set is now, next, later, plus two terminal states, done and dropped, for closing an initiative out:

[ROADMAP."core.allowed-values"]
status = ["now", "next", "later", "done", "dropped"]

An initiative with status: someday fails:

error[core.allowed-values]: metadata key 'status' has value 'someday' not in allowed set [now, next, later, done, dropped]

The set is config, not hardcoded – retype it in ctxgrd.toml if your team uses different horizon labels.

4. Chain initiatives with depends_on

An initiative that is blocked by another names it in depends_on. There is deliberately no “Dependencies” heading – the blocking relationship rides the same dependency graph your ADRs and PRDs already use.

---
id: ROADMAP-2
title: Multi-repo compliance dashboard
status: next
date: 2026-07-09
owner: Platform
depends_on: [ROADMAP-1]
---

A depends_on entry that names an initiative that does not exist fails core.dep-resolved:

error[core.dep-resolved]: depends_on entry 'ROADMAP-99' does not resolve to a document in the run

Two initiatives blocking each other fails core.dep-cycle the same way a circular ADR dependency does. Neither check is specific to roadmaps – it is the same machinery, reused.

5. View the board

ctxgrd list groups documents by namespace and prints each one’s status, so filtering to ROADMAP gives you the Now-Next-Later board directly:

ctxgrd list --namespace ROADMAP
namespace  id         status  title                            depends_on
ROADMAP    ROADMAP-1  now     Self-serve onboarding            —
ROADMAP    ROADMAP-2  next    Multi-repo compliance dashboard  ROADMAP-1

ctxgrd list --format json gives the same data as an array, and --format markdown renders it as a pipe table you can paste into a status doc. ctxgrd status is a different report – it tracks the SPEC/PRD/ADR/TASK pipeline position, not the roadmap board, so it will not show your initiatives.

6. Lint and iterate

ctxgrd                                          # human-readable output
ctxgrd --format json | jq '.diagnostics[] | select(.code | startswith("core"))'

Exit codes follow the standard contract: 0 clean, 1 diagnostics reported, 2 kernel or config error.

A note on PRD

As of 0.56.0, [PRD] is mandatory when enabled the same way: a project that claims the PRD namespace must carry at least one PRD, or core.min-docs flags it. If a deployed repo’s ctxgrd.toml already had [PRD] before this version, the new rule does not reach it automatically – packs apply by copy, not by reference, so it only takes effect after that repo runs ctxgrd pack migrate.

Next steps