git clone https://github.com/Intense-Visions/harness-engineering
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/harness-roadmap" ~/.claude/skills/intense-visions-harness-engineering-harness-roadmap-12361e && rm -rf "$T"
agents/skills/claude-code/harness-roadmap/SKILL.mdHarness Roadmap
Create and manage a unified project roadmap from existing specs and plans. Interactive, human-confirmed, always valid.
When to Use
- When a user asks about project status and a roadmap exists (default -- no args)
- When a project needs a unified roadmap and none exists yet (
)--create - When adding a new feature to an existing roadmap (
)--add <feature-name> - When roadmap statuses may be stale and need updating from plan execution state (
)--sync - When features need reordering, moving between milestones, or blocker updates (
)--edit - When user asks about project status and no roadmap exists -- suggest
--create - NOT for programmatic CRUD (use
MCP tool directly)manage_roadmap
Process
Iron Law
Never write
without the human confirming the proposed structure first.docs/roadmap.md
If the human has not seen and approved the milestone groupings and feature list, do not write the file. Present. Wait. Confirm. Then write.
Command: --create
-- Bootstrap Roadmap
--createPhase 1: SCAN -- Discover Artifacts
- Check if
already exists.docs/roadmap.md- If it exists: warn the human. "A roadmap already exists. Overwriting will replace it. Continue? (y/n)" Wait for confirmation before proceeding. If declined, stop.
- Scan for specs:
docs/changes/*/proposal.md- Record each spec's title, status (if detectable from frontmatter or content), and file path.
- Scan for plans:
docs/plans/*.md- Record each plan's title, estimated tasks, and file path.
- Match plans to specs:
- Plans often reference their spec in frontmatter (
) or body text. Link them when a match is found.spec: - Unmatched plans become standalone features.
- Plans often reference their spec in frontmatter (
- Infer feature status from artifacts:
- Has spec + plan + implementation evidence (committed code referenced in plan) ->
orin-progresscomplete - Has spec + plan but no implementation ->
planned - Has spec but no plan ->
backlog - Has plan but no spec ->
(unusual, flag for human review)planned
- Has spec + plan + implementation evidence (committed code referenced in plan) ->
- Detect project name from
harness.config.json
field, orprojectpackage.json
field, or directory name as fallback.name
Present scan summary:
SCAN COMPLETE Project: <name> Found: N specs, N plans Matched: N spec-plan pairs Unmatched specs: N (backlog candidates) Unmatched plans: N (flag for review)
Phase 2: PROPOSE -- Interactive Grouping
-
Present discovered features in default milestone groupings:
- Current Work -- features with status
in-progress - Backlog -- everything else
Proposed Roadmap Structure: ## Current Work - Feature A (in-progress) -- spec: docs/changes/feature-a/proposal.md - Feature B (in-progress) -- spec: docs/changes/feature-b/proposal.md ## Backlog - Feature C (planned) -- spec: docs/changes/feature-c/proposal.md - Feature D (backlog) -- spec: docs/changes/feature-d/proposal.md - Current Work -- features with status
-
Offer choices:
- (A) Accept -- proceed with this structure
- (B) Rename -- rename milestones or features
- (C) Reorganize -- move features between milestones
- (D) Add milestones -- create additional milestones (e.g., "v2.0", "Q2 2026")
-
Ask: "Are there additional features not captured in specs that should be on the roadmap?"
- If yes: collect name, summary, and milestone for each.
-
Repeat until the human selects (A) Accept.
Phase 3: WRITE -- Generate Roadmap
-
Build the roadmap structure:
- Frontmatter:
,project
,version: 1
,created
timestampsupdated - One H2 section per milestone
- One H3 section per feature with 5 fields:
,Status
,Spec
,Summary
,BlockersPlan
- Frontmatter:
-
Write via
MCP tool if available. If MCP is unavailable, write directly using the roadmap markdown format and warn: "External sync skipped (MCP unavailable). Runmanage_roadmap
when MCP is restored to push changes to GitHub."manage_roadmap sync--- project: <name> version: 1 created: YYYY-MM-DD updated: YYYY-MM-DD --- # Roadmap ## Current Work ### Feature A - **Status:** in-progress - **Spec:** docs/changes/feature-a/proposal.md - **Summary:** One-line description of the feature - **Blockers:** none - **Plan:** docs/plans/2026-03-20-feature-a-plan.md -
Write to
.docs/roadmap.md
Phase 4: VALIDATE -- Verify Output
-
Read back
.docs/roadmap.md -
Verify via
if MCP is available -- confirms round-trip parsing.manage_roadmap show -
Run
.harness validate -
Present summary to human:
Roadmap created: docs/roadmap.md Milestones: N Features: N harness validate: passed
Command: --add <feature-name>
-- Add a Feature
--add <feature-name>Phase 1: SCAN -- Load Existing Roadmap
- Check if
exists.docs/roadmap.md- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
first to bootstrap one."--create
- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
- Parse the roadmap (via
or direct read).manage_roadmap show - Check for duplicate feature names. If
already exists: error with message. "Feature '<feature-name>' already exists in milestone '<milestone>'. Use a different name or edit the existing feature."<feature-name>
Phase 2: PROPOSE -- Collect Feature Details
Ask the human for each field interactively:
- Milestone: "Which milestone should this feature belong to?" List existing milestones plus a
option. If[NEW]
: ask for the new milestone name.[NEW] - Status: "What is the current status?" Offer:
,backlog
,planned
,in-progress
.blocked - Spec: "Is there a spec for this feature?" If yes, ask for the path. If no, leave as
.none - Summary: "One-line summary of the feature."
- Blockers: "Any blockers?" If yes, collect. If no, set to
.none - Plan: "Is there a plan for this feature?" If yes, ask for the path. If no, leave as
.none
Present the collected details for confirmation:
New feature to add: Milestone: Current Work Name: Feature E Status: planned Spec: docs/changes/feature-e/proposal.md Summary: Add feature E to the system Blockers: none Plan: none Confirm? (y/n)
Wait for confirmation before proceeding.
Phase 3: WRITE -- Add Feature to Roadmap
- Add via
MCP tool if available. If MCP is unavailable, parse the roadmap, add the feature to the specified milestone, and serialize back. Warn: "External sync skipped (MCP unavailable). Runmanage_roadmap add
when MCP is restored to push changes to GitHub."manage_roadmap sync - If the milestone is
: create the milestone section, then add the feature.[NEW] - Write to
.docs/roadmap.md
Phase 4: VALIDATE -- Verify Output
-
Read back
.docs/roadmap.md -
Verify the new feature appears in the correct milestone.
-
Run
.harness validate -
Confirm to human:
Feature added: Feature E -> Current Work Total features: N harness validate: passed
Command: (no args) -- Show Roadmap Summary
Phase 1: SCAN -- Load Roadmap
- Check if
exists.docs/roadmap.md- If missing: suggest
. "No roadmap found at docs/roadmap.md. Run--create
to bootstrap one from existing specs and plans."--create
- If missing: suggest
- Parse the roadmap (via
or direct read).manage_roadmap show
Phase 2: PRESENT -- Display Summary
-
Display a compact summary of the roadmap:
ROADMAP: <project-name> Last synced: YYYY-MM-DD HH:MM ## <Milestone 1> (N features) - Feature A .................. in-progress - Feature B .................. planned - Feature C .................. blocked (by: Feature A) ## <Milestone 2> (N features) - Feature D .................. done - Feature E .................. backlog Total: N features | N done | N in-progress | N planned | N blocked | N backlog -
If any features have stale sync timestamps (last_synced older than 24 hours), append a note:
Hint: Roadmap may be stale. Run `--sync` to update statuses from plan execution state. -
No file writes. This is a read-only operation. No
needed.harness validate
Command: --sync
-- Sync Statuses from Execution State
--syncPhase 1: SCAN -- Load Roadmap and Execution State
- Check if
exists.docs/roadmap.md- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
first to bootstrap one."--create - Do NOT create a roadmap. Do NOT offer alternatives. Stop.
- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
- Parse the roadmap (via
or direct read).manage_roadmap show - For each feature with linked plans, scan execution state:
(root execution state).harness/state.json
(session-scoped execution state).harness/sessions/*/autopilot-state.json- Plan file completion markers
Phase 2: PROPOSE -- Present Status Changes
-
Infer status for each feature:
- All tasks complete -> suggest
done - Any task started -> suggest
in-progress - Blocker feature not done -> suggest
blocked - No execution data found -> no change
- All tasks complete -> suggest
-
Check the human-always-wins rule: if
is more recent thanlast_manual_edit
for a feature, preserve the manually set status. Report it as "skipped (manual override)".last_synced -
Present proposed changes:
SYNC RESULTS Changes detected: - Feature A: planned -> in-progress (3/8 tasks started) - Feature B: in-progress -> done (all tasks complete) - Feature C: planned -> blocked (blocked by: Feature A, not done) Unchanged: - Feature D: done (no change) Skipped (manual override): - Feature E: kept as "planned" (manually edited 2h ago) Apply these changes? (y/n) -
Wait for human confirmation before applying.
Phase 3: WRITE -- Apply Changes
- Apply via
MCP tool if available, or viamanage_roadmap sync
for each changed feature. If MCP is unavailable, parse the roadmap, update statuses, and serialize back. Warn: "External sync skipped (MCP unavailable). Runmanage_roadmap update
when MCP is restored to push changes to GitHub."manage_roadmap sync - Update
timestamp in frontmatter.last_synced - Write to
.docs/roadmap.md
Phase 4: VALIDATE -- Verify Output
-
Read back
.docs/roadmap.md -
Verify changes applied correctly via
if MCP is available.manage_roadmap show -
Run
.harness validate -
Present summary:
Sync complete: docs/roadmap.md Updated: N features Skipped: N (manual override) Unchanged: N harness validate: passed
Command: --edit
-- Interactive Edit Session
--editPhase 1: SCAN -- Load Existing Roadmap
-
Check if
exists.docs/roadmap.md- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
first to bootstrap one."--create
- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
-
Parse the roadmap (via
or direct read).manage_roadmap show -
Present current structure:
Current roadmap: <project-name> ## <Milestone 1> 1. Feature A (in-progress) 2. Feature B (planned) ## <Milestone 2> 3. Feature C (done) 4. Feature D (backlog)
Phase 2: EDIT -- Interactive Modifications
Offer edit actions in a loop until the human is done:
-
Reorder features within a milestone:
- "Move which feature? (number)" -> "To which position?" -> reorder.
-
Move a feature between milestones:
- "Move which feature? (number)" -> "To which milestone?" (list milestones +
) -> move.[NEW] - If
: ask for the new milestone name, create it.[NEW]
- "Move which feature? (number)" -> "To which milestone?" (list milestones +
-
Update blockers:
- "Update blockers for which feature? (number)" -> "Blocked by? (feature names, comma-separated, or 'none')" -> update.
-
Update status:
- "Update status for which feature? (number)" -> offer:
,backlog
,planned
,in-progress
,blocked
-> update.done
- "Update status for which feature? (number)" -> offer:
-
Rename a feature:
- "Rename which feature? (number)" -> "New name?" -> rename.
-
Remove a feature:
- "Remove which feature? (number)" -> "Confirm removal of '<name>'? (y/n)" -> remove on confirm.
-
Rename a milestone:
- "Rename which milestone?" -> "New name?" -> rename.
-
Done:
- Exit edit loop, proceed to WRITE phase.
Present the menu after each action:
Edit actions: (1) Reorder features within a milestone (2) Move feature to different milestone (3) Update blockers (4) Update status (5) Rename feature (6) Remove feature (7) Rename milestone (D) Done -- save and exit Choice?
Phase 3: WRITE -- Save Changes
-
Present a diff summary of all changes made during the edit session:
Changes to apply: - Moved "Feature B" from "Current Work" to "Q2 Release" - Updated "Feature A" blockers: none -> Feature C - Reordered "Q2 Release": Feature B now at position 1 Apply? (y/n) -
Wait for confirmation before writing.
-
Apply all changes via
/manage_roadmap update
MCP tool calls, or direct file manipulation if MCP is unavailable. If falling back to direct manipulation, warn: "External sync skipped (MCP unavailable). Runmanage_roadmap remove
when MCP is restored to push changes to GitHub."manage_roadmap sync -
Update
timestamp in frontmatter (since this is a human-driven edit).last_manual_edit -
Write to
.docs/roadmap.md
Phase 4: VALIDATE -- Verify Output
-
Read back
.docs/roadmap.md -
Verify changes applied correctly.
-
Run
.harness validate -
Present summary:
Edit complete: docs/roadmap.md Changes applied: N harness validate: passed
Command: --query <filter>
-- Query Features by Filter
--query <filter>Phase 1: SCAN -- Load Roadmap
- Check if
exists.docs/roadmap.md- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
first to bootstrap one."--create
- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
- Parse the roadmap (via
or direct read).manage_roadmap query
Phase 2: FILTER -- Apply Query
-
Accept filter patterns:
- Status filter:
,backlog
,planned
,in-progress
,done
-- returns all features with that statusblocked - Milestone filter:
-- returns all features in the named milestone (partial match)milestone:<name>
- Status filter:
-
Display matching features with their milestone context:
QUERY: <filter> Results (N matches): - Feature A (Current Work) .................. in-progress - Feature B (Backlog) ....................... planned Total: N matches -
No file writes. This is a read-only operation.
Harness Integration
MCP tool -- Primary read/write interface for roadmap operations. Supportsmanage_roadmap
,show
,add
,update
, andremove
actions. Use this when MCP is available for structured CRUD.query
-- Run after any roadmap modification to verify project health. Mandatory in the VALIDATE phase of bothharness validate
and--create
.--add- Core
/parseRoadmap
-- Fallback when MCP is unavailable. These functions inserializeRoadmap
handle parsing and serializing the roadmap markdown format directly.packages/core/src/roadmap/ - Roadmap file -- Always at
. This is the single source of truth for the project roadmap.docs/roadmap.md
Success Criteria
discovers all specs (--create
) and plans (docs/changes/*/proposal.md
)docs/plans/*.md
proposes groupings and waits for human confirmation before writing--create
produces a valid--create
that round-trips throughdocs/roadmap.md
/parseRoadmapserializeRoadmap
collects all fields interactively (milestone, status, spec, summary, blockers, plan)--add
rejects duplicate feature names with a clear error message--add
errors gracefully when no roadmap exists, directing the user to--add--create- Default (no args) displays a compact status summary with feature counts by status
- Default (no args) suggests
when no roadmap exists--create - Default (no args) hints at
when roadmap may be stale--sync
scans--sync
and.harness/state.json
for execution state.harness/sessions/*/autopilot-state.json
respects the human-always-wins rule -- manually edited statuses are preserved--sync
presents proposed changes and waits for human confirmation before applying--sync
errors gracefully when no roadmap exists, directing the user to--sync--create
offers reorder, move, blocker update, status update, rename, and remove actions--edit
presents a diff summary and waits for confirmation before writing--edit
updates--edit
timestamp (since changes are human-driven)last_manual_edit- Output matches the roadmap markdown format exactly (frontmatter, H2 milestones, H3 features, 5 fields each)
passes after all operationsharness validate
filters features by status or milestone and displays results with milestone context--query
errors gracefully when no roadmap exists, directing the user to--query--create
Rationalizations to Reject
| Rationalization | Reality |
|---|---|
| "The feature list looks correct, so I can skip the PROPOSE phase and write the roadmap directly" | The Iron Law: never write docs/roadmap.md without the human confirming the proposed structure first. |
| "This sync detected a status change and the inference is clearly correct, so I can apply it without confirmation" | The sync PROPOSE phase requires presenting proposed changes and waiting for human confirmation. The human-always-wins rule applies. |
| "The existing roadmap is outdated, so I will recreate it with --create to get a fresh start" | No overwriting an existing roadmap without explicit user consent. Silent overwrites destroy prior manual edits and status tracking. |
| "There is no roadmap yet but the user asked me to add a feature, so I will create one as a side effect of --add" | When the roadmap does not exist, --add must error with a clear message directing the user to --create. |
Examples
Example: --create
-- Bootstrap a Roadmap from Existing Artifacts
--createContext: A project with 3 specs and 2 plans. Two specs have matching plans (in-progress), one spec has no plan (backlog).
Phase 1: SCAN
SCAN COMPLETE Project: my-project Found: 3 specs, 2 plans Matched: 2 spec-plan pairs Unmatched specs: 1 (backlog candidates) Unmatched plans: 0
Phase 2: PROPOSE
Proposed Roadmap Structure: ## Current Work - Unified Code Review (in-progress) -- spec: docs/changes/unified-code-review/proposal.md - Update Checker (in-progress) -- spec: docs/changes/update-checker/proposal.md ## Backlog - Design System (backlog) -- spec: docs/changes/design-system/proposal.md Options: (A) Accept this structure (B) Rename milestones or features (C) Reorganize -- move features between milestones (D) Add milestones Any additional features not captured in specs? (y/n)
Human selects (A) Accept.
Phase 3: WRITE
Writing docs/roadmap.md... 2 milestones, 3 features
Phase 4: VALIDATE
Roadmap created: docs/roadmap.md Milestones: 2 (Current Work, Backlog) Features: 3 harness validate: passed
Example: --add
-- Add a Feature to an Existing Roadmap
--addContext: A roadmap exists with 2 milestones and 3 features. Adding a new feature.
Phase 1: SCAN
Roadmap loaded: docs/roadmap.md Milestones: 2 (Current Work, Backlog) Features: 3 No duplicate found for "Notification System"
Phase 2: PROPOSE
Which milestone? [1] Current Work [2] Backlog [NEW] Create new > 1 Status? [backlog] [planned] [in-progress] [blocked] > planned Spec? (path or "none") > docs/changes/notification-system/proposal.md One-line summary: > Real-time notification delivery with WebSocket and email channels Blockers? (or "none") > none Plan? (path or "none") > none New feature to add: Milestone: Current Work Name: Notification System Status: planned Spec: docs/changes/notification-system/proposal.md Summary: Real-time notification delivery with WebSocket and email channels Blockers: none Plan: none Confirm? (y/n)
Human confirms y.
Phase 3: WRITE
Adding feature to Current Work...
Phase 4: VALIDATE
Feature added: Notification System -> Current Work Total features: 4 harness validate: passed
Gates
These are hard stops. Violating any gate means the process has broken down.
- No writing
without human confirmation of structure. The PROPOSE phase must complete with an explicit accept before any file is written. Skipping confirmation produces a roadmap the human did not agree to.docs/roadmap.md - No overwriting an existing roadmap without explicit user consent. If
exists whendocs/roadmap.md
runs, the human must confirm the overwrite. Silent overwrites destroy prior work.--create - No adding features with duplicate names. If a feature with the same name already exists in any milestone, reject the add with a clear error. Duplicates corrupt the roadmap structure.
- No proceeding when
is missing fordocs/roadmap.md
. If the roadmap does not exist, do not create one silently. Error and direct the user to--add
.--create - No syncing when
does not exist.docs/roadmap.md
must error immediately with a message directing the user to--sync
. Do not create a roadmap as a side effect of sync.--create - No writing changes from
without showing a diff summary and getting confirmation. The WRITE phase must present all pending changes and wait for explicit accept before modifying--edit
.docs/roadmap.md
Escalation
- When no specs or plans are found during
: Suggest creating a minimal roadmap with just a Backlog milestone containing features described verbally by the human. Alternatively, suggest running--create
first to generate specs that can then be discovered byharness:brainstorming
.--create - When the roadmap file is malformed and cannot be parsed: Report the specific parse error with line numbers if available. Suggest manual inspection of
or recreation withdocs/roadmap.md
(after backing up the existing file).--create - When MCP tool is unavailable: Fall back to direct file manipulation via Read/Write tools using the roadmap markdown format. The core
/parseRoadmap
functions handle the format. Report the fallback to the human: "MCP tool unavailable, using direct file operations. External sync skipped — runserializeRoadmap
when MCP is restored to push changes to GitHub."manage_roadmap sync