diff --git a/commands/gsd/milestone-summary.md b/commands/gsd/milestone-summary.md new file mode 100644 index 000000000..bd379c158 --- /dev/null +++ b/commands/gsd/milestone-summary.md @@ -0,0 +1,40 @@ +--- +name: gsd:milestone-summary +description: Generate a comprehensive project summary from milestone artifacts for team onboarding and review +argument-hint: "[version]" +allowed-tools: + - Read + - Write + - Bash + - Grep + - Glob +--- + + +Generate a structured milestone summary for team onboarding and project review. Reads completed milestone artifacts (ROADMAP, REQUIREMENTS, CONTEXT, SUMMARY, VERIFICATION files) and produces a human-friendly overview of what was built, how, and why. + +Purpose: Enable new team members to understand a completed project by reading one document and asking follow-up questions. +Output: MILESTONE_SUMMARY written to `.planning/reports/`, presented inline, optional interactive Q&A. + + + +@~/.claude/get-shit-done/workflows/milestone-summary.md + + + +**Project files:** +- `.planning/ROADMAP.md` +- `.planning/PROJECT.md` +- `.planning/STATE.md` +- `.planning/RETROSPECTIVE.md` +- `.planning/milestones/v{version}-ROADMAP.md` (if archived) +- `.planning/milestones/v{version}-REQUIREMENTS.md` (if archived) +- `.planning/phases/*-*/` (SUMMARY.md, VERIFICATION.md, CONTEXT.md) + +**User input:** +- Version: $ARGUMENTS (optional — defaults to current/latest milestone) + + + +Read and execute the milestone-summary workflow from @~/.claude/get-shit-done/workflows/milestone-summary.md end-to-end. + diff --git a/get-shit-done/workflows/milestone-summary.md b/get-shit-done/workflows/milestone-summary.md new file mode 100644 index 000000000..75740f270 --- /dev/null +++ b/get-shit-done/workflows/milestone-summary.md @@ -0,0 +1,190 @@ +# Milestone Summary Workflow + +Generate a comprehensive, human-friendly project summary from completed milestone artifacts. +Designed for team onboarding — a new contributor can read the output and understand the entire project. + +--- + +## Step 1: Resolve Version + +```bash +VERSION="$ARGUMENTS" +``` + +If `$ARGUMENTS` is empty: +1. Check `.planning/STATE.md` for current milestone version +2. Check `.planning/milestones/` for the latest archived version +3. If neither found, check if `.planning/ROADMAP.md` exists (project may be mid-milestone) +4. If nothing found: error "No milestone found. Run /gsd:new-project or /gsd:new-milestone first." + +Set `VERSION` to the resolved version (e.g., "1.0"). + +## Step 2: Locate Artifacts + +Determine whether the milestone is **archived** or **current**: + +**Archived milestone** (`.planning/milestones/v{VERSION}-ROADMAP.md` exists): +``` +ROADMAP_PATH=".planning/milestones/v${VERSION}-ROADMAP.md" +REQUIREMENTS_PATH=".planning/milestones/v${VERSION}-REQUIREMENTS.md" +AUDIT_PATH=".planning/v${VERSION}-MILESTONE-AUDIT.md" +``` + +**Current/in-progress milestone** (no archive yet): +``` +ROADMAP_PATH=".planning/ROADMAP.md" +REQUIREMENTS_PATH=".planning/REQUIREMENTS.md" +AUDIT_PATH=".planning/v${VERSION}-MILESTONE-AUDIT.md" +``` + +**Always available:** +``` +PROJECT_PATH=".planning/PROJECT.md" +RETRO_PATH=".planning/RETROSPECTIVE.md" +STATE_PATH=".planning/STATE.md" +``` + +Read all files that exist. Missing files are fine — the summary adapts to what's available. + +## Step 3: Discover Phase Artifacts + +Find all phase directories: + +```bash +gsd-tools.cjs init progress +``` + +This returns phase metadata. For each phase in the milestone scope: + +- Read `{phase_dir}/{padded}-SUMMARY.md` if it exists — extract `one_liner`, `accomplishments`, `decisions` +- Read `{phase_dir}/{padded}-VERIFICATION.md` if it exists — extract status, gaps, deferred items +- Read `{phase_dir}/{padded}-CONTEXT.md` if it exists — extract key decisions from `` section +- Read `{phase_dir}/{padded}-RESEARCH.md` if it exists — note what was researched + +Track which phases have which artifacts. + +## Step 4: Gather Git Statistics + +```bash +# If milestone is tagged +git log v${VERSION} --oneline | wc -l +git diff --stat $(git log --format=%H --reverse v${VERSION} | head -1)..v${VERSION} + +# If not tagged, use date range from STATE.md or earliest phase commit +git log --oneline --since="" | wc -l +``` + +Extract: +- Total commits in milestone +- Files changed, insertions, deletions +- Timeline (start date → end date) +- Contributors (from git log authors) + +## Step 5: Generate Summary Document + +Write to `.planning/reports/MILESTONE_SUMMARY-v${VERSION}.md`: + +```markdown +# Milestone v{VERSION} — Project Summary + +**Generated:** {date} +**Purpose:** Team onboarding and project review + +--- + +## 1. Project Overview + +{From PROJECT.md: "What This Is", core value proposition, target users} +{If mid-milestone: note which phases are complete vs in-progress} + +## 2. Architecture & Technical Decisions + +{From CONTEXT.md files across phases: key technical choices} +{From SUMMARY.md decisions: patterns, libraries, frameworks chosen} +{From PROJECT.md: tech stack if documented} + +Present as a bulleted list of decisions with brief rationale: +- **Decision:** {what was chosen} + - **Why:** {rationale from CONTEXT.md} + - **Phase:** {which phase made this decision} + +## 3. Phases Delivered + +| Phase | Name | Status | One-Liner | +|-------|------|--------|-----------| +{For each phase: number, name, status (complete/in-progress/planned), one_liner from SUMMARY.md} + +## 4. Requirements Coverage + +{From REQUIREMENTS.md: list each requirement with status} +- ✅ {Requirement met} +- ⚠️ {Requirement partially met — note gap} +- ❌ {Requirement not met — note reason} + +{If MILESTONE-AUDIT.md exists: include audit verdict} + +## 5. Key Decisions Log + +{Aggregate from all CONTEXT.md sections} +{Each decision with: ID, description, phase, rationale} + +## 6. Tech Debt & Deferred Items + +{From VERIFICATION.md files: gaps found, anti-patterns noted} +{From RETROSPECTIVE.md: lessons learned, what to improve} +{From CONTEXT.md sections: ideas parked for later} + +## 7. Getting Started + +{Entry points for new contributors:} +- **Run the project:** {from PROJECT.md or SUMMARY.md} +- **Key directories:** {from codebase structure} +- **Tests:** {test command from PROJECT.md or CLAUDE.md} +- **Where to look first:** {main entry points, core modules} + +--- + +## Stats + +- **Timeline:** {start} → {end} ({duration}) +- **Phases:** {count complete} / {count total} +- **Commits:** {count} +- **Files changed:** {count} (+{insertions} / -{deletions}) +- **Contributors:** {list} +``` + +## Step 6: Commit + +```bash +gsd-tools.cjs commit "docs(v${VERSION}): generate milestone summary for onboarding" \ + --files ".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md" +``` + +## Step 7: Present Summary + +Display the full summary document inline. + +## Step 8: Offer Interactive Mode + +After presenting the summary: + +> "Summary written to `.planning/reports/MILESTONE_SUMMARY-v{VERSION}.md`. +> +> I have full context from the build artifacts. Want to ask anything about the project? +> Architecture decisions, specific phases, requirements, tech debt — ask away." + +If the user asks questions: +- Answer from the artifacts already loaded (CONTEXT.md, SUMMARY.md, VERIFICATION.md, etc.) +- Reference specific files and decisions +- Stay grounded in what was actually built (not speculation) + +If the user is done: +- Suggest next steps: `/gsd:new-milestone`, `/gsd:progress`, or sharing the summary with the team + +## Step 9: Update STATE.md + +```bash +gsd-tools.cjs state record-session \ + --stopped-at "Milestone v${VERSION} summary generated" \ + --resume-file ".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md" +``` diff --git a/tests/milestone-summary.test.cjs b/tests/milestone-summary.test.cjs new file mode 100644 index 000000000..12d622fa6 --- /dev/null +++ b/tests/milestone-summary.test.cjs @@ -0,0 +1,114 @@ +/** + * GSD Milestone Summary Tests + * + * Validates the milestone-summary command and workflow files exist + * and follow expected patterns. Tests artifact discovery logic. + */ + +const { test, describe } = require('node:test'); +const assert = require('node:assert'); +const fs = require('fs'); +const path = require('path'); + +const repoRoot = path.resolve(__dirname, '..'); +const commandPath = path.join(repoRoot, 'commands', 'gsd', 'milestone-summary.md'); +const workflowPath = path.join(repoRoot, 'get-shit-done', 'workflows', 'milestone-summary.md'); + +describe('milestone-summary command', () => { + test('command file exists', () => { + assert.ok(fs.existsSync(commandPath), 'commands/gsd/milestone-summary.md should exist'); + }); + + test('command has correct frontmatter name', () => { + const content = fs.readFileSync(commandPath, 'utf-8'); + assert.ok(content.includes('name: gsd:milestone-summary'), 'should have correct command name'); + }); + + test('command references workflow in execution_context', () => { + const content = fs.readFileSync(commandPath, 'utf-8'); + assert.ok( + content.includes('workflows/milestone-summary.md'), + 'should reference the milestone-summary workflow' + ); + }); + + test('command accepts optional version argument', () => { + const content = fs.readFileSync(commandPath, 'utf-8'); + assert.ok(content.includes('argument-hint'), 'should have argument-hint'); + assert.ok(content.includes('[version]'), 'version should be optional (bracketed)'); + }); +}); + +describe('milestone-summary workflow', () => { + test('workflow file exists', () => { + assert.ok(fs.existsSync(workflowPath), 'workflows/milestone-summary.md should exist'); + }); + + test('workflow reads milestone artifacts', () => { + const content = fs.readFileSync(workflowPath, 'utf-8'); + const requiredArtifacts = [ + 'ROADMAP.md', + 'REQUIREMENTS.md', + 'PROJECT.md', + 'SUMMARY.md', + 'VERIFICATION.md', + 'CONTEXT.md', + 'RETROSPECTIVE.md', + ]; + for (const artifact of requiredArtifacts) { + assert.ok( + content.includes(artifact), + `workflow should reference ${artifact}` + ); + } + }); + + test('workflow writes to reports directory', () => { + const content = fs.readFileSync(workflowPath, 'utf-8'); + assert.ok( + content.includes('.planning/reports/MILESTONE_SUMMARY'), + 'should write summary to .planning/reports/' + ); + }); + + test('workflow has interactive Q&A mode', () => { + const content = fs.readFileSync(workflowPath, 'utf-8'); + assert.ok( + content.includes('Interactive Mode') || content.includes('ask anything'), + 'should offer interactive Q&A after summary' + ); + }); + + test('workflow handles both archived and current milestones', () => { + const content = fs.readFileSync(workflowPath, 'utf-8'); + assert.ok(content.includes('Archived milestone'), 'should handle archived milestones'); + assert.ok(content.includes('Current') || content.includes('in-progress'), 'should handle current milestones'); + }); + + test('workflow generates all 7 summary sections', () => { + const content = fs.readFileSync(workflowPath, 'utf-8'); + const sections = [ + 'Project Overview', + 'Architecture', + 'Phases Delivered', + 'Requirements Coverage', + 'Key Decisions', + 'Tech Debt', + 'Getting Started', + ]; + for (const section of sections) { + assert.ok( + content.includes(section), + `summary should include "${section}" section` + ); + } + }); + + test('workflow updates STATE.md', () => { + const content = fs.readFileSync(workflowPath, 'utf-8'); + assert.ok( + content.includes('state record-session'), + 'should update STATE.md via gsd-tools' + ); + }); +});