Spaces:
Runtime error
Runtime error
File size: 30,098 Bytes
a6b96c2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 | <purpose>
Mark a shipped version (v1.0, v1.1, v2.0) as complete. Creates historical record in MILESTONES.md, performs full PROJECT.md evolution review, reorganizes ROADMAP.md with milestone groupings, and tags the release in git.
</purpose>
<required_reading>
1. templates/milestone.md
2. templates/milestone-archive.md
3. `.planning/ROADMAP.md`
4. `.planning/REQUIREMENTS.md`
5. `.planning/PROJECT.md`
</required_reading>
<archival_behavior>
When a milestone completes:
1. Extract full milestone details to `.planning/milestones/v[X.Y]-ROADMAP.md`
2. Archive requirements to `.planning/milestones/v[X.Y]-REQUIREMENTS.md`
3. Update ROADMAP.md β overwrite in place with milestone grouping (preserve Backlog section)
4. Safety commit archive files + updated ROADMAP.md, then `git rm REQUIREMENTS.md` (fresh for next milestone)
5. Perform full PROJECT.md evolution review
6. Offer to create next milestone inline
7. Archive UI artifacts (`*-UI-SPEC.md`, `*-UI-REVIEW.md`) alongside other phase documents
8. Clean up `.planning/ui-reviews/` screenshot files (binary assets, never archived)
**Context Efficiency:** Archives keep ROADMAP.md constant-size and REQUIREMENTS.md milestone-scoped.
**ROADMAP archive** uses `templates/milestone-archive.md` β includes milestone header (status, phases, date), full phase details, milestone summary (decisions, issues, tech debt).
**REQUIREMENTS archive** contains all requirements marked complete with outcomes, traceability table with final status, notes on changed requirements.
</archival_behavior>
<process>
<step name="pre_close_artifact_audit">
Before proceeding with milestone close, run the comprehensive open artifact audit.
```bash
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "/Users/theogengineer/Projects/Multilingual-Absa/.opencode/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="/Users/theogengineer/Projects/Multilingual-Absa/.opencode/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
gsd_run query audit-open
```
If the output contains open items (any section with count > 0):
Display the full audit report to the user.
Then ask:
```
These items are open. Choose an action:
[R] Resolve β stop and fix items, then re-run /gsd-complete-milestone
[A] Acknowledge all β document as deferred and proceed with close
[C] Cancel β exit without closing
```
If user chooses [A] (Acknowledge):
1. Re-run `gsd-tools.cjs query audit-open --json` to get structured data
2. Write acknowledged items to STATE.md under `## Deferred Items` section:
```markdown
## Deferred Items
Items acknowledged and deferred at milestone close on {date}:
| Category | Item | Status |
|----------|------|--------|
| debug | {slug} | {status} |
| quick_task | {slug} | {status} |
...
```
Sanitize all slug and status values via `sanitizeForDisplay()` before writing. Never inject raw file content into STATE.md.
3. Record in MILESTONES.md entry: `Known deferred items at close: {count} (see STATE.md Deferred Items)`
4. Proceed with milestone close.
If output shows all clear (no open items): print `All artifact types clear.` and proceed.
SECURITY: Audit JSON output is structured data from the `audit-open` query handler (same JSON contract as legacy `gsd-tools.cjs audit-open`) β validated and sanitized at source. When writing to STATE.md, item slugs and descriptions are sanitized via `sanitizeForDisplay()` before inclusion. Never inject raw user-supplied content into STATE.md without sanitization.
</step>
<step name="verify_readiness">
**Use `roadmap analyze` for comprehensive readiness check:**
```bash
ROADMAP=$(gsd_run query roadmap.analyze)
```
This returns all phases with plan/summary counts and disk status. Use this to verify:
- Which phases belong to this milestone?
- All phases complete (all plans have summaries)? Check `disk_status === 'complete'` for each.
- `progress_percent` should be 100%.
**Requirements completion check (REQUIRED before presenting):**
Parse REQUIREMENTS.md traceability table:
- Count total v1 requirements vs checked-off (`[x]`) requirements
- Identify any non-Complete rows in the traceability table
Present:
```
Milestone: [Name, e.g., "v1.0 MVP"]
Includes:
- Phase 1: Foundation (2/2 plans complete)
- Phase 2: Authentication (2/2 plans complete)
- Phase 3: Core Features (3/3 plans complete)
- Phase 4: Polish (1/1 plan complete)
Total: {phase_count} phases, {total_plans} plans, all complete
Requirements: {N}/{M} v1 requirements checked off
```
**If requirements incomplete** (N < M):
```
β Unchecked Requirements:
- [ ] {REQ-ID}: {description} (Phase {X})
- [ ] {REQ-ID}: {description} (Phase {Y})
```
MUST present 3 options:
1. **Proceed anyway** β mark milestone complete with known gaps
2. **Run audit first** β `/gsd-audit-milestone` to assess gap severity
3. **Abort** β return to development
If user selects "Proceed anyway": note incomplete requirements in MILESTONES.md under `### Known Gaps` with REQ-IDs and descriptions.
<config-check>
```bash
cat .planning/config.json 2>/dev/null || true
```
</config-check>
<if mode="yolo">
```
β‘ Auto-approved: Milestone scope verification
[Show breakdown summary without prompting]
Proceeding to stats gathering...
```
Proceed to gather_stats.
</if>
<if mode="interactive" OR="custom with gates.confirm_milestone_scope true">
```
Ready to mark this milestone as shipped?
(yes / wait / adjust scope)
```
Wait for confirmation.
- "adjust scope": Ask which phases to include.
- "wait": Stop, user returns when ready.
</if>
</step>
<step name="gather_stats">
Calculate milestone statistics:
```bash
git log --oneline --grep="feat(" | head -20
git diff --stat FIRST_COMMIT..LAST_COMMIT | tail -1
find . -name "*.swift" -o -name "*.ts" -o -name "*.py" | xargs wc -l 2>/dev/null || true
git log --format="%ai" FIRST_COMMIT | tail -1
git log --format="%ai" LAST_COMMIT | head -1
```
Present:
```
Milestone Stats:
- Phases: [X-Y]
- Plans: [Z] total
- Tasks: [N] total (from phase summaries)
- Files modified: [M]
- Lines of code: [LOC] [language]
- Timeline: [Days] days ([Start] β [End])
- Git range: feat(XX-XX) β feat(YY-YY)
```
</step>
<step name="extract_accomplishments">
Extract one-liners from SUMMARY.md files using summary-extract:
```bash
# For each phase in milestone, extract one-liner
for summary in .planning/phases/*-*/*-SUMMARY.md; do
[ -e "$summary" ] || continue
gsd_run query summary-extract "$summary" --fields one_liner --pick one_liner
done
```
Extract 4-6 key accomplishments. Present:
```
Key accomplishments for this milestone:
1. [Achievement from phase 1]
2. [Achievement from phase 2]
3. [Achievement from phase 3]
4. [Achievement from phase 4]
5. [Achievement from phase 5]
```
</step>
<step name="create_milestone_entry">
**Note:** MILESTONES.md entry is now created automatically by `gsd-tools.cjs query milestone.complete` in the archive_milestone step. The entry includes version, date, phase/plan/task counts, and accomplishments extracted from SUMMARY.md files.
If additional details are needed (e.g., user-provided "Delivered" summary, git range, LOC stats), add them manually after the CLI creates the base entry.
</step>
<step name="evolve_project_full_review">
Full PROJECT.md evolution review at milestone completion.
Read all phase summaries:
```bash
cat .planning/phases/*-*/*-SUMMARY.md
```
**Full review checklist:**
1. **"What This Is" accuracy:**
- Compare current description to what was built
- Update if product has meaningfully changed
2. **Core Value check:**
- Still the right priority? Did shipping reveal a different core value?
- Update if the ONE thing has shifted
3. **Business Context check (only if the section is present):**
- Skip entirely if PROJECT.md has no `## Business Context` section
- Customer, revenue model, and success metric still accurate after shipping?
- Update any field that drifted; refresh the linked strategy doc reference if it moved
4. **Requirements audit:**
**Validated section:**
- All Active requirements shipped this milestone β Move to Validated
- Format: `- β [Requirement] β v[X.Y]`
**Active section:**
- Remove requirements moved to Validated
- Add new requirements for next milestone
- Keep unaddressed requirements
**Out of Scope audit:**
- Review each item β reasoning still valid?
- Remove irrelevant items
- Add requirements invalidated during milestone
5. **Context update:**
- Current codebase state (LOC, tech stack)
- User feedback themes (if any)
- Known issues or technical debt
6. **Key Decisions audit:**
- Extract all decisions from milestone phase summaries
- Add to Key Decisions table with outcomes
- Mark β Good, β οΈ Revisit, or β Pending
7. **Constraints check:**
- Any constraints changed during development? Update as needed
Update PROJECT.md inline. Update "Last updated" footer:
```markdown
---
*Last updated: [date] after v[X.Y] milestone*
```
**Example full evolution (v1.0 β v1.1 prep):**
Before:
```markdown
## What This Is
A real-time collaborative whiteboard for remote teams.
## Core Value
Real-time sync that feels instant.
## Requirements
### Validated
(None yet β ship to validate)
### Active
- [ ] Canvas drawing tools
- [ ] Real-time sync < 500ms
- [ ] User authentication
- [ ] Export to PNG
### Out of Scope
- Mobile app β web-first approach
- Video chat β use external tools
```
After v1.0:
```markdown
## What This Is
A real-time collaborative whiteboard for remote teams with instant sync and drawing tools.
## Core Value
Real-time sync that feels instant.
## Requirements
### Validated
- β Canvas drawing tools β v1.0
- β Real-time sync < 500ms β v1.0 (achieved 200ms avg)
- β User authentication β v1.0
### Active
- [ ] Export to PNG
- [ ] Undo/redo history
- [ ] Shape tools (rectangles, circles)
### Out of Scope
- Mobile app β web-first approach, PWA works well
- Video chat β use external tools
- Offline mode β real-time is core value
## Context
Shipped v1.0 with 2,400 LOC TypeScript.
Tech stack: Next.js, Supabase, Canvas API.
Initial user testing showed demand for shape tools.
```
**Step complete when:**
- [ ] "What This Is" reviewed and updated if needed
- [ ] Core Value verified as still correct
- [ ] Business Context checked (or confirmed absent)
- [ ] All shipped requirements moved to Validated
- [ ] New requirements added to Active for next milestone
- [ ] Out of Scope reasoning audited
- [ ] Context updated with current state
- [ ] All milestone decisions added to Key Decisions
- [ ] "Last updated" footer reflects milestone completion
</step>
<step name="reorganize_roadmap">
Update `.planning/ROADMAP.md` β group completed milestone phases:
```markdown
# Roadmap: [Project Name]
## Milestones
- β
**v1.0 MVP** β Phases 1-4 (shipped YYYY-MM-DD)
- π§ **v1.1 Security** β Phases 5-6 (in progress)
- π **v2.0 Redesign** β Phases 7-10 (planned)
## Phases
<details>
<summary>β
v1.0 MVP (Phases 1-4) β SHIPPED YYYY-MM-DD</summary>
- [x] Phase 1: Foundation (2/2 plans) β completed YYYY-MM-DD
- [x] Phase 2: Authentication (2/2 plans) β completed YYYY-MM-DD
- [x] Phase 3: Core Features (3/3 plans) β completed YYYY-MM-DD
- [x] Phase 4: Polish (1/1 plan) β completed YYYY-MM-DD
</details>
### π§ v[Next] [Name] (In Progress / Planned)
- [ ] Phase 5: [Name] ([N] plans)
- [ ] Phase 6: [Name] ([N] plans)
## Progress
| Phase | Milestone | Plans Complete | Status | Completed |
| ----------------- | --------- | -------------- | ----------- | ---------- |
| 1. Foundation | v1.0 | 2/2 | Complete | YYYY-MM-DD |
| 2. Authentication | v1.0 | 2/2 | Complete | YYYY-MM-DD |
| 3. Core Features | v1.0 | 3/3 | Complete | YYYY-MM-DD |
| 4. Polish | v1.0 | 1/1 | Complete | YYYY-MM-DD |
| 5. Security Audit | v1.1 | 0/1 | Not started | - |
| 6. Hardening | v1.1 | 0/2 | Not started | - |
```
</step>
<step name="archive_milestone">
**Delegate archival to `gsd-tools.cjs query milestone.complete`:**
```bash
ARCHIVE=$(gsd_run query milestone.complete "v[X.Y]" --name "[Milestone Name]")
```
The CLI handles:
- Creating `.planning/milestones/` directory
- Archiving ROADMAP.md to `milestones/v[X.Y]-ROADMAP.md`
- Archiving REQUIREMENTS.md to `milestones/v[X.Y]-REQUIREMENTS.md` with archive header
- Moving audit file to milestones if it exists
- Creating/appending MILESTONES.md entry with accomplishments from SUMMARY.md files
- Updating STATE.md (status, last activity)
Extract from result: `version`, `date`, `phases`, `plans`, `tasks`, `accomplishments`, `archived`.
Verify: `β
Milestone archived to .planning/milestones/`
**Phase archival (optional):** After archival completes, ask the user:
**Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `question` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-the agent runtimes (OpenAI Codex, Gemini CLI, etc.) where `question` is not available.
question(header="Archive Phases", question="Archive phase directories to milestones/?", options: "Yes β move to milestones/v[X.Y]-phases/" | "Skip β keep phases in place")
If "Yes": move phase directories to the milestone archive:
```bash
mkdir -p .planning/milestones/v[X.Y]-phases
# For each phase directory in .planning/phases/:
mv .planning/phases/{phase-dir} .planning/milestones/v[X.Y]-phases/
```
Verify: `β
Phase directories archived to .planning/milestones/v[X.Y]-phases/`
If "Skip": Phase directories remain in `.planning/phases/` as raw execution history. Use `/gsd-cleanup` later to archive retroactively.
After archival, the AI still handles:
- Reorganizing ROADMAP.md with milestone grouping (requires judgment) β overwrite in place after extracting Backlog section
- Full PROJECT.md evolution review (requires understanding)
- Safety commit of archive files + updated ROADMAP.md, then `git rm .planning/REQUIREMENTS.md`
- These are NOT fully delegated because they require AI interpretation of content
</step>
<step name="reorganize_roadmap_and_delete_originals">
After `milestone complete` has archived, reorganize ROADMAP.md with milestone groupings, then commit archives as a safety checkpoint before removing originals.
**Backlog preservation β do this FIRST before rewriting ROADMAP.md:**
Extract the Backlog section from the current ROADMAP.md before making any changes:
```bash
# Extract lines under ## Backlog through end of file (or next ## section)
BACKLOG_SECTION=$(awk '/^## Backlog/{found=1} found{print}' .planning/ROADMAP.md)
```
If `$BACKLOG_SECTION` is empty, there is no Backlog section β skip silently.
**Reorganize ROADMAP.md** β overwrite in place (do NOT delete first) with milestone groupings:
```markdown
# Roadmap: [Project Name]
## Milestones
- β
**v1.0 MVP** β Phases 1-4 (shipped YYYY-MM-DD)
- π§ **v1.1 Security** β Phases 5-6 (in progress)
## Phases
<details>
<summary>β
v1.0 MVP (Phases 1-4) β SHIPPED YYYY-MM-DD</summary>
- [x] Phase 1: Foundation (2/2 plans) β completed YYYY-MM-DD
- [x] Phase 2: Authentication (2/2 plans) β completed YYYY-MM-DD
</details>
```
**Re-append Backlog section after the rewrite** (only if `$BACKLOG_SECTION` was non-empty):
Append the extracted Backlog content verbatim to the end of the newly written ROADMAP.md. This ensures 999.x backlog items are never silently dropped during milestone reorganization.
**Safety commit β commit archive files BEFORE deleting any originals:**
```bash
gsd_run query commit "chore: archive v[X.Y] milestone files" --files .planning/milestones/v[X.Y]-ROADMAP.md .planning/milestones/v[X.Y]-REQUIREMENTS.md .planning/milestones/v[X.Y]-MILESTONE-AUDIT.md .planning/MILESTONES.md .planning/PROJECT.md .planning/STATE.md .planning/ROADMAP.md
```
This creates a durable checkpoint in git history. If anything fails after this point, the working tree can be reconstructed from git.
**Remove REQUIREMENTS.md via git rm** (preserves history, stages deletion atomically):
```bash
git rm .planning/REQUIREMENTS.md
```
</step>
<step name="write_retrospective">
**Append to living retrospective:**
Check for existing retrospective:
```bash
ls .planning/RETROSPECTIVE.md 2>/dev/null || true
```
**If exists:** Read the file, append new milestone section before the "## Cross-Milestone Trends" section.
**If doesn't exist:** Create from template at `/Users/theogengineer/Projects/Multilingual-Absa/.opencode/gsd-core/templates/retrospective.md`.
**Gather retrospective data:**
1. From SUMMARY.md files: Extract key deliverables, one-liners, tech decisions
2. From VERIFICATION.md files: Extract verification scores, gaps found
3. From UAT.md files: Extract test results, issues found
4. From git log: Count commits, calculate timeline
5. From the milestone work: Reflect on what worked and what didn't
**Write the milestone section:**
```markdown
## Milestone: v{version} β {name}
**Shipped:** {date}
**Phases:** {phase_count} | **Plans:** {plan_count}
### What Was Built
{Extract from SUMMARY.md one-liners}
### What Worked
{Patterns that led to smooth execution}
### What Was Inefficient
{Missed opportunities, rework, bottlenecks}
### Patterns Established
{New conventions discovered during this milestone}
### Key Lessons
{Specific, actionable takeaways}
### Cost Observations
- Model mix: {X}% opus, {Y}% sonnet, {Z}% haiku
- Sessions: {count}
- Notable: {efficiency observation}
```
**Update cross-milestone trends:**
If the "## Cross-Milestone Trends" section exists, update the tables with new data from this milestone.
**Commit:**
```bash
gsd_run query commit "docs: update retrospective for v${VERSION}" --files .planning/RETROSPECTIVE.md
```
</step>
<step name="update_state">
Most STATE.md updates were handled by `milestone complete`, but verify and update remaining fields:
**Project Reference:**
```markdown
## Project Reference
See: .planning/PROJECT.md (updated [today])
**Core value:** [Current core value from PROJECT.md]
**Current focus:** [Next milestone or "Planning next milestone"]
```
**Accumulated Context:**
- Clear decisions summary (full log in PROJECT.md)
- Clear resolved blockers
- Keep open blockers for next milestone
</step>
<step name="handle_branches">
Check branching strategy and offer merge options.
Use `init milestone-op` for context, or load config directly:
```bash
INIT=$(gsd_run query init.execute-phase "1")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
Extract `branching_strategy`, `phase_branch_template`, `milestone_branch_template`, and `commit_docs` from init JSON.
Detect base branch:
```bash
BASE_BRANCH=$(gsd_run query git.base-branch)
```
**If "none":** Skip to git_tag.
**For "phase" strategy:**
```bash
BRANCH_PREFIX=$(echo "$PHASE_BRANCH_TEMPLATE" | sed 's/{.*//')
PHASE_BRANCHES=$(git branch --list "${BRANCH_PREFIX}*" 2>/dev/null | sed 's/^\*//' | tr -d ' ')
```
**For "milestone" strategy:**
```bash
BRANCH_PREFIX=$(echo "$MILESTONE_BRANCH_TEMPLATE" | sed 's/{.*//')
MILESTONE_BRANCH=$(git branch --list "${BRANCH_PREFIX}*" 2>/dev/null | sed 's/^\*//' | tr -d ' ' | head -1)
```
**If no branches found:** Skip to git_tag.
**If branches exist:**
```
## Git Branches Detected
Branching strategy: {phase/milestone}
Branches: {list}
Options:
1. **Merge to main** β Merge branch(es) to main
2. **Delete without merging** β Already merged or not needed
3. **Keep branches** β Leave for manual handling
```
question with options: Squash merge (Recommended), Merge with history, Delete without merging, Keep branches.
**Squash merge:**
```bash
CURRENT_BRANCH=$(git branch --show-current)
git checkout ${BASE_BRANCH}
if [ "$BRANCHING_STRATEGY" = "phase" ]; then
for branch in $PHASE_BRANCHES; do
git merge --squash "$branch"
# Strip .planning/ from staging if commit_docs is false
if [ "$COMMIT_DOCS" = "false" ]; then
git reset HEAD .planning/ 2>/dev/null || true
fi
git commit -m "feat: $branch for v[X.Y]"
done
fi
if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
git merge --squash "$MILESTONE_BRANCH"
# Strip .planning/ from staging if commit_docs is false
if [ "$COMMIT_DOCS" = "false" ]; then
git reset HEAD .planning/ 2>/dev/null || true
fi
git commit -m "feat: $MILESTONE_BRANCH for v[X.Y]"
fi
git checkout "$CURRENT_BRANCH"
```
**Merge with history:**
```bash
CURRENT_BRANCH=$(git branch --show-current)
git checkout ${BASE_BRANCH}
if [ "$BRANCHING_STRATEGY" = "phase" ]; then
for branch in $PHASE_BRANCHES; do
git merge --no-ff --no-commit "$branch"
# Strip .planning/ from staging if commit_docs is false
if [ "$COMMIT_DOCS" = "false" ]; then
git reset HEAD .planning/ 2>/dev/null || true
fi
git commit -m "Merge branch '$branch' for v[X.Y]"
done
fi
if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
git merge --no-ff --no-commit "$MILESTONE_BRANCH"
# Strip .planning/ from staging if commit_docs is false
if [ "$COMMIT_DOCS" = "false" ]; then
git reset HEAD .planning/ 2>/dev/null || true
fi
git commit -m "Merge branch '$MILESTONE_BRANCH' for v[X.Y]"
fi
git checkout "$CURRENT_BRANCH"
```
**Delete without merging:**
```bash
if [ "$BRANCHING_STRATEGY" = "phase" ]; then
for branch in $PHASE_BRANCHES; do
git branch -d "$branch" 2>/dev/null || git branch -D "$branch"
done
fi
if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
git branch -d "$MILESTONE_BRANCH" 2>/dev/null || git branch -D "$MILESTONE_BRANCH"
fi
```
**Keep branches:** Report "Branches preserved for manual handling"
</step>
<step name="git_tag">
<config-check>
Read `git.create_tag` via `gsd-tools.cjs query config-get git.create_tag 2>/dev/null || echo "true"`.
If the result is `false` β skip this step entirely and proceed to `git_commit_milestone`.
</config-check>
Create git tag:
```bash
# Pre-check: skip if tag already exists (prevents silent failure on retry)
if git rev-parse "v[X.Y]" >/dev/null 2>&1; then echo "Tag v[X.Y] already exists, skipping"; exit 0; fi
git tag -a v[X.Y] -m "v[X.Y] [Name]
Delivered: [One sentence]
Key accomplishments:
- [Item 1]
- [Item 2]
- [Item 3]
See .planning/MILESTONES.md for full details."
```
Confirm: "Tagged: v[X.Y]"
Ask: "Push tag to remote? (y/n)"
If yes:
```bash
git push origin v[X.Y]
```
</step>
<step name="git_commit_milestone">
Commit the REQUIREMENTS.md deletion (archive files and ROADMAP.md were already committed in the safety commit in `reorganize_roadmap_and_delete_originals`).
```bash
git commit -m "chore: remove REQUIREMENTS.md for v[X.Y] milestone"
```
Confirm: "Committed: chore: remove REQUIREMENTS.md for v[X.Y] milestone"
</step>
<step name="offer_next">
```
β
Milestone v[X.Y] [Name] complete
Shipped:
- [N] phases ([M] plans, [P] tasks)
- [One sentence of what shipped]
Archived:
- milestones/v[X.Y]-ROADMAP.md
- milestones/v[X.Y]-REQUIREMENTS.md
Summary: .planning/MILESTONES.md
Tag: v[X.Y]
---
## βΆ Next Up β [${PROJECT_CODE}] ${PROJECT_TITLE}
**Start Next Milestone** β questioning β research β requirements β roadmap
`/clear` then:
`/gsd-new-milestone`
---
```
</step>
</process>
<milestone_naming>
**Version conventions:**
- **v1.0** β Initial MVP
- **v1.1, v1.2** β Minor updates, new features, fixes
- **v2.0, v3.0** β Major rewrites, breaking changes, new direction
**Names:** Short 1-2 words (v1.0 MVP, v1.1 Security, v1.2 Performance, v2.0 Redesign).
</milestone_naming>
<what_qualifies>
**Create milestones for:** Initial release, public releases, major feature sets shipped, before archiving planning.
**Don't create milestones for:** Every phase completion (too granular), work in progress, internal dev iterations (unless truly shipped).
Heuristic: "Is this deployed/usable/shipped?" If yes β milestone. If no β keep working.
</what_qualifies>
<success_criteria>
Milestone completion is successful when:
- [ ] Pre-close artifact audit run and output shown to user
- [ ] Deferred items recorded in STATE.md if user acknowledged
- [ ] Known deferred items count noted in MILESTONES.md entry
- [ ] MILESTONES.md entry created with stats and accomplishments
- [ ] PROJECT.md full evolution review completed
- [ ] All shipped requirements moved to Validated in PROJECT.md
- [ ] Key Decisions updated with outcomes
- [ ] ROADMAP.md Backlog section extracted before rewrite, re-appended after (skipped if absent)
- [ ] ROADMAP.md reorganized with milestone grouping (overwritten in place, not deleted)
- [ ] Roadmap archive created (milestones/v[X.Y]-ROADMAP.md)
- [ ] Requirements archive created (milestones/v[X.Y]-REQUIREMENTS.md)
- [ ] Safety commit made (archive files + updated ROADMAP.md) BEFORE deleting REQUIREMENTS.md
- [ ] REQUIREMENTS.md removed via `git rm` (fresh for next milestone, history preserved)
- [ ] STATE.md updated with fresh project reference
- [ ] Git tag created (v[X.Y]) (if `git.create_tag` enabled)
- [ ] Milestone commit made (includes archive files and deletion)
- [ ] Requirements completion checked against REQUIREMENTS.md traceability table
- [ ] Incomplete requirements surfaced with proceed/audit/abort options
- [ ] Known gaps recorded in MILESTONES.md if user proceeded with incomplete requirements
- [ ] RETROSPECTIVE.md updated with milestone section
- [ ] Cross-milestone trends updated
- [ ] User knows next step (/gsd-new-milestone)
</success_criteria>
|