Reconcile Roadmap (pre-execution, cross-plan)
Brush across all the finished task plans of a roadmap at once and stress-test that they
cohere as a system — that the seams the roadmap's depends-on edges promised are actually
honored by the missions on both sides — before /start-roadmap executes anything. This
skill produces pushbacks, not suggestions; it never gold-plates plans that already fit
together.
Silence is the expected outcome. A set of plans whose seams line up, whose coverage is complete, and whose terms agree gets a one-line "No discrepancies — the plans cohere." Do not manufacture concerns to look thorough.
ALWAYS check .ab-method/structure/index.yaml FIRST for where roadmaps, tasks, and the
domain model live — paths are user-configurable, never hardcode them.
Where this sits (and what it is NOT)
Three critics guard a roadmap at three different moments. Keep them distinct:
critique-plan → ONE plan vs the domain model (pre-plan / per-task)
reconcile-roadmap → ALL plans vs EACH OTHER (pre-execution, whole roadmap) ← this skill
review-implementation → one task's diff vs quality critics (post-implementation)
critique-plan at roadmap time only saw the coarse DAG (one-line task scopes), and each
task's own critique-plan only saw that one task's missions. Neither ever reads the whole
set of finished progress-tracker.md files together, so discrepancies that only exist
between plans slip through to execution. That is exactly the gap this skill closes: it is the
pre-execution counterpart of an integration test, run at the plan level.
It is read-only and advisory — it surfaces discrepancies and points at the fix; it never
edits a plan, reshapes a task, or blocks a run. It is standalone: invoke it manually
(/reconcile-roadmap <name>), typically once planning is done and before /start-roadmap.
Process
1. Identify the roadmap
- If the user passed a roadmap name or a path to its
roadmap.md, use it. - Otherwise list folders under
docs/roadmaps/and ask which to reconcile.
2. Load the material
Read (skip missing files silently — don't flag them or offer to create them):
roadmap.md— the Objective (the destination), the task list, everydepends-onedge (the DAG), and — when present —## Open decisions,## Not yet specified(fog), and## Out of scope.- Every planned task's tracker — for each task marked
plan: ✅, readdocs/tasks/<slug>/progress-tracker.md. Confirm the file actually exists with missions; don't trust the flag alone (same discipline as/start-roadmap). - Every planned task's
unresolved-questions.md, where one exists — the black boxes those plans intend to ship. Usually absent; when present, it's exactly the kind of assumption that only misbehaves across plans. - The domain model that exists —
UBIQUITOUS_LANGUAGE.md,CONTEXT.md(orCONTEXT-MAP.md- per-context
src/<context>/CONTEXT.md),docs/adr/,docs/architecture/*. Used to judge terminology and seam ownership, not re-critiqued per plan.
- per-context
3. Handle partial planning
Reconcile only the planned subset. A roadmap may be partially planned — that's fine.
- Any task still
plan: ⬜(or whoseprogress-tracker.mdis missing) is reported as "couldn't check." - Any seam that touches an unplanned task is flagged unverifiable, not assumed fine — you can't confirm a handoff whose other end doesn't exist yet.
(This mirrors /start-roadmap's tolerance for running a planned prefix.)
4. Spin up ONE read-only reconciler subagent
Spawn a single subagent — reconciler — with the roadmap, all the planned trackers, and the
domain-model files from Step 2, and the rule that it is read-only: it returns discrepancies
as text and edits nothing. Isolating it keeps the cross-plan analysis out of the main context.
(For a very large roadmap you may fan out one reconciler per seam, but the default is one
reconciler holding the whole set — the discrepancies live in the relationships between plans,
so a single reader sees them best.)
Its brief — fire ONLY on a genuine cross-plan discrepancy, one of:
- Broken seam / contract mismatch — Task B
depends-onA, and B's missions consume a type / endpoint / table / interface that A's missions never produce, or produce under a different name or shape. The edge promised a handoff the plans don't honor. - Coverage gap — a piece of the roadmap Objective, or a seam implied by an edge, that no task's missions actually implement. Work that falls between tasks.
- Overlap / duplication — two tasks plan the same artifact (same file, table, function, endpoint) — a double-build or a merge collision waiting to happen at execution.
- Ordering / edge defect — a mission in an upstream task actually needs an artifact only
produced downstream (an edge is reversed, or a needed edge is missing). This is grounded
in the actual missions, which the roadmap-time
critique-plannever saw. - Cross-task terminology drift — the same concept named differently across two tasks'
missions (e.g.
cancelOrderin one,voidOrderin another), which will fragment the codebase.critique-plansees one task at a time and structurally cannot catch this. - Conflicting assumptions — two tasks assume incompatible things about a shared entity or contract (soft- vs hard-delete of the same record, sync vs async on the same boundary, differing auth or ownership model).
- The map contradicts the plans — the roadmap's own sections have gone stale against the
finished trackers. Never fire on fog merely existing (an uncharted area is honest). Fire when:
a
## Not yet specifiedpatch is already covered by a planned task's missions (it graduated and nobody cleared it); an## Out of scopeitem is implemented by a task's missions (the scope boundary was crossed without redrawing the destination); an## Open decisionsentry blocks a task that is nonethelessplan: ✅(planned around an unsettled decision — say which missions would change if it resolves the other way); or a## Decisionsline points at an ADR/term that doesn't exist. - Black boxes that leak across tasks — a parked question (
⚠️ UQ-n) is a deliberate placeholder within its own task, so never fire on one existing. Fire when it stops being local: a downstream task's missions build real logic on the answer an upstream task left open; two tasks park the same question with different placeholders (the codebase gets two conflicting defaults); or a task'sIf the answer differsblast radius names work that a different task owns, so answering it later reopens a plan nobody flagged. Do not propose the answer — say which plans collide and that resolvingUQ-nbefore execution is cheaper than after.
For each finding, return: What (the tasks/missions involved), Discrepancy (the exact
mismatch, citing both sides — task-slug + the mission on each), Why it matters (the
concrete cost at execution, not taste), Suggested resolution.
Example pushback: "Broken seam.
checkout-ui(mission 2, "call POST /charges") depends-oncharge-api, butcharge-api's missions only planPOST /payments— no/chargesendpoint is ever produced. At executioncheckout-uiwill build against a route that doesn't exist. Either renamecharge-api's endpoint to/charges, or fixcheckout-ui's mission to call/payments— and align the glossary term so both tasks agree."
Out of scope for this critic — do not raise:
- single-plan domain conflicts (terminology/context/ADR issues within one task) → that's critique-plan,
- implementation quality, tests, performance, code style → that's post-implementation review-implementation,
- reshaping or re-scoping tasks → that's
/create-task//extend-task.
With nothing anchored across the plans, the reconciler returns exactly:
No discrepancies — the plans cohere.
5. Surface findings — advisory, never blocking
Bring the pushbacks back into the session. The user resolves each their way:
- Amend a tracker — add or fix a mission so the seam is honored (via
/extend-task, or inline in that task'sprogress-tracker.md). - Redraw an edge in
roadmap.md— add, remove, or reverse adepends-onso ordering matches what the missions actually need. - Rename to the canonical term across the affected trackers so both tasks speak one language.
- Dismiss → drop it. If the dismissal rests on a load-bearing reason a future reader would need in order not to re-raise it, offer to record an ADR (../domain-model/ADR-FORMAT.md). Skip ephemeral ("not now") and self-evident reasons.
Also report the "couldn't check" list from Step 3 (unplanned tasks and unverifiable seams) so the user knows the reconciliation's coverage, not just its findings.
If the reconciler returned "No discrepancies," say so in one line (plus the couldn't-check list if any) and stop. Don't pad it.
Key Principles
- Cross-plan, not single-plan — the discrepancies live in the relationships between
finished plans; that's the whole reason this skill exists alongside
critique-plan. - Silent by default — coherent plans get one line; never invent concerns.
- Read-only and advisory — surfaces and points at the fix; the user resolves. It never edits a plan or blocks a run.
- Standalone — invoked manually, typically after planning and before
/start-roadmap; not auto-wired into any workflow. - Reconcile what's planned — a partial roadmap is fine; report what couldn't be checked rather than assuming unplanned seams are sound.
Remember
- Check
.ab-method/structure/index.yamlfor paths and therelationshipsmap. - Confirm each
plan: ✅task'sprogress-tracker.mdtruly exists with missions — don't trust the flag alone. - Roadmaps and tasks are referenced by slug; tasks live in the normal
docs/tasks/<slug>/.