feat: MGW/GSD architecture repair — ROADMAP-first flow, debug route, phase traceability#102
Conversation
…route
- Create CLAUDE.md at repo root with architecture overview, delegation boundary,
command surface, coding conventions, and GSD integration points
- Add parseRoadmap() to template-loader.cjs: parses GSD ROADMAP.md phase sections,
progress table status, goals, requirements, and success criteria into structured JSON
- Add 'debug' and 'diagnose-issues' to VALID_GSD_ROUTES
- Add parse-roadmap CLI subcommand to template-loader.cjs
- Refactor mgw:project to detect .planning/ROADMAP.md (Path A) and generate GitHub
issues from parsed roadmap data instead of AI hallucination; retain AI fallback (Path B)
- Add gsd:diagnose-issues to issue.md triage route options with route selection guide
- Add GSD Debug Pipeline Pattern to workflows/gsd.md with two-step diagnose-then-fix flow
- Update docs/ARCHITECTURE.md: ROADMAP.md integration flow, mgw:project description,
diagnose-issues route in pipeline, .planning/debug/{slug}.md artifact documentation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…traceability, recovery - run.md: add execute_gsd_debug step for gsd:diagnose-issues / gsd:debug routes - run.md: replace inline roadmapper with ROADMAP.md existence gate in milestone route - run.md: add phase_map lookup from project.json for phase context in PRs and comments - run.md: add PLAN.md content and Verification sections to inline PR body template - pr.md: add Phase Context section, Plan (collapsed), and Verification to PR body - pr.md: read PLAN.md content and paths for traceability - milestone.md: add failed issue recovery with Retry/Skip/Abort prompt - milestone.md: add end-of-milestone execution report table - state.md: add diagnosing to pipeline_stage enum and valid stages list - state.md: add diagnosing transitions to stage flow diagram - state.md: document phase_map usage for GSD phase directory lookup - next.md: surface failed issues as advisory alongside primary recommendation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
this looks like we're finally lineing up with our vision. however, the roadmap is attached to a specific milestone right? or is that the project? I'm seeing potentional collision of visions because mgw should be capable of handling multiple milestones, while I think gsd tends to deep focus 1 specific milestone at a time? |
|
Great question — the concern is valid but the architecture actually handles this correctly. Let me break it down: GSD ROADMAP.md is milestone-scoped, not project-scopedGSD's ROADMAP.md is replaced with each
So ROADMAP.md always contains only the current active milestone's phases. It is not a cumulative document — it's a rolling window. The intended handshakeThe correct flow is:
MGW's What this PR actually doesPath A ( The one gap worth notingThe Short answer: your vision is intact. GSD deep-focuses one milestone at a time, MGW tracks the full project history across all milestones. ROADMAP.md is the handoff point — one milestone at a time, both tools agree on what's current. |
|
lets address some things First, the correct flow is: mgw:project (init) → (Should determine if previous work across gh, gsd, the local repo, or mgw has occurred. If it does this should trigger some sort of "Lets align with the current projects potential status" stage where it looks at dates, times, issues, comments, etc. it needs to determine WHAT project it's orchestrating. Previous milestones in existing gsd projects should be mapped for historical purposes, future milestones that might exist or phases should be loaded into gh as part of the reflection. If it determines it's a fresh project it should assist the user running gsd:new-project to gauge the FULL scope of the entire project. This will be incredibly extensive in MOST cases, so a collaboration, deliberation, recommendation cycle should occur with the user FIRST. This probably requires new agents, nested cycles and flow driven architecture, so research it.) Originally: gsd:new-project → PROJECT.md + ROADMAP.md
What I WANT to do /mgw:project "I need to design a website for my customer. He's a mechanic, and he's wanting a site to give him visibility on googles search engine, yelp, and other related social 'find a helper' kind of job sites" MGW takes me through an extensive cycle where it has internal deliberation, suggestion, review, enhance, condence, etc phases. The idea here is that we end up flushing out the "Full Vision" without pretending we're done or pretending we've covered everything. We want to orchestrate, in some cases, the entire E2E fortune 500 business. Or a NASA flight command center module. Failure is not an option. GSD uses this same failure is not an option methodology which is why tens of thousands of people have flocked to it. Let's not make it worse, trying to make it better. |
Architectural Response:
|
| Signal | Check |
|---|---|
P |
.planning/PROJECT.md exists |
R |
.planning/ROADMAP.md exists |
S |
.planning/STATE.md exists |
M |
.mgw/project.json exists |
G |
GitHub milestones exist for this repo |
| P | R | S | M | G | Classification | Action |
|---|---|---|---|---|---|---|
| - | - | - | - | - | Fresh | Full Vision cycle → gsd:new-project |
| Y | - | - | - | - | GSD-Only (project started) | Alignment: import PROJECT.md context, backfill MGW state |
| Y | Y | Y | - | - | GSD-Only (mid-execution) | Alignment: parse ROADMAP.md + MILESTONES.md, create GitHub milestones, build project.json |
| Y | Y | Y | Y | Y | Aligned | Already initialized — report status, offer extend |
| Y | Y | Y | Y | Y | Diverged | project.json doesn't match GitHub reality — reconcile first |
The critical missing case today: someone runs gsd:new-project, works for weeks, then installs MGW. Currently MGW asks "what are you building?" — it should say "I see you have X phases completed. Let me mirror that into GitHub." An alignment-analyzer Task agent handles this — reads .planning/* and git log, returns structured state the orchestrator uses to backfill project.json and create GitHub milestones.
2. "Full Vision" Collaboration Cycle
For the Fresh path — mechanic website or NASA flight module — the cycle before GSD ever touches .planning/:
Stage 1 — Intake (user-facing): Freeform. "What do you want to build?" Capture the raw idea.
Stage 2 — Domain Expansion (Task agent, silent): Spawn vision-researcher. Takes the raw idea and returns: domain analysis (what does a mechanic website actually need?), platform requirements (Google Business Profile, Yelp integration, schema.org markup, local SEO), competitive landscape, and risk factors. For the mechanic — surfaces mobile-first design, ADA compliance, review aggregation, booking system decision.
Stage 3 — Structured Questioning (user-facing, 3-8 rounds): Not "tell me more" — targeted questions informed by the research. "Should we integrate Google Business Profile directly, or optimize for organic search? Here's the tradeoff..." Each round narrows scope. Soft cap at 8 rounds, hard cap at 15.
Context strategy: The orchestrator maintains a rolling summary, not a growing transcript. Decisions get appended to .mgw/vision-draft.md after each round. Agents receive the current Brief plus latest delta — never the full conversation history. Context growth stays bounded.
Stage 4 — Vision Synthesis (Task agent, silent): Spawn vision-synthesizer. Takes all Q&A context and produces a draft Vision Brief: project identity, target users, core value proposition, feature categories (must/should/could/won't), technical constraints, success metrics, estimated scope, and recommended milestone structure.
Stage 5 — Review and Refine (user-facing): Present the Brief. User accepts, revises sections, or "dig deeper on X." Revisions loop back to Stage 4 with correction context.
Stage 6 — Condense (Task agent, silent): Spawn vision-condenser. Produces the handoff document — a structured prompt context passed directly into the gsd:new-project Task spawn. This is not a file, it's the full context package that makes gsd:new-project produce a PROJECT.md that reflects everything deliberated.
Agent roster for the cycle:
| Agent | Runs | Output |
|---|---|---|
vision-researcher |
Once (Stage 2) | Domain analysis |
vision-synthesizer |
1-N (Stage 4, loops on revision) | Vision Brief draft |
vision-condenser |
Once (Stage 6) | Handoff context for gsd:new-project |
3. GSD Project vs Milestone — Definitive Clarification
GSD Project (PROJECT.md) — the full vision. What you're building, why, for whom, success criteria, explicit out-of-scope. Persists across the entire project lifetime. Never replaced, only updated (requirements move from Active → Validated).
GSD Milestone (ROADMAP.md) — a sprint-sized unit of work. 3-12 phases. ROADMAP.md gets replaced by gsd:new-milestone. The old one gets archived to MILESTONES.md. One milestone = ~1-4 weeks of work.
One MGW project = one GSD project. Always. One repo, one PROJECT.md, one .mgw/project.json. MGW holds the full timeline (all milestones). GSD holds the current focus (one ROADMAP.md at a time). This asymmetry is correct — it's not a bug.
Milestone counts by scale: Mechanic website: 2-3 milestones. Enterprise SaaS: 10-20+. MGW itself: 7 milestones so far.
4. Multi-GSD-Milestone Tracking
The current project.json uses current_milestone as a single integer. This breaks when a user has issues open across two GSD milestones simultaneously.
Proposed schema change — replace current_milestone with:
{
"active_gsd_milestone": "v1.1",
"milestones": [
{
"github_number": 3,
"name": "v1 — Foundation",
"gsd_milestone_id": "v1.0",
"gsd_state": "completed",
"roadmap_archived_at": "2026-02-20T...",
"issues": [...]
},
{
"github_number": 4,
"name": "v1 — Integrations",
"gsd_milestone_id": "v1.1",
"gsd_state": "active",
"issues": [...]
}
]
}Jumping between milestones: mgw:run looks at the issue's milestone assignment in project.json and checks whether it matches active_gsd_milestone.
- Doesn't match + issue is
gsd:quick: Run in isolation. Quick-route bugs don't need ROADMAP.md context — no milestone switch needed. - Doesn't match + issue is
gsd:plan-phase: Warn and offer to switch active GSD milestone (archive current ROADMAP.md, load archived target milestone). This is deliberate becauseplan-phasework needs ROADMAP.md awareness.
Cross-ref addition: New link type for the GitHub-to-GSD handshake:
{ "a": "milestone:3", "b": "gsd-milestone:v1.0", "type": "maps-to" }5. mgw:map-project-milestones — Design
This is a step within mgw:project (and called by mgw:milestone on completion), not a standalone command.
What it does:
- Read
.planning/PROJECT.md,.planning/MILESTONES.md(archived milestones),.planning/ROADMAP.md(active milestone) - Read
.mgw/project.json(what MGW already knows) - Query GitHub for all milestones + issue counts in the repo
- Diff: which GSD milestones have no GitHub milestone? Which GitHub milestones have no GSD counterpart?
- Create missing GitHub milestones, backfill
project.jsonentries withgsd_milestone_idandgsd_state
The "3 GSD milestones, 2 GitHub milestones" case: Mapping agent detects the gap, creates the missing GitHub milestone using the archived milestone's name and description from MILESTONES.md, then creates issues from the phase structure. This is a scoped replay of the milestone/issue creation steps for just the missing entry.
6. Orchestrator Agent Architecture
The orchestrator is a thin coordinator. Here is the full spawn tree for the redesigned mgw:project:
/mgw:project "mechanic website..."
│
├─[State Detection — orchestrator directly, no agent needed]
│ File checks + single GraphQL call → classification
│
├─[Fresh] ──────────────────────────────────────────────────────────
│ Task: vision-researcher (Stage 2)
│ [Questioning rounds — orchestrator handles user-facing]
│ Task: vision-synthesizer (Stage 4, loops on revision)
│ [User review — orchestrator handles]
│ Task: vision-condenser (Stage 6)
│ Task: gsd:new-project (receives condensed Vision Brief)
│ └─ GSD produces PROJECT.md + ROADMAP.md
│ Task: milestone-mapper (reads GSD output → GitHub milestones/issues)
│ Orchestrator: write project.json, report summary
│
├─[GSD-Only] ───────────────────────────────────────────────────────
│ Task: alignment-analyzer (reads .planning/*, git log → structured state)
│ Task: milestone-mapper (creates GitHub structure from GSD state)
│ Orchestrator: write project.json, report summary
│
├─[Aligned] ────────────────────────────────────────────────────────
│ Orchestrator: report status, offer extend mode
│
└─[Diverged] ───────────────────────────────────────────────────────
Task: drift-analyzer (compare project.json vs GitHub reality)
Task: reconciler (fix gaps)
Orchestrator: report what was fixed
What the orchestrator itself does and nothing more: state detection (file checks + one API call), classification, user-facing questioning, Task spawning with context passing, writing project.json from agent returns, displaying summaries. Everything analytical or creative is delegated.
7. Risks Worth Calling Out
GSD phases that got renamed/split during execution. The alignment agent tries to match phases to GitHub issues. If someone renamed a phase mid-sprint, fuzzy matching on title is needed — not exact slug matching. This needs to be explicit in the alignment agent's prompt.
Half-initialized GSD project (PROJECT.md exists, ROADMAP.md doesn't). User started gsd:new-project but didn't finish. Detection: P=true, R=false. Not GSD-Only — it's partial init. MGW should offer to resume gsd:new-project with existing PROJECT.md as context, not start over.
10+ milestone projects. The schema scales (just a longer array) but the Vision Cycle needs to handle scope gracefully. Only the first 2-3 milestones should be fully detailed in the Brief; later ones stay at "category" level. You can't plan milestone 9 before milestone 3 is done.
Vision Cycle context overload past round 12. The rolling summary + .mgw/vision-draft.md file approach addresses this. If compaction hits, the file persists and the orchestrator reads it back rather than relying on in-context history.
Extend mode while GSD is mid-milestone. mgw:project --extend should check STATE.md for active phase work before proceeding. If work is in progress: "You have active work in phase N. Complete or shelve it before extending the project."
Proposed Execution Plan
Milestone A — State Detection + Alignment (3-4 issues)
- State detection algorithm in
mgw:project(signal matrix + classification) alignment-analyzeragent prompt (GSD-Only path)milestone-mapperagent (create GitHub milestones/issues from GSD state)- Add
gsd_milestone_id,gsd_state,active_gsd_milestonetoproject.jsonschema
Milestone B — Vision Collaboration Cycle (4-5 issues)
- Vision Brief document format (fields, structure)
vision-researcheragent prompt- Structured questioning flow with round caps + rolling summary
vision-synthesizer+vision-condenseragents- Wire condensed output into
gsd:new-projectTask spawn
Milestone C — Multi-Milestone Tracking (3-4 issues)
- Replace
current_milestonewithactive_gsd_milestoneinproject.json - Milestone-switching logic in
mgw:run(detect cross-milestone issue, quick vs plan-phase routing) maps-tolink type in cross-refs- Integrate
map-project-milestonesstep intomgw:projectalignment andmgw:milestonecompletion
Milestone A first — it unblocks both B and C and solves the most common real-world case (existing GSD projects adopting MGW). Milestone B is the largest and most novel. Milestone C is mechanical once A's schema changes land.
Add migrateProjectState() for backward-compatible schema migration (gsd_milestone_id, gsd_state, roadmap_archived_at, active_gsd_milestone). Add resolveActiveMilestoneIndex() with dual-mode resolution for both current_milestone (legacy) and active_gsd_milestone (new schema). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace two-gate project.json check with 5-signal state detection (P/R/S/M/G) routing to Fresh/GSD-Only/GSD-Mid-Exec/Aligned/Diverged/Extend paths. Stubs align_from_gsd and reconcile_drift for A2/A5. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A2: alignment-analyzer Task agent reads .planning/* and produces .mgw/alignment-report.json with structured GSD state for backfill. A5: drift-analyzer Task agent compares project.json vs GitHub reality, produces .mgw/drift-report.json with mismatches and reconciliation actions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
templates/vision-brief-schema.json: JSON Schema for the structured Vision Brief output from vision-synthesizer (project_identity, target_users, feature_categories MoSCoW, success_metrics, scope). CLAUDE.md: document Vision Collaboration Cycle flow and runtime artifact paths in Key Directories table. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
milestone_mapper step reads .mgw/alignment-report.json and creates GitHub milestones/issues from GSD state, writes cross-refs with maps-to links (milestone:N <-> gsd-milestone:id). link.md: add maps-to as recognized link type with milestone:N and gsd-milestone:name reference normalization. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace direct current_milestone integer reads with resolveActiveMilestoneIndex() in milestone.md, next.md, status.md, and run.md. Maintains backward compatibility with legacy integer schema while supporting new active_gsd_milestone string resolution. - milestone.md: parse_arguments resolves active idx via node instead of python3 current_milestone read; resume_detection and execute_loop checkpoint updates use resolveActiveMilestoneIndex; post_loop advances active_gsd_milestone to next milestone's gsd_milestone_id - next.md: load_state uses resolveActiveMilestoneIndex for milestone data lookup instead of current_milestone - 1 - status.md: load_project resolves active index via node call and exposes active_milestone_idx in JSON output alongside legacy field - run.md: post_triage_update milestone context lookup iterates all milestones via node instead of python3 current_milestone read Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Before creating a worktree, detect if the issue belongs to a non-active GSD milestone. gsd:quick issues proceed in isolation with a note. gsd:plan-phase issues warn and offer switch/continue/abort options. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
For Fresh state, replaces shallow gather_inputs with structured intake capturing RAW_IDEA to .mgw/vision-draft.md, then spawns vision-researcher Task agent to produce domain analysis in .mgw/vision-research.json. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
For each maps-to link in cross-refs.json, verify the GSD milestone ID exists in .planning/ROADMAP.md or .planning/MILESTONES.md. Flags missing GSD milestones in the sync report. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Structured 8-round (soft cap) / 15-round (hard cap) questioning loop that presents research-informed questions, captures answers to .mgw/vision-draft.md with key decisions extracted inline. User can exit early with 'done' or extend past soft cap. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After advancing active_gsd_milestone in post_loop, verify next milestone's GSD linkage and ROADMAP.md consistency. Unlinked milestones prompt user to run gsd:new-milestone + mgw:project extend. In extend mode of mgw:project, report GSD linkage status for each newly added milestone so users know to run gsd:new-milestone before executing the next milestone. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
vision_synthesis: spawns vision-synthesizer to produce .mgw/vision-brief.json with full structured Vision Brief (MoSCoW features, personas, scope). Includes user review loop with accept/revise/dig-deeper options. vision_condense: spawns vision-condenser to produce .mgw/vision-handoff.md, a structured context document for the gsd:new-project Task spawn. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
spawn_gsd_new_project step reads .mgw/vision-handoff.md and spawns a gsd:new-project agent with the full Vision Brief as context prefix. Verifies .planning/PROJECT.md and ROADMAP.md are created, then proceeds to milestone_mapper to create GitHub milestones. Completes the Vision Collaboration Cycle (Milestone B). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mgw:assign now resolves the assignee's GitHub ID and builds their noreply
tag ({id}+{login}@users.noreply.github.com), stored as `coauthor` in the
active state file. Falls back to project.json project.coauthor default.
Co-Authored-By: Stephen Miller <21005207+snipcodeit@users.noreply.github.com>
3d8426c to
90f2119
Compare
…e schema readers Every command that touches .mgw/ calls validate_and_load from state.md, but migrateProjectState() was defined in state.cjs and never invoked anywhere. Existing project.json files on legacy schema would never gain the new fields (active_gsd_milestone, gsd_milestone_id, gsd_state, roadmap_archived_at), causing resolveActiveMilestoneIndex() to silently fall through to -1. Changes: - validate_and_load step 4: call migrateProjectState() non-blocking on startup for any command that finds an existing project.json - "Read Project State" snippet: replace python3 current_milestone read with resolveActiveMilestoneIndex() — handles both new and legacy schema - "Read Milestone Issues" snippet: use resolveActiveMilestoneIndex() in node - "Update Issue Pipeline Stage" snippet: use resolveActiveMilestoneIndex() - "Advance Current Milestone" snippet: use active_gsd_milestone string with legacy current_milestone fallback (matching the pattern in milestone.md) Co-Authored-By: snipcodeit <snipcodeit@users.noreply.github.com>
…gned extend prompt
Bug 1 — milestone_mapper source mismatch on Fresh path:
The Fresh path (vision cycle → spawn_gsd_new_project) creates .planning/ROADMAP.md
and .planning/PROJECT.md, then falls through to milestone_mapper. But milestone_mapper
reads .mgw/alignment-report.json, which only exists when align_from_gsd ran (GSD-Only
path). Fresh path never produces it, causing a read failure at milestone_mapper.
Fix: add step 4b to spawn_gsd_new_project — synthesizes alignment-report.json from
the freshly created ROADMAP.md and PROJECT.md using inline python3 parsing. Extracts
project name, description, milestone name, and phase list. milestone_mapper now receives
consistent input regardless of which path reached it.
Bug 2 — Aligned state exits cold with no mid-project extend path:
Aligned STATE_CLASS displayed status info then exit 0. A user who wants to add new
milestones while still working on existing ones had no path in — Extend state only
triggered when ALL milestones are complete.
Fix: replace exit 0 with interactive read prompt offering three choices:
1) Proceed with /mgw:milestone (exit)
2) Add new milestones — sets EXTEND_MODE=true, computes EXISTING_MILESTONE_COUNT
and EXISTING_PHASE_COUNT, falls through to gather_inputs without exiting
3) View full status (exit)
Both fixes applied identically to commands/project.md and .claude/commands/mgw/project.md.
Co-Authored-By: snipcodeit <snipcodeit@users.noreply.github.com>
…ck against live labels
Bug 1 — milestone switch writes project.json without validating ROADMAP.md:
Cross-milestone option 1 ("switch active milestone") updated active_gsd_milestone in
project.json but left .planning/ROADMAP.md pointing to the old milestone. A passive
advisory was the only guard, meaning plan-phase issues could execute against the wrong
ROADMAP.md context with no enforcement.
Fix: after the node -e write, immediately check ROADMAP.md for the new GSD ID:
- match → confirm and proceed
- mismatch → HARD BLOCK: rollback active_gsd_milestone to previous value, tell user
to run /gsd:new-milestone first, exit 0
- missing → HARD BLOCK: same rollback and instructions
Bug 2 — gsd:quick cross-milestone bypass trusts stale project.json route:
The isolation:* case (gsd:quick in a non-active milestone) granted a silent bypass based
on the GSD_ROUTE value stored in project.json at triage time. If the issue was re-labeled
after triage or the route was recorded incorrectly, the bypass was unconditional.
Fix: before granting isolation exemption, fetch live GitHub labels and grep for
gsd-route:quick / gsd:quick / quick patterns:
- confirmed → issue the isolation note (updated to say "Confirmed via live labels")
- mismatch → drop into a 3-option prompt identical to the warn:* case:
1) Switch active milestone + ROADMAP.md validation + rollback logic
2) Re-triage the issue (/mgw:issue N)
3) Abort
Both fixes applied identically to commands/run.md and .claude/commands/mgw/run.md.
Co-Authored-By: snipcodeit <snipcodeit@users.noreply.github.com>
…GW v3 architecture) - Vision Collaboration Cycle (6-stage Fresh path in mgw:project) - 5-signal state detection matrix (P/R/S/M/G → Fresh/GSD-Only/Aligned/Diverged/Extend) - diagnosing pipeline stage (gsd:diagnose-issues route) - maps-to link type (milestone:N ↔ gsd-milestone:id) and sync consistency check - project.json v3 schema fields (active_gsd_milestone, gsd_milestone_id, gsd_state, etc.) - migrateProjectState / resolveActiveMilestoneIndex in lib/state.cjs - Cross-milestone detection and ROADMAP.md enforcement in mgw:run - Failed-issue recovery (Retry/Skip/Abort) and next-milestone GSD linkage check in mgw:milestone - Vision agents (researcher, synthesizer, condenser) and alignment/drift agents in agent table - Add .playwright-mcp/, dist/, node_modules/ to .gitignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Full MGW v3 architecture implementation. What started as a foundation repair now covers state-aware project initialization, a 6-stage vision collaboration cycle for fresh projects, and multi-milestone GSD tracking.
Originally landed (Phase 1 + Phase 2)
Milestone A — State Detection + Alignment (issues #103–107, closed)
Milestone B — Vision Collaboration Cycle (issues #108–112, closed)
Milestone C — Multi-Milestone Tracking (issues #113–116, closed)
project.json Schema Delta
State Sync
Test Plan
Closes #100