Harness 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 the roadmap needs tidying -- completed work archived, dead
planned rows demoted (--groom)
- When user asks about project status and no roadmap exists -- suggest
--create
- NOT for programmatic CRUD (use
manage_roadmap MCP tool directly)
Process
Iron Law
Never write docs/roadmap.md without the human confirming the proposed structure first.
If the human has not seen and approved the milestone groupings and feature list, do not write the file. Present. Wait. Confirm. Then write.
Prompt the human in plain text — every (y/n), "which feature?", and similar prompt in this skill is plain text only. Do not elevate them to AskUserQuestion: feature lists routinely exceed its 4-option cap, and natural header choices ("Pick feature", "Remove feature") exceed its 12-char cap, causing the call to render as ERR.
Storage mode: monolith vs sharded
The roadmap has two physical layouts, auto-detected (not configured) by the presence of docs/roadmap.d/:
- Monolith — a single
docs/roadmap.md aggregate is canonical (legacy default).
- Sharded — per-row shards
docs/roadmap.d/<slug>.md (plus _meta.md) are canonical, and docs/roadmap.md is a generated merge=ours aggregate. New harness init projects are sharded by default.
In sharded mode a write patches a single shard (conflict-free by construction) and regenerates the aggregate — so when committing a roadmap change, stage both docs/roadmap.d/ and the regenerated docs/roadmap.md. Read/write only through manage_roadmap / the RoadmapStore; never parse the aggregate for content (read-source invariant R, ADR 0050). Subcommands:
harness roadmap shard — adopt sharding (split the monolith into shards), reversible with harness roadmap unshard (semantic round-trip).
harness roadmap regen — regenerate the aggregate from the shards (the fix when harness validate warns the aggregate has drifted).
harness roadmap reconcile — offline merge-triggered auto-done (flip closed-issue rows to done).
Stop hand-marking rows done — rows reach done automatically when the implementing PR merges (auto-done reconciler; see knowledge merge-triggered-auto-done.md). See also the adoption guide docs/guides/roadmap-sharding.md.
Command: --create -- Bootstrap Roadmap
Phase 1: SCAN -- Discover Artifacts
- Check if
docs/roadmap.md already exists.
- 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/changes/*/plans/*.md (preferred — co-located with proposals)
docs/plans/*.md (legacy fallback for plans not yet migrated)
- Record each plan's title, estimated tasks, and file path.
- Match plans to specs:
- Plans often reference their spec in frontmatter (
spec:) or body text. Link them when a match is found.
- Unmatched plans become standalone features.
- Infer feature status from artifacts:
- Has spec + plan + implementation evidence (committed code referenced in plan) ->
in-progress or complete
- Has spec + plan but no implementation ->
planned
- Has spec but no plan ->
backlog
- Has plan but no spec ->
planned (unusual, flag for human review)
- Detect project name from
harness.config.json project field, or package.json name field, or directory name as fallback.
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
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, updated timestamps
- One H2 section per milestone
- One H3 section per feature with 5 fields:
Status, Spec, Summary, Blockers, Plan
Write via manage_roadmap MCP tool if available. If MCP is unavailable, write directly using the roadmap markdown format and warn: "External sync skipped (MCP unavailable). Run manage_roadmap sync when MCP is restored to push changes to GitHub."
---
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/changes/feature-a/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 manage_roadmap show if MCP is available -- confirms round-trip parsing.
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
Phase 1: SCAN -- Load Existing Roadmap
- Check if
docs/roadmap.md exists.
- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
--create first to bootstrap one."
- Parse the roadmap (via
manage_roadmap show or direct read).
- Check for duplicate feature names. If
<feature-name> already exists: error with message. "Feature '' already exists in milestone ''. Use a different name or edit the existing feature."
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
[NEW] option. If [NEW]: ask for the new milestone name.
- 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
manage_roadmap add 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). Run manage_roadmap sync when MCP is restored to push changes to GitHub."
- If the milestone is
[NEW]: create the milestone section, then add the feature.
- 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
docs/roadmap.md exists.
- If missing: suggest
--create. "No roadmap found at docs/roadmap.md. Run --create to bootstrap one from existing specs and plans."
- Parse the roadmap (via
manage_roadmap show or direct read).
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 harness validate needed.
Command: --sync -- Sync Statuses from Execution State
Phase 1: SCAN -- Load Roadmap and Execution State
- Check if
docs/roadmap.md exists.
- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
--create first to bootstrap one."
- Do NOT create a roadmap. Do NOT offer alternatives. Stop.
- Parse the roadmap (via
manage_roadmap show or direct read).
- For each feature with linked plans, scan execution state:
.harness/state.json (root execution state)
.harness/sessions/*/autopilot-state.json (session-scoped execution state)
- 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
Check the human-always-wins rule: if last_manual_edit is more recent than last_synced for a feature, preserve the manually set status. Report it as "skipped (manual override)".
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
manage_roadmap sync MCP tool if available, or via manage_roadmap update for each changed feature. If MCP is unavailable, parse the roadmap, update statuses, and serialize back. Warn: "External sync skipped (MCP unavailable). Run manage_roadmap sync when MCP is restored to push changes to GitHub."
- Update
last_synced timestamp in frontmatter.
- Write to
docs/roadmap.md.
Phase 4: VALIDATE -- Verify Output
Read back docs/roadmap.md.
Verify changes applied correctly via manage_roadmap show if MCP is available.
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
Phase 1: SCAN -- Load Existing Roadmap
Check if docs/roadmap.md exists.
- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
--create first to bootstrap one."
Parse the roadmap (via manage_roadmap show or direct read).
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 +
[NEW]) -> move.
- If
[NEW]: ask for the new milestone name, create it.
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, done -> update.
Rename a feature:
- "Rename which feature? (number)" -> "New name?" -> rename.
Remove a feature:
- "Remove which feature? (number)" -> "Confirm removal of ''? (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 / manage_roadmap remove MCP tool calls, or direct file manipulation if MCP is unavailable. If falling back to direct manipulation, warn: "External sync skipped (MCP unavailable). Run manage_roadmap sync when MCP is restored to push changes to GitHub."
Update last_manual_edit timestamp in frontmatter (since this is a human-driven 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
Phase 1: SCAN -- Load Roadmap
- Check if
docs/roadmap.md exists.
- If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run
--create first to bootstrap one."
- Parse the roadmap (via
manage_roadmap query or direct read).
Phase 2: FILTER -- Apply Query
Accept filter patterns:
- Status filter:
backlog, planned, in-progress, done, blocked -- returns all features with that status
- Milestone filter:
milestone:<name> -- returns all features in the named milestone (partial match)
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.
Command: --groom -- Tidy the Roadmap
Keeps the roadmap manageable over time. Milestones are themes; statuses are lifecycle stages -- grooming enforces that separation so the backlog never decays back into an undifferentiated dump.
Phase 1: SCAN -- Detect Untidiness
- Check if
docs/roadmap.md exists. If missing: error and direct the user to --create.
- Run
manage_roadmap (action: "groom") in a dry-run frame, or call checkRoadmapHealth from @harness-engineering/core, to surface the four health signals:
- RMH001 -- completed (
done) features still sitting in an active milestone.
- RMH002 --
planned rows with neither a spec nor a plan (the orchestrator cannot auto-execute these; it escalates them to a human).
- RMH003 -- lifecycle catch-all milestones (
Backlog, Current Work) that should not exist.
- RMH004 -- active milestones that have grown past the size cap (a mini-dump).
Phase 2: PROPOSE -- Present the Plan
Show the human exactly what grooming will do, in plain text:
GROOM PLAN
Demote to backlog (planned with no spec/plan):
- Feature A (Theme X)
- Feature B (Theme Y)
Archive to docs/roadmap-archive.md (completed):
- Feature C (Theme X)
Flagged for manual routing (not auto-changed):
- Intake lane has 3 items awaiting a theme
- "Theme Z" has 28 features (cap 25) -- consider splitting
Apply? (y/n)
Wait for confirmation. The mechanical changes (demote, archive) are safe and automated; draining the Intake lane into themed milestones and splitting oversized milestones are human decisions -- propose, do not auto-apply.
Phase 3: WRITE -- Apply
- Run
manage_roadmap (action: "groom"). It demotes unactionable planned rows to backlog and moves done features into docs/roadmap-archive.md under a Shipped milestone, returning the list of changes.
- For Intake-draining or milestone-splitting the human approved, follow up with
--edit (move features between milestones).
Phase 4: VALIDATE -- Verify
Run harness validate and confirm the roadmapHealth check passed -- checks.roadmapHealth === true in --json, not merely "not false" (no RMH003 errors; RMH001/002/004 warnings cleared or acknowledged). If validate exits 3 or reports the check under "Checks that could not run", the roadmap could not be parsed and NO health rule ran: fix the reported section and re-run. A check that did not run is not a check that passed.
Summarize:
Groom complete.
Demoted: N | Archived: N -> docs/roadmap-archive.md | Flagged for manual routing: N
harness validate (roadmapHealth): passed
Harness Integration
manage_roadmap MCP tool -- Primary read/write interface for roadmap operations. Supports show, add, update, remove, query, sync, promote, and groom actions. Use this when MCP is available for structured CRUD.
harness validate -- Run after any roadmap modification to verify project health. Mandatory in the VALIDATE phase of --create, --add, and --groom. The roadmapHealth check enforces the maintenance rules (RMH001-RMH004) as a regression guard.
- Core
checkRoadmapHealth/groomRoadmap -- Maintenance engine in packages/core/src/roadmap/health.ts. checkRoadmapHealth is read-only diagnostics; groomRoadmap is the pure transform (demote unactionable planned, archive done). Both are surfaced via manage_roadmap and harness validate.
- Core
parseRoadmap/serializeRoadmap -- Fallback when MCP is unavailable. These functions in packages/core/src/roadmap/ handle parsing and serializing the roadmap markdown format directly. Note: the serializer only preserves frontmatter, milestones, features, and the Assignment History table -- never add convention prose or comments to docs/roadmap.md, they are dropped on the next write.
- Roadmap files -- Live work in
docs/roadmap.md (the orchestrator's source of truth); completed work archived to docs/roadmap-archive.md by --groom. Milestones are themes, not lifecycle stages -- promoted items land in the Intake lane and are groomed into themes.
Success Criteria
--create discovers all specs (docs/changes/*/proposal.md) and plans (docs/changes/*/plans/*.md and legacy docs/plans/*.md)
--create proposes groupings and waits for human confirmation before writing
--create produces a valid docs/roadmap.md that round-trips through parseRoadmap/serializeRoadmap
--add 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 --create
- Default (no args) displays a compact status summary with feature counts by status
- Default (no args) suggests
--create when no roadmap exists
- Default (no args) hints at
--sync when roadmap may be stale
--sync scans .harness/state.json and .harness/sessions/*/autopilot-state.json for execution state
--sync 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 --create
--edit offers reorder, move, blocker update, status update, rename, and remove actions
--edit presents a diff summary and waits for confirmation before writing
--edit updates last_manual_edit timestamp (since changes are human-driven)
- Output matches the roadmap markdown format exactly (frontmatter, H2 milestones, H3 features, 5 fields each)
harness validate passes after all operations
--query filters features by status or milestone and displays results with milestone context
--query errors gracefully when no roadmap exists, directing the user to --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
Context: 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
Context: 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
docs/roadmap.md 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.
- No overwriting an existing roadmap without explicit user consent. If
docs/roadmap.md exists when --create runs, the human must confirm the overwrite. Silent overwrites destroy prior work.
- 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
docs/roadmap.md is missing for --add. If the roadmap does not exist, do not create one silently. Error and direct the user to --create.
- No syncing when
docs/roadmap.md does not exist. --sync must error immediately with a message directing the user to --create. Do not create a roadmap as a side effect of sync.
- No writing changes from
--edit without showing a diff summary and getting confirmation. The WRITE phase must present all pending changes and wait for explicit accept before modifying docs/roadmap.md.
Escalation
- When no specs or plans are found during
--create: Suggest creating a minimal roadmap with just a Backlog milestone containing features described verbally by the human. Alternatively, suggest running harness:brainstorming first to generate specs that can then be discovered by --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
docs/roadmap.md or recreation with --create (after backing up the existing file).
- When MCP tool is unavailable: Fall back to direct file manipulation via Read/Write tools using the roadmap markdown format. The core
parseRoadmap/serializeRoadmap functions handle the format. Report the fallback to the human: "MCP tool unavailable, using direct file operations. External sync skipped — run manage_roadmap sync when MCP is restored to push changes to GitHub."
1---2name: harness-roadmap3description: Harness Roadmap4---5# Harness Roadmap67> Create and manage a unified project roadmap from existing specs and plans. Interactive, human-confirmed, always valid.89## When to Use1011- When a user asks about project status and a roadmap exists (default -- no args)12- When a project needs a unified roadmap and none exists yet (`--create`)13- When adding a new feature to an existing roadmap (`--add <feature-name>`)14- When roadmap statuses may be stale and need updating from plan execution state (`--sync`)15- When features need reordering, moving between milestones, or blocker updates (`--edit`)16- When the roadmap needs tidying -- completed work archived, dead `planned` rows demoted (`--groom`)17- When user asks about project status and no roadmap exists -- suggest `--create`18- NOT for programmatic CRUD (use `manage_roadmap` MCP tool directly)1920## Process2122### Iron Law2324**Never write `docs/roadmap.md` without the human confirming the proposed structure first.**2526If the human has not seen and approved the milestone groupings and feature list, do not write the file. Present. Wait. Confirm. Then write.2728**Prompt the human in plain text — every `(y/n)`, "which feature?", and similar prompt in this skill is plain text only.** Do not elevate them to `AskUserQuestion`: feature lists routinely exceed its 4-option cap, and natural header choices ("Pick feature", "Remove feature") exceed its 12-char cap, causing the call to render as ERR.2930---3132### Storage mode: monolith vs sharded3334The roadmap has two physical layouts, auto-detected (not configured) by the presence of `docs/roadmap.d/`:3536- **Monolith** — a single `docs/roadmap.md` aggregate is canonical (legacy default).37- **Sharded** — per-row shards `docs/roadmap.d/<slug>.md` (plus `_meta.md`) are canonical, and `docs/roadmap.md` is a generated `merge=ours` aggregate. New `harness init` projects are sharded by default.3839In sharded mode a write patches a **single shard** (conflict-free by construction) and **regenerates the aggregate** — so when committing a roadmap change, stage both `docs/roadmap.d/` and the regenerated `docs/roadmap.md`. Read/write only through `manage_roadmap` / the `RoadmapStore`; never parse the aggregate for content (read-source invariant R, ADR 0050). Subcommands:4041- `harness roadmap shard` — adopt sharding (split the monolith into shards), reversible with `harness roadmap unshard` (semantic round-trip).42- `harness roadmap regen` — regenerate the aggregate from the shards (the fix when `harness validate` warns the aggregate has drifted).43- `harness roadmap reconcile` — offline merge-triggered auto-done (flip closed-issue rows to `done`).4445**Stop hand-marking rows `done`** — rows reach `done` automatically when the implementing PR merges (auto-done reconciler; see knowledge [`merge-triggered-auto-done.md`](../../../../docs/knowledge/roadmap/merge-triggered-auto-done.md)). See also the adoption guide [`docs/guides/roadmap-sharding.md`](../../../../docs/guides/roadmap-sharding.md).4647---4849### Command: `--create` -- Bootstrap Roadmap5051#### Phase 1: SCAN -- Discover Artifacts52531. Check if `docs/roadmap.md` already exists.54 - 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.552. Scan for specs:56 - `docs/changes/*/proposal.md`57 - Record each spec's title, status (if detectable from frontmatter or content), and file path.583. Scan for plans:59 - `docs/changes/*/plans/*.md` (preferred — co-located with proposals)60 - `docs/plans/*.md` (legacy fallback for plans not yet migrated)61 - Record each plan's title, estimated tasks, and file path.624. Match plans to specs:63 - Plans often reference their spec in frontmatter (`spec:`) or body text. Link them when a match is found.64 - Unmatched plans become standalone features.655. Infer feature status from artifacts:66 - Has spec + plan + implementation evidence (committed code referenced in plan) -> `in-progress` or `complete`67 - Has spec + plan but no implementation -> `planned`68 - Has spec but no plan -> `backlog`69 - Has plan but no spec -> `planned` (unusual, flag for human review)706. Detect project name from `harness.config.json` `project` field, or `package.json` `name` field, or directory name as fallback.7172Present scan summary:7374```75SCAN COMPLETE7677Project: <name>78Found: N specs, N plans79Matched: N spec-plan pairs80Unmatched specs: N (backlog candidates)81Unmatched plans: N (flag for review)82```8384#### Phase 2: PROPOSE -- Interactive Grouping85861. Present discovered features in default milestone groupings:87 - **Current Work** -- features with status `in-progress`88 - **Backlog** -- everything else8990 ```91 Proposed Roadmap Structure:9293 ## Current Work94 - Feature A (in-progress) -- spec: docs/changes/feature-a/proposal.md95 - Feature B (in-progress) -- spec: docs/changes/feature-b/proposal.md9697 ## Backlog98 - Feature C (planned) -- spec: docs/changes/feature-c/proposal.md99 - Feature D (backlog) -- spec: docs/changes/feature-d/proposal.md100 ```1011022. Offer choices:103 - **(A) Accept** -- proceed with this structure104 - **(B) Rename** -- rename milestones or features105 - **(C) Reorganize** -- move features between milestones106 - **(D) Add milestones** -- create additional milestones (e.g., "v2.0", "Q2 2026")1071083. Ask: "Are there additional features not captured in specs that should be on the roadmap?"109 - If yes: collect name, summary, and milestone for each.1101114. Repeat until the human selects **(A) Accept**.112113#### Phase 3: WRITE -- Generate Roadmap1141151. Build the roadmap structure:116 - Frontmatter: `project`, `version: 1`, `created`, `updated` timestamps117 - One H2 section per milestone118 - One H3 section per feature with 5 fields: `Status`, `Spec`, `Summary`, `Blockers`, `Plan`1191202. Write via `manage_roadmap` MCP tool if available. If MCP is unavailable, write directly using the roadmap markdown format and warn: "External sync skipped (MCP unavailable). Run `manage_roadmap sync` when MCP is restored to push changes to GitHub."121122 ```markdown123 ---124 project: <name>125 version: 1126 created: YYYY-MM-DD127 updated: YYYY-MM-DD128 ---129130 # Roadmap131132 ## Current Work133134 ### Feature A135136 - **Status:** in-progress137 - **Spec:** docs/changes/feature-a/proposal.md138 - **Summary:** One-line description of the feature139 - **Blockers:** none140 - **Plan:** docs/changes/feature-a/plans/2026-03-20-feature-a-plan.md141 ```1421433. Write to `docs/roadmap.md`.144145#### Phase 4: VALIDATE -- Verify Output1461471. Read back `docs/roadmap.md`.1482. Verify via `manage_roadmap show` if MCP is available -- confirms round-trip parsing.1493. Run `harness validate`.1504. Present summary to human:151152 ```153 Roadmap created: docs/roadmap.md154 Milestones: N155 Features: N156 harness validate: passed157 ```158159---160161### Command: `--add <feature-name>` -- Add a Feature162163#### Phase 1: SCAN -- Load Existing Roadmap1641651. Check if `docs/roadmap.md` exists.166 - If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run `--create` first to bootstrap one."1672. Parse the roadmap (via `manage_roadmap show` or direct read).1683. Check for duplicate feature names. If `<feature-name>` already exists: error with message. "Feature '<feature-name>' already exists in milestone '<milestone>'. Use a different name or edit the existing feature."169170#### Phase 2: PROPOSE -- Collect Feature Details171172Ask the human for each field interactively:1731741. **Milestone:** "Which milestone should this feature belong to?" List existing milestones plus a `[NEW]` option. If `[NEW]`: ask for the new milestone name.1752. **Status:** "What is the current status?" Offer: `backlog`, `planned`, `in-progress`, `blocked`.1763. **Spec:** "Is there a spec for this feature?" If yes, ask for the path. If no, leave as `none`.1774. **Summary:** "One-line summary of the feature."1785. **Blockers:** "Any blockers?" If yes, collect. If no, set to `none`.1796. **Plan:** "Is there a plan for this feature?" If yes, ask for the path. If no, leave as `none`.180181Present the collected details for confirmation:182183```184New feature to add:185186 Milestone: Current Work187 Name: Feature E188 Status: planned189 Spec: docs/changes/feature-e/proposal.md190 Summary: Add feature E to the system191 Blockers: none192 Plan: none193194Confirm? (y/n)195```196197Wait for confirmation before proceeding.198199#### Phase 3: WRITE -- Add Feature to Roadmap2002011. Add via `manage_roadmap add` 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). Run `manage_roadmap sync` when MCP is restored to push changes to GitHub."2022. If the milestone is `[NEW]`: create the milestone section, then add the feature.2033. Write to `docs/roadmap.md`.204205#### Phase 4: VALIDATE -- Verify Output2062071. Read back `docs/roadmap.md`.2082. Verify the new feature appears in the correct milestone.2093. Run `harness validate`.2104. Confirm to human:211212 ```213 Feature added: Feature E -> Current Work214 Total features: N215 harness validate: passed216 ```217218---219220### Command: _(no args)_ -- Show Roadmap Summary221222#### Phase 1: SCAN -- Load Roadmap2232241. Check if `docs/roadmap.md` exists.225 - If missing: suggest `--create`. "No roadmap found at docs/roadmap.md. Run `--create` to bootstrap one from existing specs and plans."2262. Parse the roadmap (via `manage_roadmap show` or direct read).227228#### Phase 2: PRESENT -- Display Summary2292301. Display a compact summary of the roadmap:231232 ```233 ROADMAP: <project-name>234 Last synced: YYYY-MM-DD HH:MM235236 ## <Milestone 1> (N features)237 - Feature A .................. in-progress238 - Feature B .................. planned239 - Feature C .................. blocked (by: Feature A)240241 ## <Milestone 2> (N features)242 - Feature D .................. done243 - Feature E .................. backlog244245 Total: N features | N done | N in-progress | N planned | N blocked | N backlog246 ```2472482. If any features have stale sync timestamps (last_synced older than 24 hours), append a note:249250 ```251 Hint: Roadmap may be stale. Run `--sync` to update statuses from plan execution state.252 ```2532543. No file writes. This is a read-only operation. No `harness validate` needed.255256---257258### Command: `--sync` -- Sync Statuses from Execution State259260#### Phase 1: SCAN -- Load Roadmap and Execution State2612621. Check if `docs/roadmap.md` exists.263 - If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run `--create` first to bootstrap one."264 - Do NOT create a roadmap. Do NOT offer alternatives. Stop.2652. Parse the roadmap (via `manage_roadmap show` or direct read).2663. For each feature with linked plans, scan execution state:267 - `.harness/state.json` (root execution state)268 - `.harness/sessions/*/autopilot-state.json` (session-scoped execution state)269 - Plan file completion markers270271#### Phase 2: PROPOSE -- Present Status Changes2722731. Infer status for each feature:274 - All tasks complete -> suggest `done`275 - Any task started -> suggest `in-progress`276 - Blocker feature not done -> suggest `blocked`277 - No execution data found -> no change2782792. Check the **human-always-wins** rule: if `last_manual_edit` is more recent than `last_synced` for a feature, preserve the manually set status. Report it as "skipped (manual override)".2802813. Present proposed changes:282283 ```284 SYNC RESULTS285286 Changes detected:287 - Feature A: planned -> in-progress (3/8 tasks started)288 - Feature B: in-progress -> done (all tasks complete)289 - Feature C: planned -> blocked (blocked by: Feature A, not done)290291 Unchanged:292 - Feature D: done (no change)293294 Skipped (manual override):295 - Feature E: kept as "planned" (manually edited 2h ago)296297 Apply these changes? (y/n)298 ```2993004. Wait for human confirmation before applying.301302#### Phase 3: WRITE -- Apply Changes3033041. Apply via `manage_roadmap sync` MCP tool if available, or via `manage_roadmap update` for each changed feature. If MCP is unavailable, parse the roadmap, update statuses, and serialize back. Warn: "External sync skipped (MCP unavailable). Run `manage_roadmap sync` when MCP is restored to push changes to GitHub."3052. Update `last_synced` timestamp in frontmatter.3063. Write to `docs/roadmap.md`.307308#### Phase 4: VALIDATE -- Verify Output3093101. Read back `docs/roadmap.md`.3112. Verify changes applied correctly via `manage_roadmap show` if MCP is available.3123. Run `harness validate`.3134. Present summary:314315 ```316 Sync complete: docs/roadmap.md317 Updated: N features318 Skipped: N (manual override)319 Unchanged: N320 harness validate: passed321 ```322323---324325### Command: `--edit` -- Interactive Edit Session326327#### Phase 1: SCAN -- Load Existing Roadmap3283291. Check if `docs/roadmap.md` exists.330 - If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run `--create` first to bootstrap one."3312. Parse the roadmap (via `manage_roadmap show` or direct read).3323. Present current structure:333334 ```335 Current roadmap: <project-name>336337 ## <Milestone 1>338 1. Feature A (in-progress)339 2. Feature B (planned)340341 ## <Milestone 2>342 3. Feature C (done)343 4. Feature D (backlog)344 ```345346#### Phase 2: EDIT -- Interactive Modifications347348Offer edit actions in a loop until the human is done:3493501. **Reorder features within a milestone:**351 - "Move which feature? (number)" -> "To which position?" -> reorder.3523532. **Move a feature between milestones:**354 - "Move which feature? (number)" -> "To which milestone?" (list milestones + `[NEW]`) -> move.355 - If `[NEW]`: ask for the new milestone name, create it.3563573. **Update blockers:**358 - "Update blockers for which feature? (number)" -> "Blocked by? (feature names, comma-separated, or 'none')" -> update.3593604. **Update status:**361 - "Update status for which feature? (number)" -> offer: `backlog`, `planned`, `in-progress`, `blocked`, `done` -> update.3623635. **Rename a feature:**364 - "Rename which feature? (number)" -> "New name?" -> rename.3653666. **Remove a feature:**367 - "Remove which feature? (number)" -> "Confirm removal of '<name>'? (y/n)" -> remove on confirm.3683697. **Rename a milestone:**370 - "Rename which milestone?" -> "New name?" -> rename.3713728. **Done:**373 - Exit edit loop, proceed to WRITE phase.374375Present the menu after each action:376377```378Edit actions:379 (1) Reorder features within a milestone380 (2) Move feature to different milestone381 (3) Update blockers382 (4) Update status383 (5) Rename feature384 (6) Remove feature385 (7) Rename milestone386 (D) Done -- save and exit387388Choice?389```390391#### Phase 3: WRITE -- Save Changes3923931. Present a diff summary of all changes made during the edit session:394395 ```396 Changes to apply:397398 - Moved "Feature B" from "Current Work" to "Q2 Release"399 - Updated "Feature A" blockers: none -> Feature C400 - Reordered "Q2 Release": Feature B now at position 1401402 Apply? (y/n)403 ```4044052. Wait for confirmation before writing.4063. Apply all changes via `manage_roadmap update` / `manage_roadmap remove` MCP tool calls, or direct file manipulation if MCP is unavailable. If falling back to direct manipulation, warn: "External sync skipped (MCP unavailable). Run `manage_roadmap sync` when MCP is restored to push changes to GitHub."4074. Update `last_manual_edit` timestamp in frontmatter (since this is a human-driven edit).4085. Write to `docs/roadmap.md`.409410#### Phase 4: VALIDATE -- Verify Output4114121. Read back `docs/roadmap.md`.4132. Verify changes applied correctly.4143. Run `harness validate`.4154. Present summary:416417 ```418 Edit complete: docs/roadmap.md419 Changes applied: N420 harness validate: passed421 ```422423---424425### Command: `--query <filter>` -- Query Features by Filter426427#### Phase 1: SCAN -- Load Roadmap4284291. Check if `docs/roadmap.md` exists.430 - If missing: error with clear message. "No roadmap found at docs/roadmap.md. Run `--create` first to bootstrap one."4312. Parse the roadmap (via `manage_roadmap query` or direct read).432433#### Phase 2: FILTER -- Apply Query4344351. Accept filter patterns:436 - **Status filter:** `backlog`, `planned`, `in-progress`, `done`, `blocked` -- returns all features with that status437 - **Milestone filter:** `milestone:<name>` -- returns all features in the named milestone (partial match)4384392. Display matching features with their milestone context:440441 ```442 QUERY: <filter>443444 Results (N matches):445 - Feature A (Current Work) .................. in-progress446 - Feature B (Backlog) ....................... planned447448 Total: N matches449 ```4504513. No file writes. This is a read-only operation.452453---454455### Command: `--groom` -- Tidy the Roadmap456457Keeps the roadmap manageable over time. **Milestones are themes; statuses are lifecycle stages** -- grooming enforces that separation so the backlog never decays back into an undifferentiated dump.458459#### Phase 1: SCAN -- Detect Untidiness4604611. Check if `docs/roadmap.md` exists. If missing: error and direct the user to `--create`.4622. Run `manage_roadmap` (`action: "groom"`) in a dry-run frame, or call `checkRoadmapHealth` from `@harness-engineering/core`, to surface the four health signals:463 - **RMH001** -- completed (`done`) features still sitting in an active milestone.464 - **RMH002** -- `planned` rows with neither a spec nor a plan (the orchestrator cannot auto-execute these; it escalates them to a human).465 - **RMH003** -- lifecycle catch-all milestones (`Backlog`, `Current Work`) that should not exist.466 - **RMH004** -- active milestones that have grown past the size cap (a mini-dump).467468#### Phase 2: PROPOSE -- Present the Plan469470Show the human exactly what grooming will do, in plain text:471472```473GROOM PLAN474475Demote to backlog (planned with no spec/plan):476 - Feature A (Theme X)477 - Feature B (Theme Y)478479Archive to docs/roadmap-archive.md (completed):480 - Feature C (Theme X)481482Flagged for manual routing (not auto-changed):483 - Intake lane has 3 items awaiting a theme484 - "Theme Z" has 28 features (cap 25) -- consider splitting485486Apply? (y/n)487```488489Wait for confirmation. The mechanical changes (demote, archive) are safe and automated; **draining the Intake lane into themed milestones and splitting oversized milestones are human decisions** -- propose, do not auto-apply.490491#### Phase 3: WRITE -- Apply4924931. Run `manage_roadmap` (`action: "groom"`). It demotes unactionable `planned` rows to `backlog` and moves `done` features into `docs/roadmap-archive.md` under a `Shipped` milestone, returning the list of changes.4942. For Intake-draining or milestone-splitting the human approved, follow up with `--edit` (move features between milestones).495496#### Phase 4: VALIDATE -- Verify4974981. Run `harness validate` and confirm the `roadmapHealth` check **passed** -- `checks.roadmapHealth === true` in `--json`, not merely "not false" (no RMH003 errors; RMH001/002/004 warnings cleared or acknowledged). If `validate` exits 3 or reports the check under "Checks that could not run", the roadmap could not be parsed and NO health rule ran: fix the reported section and re-run. A check that did not run is not a check that passed.4992. Summarize:500501 ```502 Groom complete.503 Demoted: N | Archived: N -> docs/roadmap-archive.md | Flagged for manual routing: N504 harness validate (roadmapHealth): passed505 ```506507---508509## Harness Integration510511- **`manage_roadmap` MCP tool** -- Primary read/write interface for roadmap operations. Supports `show`, `add`, `update`, `remove`, `query`, `sync`, `promote`, and `groom` actions. Use this when MCP is available for structured CRUD.512- **`harness validate`** -- Run after any roadmap modification to verify project health. Mandatory in the VALIDATE phase of `--create`, `--add`, and `--groom`. The `roadmapHealth` check enforces the maintenance rules (RMH001-RMH004) as a regression guard.513- **Core `checkRoadmapHealth`/`groomRoadmap`** -- Maintenance engine in `packages/core/src/roadmap/health.ts`. `checkRoadmapHealth` is read-only diagnostics; `groomRoadmap` is the pure transform (demote unactionable planned, archive done). Both are surfaced via `manage_roadmap` and `harness validate`.514- **Core `parseRoadmap`/`serializeRoadmap`** -- Fallback when MCP is unavailable. These functions in `packages/core/src/roadmap/` handle parsing and serializing the roadmap markdown format directly. Note: the serializer only preserves frontmatter, milestones, features, and the Assignment History table -- never add convention prose or comments to `docs/roadmap.md`, they are dropped on the next write.515- **Roadmap files** -- Live work in `docs/roadmap.md` (the orchestrator's source of truth); completed work archived to `docs/roadmap-archive.md` by `--groom`. Milestones are themes, not lifecycle stages -- promoted items land in the `Intake` lane and are groomed into themes.516517## Success Criteria5185191. `--create` discovers all specs (`docs/changes/*/proposal.md`) and plans (`docs/changes/*/plans/*.md` and legacy `docs/plans/*.md`)5202. `--create` proposes groupings and waits for human confirmation before writing5213. `--create` produces a valid `docs/roadmap.md` that round-trips through `parseRoadmap`/`serializeRoadmap`5224. `--add` collects all fields interactively (milestone, status, spec, summary, blockers, plan)5235. `--add` rejects duplicate feature names with a clear error message5246. `--add` errors gracefully when no roadmap exists, directing the user to `--create`5257. Default (no args) displays a compact status summary with feature counts by status5268. Default (no args) suggests `--create` when no roadmap exists5279. Default (no args) hints at `--sync` when roadmap may be stale52810. `--sync` scans `.harness/state.json` and `.harness/sessions/*/autopilot-state.json` for execution state52911. `--sync` respects the human-always-wins rule -- manually edited statuses are preserved53012. `--sync` presents proposed changes and waits for human confirmation before applying53113. `--sync` errors gracefully when no roadmap exists, directing the user to `--create`53214. `--edit` offers reorder, move, blocker update, status update, rename, and remove actions53315. `--edit` presents a diff summary and waits for confirmation before writing53416. `--edit` updates `last_manual_edit` timestamp (since changes are human-driven)53517. Output matches the roadmap markdown format exactly (frontmatter, H2 milestones, H3 features, 5 fields each)53618. `harness validate` passes after all operations53719. `--query` filters features by status or milestone and displays results with milestone context53820. `--query` errors gracefully when no roadmap exists, directing the user to `--create`539540## Rationalizations to Reject541542| Rationalization | Reality |543| ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |544| "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. |545| "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. |546| "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. |547| "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. |548549## Examples550551### Example: `--create` -- Bootstrap a Roadmap from Existing Artifacts552553**Context:** A project with 3 specs and 2 plans. Two specs have matching plans (in-progress), one spec has no plan (backlog).554555**Phase 1: SCAN**556557```558SCAN COMPLETE559560Project: my-project561Found: 3 specs, 2 plans562Matched: 2 spec-plan pairs563Unmatched specs: 1 (backlog candidates)564Unmatched plans: 0565```566567**Phase 2: PROPOSE**568569```570Proposed Roadmap Structure:571572## Current Work573- Unified Code Review (in-progress) -- spec: docs/changes/unified-code-review/proposal.md574- Update Checker (in-progress) -- spec: docs/changes/update-checker/proposal.md575576## Backlog577- Design System (backlog) -- spec: docs/changes/design-system/proposal.md578579Options:580 (A) Accept this structure581 (B) Rename milestones or features582 (C) Reorganize -- move features between milestones583 (D) Add milestones584585Any additional features not captured in specs? (y/n)586```587588Human selects **(A) Accept**.589590**Phase 3: WRITE**591592```593Writing docs/roadmap.md...594 2 milestones, 3 features595```596597**Phase 4: VALIDATE**598599```600Roadmap created: docs/roadmap.md601Milestones: 2 (Current Work, Backlog)602Features: 3603harness validate: passed604```605606### Example: `--add` -- Add a Feature to an Existing Roadmap607608**Context:** A roadmap exists with 2 milestones and 3 features. Adding a new feature.609610**Phase 1: SCAN**611612```613Roadmap loaded: docs/roadmap.md614Milestones: 2 (Current Work, Backlog)615Features: 3616No duplicate found for "Notification System"617```618619**Phase 2: PROPOSE**620621```622Which milestone? [1] Current Work [2] Backlog [NEW] Create new623> 1624625Status? [backlog] [planned] [in-progress] [blocked]626> planned627628Spec? (path or "none")629> docs/changes/notification-system/proposal.md630631One-line summary:632> Real-time notification delivery with WebSocket and email channels633634Blockers? (or "none")635> none636637Plan? (path or "none")638> none639640New feature to add:641642 Milestone: Current Work643 Name: Notification System644 Status: planned645 Spec: docs/changes/notification-system/proposal.md646 Summary: Real-time notification delivery with WebSocket and email channels647 Blockers: none648 Plan: none649650Confirm? (y/n)651```652653Human confirms **y**.654655**Phase 3: WRITE**656657```658Adding feature to Current Work...659```660661**Phase 4: VALIDATE**662663```664Feature added: Notification System -> Current Work665Total features: 4666harness validate: passed667```668669## Gates670671These are hard stops. Violating any gate means the process has broken down.672673- **No writing `docs/roadmap.md` 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.674- **No overwriting an existing roadmap without explicit user consent.** If `docs/roadmap.md` exists when `--create` runs, the human must confirm the overwrite. Silent overwrites destroy prior work.675- **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.676- **No proceeding when `docs/roadmap.md` is missing for `--add`.** If the roadmap does not exist, do not create one silently. Error and direct the user to `--create`.677- **No syncing when `docs/roadmap.md` does not exist.** `--sync` must error immediately with a message directing the user to `--create`. Do not create a roadmap as a side effect of sync.678- **No writing changes from `--edit` without showing a diff summary and getting confirmation.** The WRITE phase must present all pending changes and wait for explicit accept before modifying `docs/roadmap.md`.679680## Escalation681682- **When no specs or plans are found during `--create`:** Suggest creating a minimal roadmap with just a Backlog milestone containing features described verbally by the human. Alternatively, suggest running `harness:brainstorming` first to generate specs that can then be discovered by `--create`.683- **When the roadmap file is malformed and cannot be parsed:** Report the specific parse error with line numbers if available. Suggest manual inspection of `docs/roadmap.md` or recreation with `--create` (after backing up the existing file).684- **When MCP tool is unavailable:** Fall back to direct file manipulation via Read/Write tools using the roadmap markdown format. The core `parseRoadmap`/`serializeRoadmap` functions handle the format. Report the fallback to the human: "MCP tool unavailable, using direct file operations. External sync skipped — run `manage_roadmap sync` when MCP is restored to push changes to GitHub."