From 8fce09722287ad4077b672bf7140e4888b5be70c Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Fri, 3 Apr 2026 12:40:31 -0400 Subject: [PATCH] feat: add /gsd:analyze-dependencies command to detect phase dependencies (#1607) Analyzes ROADMAP.md phases for file overlap and semantic dependencies, then suggests Depends on entries before running /gsd:manager. Complements the files_modified overlap detection added in the executor (PR #1600). Closes #1530 --- commands/gsd/analyze-dependencies.md | 34 +++++++ docs/COMMANDS.md | 20 ++++ .../workflows/analyze-dependencies.md | 96 +++++++++++++++++++ tests/analyze-dependencies.test.cjs | 51 ++++++++++ 4 files changed, 201 insertions(+) create mode 100644 commands/gsd/analyze-dependencies.md create mode 100644 get-shit-done/workflows/analyze-dependencies.md create mode 100644 tests/analyze-dependencies.test.cjs diff --git a/commands/gsd/analyze-dependencies.md b/commands/gsd/analyze-dependencies.md new file mode 100644 index 000000000..944442138 --- /dev/null +++ b/commands/gsd/analyze-dependencies.md @@ -0,0 +1,34 @@ +--- +name: gsd:analyze-dependencies +description: Analyze phase dependencies and suggest Depends on entries for ROADMAP.md +allowed-tools: + - Read + - Write + - Bash + - Glob + - Grep + - AskUserQuestion +--- + +Analyze the phase dependency graph for the current milestone. For each phase pair, determine if there is a dependency relationship based on: +- File overlap (phases that modify the same files must be ordered) +- Semantic dependencies (a phase that uses an API built by another phase) +- Data flow (a phase that consumes output from another phase) + +Then suggest `Depends on` updates to ROADMAP.md. + + + +@~/.claude/get-shit-done/workflows/analyze-dependencies.md + + + +No arguments required. Requires an active milestone with ROADMAP.md. + +Run this command BEFORE `/gsd:manager` to fill in missing `Depends on` fields and prevent merge conflicts from unordered parallel execution. + + + +Execute the analyze-dependencies workflow from @~/.claude/get-shit-done/workflows/analyze-dependencies.md end-to-end. +Present dependency suggestions clearly and apply confirmed updates to ROADMAP.md. + diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md index 6f425cf76..2f2d6f1ff 100644 --- a/docs/COMMANDS.md +++ b/docs/COMMANDS.md @@ -410,6 +410,26 @@ Preview Claude's intended approach before planning. /gsd:list-phase-assumptions 2 # See assumptions for phase 2 ``` +### `/gsd:analyze-dependencies` + +Analyze phase dependencies and suggest `Depends on` entries for ROADMAP.md before running `/gsd:manager`. + +**Prerequisites:** `.planning/ROADMAP.md` exists +**Produces:** Dependency suggestion table; optionally updates `Depends on` fields in ROADMAP.md with confirmation + +**Run this before `/gsd:manager`** when phases have empty `Depends on` fields and you want to avoid merge conflicts from unordered parallel execution. + +```bash +/gsd:analyze-dependencies # Analyze all phases and suggest dependencies +``` + +**Detection methods:** +- File overlap — phases touching the same files/domains must be ordered +- Semantic dependencies — a phase that consumes an API or schema built by another phase +- Data flow — a phase that reads output produced by another phase + +--- + ### `/gsd:plan-milestone-gaps` Create phases to close gaps from milestone audit. diff --git a/get-shit-done/workflows/analyze-dependencies.md b/get-shit-done/workflows/analyze-dependencies.md new file mode 100644 index 000000000..376e31c9e --- /dev/null +++ b/get-shit-done/workflows/analyze-dependencies.md @@ -0,0 +1,96 @@ + +Analyze ROADMAP.md phases for dependency relationships before execution. Detect file overlap between phases, semantic API/data-flow dependencies, and suggest `Depends on` entries to prevent merge conflicts during parallel execution by `/gsd:manager`. + + + + +## 1. Load ROADMAP.md + +Read `.planning/ROADMAP.md`. If it does not exist, error: "No ROADMAP.md found — run `/gsd:new-project` first." + +Extract all phases. For each phase capture: +- Phase number and name +- Scope/Goal description +- Files listed in `Files` or `files_modified` fields (if present) +- Existing `Depends on` field value + +## 2. Infer Likely File Modifications + +For each phase without explicit `files_modified`, analyze the scope/goal description to infer which files will likely be modified. Use these heuristics: + +- **Database/schema phases** → migration files, schema definitions, model files +- **API/backend phases** → route files, controller files, service files, handler files +- **Frontend/UI phases** → component files, page files, style files +- **Auth phases** → middleware files, auth route files, session/token files +- **Config/infra phases** → config files, environment files, CI/CD files +- **Test phases** → test files, spec files, fixture files +- **Shared utility phases** → lib/utils files, shared type definitions + +Group phases by their inferred file domain (database, API, frontend, auth, config, shared). + +## 3. Detect Dependency Relationships + +For each pair of phases (A, B), check for dependency signals: + +### File Overlap Detection +If phases A and B will both modify files in the same domain or the same specific files, one must run before the other. The phase that *provides* the foundation runs first. + +### Semantic Dependency Detection +Read each phase's scope/goal for these patterns: +- Phase B mentions consuming, using, or calling something that Phase A creates/implements +- Phase B references an "API", "schema", "model", "endpoint", or "interface" that Phase A builds +- Phase B says "after X is complete", "once X is built", "using the X from Phase N" +- Phase B extends or modifies code that Phase A establishes + +### Data Flow Detection +- Phase A creates data structures, schemas, or types → Phase B consumes or transforms them +- Phase A seeds/migrates the database → Phase B reads from that database +- Phase A exposes an API contract → Phase B implements the client for that contract + +## 4. Build Dependency Table + +Output a dependency suggestion table: + +``` +Phase Dependency Analysis +========================= + +Phase N: + Scope: + Likely touches: + + Suggested dependencies: + → Depends on: — reason: + + Current "Depends on": +``` + +For phase pairs with no detected dependency, state: "No dependency detected between Phase X and Phase Y." + +## 5. Summarize Suggested Changes + +Show a consolidated diff of proposed ROADMAP.md `Depends on` changes: + +``` +Suggested ROADMAP.md updates: + Phase 3: add "Depends on: 1, 2" (file overlap: database schema) + Phase 5: add "Depends on: 3" (semantic: uses auth API from Phase 3) + Phase 4: no change needed (independent scope) +``` + +## 6. Confirm and Apply + +Ask the user: "Apply these `Depends on` suggestions to ROADMAP.md? (yes / no / edit)" + +- **yes** — Write all suggested `Depends on` entries to ROADMAP.md. Confirm each write. +- **no** — Print the suggestions as text only. User updates manually. +- **edit** — Present each suggestion individually with yes/no/skip per suggestion. + +When writing to ROADMAP.md: +- Locate the phase entry and add or update the `Depends on:` field +- Preserve all other phase content unchanged +- Do not reorder phases + +After applying: "ROADMAP.md updated. Run `/gsd:manager` to execute phases in the correct order." + + diff --git a/tests/analyze-dependencies.test.cjs b/tests/analyze-dependencies.test.cjs new file mode 100644 index 000000000..835827a7a --- /dev/null +++ b/tests/analyze-dependencies.test.cjs @@ -0,0 +1,51 @@ +const { test, describe, beforeEach, afterEach } = require('node:test'); +const assert = require('node:assert'); +const fs = require('fs'); +const path = require('path'); + +describe('analyze-dependencies command', () => { + test('command file exists', () => { + const p = path.join(__dirname, '..', 'commands', 'gsd', 'analyze-dependencies.md'); + assert.ok(fs.existsSync(p), 'commands/gsd/analyze-dependencies.md should exist'); + }); + + test('command file has description frontmatter', () => { + const p = path.join(__dirname, '..', 'commands', 'gsd', 'analyze-dependencies.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok(content.includes('description:'), 'Command file must have description frontmatter'); + }); + + test('workflow file exists', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'analyze-dependencies.md'); + assert.ok(fs.existsSync(p), 'workflows/analyze-dependencies.md should exist'); + }); + + test('workflow describes dependency analysis approach', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'analyze-dependencies.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok(content.includes('ROADMAP') || content.includes('phase'), + 'workflow should reference ROADMAP.md/phases'); + assert.ok( + content.includes('depends') || content.includes('Depends') || content.includes('dependency'), + 'workflow should reference dependency detection' + ); + }); + + test('workflow mentions file overlap detection', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'analyze-dependencies.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok( + content.includes('file') && (content.includes('overlap') || content.includes('conflict')), + 'workflow should mention file overlap/conflict detection' + ); + }); + + test('docs/COMMANDS.md references analyze-dependencies', () => { + const p = path.join(__dirname, '..', 'docs', 'COMMANDS.md'); + if (fs.existsSync(p)) { + const content = fs.readFileSync(p, 'utf-8'); + assert.ok(content.includes('analyze-dependencies'), + 'COMMANDS.md should document the new command'); + } + }); +});