diff --git a/.claude/commands/ddd/auto.md b/.claude/commands/ddd/auto.md deleted file mode 100644 index 509cc6de..00000000 --- a/.claude/commands/ddd/auto.md +++ /dev/null @@ -1,359 +0,0 @@ ---- -name: auto -description: Chain command - automated document-driven development flow. Detects project state and runs the appropriate chain for new or existing projects. -argument-hint: "[-y|--yes] [--skip-spec] [--skip-build] [--spec ] [--resume] \"project idea or task description\"" -allowed-tools: TodoWrite(*), Agent(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*) ---- - -## Auto Mode - -When `--yes` or `-y`: All sub-commands run in auto mode. Minimal human intervention. - -# DDD Auto Command (/ddd:auto) - -## Purpose - -Orchestrate the full document-driven development lifecycle. **Adapts to project state** — works for both new projects and existing codebases. - -## Flow Variants - -### Variant 1: New Project (no code, no spec) -``` -spec-generator → ddd:index-build → ddd:plan → ddd:execute → verify → ddd:sync -``` - -### Variant 2: Existing Project (has code, no spec) -``` -ddd:scan → ddd:plan → ddd:execute → verify → ddd:sync -``` - -### Variant 3: Existing Project with Spec (has code + spec) -``` -ddd:index-build → ddd:plan → ddd:execute → verify → ddd:sync -``` - -### Variant 4: Index Exists (has doc-index.json) -``` -ddd:plan → ddd:execute → verify → ddd:sync -``` - -## Flow Diagram - -``` -┌────────────────────────────────────────────────────────────┐ -│ /ddd:auto │ -│ │ -│ Stage 0: Detect Project State │ -│ ┌───────────────────────────────────┐ │ -│ │ has_codebase? has_spec? has_index?│ │ -│ └────────────┬──────────────────────┘ │ -│ │ │ -│ ┌──────────┼──────────────┐ │ -│ ▼ ▼ ▼ │ -│ No Code Code Only Code + Spec Index Exists │ -│ │ │ │ │ │ -│ ▼ │ │ │ │ -│ Stage 1 │ │ │ │ -│ Spec Gen │ │ │ │ -│ │ │ │ │ │ -│ ▼ │ ▼ │ │ -│ Stage 2a Stage 2b Stage 2a │ │ -│ index-build ddd:scan index-build │ │ -│ (Path A or Path B auto-detected) │ │ -│ │ │ │ -│ └───────────────────┬───────────────────┘ │ -│ ▼ │ -│ Stage 3: DDD Plan (enhanced) │ -│ (doc-index query + exploration + │ -│ clarification + task planning) │ -│ │ │ -│ ▼ │ -│ Stage 4: Execute │ -│ (ddd:execute = doc-aware execution) │ -│ │ │ -│ ▼ │ -│ Stage 4.5: Verify Gate │ -│ (convergence + build + lint + tests │ -│ → execution-manifest.json) │ -│ │ │ -│ PASS / WARN → continue │ -│ FAIL → ask user │ -│ │ │ -│ ▼ │ -│ Stage 5: Doc Sync │ -│ (auto-triggered with --from-manifest, │ -│ or manual /ddd:sync) │ -└────────────────────────────────────────────────────────────┘ -``` - -## Stage 0: Project State Detection - -Automatically detect project state to determine which stages to run: - -``` -Check 1: doc-index.json exists? → has_index -Check 2: SPEC-* directories exist? → has_spec -Check 3: Source code directories? → has_codebase -Check 4: project-tech.json exists? → has_tech_analysis -``` - -### Decision Matrix - -| has_codebase | has_spec | has_index | Action | -|:---:|:---:|:---:|--------| -| No | No | No | Stage 1 (spec-gen) → Stage 2a (index-build) → Stage 3-5 | -| No | Yes | No | Stage 2a (index-build) → Stage 3-5 | -| Yes | No | No | **Stage 2b (ddd:scan)** → Stage 3-5 | -| Yes | Yes | No | Stage 2a (index-build) → Stage 3-5 | -| Yes | * | Yes | **Skip to Stage 3** (index exists) | - -### Override Flags - -| Flag | Effect | -|------|--------| -| `--skip-spec` | Never run spec-generator | -| `--skip-build` | Never run index-build | -| `--spec ` | Use specific spec session, force Path A | -| `--from-scratch` | Rebuild index even if exists | - -## Stage 1: Specification (conditional) - -### Run When -- No codebase AND no spec AND `--skip-spec` not set -- User provides a new project idea (not an existing task description) - -### Skip When -- `--skip-spec` flag -- Codebase already exists (existing project) -- `--spec ` pointing to existing session - -### Execution -``` -Invoke /spec-generator with user input -→ Output: .workflow/.doc-index/specs/SPEC-{slug}-{date}/ -``` - -## Stage 2: Index Construction (conditional) - -### Run When -- `doc-index.json` does not exist -- OR `--from-scratch` flag - -### Route Selection - -``` -Has spec outputs → Stage 2a: /ddd:index-build (spec-first) -No spec, has code → Stage 2b: /ddd:scan (code-first) -``` - -### Stage 2a: /ddd:index-build (has spec) -``` -Invoke /ddd:index-build [-y] [-s ] -→ Output: doc-index.json from spec entities + code mapping -``` - -### Stage 2b: /ddd:scan (no spec, has code) -``` -Invoke /ddd:scan [-y] -→ Output: doc-index.json from code analysis + inferred features -``` - -### Skip When -- `--skip-build` flag -- `doc-index.json` exists AND NOT `--from-scratch` - - In this case, suggest `/ddd:update` for incremental refresh - -## Stage 3: Planning (always runs) - -### Execution - -``` -Invoke /ddd:plan [-y] "task description" -``` - -The enhanced `/ddd:plan` now performs: -1. Doc-index query (instant context from features, requirements, components, ADRs) -2. Doc-index-guided exploration (1-4 angles based on affected features) -3. Clarification (aggregate ambiguities from exploration + doc-index gaps) -4. Task planning (plan.json + TASK-*.json with doc_context traceability) -5. Handoff selection - -Output: -- `plan.json` — plan overview with doc_context -- `.task/TASK-*.json` — individual tasks with doc_context -- `exploration-{angle}.json` — exploration results (if Phase 2 ran) -- `planning-context.md` — legacy context package - -### Handoff Decision - -After planning, `/ddd:plan` presents execution options: - -| Option | Description | Auto-Select When | -|--------|-------------|-----------------| -| **ddd:execute** | Document-aware execution (recommended) | Default in ddd workflow | -| **lite-execute** | Standard execution (no doc awareness) | When doc traceability not needed | -| **direct** | Start coding with context | User prefers manual | -| **stop** | Just the plan context | Planning/research only | - -With `-y`: Auto-select `ddd:execute`. - -## Stage 4: Execution - -Based on Stage 3 handoff decision: - -| Mode | Delegates To | -|------|-------------| -| **ddd:execute** | `/ddd:execute --in-memory` with plan.json + doc-index enrichment | -| lite-execute | `/workflow:lite-execute` with plan.json path | -| direct | Output context package, developer works manually | -| stop | End here, no execution | - -### ddd:execute Features (when selected) -- Doc-enriched task prompts (feature context + component docs + ADR constraints) -- Per-batch impact verification (changes stay within planned scope) -- Result persistence (`TASK-*.result.json` per task, `execution-manifest.json` per session) -- Post-execution verify gate (Stage 4.5, unless `--skip-verify`) -- Post-completion auto-sync with manifest (Stage 5 triggered automatically) - -**Note**: When using `ddd:execute`, Stage 4.5 and Stage 5 are auto-triggered. For other modes, run Stage 5 manually. - -## Stage 4.5: Verify Gate - -Embedded within `ddd:execute` (Step 4.5). Runs after all batches complete, before doc sync. - -### Purpose - -Quality gate ensuring execution output is correct before committing to documentation updates. Prevents bad code from being "blessed" into the doc-index. - -### Checks Performed - -| Check | Description | Gate Behavior | -|-------|-------------|---------------| -| **Convergence** | Run `task.convergence.verification` for each task | FAIL if any critical task fails | -| **Build** | Run project build command (`tsc --noEmit`, etc.) | FAIL on build errors | -| **Lint** | Run project linter (`eslint`, etc.) | WARN only (non-blocking) | -| **Regression** | Run full test suite, compare to baseline | FAIL on new test failures | - -### Gate Results - -| Result | Action | -|--------|--------| -| **PASS** | All checks passed → proceed to Stage 5 | -| **WARN** | Non-critical issues (lint warnings) → proceed with warnings logged | -| **FAIL** | Critical issues → ask user: fix now / skip sync / abort | -| **FAIL + `-y`** | Log failures, set `error_state` in session, stop | - -### Output - -- `execution-manifest.json` — persisted to session folder, consumed by Stage 5 -- Contains: task results, files_modified (with task attribution), verify gate results - -## Stage 5: Post-Task Sync - -### Trigger -- **Auto**: `/ddd:execute` triggers `/ddd:sync --from-manifest` automatically after verify gate passes -- **Manual**: User runs `/ddd:sync` after completing work in direct/lite-execute mode -- **Resume**: `/ddd:auto --resume` after task completion - -### Execution -``` -# Auto mode (from ddd:execute): uses manifest for precise change tracking -Invoke /ddd:sync [-y] --task-id --from-manifest {session}/execution-manifest.json "task summary" - -# Manual mode (from direct/lite-execute): falls back to git diff -Invoke /ddd:sync [-y] [--task-id ] "task summary" - -→ Updates: doc-index.json, feature-maps/, tech-registry/, action-logs/ -``` - -## State Tracking - -### Session File: `.workflow/.doc-index/.auto-session.json` - -```json -{ - "session_id": "DAUTO-{timestamp}", - "input": "user's original input", - "detected_state": { - "has_codebase": true, - "has_spec": false, - "has_index": false, - "build_path": "code-first" - }, - "stages_completed": ["detect", "index-build", "plan"], - "current_stage": "execute", - "spec_session": "SPEC-{slug}-{date}|null", - "plan_session": "planning/{task-slug}-{date}/", - "plan_context": "planning/{task-slug}-{date}/plan.json", - "execution_mode": "ddd:execute|lite-execute|direct|stop", - "execution_manifest": "planning/{task-slug}-{date}/execution-manifest.json|null", - "verify_gate": "PASS|WARN|FAIL|null", - "error_state": null, - "last_error": { - "stage": "execute", - "message": "Task TASK-002 failed: compilation error", - "timestamp": "ISO8601", - "recoverable": true - }, - "created_at": "ISO8601", - "last_updated": "ISO8601" -} -``` - -### Resume -``` -/ddd:auto --resume → Resume from current_stage in .auto-session.json -``` - -### Error Recovery -``` -/ddd:auto --resume - IF error_state is set: - Display last error context - Ask: retry current stage / skip to next / abort - ELSE: - Resume from current_stage normally -``` - -## Example Workflows - -### New Project (Full Flow) -``` -/ddd:auto "Build a task management API with user auth and team features" -→ Stage 0: No code, no spec → need spec-gen -→ Stage 1: spec-generator produces full spec -→ Stage 2: index-build creates index from spec + empty codebase -→ Stage 3: ddd:plan produces plan.json + TASK-*.json with doc_context -→ Stage 4: ddd:execute runs tasks with feature context enrichment -→ Stage 4.5: verify gate — convergence ✓, build ✓, tests ✓ → PASS -→ Stage 5: ddd:sync --from-manifest auto-triggered, updates index -``` - -### Existing Project, No Spec (Code-First) -``` -/ddd:auto "Add rate limiting to API endpoints" -→ Stage 0: Has code, no spec, no index -→ Stage 2b: ddd:scan analyzes code, infers features from codebase -→ Stage 3: ddd:plan queries index, explores with security + patterns angles -→ Stage 4: ddd:execute runs with rate-limit component docs as context -→ Stage 4.5: verify gate — convergence ✓, tests 41/42 (1 regression) → WARN -→ Stage 5: ddd:sync --from-manifest, registers new rate-limit component -``` - -### Existing Project with Index (Incremental) -``` -/ddd:auto "Fix auth token expiration bug" -→ Stage 0: Has code, has index → skip to plan -→ Stage 3: ddd:plan finds feat-auth, REQ-002, tech-auth-service (Low complexity, skip exploration) -→ Stage 4: ddd:execute runs single task with auth feature context -→ Stage 4.5: verify gate — convergence ✓, build ✓, tests ✓ → PASS -→ Stage 5: ddd:sync --from-manifest, updates tech-auth-service code locations -``` - -### Planning Only -``` -/ddd:auto "Investigate payment module architecture" -→ Stage 0-2: (as needed) -→ Stage 3: ddd:plan shows full context with exploration results -→ Stage 4: user selects "stop" → gets plan.json + context package only -``` diff --git a/.claude/commands/ddd/doc-generate.md b/.claude/commands/ddd/doc-generate.md deleted file mode 100644 index 9b2819a2..00000000 --- a/.claude/commands/ddd/doc-generate.md +++ /dev/null @@ -1,222 +0,0 @@ ---- -name: doc-generate -description: Generate full document tree from doc-index.json. Layer 3 (components) → Layer 2 (features) → Layer 1 (indexes/overview). Standalone or called by scan/index-build. -argument-hint: "[-y|--yes] [--layer <3|2|1|all>] [--force] [--skip-overview] [--skip-schema]" -allowed-tools: TodoWrite(*), Agent(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*) ---- - -## Auto Mode - -When `--yes` or `-y`: Auto-generate all layers without confirmation prompts. - -# DDD Doc Generate Command (/ddd:doc-generate) - -## Purpose - -Generate the complete document tree from `doc-index.json`. **Single source of truth** for all document generation logic, following bottom-up Layer 3 → 2 → 1 strategy. - -``` -doc-index.json → tech-registry/*.md (L3) → feature-maps/*.md (L2) → _index.md + README + ARCHITECTURE (L1) -``` - -## When to Use - -| Scenario | Use | -|----------|-----| -| After `/ddd:scan` builds doc-index.json | **doc-generate** (auto-called by scan) | -| After `/ddd:index-build` builds doc-index.json | **doc-generate** (auto-called by index-build) | -| Rebuild all docs from existing index | **doc-generate --force** | -| Regenerate only component docs | **doc-generate --layer 3** | -| Regenerate only overview/index docs | **doc-generate --layer 1** | - -## Prerequisite - -- `doc-index.json` must exist at `.workflow/.doc-index/doc-index.json` -- If not found → error: "No doc-index.json found. Run /ddd:scan or /ddd:index-build first." - -## Storage Output - -``` -.workflow/.doc-index/ -├── doc-index.json ← Input (read-only, not modified) -├── SCHEMA.md ← Schema documentation -├── README.md ← Project overview (Layer 1) -├── ARCHITECTURE.md ← Architecture overview (Layer 1) -├── feature-maps/ ← Feature documentation (Layer 2) -│ ├── _index.md -│ └── {feature-slug}.md -├── tech-registry/ ← Component documentation (Layer 3) -│ ├── _index.md -│ └── {component-slug}.md -└── planning/ ← Planning sessions (Layer 1) - ├── _index.md ← Planning sessions index - └── {task-slug}-{date}/ ← Individual session folders -``` - -## Phase 1: Load & Validate - -### 1.1 Load doc-index.json - -``` -Read .workflow/.doc-index/doc-index.json -Validate: features[], technicalComponents[] are non-empty arrays -``` - -### 1.2 Schema Version Check - -```javascript -const schemaVersion = docIndex.schema_version || '0.0'; -if (schemaVersion !== '1.0') { - warn(`Schema version mismatch: found ${schemaVersion}, expected 1.0`); -} -``` - -### 1.3 Determine Generation Scope - -``` -IF --layer 3: generate Layer 3 only -IF --layer 2: generate Layer 2 only (requires Layer 3 exists) -IF --layer 1: generate Layer 1 only (requires Layer 2 exists) -IF --layer all (default): generate Layer 3 → 2 → 1 -``` - -### 1.4 Check Existing Docs - -``` -IF docs already exist AND NOT --force: - Warn: "Documents already exist. Use --force to overwrite." - Ask user (unless -y → overwrite) -``` - -## Phase 2: Layer 3 -- Component Documentation - -For each component in `technicalComponents[]`, call the generate_ddd_docs endpoint: - -```bash -for COMPONENT_ID in "${technicalComponents[@]}"; do - ccw tool exec generate_ddd_docs '{"strategy":"component","entityId":"'"$COMPONENT_ID"'","tool":"gemini"}' -done -``` - -The endpoint handles: -- Loading the component entity from doc-index.json -- Building YAML frontmatter (layer: 3, component_id, name, type, features, code_locations, generated_at) -- Constructing the CLI prompt with code context paths -- **Including Change History section**: Pull related entries from `doc-index.json.actions[]` where `affectedComponents` includes this component ID. Display as timeline (date, action type, description) -- Writing output to `.workflow/.doc-index/tech-registry/{slug}.md` -- Tool fallback (gemini -> qwen -> codex) on failure - -Output: `.workflow/.doc-index/tech-registry/{component-slug}.md` - -## Phase 3: Layer 2 -- Feature Documentation - -For each feature in `features[]`, call the generate_ddd_docs endpoint: - -```bash -for FEATURE_ID in "${features[@]}"; do - ccw tool exec generate_ddd_docs '{"strategy":"feature","entityId":"'"$FEATURE_ID"'","tool":"gemini"}' -done -``` - -The endpoint handles: -- Loading the feature entity from doc-index.json -- Building YAML frontmatter (layer: 2, feature_id, name, epic_id, status, requirements, components, tags, generated_at) -- Constructing the CLI prompt referencing Layer 3 component docs -- **Including Change History section**: Pull related entries from `doc-index.json.actions[]` where `affectedFeatures` includes this feature ID. Display as timeline (date, action type, description) -- Writing output to `.workflow/.doc-index/feature-maps/{slug}.md` -- Tool fallback (gemini -> qwen -> codex) on failure - -Output: `.workflow/.doc-index/feature-maps/{feature-slug}.md` - -## Phase 4: Layer 1 -- Index & Overview Documentation - -### 4.1 Index Documents - -Generate catalog files for each subdirectory: - -```bash -# Feature maps index -ccw tool exec generate_ddd_docs '{"strategy":"index","entityId":"feature-maps","tool":"gemini"}' - -# Tech registry index -ccw tool exec generate_ddd_docs '{"strategy":"index","entityId":"tech-registry","tool":"gemini"}' - -# Action logs index -ccw tool exec generate_ddd_docs '{"strategy":"index","entityId":"action-logs","tool":"gemini"}' - -# Planning sessions index -ccw tool exec generate_ddd_docs '{"strategy":"index","entityId":"planning","tool":"gemini"}' -``` - -Or generate all indexes at once (omit entityId): - -```bash -ccw tool exec generate_ddd_docs '{"strategy":"index","tool":"gemini"}' -``` - -### 4.2 README.md (unless --skip-overview) - -```bash -ccw tool exec generate_ddd_docs '{"strategy":"overview","tool":"gemini"}' -``` - -### 4.3 ARCHITECTURE.md (unless --skip-overview) - -```bash -ccw tool exec generate_ddd_docs '{"strategy":"overview","entityId":"architecture","tool":"gemini"}' -``` - -## Phase 5: SCHEMA.md (unless --skip-schema) - -### 5.1 Generate Schema Documentation - -```bash -ccw tool exec generate_ddd_docs '{"strategy":"schema","tool":"gemini"}' -``` - -### 5.2 Versioning Policy - -**Semantic Versioning**: -- **Major** (X.0): Breaking changes (field removal, type changes, incompatible structure) -- **Minor** (X.Y): Non-breaking additions (new optional fields, new sections) - -**Migration Protocol**: -1. Detect version mismatch in ddd:plan/ddd:sync -2. Log warning with migration instructions -3. Provide migration script or regeneration option -4. Update schema_version after successful migration - -## Phase 6: Generation Report - -``` -Document Generation Report - -Project: {name} -Source: doc-index.json (build_path: {spec-first|code-first}) - -Generated: - Layer 3 (Components): {N} documents in tech-registry/ - Layer 2 (Features): {N} documents in feature-maps/ - Layer 1 (Indexes): {N} documents (_index.md, README, ARCHITECTURE) - Schema: SCHEMA.md - -Total: {N} documents generated -``` - -## Flags - -| Flag | Effect | -|------|--------| -| `-y, --yes` | Auto-confirm all decisions | -| `--layer <3\|2\|1\|all>` | Generate specific layer only (default: all) | -| `--force` | Overwrite existing documents | -| `--skip-overview` | Skip README.md, ARCHITECTURE.md, planning/_index.md | -| `--skip-schema` | Skip SCHEMA.md generation | - -## Integration Points - -- **Input from**: `doc-index.json` (from `/ddd:scan` or `/ddd:index-build`) -- **Called by**: `/ddd:scan` (after index assembly), `/ddd:index-build` (after index assembly) -- **Standalone**: Can be run independently on any project with existing doc-index.json -- **Output**: Complete document tree in `.workflow/.doc-index/` -- **Endpoint**: `ccw tool exec generate_ddd_docs` handles prompt construction, frontmatter, tool fallback, and file creation diff --git a/.claude/commands/ddd/doc-refresh.md b/.claude/commands/ddd/doc-refresh.md deleted file mode 100644 index 14963459..00000000 --- a/.claude/commands/ddd/doc-refresh.md +++ /dev/null @@ -1,218 +0,0 @@ ---- -name: doc-refresh -description: Incrementally update affected documents based on changed components/features. Layer 3 → 2 → 1 selective refresh. Called by sync/update or used standalone. -argument-hint: "[-y|--yes] [--components ] [--features ] [--minimal] [--dry-run]" -allowed-tools: TodoWrite(*), Agent(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*) ---- - -## Auto Mode - -When `--yes` or `-y`: Auto-update affected documents without confirmation prompts. - -# DDD Doc Refresh Command (/ddd:doc-refresh) - -## Purpose - -Incrementally update **only the affected documents** after code changes. Unlike `/ddd:doc-generate` (full generation), this command selectively refreshes documents for specific components and features. - -``` -affected component/feature IDs → update tech-registry (L3) → update feature-maps (L2) → update indexes (L1) -``` - -## When to Use - -| Scenario | Use | -|----------|-----| -| After `/ddd:sync` detects code changes | **doc-refresh** (auto-called by sync) | -| After `/ddd:update` traces impact | **doc-refresh** (auto-called by update) | -| Manual refresh of specific component docs | **doc-refresh --components tech-auth-service** | -| Quick metadata-only update | **doc-refresh --minimal --components tech-auth-service** | -| Preview what would change | **doc-refresh --dry-run --components tech-auth-service** | - -## Prerequisite - -- `doc-index.json` must exist at `.workflow/.doc-index/doc-index.json` -- At least one of `--components` or `--features` must be provided (or received from caller) -- Corresponding documents must already exist (generated by `/ddd:doc-generate`) -- If documents missing → error: "Documents not found. Run /ddd:doc-generate first." - -## Phase 1: Determine Refresh Scope - -### 1.1 Resolve Affected Entities - -``` -IF --components provided: - affected_components = parse comma-separated IDs - affected_features = lookup featureIds for each component in doc-index.json - -IF --features provided: - affected_features = parse comma-separated IDs - affected_components = union of all component IDs linked to features - -Merge both sets if both flags provided. -``` - -### 1.2 Validate Entities Exist - -For each ID, verify it exists in doc-index.json. Warn and skip missing IDs. - -### 1.3 Check Document Existence - -For each affected entity, check if corresponding .md file exists: -- Missing Layer 3 doc → warn: "Component doc not found. Run /ddd:doc-generate first." -- Missing Layer 2 doc → warn: "Feature doc not found. Run /ddd:doc-generate first." - -## Phase 2: Layer 3 — Update Component Docs - -For each affected component's `tech-registry/{slug}.md`: - -```bash -ccw cli -p "PURPOSE: Update component documentation for {component.name} after code changes -TASK: -• Update code locations and line ranges -• Update symbol list (add new exports, remove deleted) -• Add change entry to history table -• Refresh usage examples if API changed -MODE: write -CONTEXT: @{component.codeLocations[].path} -EXPECTED: Updated markdown with current API state -CONSTRAINTS: Preserve existing structure | Only update changed sections -" --tool gemini --mode write --cd .workflow/.doc-index/tech-registry/ -``` - -Update frontmatter: -```markdown ---- -layer: 3 -component_id: tech-auth-service -generated_at: {original} -last_updated: ISO8601 ---- -``` - -### 2.1 Minimal Mode (--minimal) - -With `--minimal`, only update: -- `codeLocations` in frontmatter -- `last_updated` timestamp -- Skip CLI call for content regeneration - -## Phase 3: Layer 2 — Update Feature Docs - -For each affected feature's `feature-maps/{slug}.md`: - -```bash -ccw cli -p "PURPOSE: Update feature documentation for {feature.name} after component changes -TASK: -• Update component list if new components added -• Update status if requirements now fully implemented -• Add change entry to history table -• Refresh integration guide if component APIs changed -MODE: write -CONTEXT: @.workflow/.doc-index/tech-registry/{affected-components}.md -EXPECTED: Updated markdown reflecting current feature state -CONSTRAINTS: Reference updated Layer 3 docs | Preserve business language -" --tool gemini --mode write --cd .workflow/.doc-index/feature-maps/ -``` - -Update frontmatter: -```markdown ---- -layer: 2 -feature_id: feat-auth -depends_on_layer3: [tech-auth-service, tech-user-model] -generated_at: {original} -last_updated: ISO8601 ---- -``` - -### 3.1 Minimal Mode (--minimal) - -With `--minimal`, only update: -- Component list in frontmatter -- Feature status (if requirements mapping changed) -- `last_updated` timestamp -- Skip CLI call for content regeneration - -## Phase 4: Layer 1 — Update Index Docs (conditional) - -### 4.1 Trigger Conditions - -| Condition | Action | -|-----------|--------| -| New component registered | Update `tech-registry/_index.md` | -| Component removed | Update `tech-registry/_index.md` | -| Feature status changed | Update `feature-maps/_index.md` | -| New feature added | Update `feature-maps/_index.md` + README.md | -| Major architecture change | Update ARCHITECTURE.md | -| New action-log entry | Update `action-logs/_index.md` | - -### 4.2 Update _index.md Files - -Refresh table entries for affected features/components: -- `feature-maps/_index.md` -- `tech-registry/_index.md` -- `action-logs/_index.md` (if new action entry) - -### 4.3 Update Overview Docs (only if significant) - -If new features added or major status changes: - -```bash -ccw cli -p "PURPOSE: Update project overview docs after feature changes -TASK: -• Update README.md feature list -• Update ARCHITECTURE.md if new components added -• Update planning/_index.md with new planning sessions -MODE: write -CONTEXT: @.workflow/.doc-index/feature-maps/*.md @.workflow/.doc-index/doc-index.json -EXPECTED: Updated overview docs with current project state -CONSTRAINTS: High-level only | Link to Layer 2 for details -" --tool gemini --mode write --cd .workflow/.doc-index/ -``` - -### 4.4 Skip Layer 1 - -With `--minimal` or when changes are minor (only code location updates): skip Layer 1 entirely. - -## Phase 5: Refresh Report - -``` -Document Refresh Report - -Affected Scope: - Components: {N} ({component IDs}) - Features: {N} ({feature IDs}) - -Updated: - Layer 3 (Components): {N} documents refreshed - Layer 2 (Features): {N} documents refreshed - Layer 1 (Indexes): {N} documents refreshed (or "skipped") - -Mode: {full|minimal} -``` - -## Dry-Run Mode - -With `--dry-run`: -- Execute Phase 1 (scope determination) -- Display what would be updated (affected files list) -- Skip all file writes (Phase 2-4) -- Output: "Dry-run complete. {N} documents would be refreshed." - -## Flags - -| Flag | Effect | -|------|--------| -| `-y, --yes` | Auto-confirm all updates | -| `--components ` | Comma-separated component IDs to refresh | -| `--features ` | Comma-separated feature IDs to refresh | -| `--minimal` | Only update metadata/frontmatter, skip content regeneration | -| `--dry-run` | Preview what would change without modifying files | - -## Integration Points - -- **Input from**: `doc-index.json`, affected entity IDs (from `/ddd:sync` or `/ddd:update`) -- **Called by**: `/ddd:sync` (after change detection + index update), `/ddd:update` (after impact tracing + index update) -- **Standalone**: Can be run independently to refresh specific component/feature docs -- **Prerequisite**: Documents must exist (generated by `/ddd:doc-generate`) diff --git a/.claude/commands/ddd/execute.md b/.claude/commands/ddd/execute.md deleted file mode 100644 index 81134e8e..00000000 --- a/.claude/commands/ddd/execute.md +++ /dev/null @@ -1,416 +0,0 @@ ---- -name: execute -description: Document-aware execution engine — executes plan.json + TASK-*.json with doc-index context enrichment, per-batch impact verification, and post-completion doc sync. -argument-hint: "[-y|--yes] [--skip-sync] [--skip-verify] [--plan ] [--in-memory] \"optional task description\"" -allowed-tools: TodoWrite(*), Agent(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*), mcp__ace-tool__search_context(*) ---- - -## Auto Mode - -When `--yes` or `-y`: Auto-confirm all decisions, auto-sync after completion. - -# DDD Execute Command (/ddd:execute) - -## Purpose - -Same execution engine model as lite-execute, but each step is **doc-index-aware**: -- Tasks are enriched with feature context, component docs, and architecture constraints -- Per-batch impact verification ensures changes stay within planned scope -- Post-completion automatically syncs the document index - -### Core Differentiator -Unlike generic execution engines, ddd:execute leverages the document architecture: -- Feature-maps provide business context for each task -- Tech-registry provides implementation patterns to follow -- ADRs surface as hard constraints during execution -- Requirement acceptance criteria inform convergence verification - -## Prerequisite - -- `plan.json` + `.task/TASK-*.json` files from `/ddd:plan` -- `doc-index.json` at `.workflow/.doc-index/doc-index.json` -- If `--in-memory`: receives executionContext from `/ddd:plan` handoff - ---- - -## Step 1: Initialize & Load Context - -### 1.1 Locate Plan - -``` -IF --in-memory: - Load executionContext from ddd:plan handoff - plan_path = executionContext.plan_path - task_dir = executionContext.task_dir -ELIF --plan : - plan_path = - task_dir = {dirname(path)}/.task/ -ELSE: - Scan .workflow/.doc-index/planning/ for most recent session - plan_path = {latest_session}/plan.json - task_dir = {latest_session}/.task/ -``` - -### 1.2 Load Plan & Tasks - -- Read `plan.json` — validate against plan-overview-base-schema -- Read all `TASK-*.json` from `.task/` directory — validate against task-schema -- Read `doc-index.json` from `.workflow/.doc-index/` - -### 1.3 Pre-Load Doc Context - -For each task with `doc_context`: -- Load referenced `feature_docs` (feature-maps/{slug}.md) -- Load referenced `component_docs` (tech-registry/{slug}.md) -- Load ADR excerpts from doc-index `architectureDecisions[]` -- Extract requirement acceptance criteria from doc-index `requirements[]` -- Load `doc_context.symbol_docs[]` documentation content (if present) - -### 1.4 Echo Strategy - -Display execution summary: - -``` -DDD Execute: {plan.summary} -Complexity: {plan.complexity} -Tasks: {plan.task_count} - -Doc-Index Impact: - Features: {doc_context.affected_features} - Requirements: {doc_context.affected_requirements} - Components: {doc_context.affected_components} - Constraints: {doc_context.architecture_constraints} - -Execution plan: {batch count} batches, {parallel tasks} parallel where possible -``` - ---- - -## Step 2: Task Grouping & Batch Creation - -### 2.1 Extract Dependencies - -From each `TASK-*.json`, read `depends_on[]` to build dependency graph. - -### 2.2 Group into Batches - -``` -Batch 1: Tasks with no dependencies (depends_on: []) -Batch 2: Tasks depending only on Batch 1 tasks -Batch 3: Tasks depending on Batch 1 + 2 tasks -... -``` - -Within each batch, tasks with the same `parallel_group` can run concurrently. - -### 2.3 Assign Executor per Task - -| Signal | Executor | -|--------|----------| -| `meta.execution_config.method == "cli"` | CLI tool (gemini/codex/qwen) | -| `meta.execution_config.method == "agent"` | Agent (code-developer/universal-executor) | -| Default | Agent (code-developer) | - ---- - -## Step 3: Doc-Enriched Execution - -For each task in batch order, build an enriched prompt: - -### 3.1 Task Prompt Template - -```markdown -## Goal -${plan.summary} — specifically: ${task.title} - -## Document Context - -### Feature: ${feature.name} (${feature.id}) -${feature-map content excerpt — overview + requirements section} - -### Components -${for each component in task.doc_context.component_ids: - tech-registry excerpt — responsibility + code locations + key patterns} - -### Symbol Documentation -${if doc_context.symbol_docs is non-empty: - for each component in doc_context.component_ids: - #### ${component.name} Symbols (Top-5) - ${for each symbol in component.symbol_docs.slice(0, 5): - - **${symbol.name}** (${symbol.type}): ${symbol.doc_summary} - Source: `${symbol.source_path}` | Freshness: ${symbol.freshness} - } -} - -### Architecture Constraints -${for each ADR in task.doc_context.adr_ids: - ADR title + decision + rationale from doc-index} - -### Requirement Acceptance Criteria -${for each requirement in task.doc_context.requirement_ids: - requirement title + priority + success criteria from doc-index} - -## Task Details -${task.description} - -### Files to Modify -${task.files[] — path, action, changes} - -### Implementation Steps -${task.implementation[] — step-by-step guide} - -## Done When -${task.convergence.criteria[]} -${task.convergence.verification} -``` - -### 3.2 Execute Task - -**Agent execution**: -``` -Agent(subagent_type="code-developer", prompt="{enriched prompt}") -``` - -**CLI execution**: -```bash -ccw cli -p "{enriched prompt}" --tool {cli_tool} --mode write -``` - -### 3.3 Record & Persist Result - -After each task completes: -- Update `TASK-*.json` with `status`, `executed_at`, `result` -- Track `result.files_modified` for impact verification -- **Persist** result to `TASK-{id}.result.json` alongside the task file: - -```json -{ - "task_id": "TASK-001", - "status": "completed|failed", - "executed_at": "ISO8601", - "executor": "code-developer|gemini|codex", - "files_modified": [ - { "path": "src/services/auth.ts", "action": "modified", "symbols_changed": ["AuthService.validate"] }, - { "path": "src/routes/login.ts", "action": "created", "symbols_changed": ["loginRoute"] } - ], - "convergence_result": { - "criteria_met": ["Rate limiter middleware exists"], - "criteria_unmet": [], - "verification_output": "test output snippet..." - }, - "error": null -} -``` - -This file serves as the durable handoff between execute and sync — survives process interruptions. - ---- - -## Step 4: Per-Batch Impact Verification - -After each batch completes (unless `--skip-verify`): - -### 4.1 Trace Changed Files - -For each file modified in the batch: -``` -changed_file → match to doc-index.technicalComponents[].codeLocations[].path - → component_ids → featureIds → requirementIds -``` - -### 4.2 Scope Verification - -Compare actual impact to planned impact: - -``` -Planned scope: - Features: [feat-auth] - Components: [tech-auth-service, tech-user-model] - -Actual impact: - Features: [feat-auth] ← OK, within scope - Components: [tech-auth-service, tech-user-model, tech-email-service] - ← WARNING: tech-email-service not in plan -``` - -### 4.3 Flag Unexpected Impact - -If changes affect features/components NOT in `plan.doc_context`: -- **Warning**: Display unexpected impact -- **No -y**: Ask user to confirm continuation -- **With -y**: Log warning, continue execution - -### 4.4 Skip Conditions - -Skip verification when: -- `--skip-verify` flag is set -- Only 1 batch (no intermediate verification needed for simple plans) - ---- - -## Step 4.5: Post-Execution Verify Gate - -After all batches complete, before doc sync (unless `--skip-verify`): - -### 4.5.1 Convergence Verification - -For each completed task with `convergence.verification`: -``` -Execute: {task.convergence.verification} - → e.g., "npm test -- --grep rate-limit" -Record: pass/fail → update TASK-{id}.result.json.convergence_result -``` - -### 4.5.2 Build & Lint Check - -``` -Run project build command (if configured): - → npm run build / tsc --noEmit / etc. -Run project lint command (if configured): - → npm run lint / eslint src/ / etc. -``` - -If build or lint fails: -- **No -y**: Display errors, ask user: fix now / continue anyway / abort -- **With -y**: Log warning, continue (non-blocking) - -### 4.5.3 Regression Test - -``` -Run project test suite: - → npm test / pytest / etc. -Compare: test results before execution (baseline) vs after -``` - -If tests fail: -- **No -y**: Display failures, ask user: fix now / skip sync / abort -- **With -y**: Log failures as warning in execution results, continue - -### 4.5.4 Verify Summary - -``` -Verify Gate Results: - Convergence: {passed}/{total} tasks verified - Build: pass|fail|skipped - Lint: pass|fail|skipped - Tests: {passed}/{total} ({new_failures} regressions) - - Gate: PASS / WARN (continue with warnings) / FAIL (blocked) -``` - -### 4.5.5 Persist Verify Manifest - -Write `execution-manifest.json` to session folder: - -```json -{ - "session_id": "{session-id}", - "plan_path": "planning/{slug}/plan.json", - "completed_at": "ISO8601", - "tasks": [ - { - "task_id": "TASK-001", - "status": "completed", - "result_file": ".task/TASK-001.result.json" - } - ], - "files_modified": [ - { "path": "src/services/auth.ts", "action": "modified", "task_id": "TASK-001" }, - { "path": "src/routes/login.ts", "action": "created", "task_id": "TASK-001" } - ], - "verify": { - "convergence": { "passed": 2, "total": 2 }, - "build": "pass", - "lint": "pass", - "tests": { "passed": 42, "total": 42, "regressions": 0 }, - "gate": "PASS" - } -} -``` - -This manifest is the **single source of truth** consumed by `ddd:sync --from-manifest`. - ---- - -## Step 5: Post-Completion Doc Sync - -After all batches complete (unless `--skip-sync`): - -### 5.1 Auto-Trigger ddd:sync - -``` -Invoke /ddd:sync [-y] --task-id {session-id} --from-manifest {session}/execution-manifest.json "{plan.summary}" -``` - -Note: `/ddd:sync` automatically creates a backup of `doc-index.json` before modifications. - -When `--from-manifest` is provided, sync uses the **execution manifest** as its primary data source instead of git diff. This ensures: -- Precise file-level and symbol-level change tracking (from TASK-*.result.json) -- Task-to-file attribution (which task modified which file) -- Convergence verification results carried forward -- Survives process interruptions (manifest is persisted to disk) - -Fallback: If manifest is unavailable (e.g., manual mode), sync falls back to git diff discovery. - -### 5.2 Generate Action Log - -Create action entry with: -- All tasks executed and their results -- Files modified across all batches -- Features and requirements addressed - -### 5.3 Update Feature Status - -Based on execution results: -- Requirements with verified convergence → update status -- Features with all requirements met → `status: "implemented"` - ---- - -## Step 6: Summary & Follow-up - -### 6.1 Execution Results - -``` -DDD Execute Complete - -Tasks: {completed}/{total} ({failed} failed) -Files modified: {count} -Batches: {batch_count} - -Doc-Index Changes: - Features updated: {list} - Components updated: {list} - New components registered: {list} - Requirements addressed: {list} - -Convergence: - {for each task: task.id — criteria met: X/Y} -``` - -### 6.2 Follow-up Suggestions - -Based on execution results, suggest: -- **New issues**: If unexpected scope expansion was detected -- **Additional tests**: If convergence criteria only partially met -- **Documentation gaps**: If new components were created without docs -- **Next tasks**: If plan had tasks marked as future/deferred - ---- - -## Flags - -| Flag | Effect | -|------|--------| -| `-y, --yes` | Auto-confirm, auto-sync | -| `--skip-sync` | Skip post-completion ddd:sync (Step 5) | -| `--skip-verify` | Skip per-batch impact verification (Step 4) AND post-execution verify gate (Step 4.5) | -| `--plan ` | Explicit plan.json path | -| `--in-memory` | Accept executionContext from ddd:plan handoff | - -## Integration Points - -- **Input from**: `/ddd:plan` output (plan.json + TASK-*.json), `doc-index.json` -- **Output to**: Updated `doc-index.json` (via ddd:sync), `TASK-*.result.json` (per-task), `execution-manifest.json` (session-level) -- **Schemas**: `plan-overview-ddd-schema.json` (input), `task-schema.json` + `task-ddd-extension-schema.json` (input), `doc-index.json` (enrichment) -- **Delegates to**: `/ddd:sync` for post-completion synchronization diff --git a/.claude/commands/ddd/index-build.md b/.claude/commands/ddd/index-build.md deleted file mode 100644 index 09d1cb38..00000000 --- a/.claude/commands/ddd/index-build.md +++ /dev/null @@ -1,212 +0,0 @@ ---- -name: index-build -description: Build document index from spec-generator outputs + codebase mapping. Requires existing spec session. For projects without specs, use /ddd:scan instead. -argument-hint: "[-y|--yes] [-s|--spec ] [--from-scratch]" -allowed-tools: TodoWrite(*), Agent(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*), mcp__ace-tool__search_context(*) ---- - -## Auto Mode - -When `--yes` or `-y`: Auto-confirm all decisions, use inferred mappings, skip interactive review. - -# DDD Index Build Command (/ddd:index-build) - -## Purpose - -From **spec-generator outputs** (requirements, architecture, epics), construct the central document index and map spec entities to actual code locations. - -``` -Spec outputs (REQ, ADR, EPIC) + Codebase → doc-index.json -``` - -> **No spec?** Use `/ddd:scan` instead — it reverse-engineers the index from code alone. - -## Prerequisite - -- At least one spec session in `.workflow/.doc-index/specs/` or `.workflow/.spec/` -- If no spec found → error with suggestion: "No spec session found. Run /ddd:scan for code-first indexing, or /spec-generator to create specs." - -## Storage Location - -``` -.workflow/.doc-index/ -├── doc-index.json ← Central index (primary output) -├── specs/ ← Spec-generator outputs -│ └── SPEC-{slug}-{date}/ -├── feature-maps/ ← Feature documentation (from Epics) -│ ├── _index.md -│ └── {feature-slug}.md -├── tech-registry/ ← Technical component docs (from code mapping) -│ ├── _index.md -│ └── {component-slug}.md -└── action-logs/ ← Change history (initially empty) - └── _index.md -``` - -## Phase 1: Discover & Parse Spec Sources - -### 1.1 Locate Spec Session - -``` -IF --spec provided: - Load from .workflow/.doc-index/specs// OR .workflow/.spec// -ELSE: - Scan for all SPEC-* directories - IF multiple → present list, ask user to select (-y picks latest) - IF none → ERROR: "No spec session found. Use /ddd:scan or /spec-generator." -``` - -### 1.2 Migrate Specs (if needed) - -If spec in `.workflow/.spec/` but not in `.workflow/.doc-index/specs/`: -- Copy to `.workflow/.doc-index/specs/` -- Preserve original (backward compatibility) - -### 1.3 Extract Structured Entities - -| Source File | Extract To | -|------------|------------| -| `spec-config.json` | project name, domain, spec_type | -| `glossary.json` | → index glossary[] | -| `product-brief.md` | vision, goals | -| `requirements/REQ-*.md` | → index requirements[] (with MoSCoW priority) | -| `requirements/NFR-*.md` | → index requirements[] (non-functional) | -| `architecture/ADR-*.md` | → index architectureDecisions[] | -| `epics/EPIC-*.md` | → feature grouping seeds | - -## Phase 2: Codebase Mapping - -Map spec entities to actual code locations using Gemini: - -```bash -ccw cli -p "PURPOSE: Map codebase to specification entities for documentation indexing. -TASK: -• Scan the codebase and identify all major modules/components -• For each component: extract file paths, exported symbols (classes, functions, types) -• Match components to these specification entities by name/domain similarity: - Requirements: {REQ-001: desc, REQ-002: desc, ...extracted from Phase 1} - Architecture decisions: {ADR-001: title, ...extracted from Phase 1} -• Report unmatched components (exist in code but no spec counterpart) -• Report unmatched requirements (in spec but no code found) -MODE: analysis -CONTEXT: @**/* -EXPECTED: JSON: { components: [{ name, type, files, symbols, matched_req_ids, matched_adr_id, is_orphan }], unmatched_reqs: [REQ-NNN] } -CONSTRAINTS: Focus on source directories | Ignore node_modules, dist, build" --tool gemini --mode analysis -``` - -### 2.1 Generate Component IDs & Link - -For each discovered component: -- ID: `tech-{kebab-case-name}` -- Link to matched `REQ-NNN` and `ADR-NNN` -- Flag orphans for user review - -## Phase 3: Build Feature Map (from Epics) - -### 3.1 Epic → Feature Mapping - -``` -Each EPIC-NNN → one feat-{slug} - - id: feat-{slug} (from epic slug) - - name: from Epic name - - epicId: EPIC-NNN - - status: inferred from code mapping - - all requirements have matched components → "implemented" - - some matched → "in-progress" - - none matched → "planned" - - requirementIds: from Epic's stories → requirement links - - tags: from domain keywords -``` - -### 3.2 Document Generation (delegated) - -Feature-map and tech-registry document generation is handled by `/ddd:doc-generate` in Phase 5. -Phase 3 only builds the data structures (feature → requirement → component mappings) that doc-generate consumes. - -## Phase 4: Assemble doc-index.json - -```json -{ - "version": "1.0", - "project": "{project-name}", - "build_path": "spec-first", - "spec_session": "SPEC-{slug}-{date}", - "last_updated": "ISO8601", - "glossary": [ - { "id": "gloss-{slug}", "term": "Term", "definition": "...", "aliases": [], "category": "core|technical|business" } - ], - "features": [ - { "id": "feat-{slug}", "name": "...", "epicId": "EPIC-NNN", "status": "...", "docPath": "feature-maps/{slug}.md", "requirementIds": ["REQ-NNN"], "tags": [] } - ], - "requirements": [ - { "id": "REQ-NNN", "title": "...", "source": "spec", "priority": "Must|Should|Could|Won't", "sourcePath": "specs/SPEC-*/requirements/REQ-NNN-*.md", "techComponentIds": ["tech-{slug}"], "featureId": "feat-{slug}" } - ], - "technicalComponents": [ - { "id": "tech-{slug}", "name": "...", "type": "...", "responsibility": "...", "adrId": "ADR-NNN|null", "docPath": "tech-registry/{slug}.md", "codeLocations": [{ "path": "...", "symbols": [], "lineRange": [0,0] }], "dependsOn": [], "featureIds": ["feat-{slug}"], "actionIds": [] } - ], - "architectureDecisions": [ - { "id": "ADR-NNN", "title": "...", "source": "spec", "sourcePath": "specs/SPEC-*/architecture/ADR-NNN-*.md", "componentIds": ["tech-{slug}"] } - ], - "actions": [] -} -``` - -### Merge with Existing Code-First Index - -If a code-first index exists (from prior `/ddd:scan`): -- Replace `IREQ-NNN` with matching `REQ-NNN` where content overlaps -- Keep `IREQ-NNN` without spec counterpart (mark `source: "legacy-inferred"`) -- Replace `IADR-NNN` with `ADR-NNN` where applicable -- Update `build_path` to `"spec-first"` -- Preserve existing `tech-*` components (update links only) - -## Phase 5: Generate Documents - -Delegate all document generation to `/ddd:doc-generate`: - -``` -Invoke /ddd:doc-generate [-y] -``` - -This generates the complete document tree (Layer 3 → 2 → 1): -- `tech-registry/{slug}.md` — component docs from Phase 2 mapping (Layer 3) -- `feature-maps/{slug}.md` — feature docs from Phase 3 mapping (Layer 2) -- `_index.md`, `README.md`, `ARCHITECTURE.md`, `SCHEMA.md` — index/overview docs (Layer 1) - -See `/ddd:doc-generate` for full details on generation strategy and flags. - -## Phase 6: Coverage Report - -``` -Index Build Report (spec-first) - -Spec: {session-id} -Features: {N} (from {N} Epics) -Requirements: {N} (REQ: {n}, NFR: {n}) -Components: {N} ({orphan} orphans without spec match) -ADRs: {N} - -Mapping Coverage: - Requirements → Components: {%} ({unmapped} unmapped) - Components → Features: {%} - Epics → Features: 100% - -Gaps: - - {N} requirements have no matching code component - - {N} code components are not linked to any requirement -``` - -## Flags - -| Flag | Effect | -|------|--------| -| `-y, --yes` | Skip all interactive prompts | -| `-s, --spec ` | Use specific spec session | -| `--from-scratch` | Delete existing index and rebuild | - -## Integration Points - -- **Input from**: `spec-generator` outputs, codebase, existing `/ddd:scan` index -- **Delegates to**: `/ddd:doc-generate` (Phase 5, full document generation) -- **Output to**: `ddd:plan`, `ddd:sync`, `ddd:update` -- **Upgrades**: Can merge with prior code-first (`/ddd:scan`) index diff --git a/.claude/commands/ddd/plan.md b/.claude/commands/ddd/plan.md deleted file mode 100644 index beabafdf..00000000 --- a/.claude/commands/ddd/plan.md +++ /dev/null @@ -1,611 +0,0 @@ ---- -name: plan -description: Document-driven planning pipeline — queries doc-index, explores codebase with doc-aware angles, clarifies ambiguities, and produces unified plan.json + TASK-*.json artifacts with doc_context traceability. -argument-hint: "[-y|--yes] [--explore] [--skip-explore] [--skip-clarify] \"task description or feature keyword\"" -allowed-tools: TodoWrite(*), Agent(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Write(*), mcp__ace-tool__search_context(*) ---- - -## Auto Mode - -When `--yes` or `-y`: Skip clarification (Phase 3), auto-select ddd:execute (Phase 5), skip interactive refinement. - -# DDD Plan Command (/ddd:plan) - -## Purpose - -Full planning pipeline for document-driven development. Unlike simple context lookup, this command: -1. **Queries** the doc-index for instant context (features, requirements, components, ADRs) -2. **Explores** the codebase with doc-index-informed angles (not generic presets) -3. **Clarifies** ambiguities from exploration results and doc-index gaps -4. **Plans** with unified schema output (plan.json + TASK-*.json with doc_context) -5. **Hands off** to ddd:execute or other execution engines - -### Key Differentiation from lite-plan -- Phase 1 provides instant context from doc-index (no cold-start exploration) -- Exploration angles are doc-index-informed (not generic preset selection) -- Tasks carry doc_context for traceability (features → requirements → code) -- Architecture decisions (ADRs) automatically surface as constraints - -## Prerequisite - -- `doc-index.json` must exist at `.workflow/.doc-index/doc-index.json` -- If not found → suggest running `/ddd:index-build` or `/ddd:scan` first - -## Session Folder - -``` -.workflow/.doc-index/planning/{task-slug}-{YYYY-MM-DD}/ -├── exploration-{angle}.json # Per-angle exploration (Phase 2) -├── explorations-manifest.json # Exploration index -├── plan.json # Plan overview (Phase 4) -├── planning-context.md # Legacy context package (Phase 0+1 combined) -├── .process/ -│ └── doc-context-package.json # Bundled doc_context (Phase 1.8) -└── .task/ - ├── TASK-001.json - └── TASK-002.json -``` - ---- - -## Phase 0: Parse Task Intent (enhanced) - -### 0.1 Extract Keywords - -From the user's task description, extract: -- **Domain keywords**: feature names, module names, business terms -- **Technical keywords**: file paths, class names, function names -- **Action type**: feature | bugfix | refactor | optimization | migration - -### 0.2 Glossary Match - -Cross-reference extracted keywords against `doc-index.json.glossary[]`: -- Match terms and aliases -- Expand user's vocabulary with canonical terms - -### 0.3 Classify Complexity - -Assess task complexity based on: -- Number of features potentially affected (from keyword matching) -- Whether new components are needed or existing ones modified -- Cross-feature impact (single feature vs multiple) - -| Signal | Complexity | -|--------|-----------| -| Single feature, existing components | Low | -| 1-2 features, some new components | Medium | -| 3+ features, new architecture needed | High | - ---- - -## Phase 1: Doc-Index Query - -### 1.0 Schema Version Check (TASK-006) - -Before querying doc-index, verify schema compatibility: - -```javascript -const docIndex = JSON.parse(Read('.workflow/.doc-index/doc-index.json')); -const schemaVersion = docIndex.schema_version || '0.0'; // Default for legacy - -if (schemaVersion !== '1.0') { - console.warn(`Schema version mismatch: found ${schemaVersion}, expected 1.0`); - console.warn('Consider running schema migration or regenerating doc-index with /ddd:scan'); - // Continue with degraded functionality - may encounter missing fields -} -``` - -**Graceful degradation**: If version mismatch detected → log warning → continue with caution (some features may not work as expected). - -### 1.1 Feature Search - -``` -Search doc-index.json.features[] where: - - name CONTAINS keyword (fuzzy) - - tags INTERSECT keywords - - requirementIds link to matching requirements -→ Output: matched feature IDs + names -``` - -### 1.2 Requirement Search - -``` -Search doc-index.json.requirements[] where: - - title CONTAINS keyword - - id matches explicit REQ-NNN reference - - featureId matches found features -→ Output: matched requirement IDs + titles + priorities -``` - -### 1.3 Component Search - -``` -Search doc-index.json.technicalComponents[] where: - - name CONTAINS keyword - - codeLocations[].path CONTAINS file path keyword - - codeLocations[].symbols CONTAINS symbol keyword - - featureIds INTERSECT found features -→ Output: matched component IDs + code locations -``` - -### 1.4 ADR Search - -``` -Search doc-index.json.architectureDecisions[] where: - - componentIds INTERSECT found components -→ Output: matched ADR IDs + titles -``` - -### 1.5 Action History Search - -``` -Search doc-index.json.actions[] where: - - related to found features or components -→ Output: recent actions with descriptions -``` - -### 1.6 Build Impact Map - -Assemble all found references into a structured impact map: - -```json -{ - "affected_features": ["feat-auth"], - "affected_requirements": ["REQ-001", "REQ-002"], - "affected_components": ["tech-auth-service", "tech-user-model"], - "architecture_constraints": ["ADR-001"], - "recent_actions": ["task-123"], - "complexity": "Medium" -} -``` - -Save as `planning-context.md` (legacy format for backward compatibility). - -### Phase 1.7: Symbol Query (DeepWiki Bridge) - -If DeepWiki is available (`deepwiki_feature_to_symbol_index` exists in doc-index.json): - -1. Collect all `codeLocations[].path` from matched `technicalComponents[]` -2. Query DeepWiki: `POST /api/deepwiki/symbols-for-paths { paths: unique_paths }` -3. Build symbol_docs by component, sorted by type priority (class > function > method) -4. Populate `doc_context.symbol_docs[]` with Top-5 symbols per component - -**Graceful degradation**: If DeepWiki unavailable → log warning → skip symbol injection → continue flow. - -### Phase 1.8: Persist Doc Context Package - -After building doc_context (including symbol_docs from Phase 1.7), persist it as a reusable context package: - -1. Bundle doc_context into JSON structure: -```json -{ - "affected_features": ["feat-auth"], - "affected_requirements": ["REQ-001", "REQ-002"], - "affected_components": ["tech-auth-service"], - "architecture_constraints": ["ADR-001"], - "index_path": ".workflow/.doc-index/doc-index.json", - "symbol_docs": [...] -} -``` - -2. Write to session folder: `{sessionFolder}/.process/doc-context-package.json` -3. Store relative path for task.json population: `../.process/doc-context-package.json` - -**Error handling**: If write fails → log warning → continue without context package (backward compatible). - ---- - -## Phase 2: Doc-Index-Guided Exploration (NEW) - -Use Phase 1 results to **SELECT exploration angles intelligently**: - -### 2.1 Angle Selection Logic - -| Phase 1 Signal | Add Exploration Angle | -|----------------|----------------------| -| feat-auth or security-related ADR affected | `security` | -| Multiple features crossed (2+) | `integration-points` | -| New component needed (no matching tech-*) | `architecture` | -| Performance-related requirements | `performance` | -| Default (always included) | `patterns` + `dependencies` | - -Select 1-4 angles total. More angles for higher complexity. - -### 2.2 Skip & Trigger Conditions - -| Complexity | Default Behavior | Override | -|-----------|-----------------|---------| -| **Low** | Auto-skip Phase 2 | `--explore` forces exploration | -| **Medium** | Ask user (unless `-y` → skip) | `--explore` forces, `--skip-explore` forces skip | -| **High** | Always run | `--skip-explore` forces skip | - -Skip Phase 2 entirely when: -- Complexity is Low AND `--explore` not set -- OR `--skip-explore` flag is set -- OR `-y` flag AND complexity is Medium - -### 2.3 Parallel Exploration - -Launch 1-4 parallel `cli-explore-agent` runs: - -``` -For each selected angle: - Agent(subagent_type="cli-explore-agent", prompt=" - Explore codebase for: {user task description} - Angle: {angle} - - ## Doc-Index Context (pre-loaded) - Features affected: {feature names + IDs} - Components: {component names + code locations} - Requirements: {requirement titles} - Architecture decisions: {ADR titles + decisions} - - Focus exploration on {angle}-specific concerns. - Output: explore-json-schema format. - ") -``` - -Each agent receives doc-index context (feature-maps, tech-registry docs) to avoid cold-start. - -### 2.4 Save Exploration Results - -- Each exploration → `exploration-{angle}.json` (explore-json-schema) -- Manifest → `explorations-manifest.json`: - -```json -{ - "explorations": [ - { "angle": "patterns", "path": "exploration-patterns.json", "file_count": 12 }, - { "angle": "security", "path": "exploration-security.json", "file_count": 8 } - ], - "total_files_discovered": 18, - "timestamp": "ISO8601" -} -``` - ---- - -## Phase 3: Clarification (NEW) - -### 3.1 Aggregate Clarification Needs - -Collect from three sources: -1. **Exploration results**: `clarification_needs[]` from each exploration JSON -2. **Doc-index gaps**: unmapped requirements, orphan components, missing feature coverage -3. **Conflicting constraints**: contradictory architecture decisions, requirement priority conflicts - -### 3.2 Deduplicate & Batch - -- Merge duplicate/similar questions across exploration angles -- Group into rounds (max 4 questions per AskUserQuestion call) -- Prioritize: blocking questions first, nice-to-have last - -### 3.3 Skip Conditions - -Skip Phase 3 when: -- `-y` flag is set -- `--skip-clarify` flag is set -- No clarification needs collected from any source -- Complexity is Low AND Phase 2 was skipped (no exploration results to aggregate) - -### 3.4 Execute Clarification - -``` -AskUserQuestion(questions=[ - { - question: "Which authentication strategy should the new endpoint use?", - header: "Auth strategy", - options: [ - { label: "JWT Bearer (Recommended)", description: "Consistent with ADR-001 and existing auth middleware" }, - { label: "API Key", description: "Simpler but inconsistent with current architecture" }, - { label: "OAuth2", description: "Most flexible but higher implementation cost" } - ], - multiSelect: false - } -]) -``` - -Feed answers back into Phase 4 as constraints. - ---- - -## Phase 4: Task Planning (NEW — produces plan.json + TASK-*.json) - -### 4.1 Planning Strategy Selection - -| Complexity | Strategy | -|-----------|---------| -| Low | Direct Claude planning (inline) | -| Medium | cli-lite-planning-agent with doc-index context | -| High | cli-lite-planning-agent with full exploration + doc-index context | - -### 4.2 Planning Input Assembly - -Combine: -- User's original task description -- Phase 1 impact map (features, requirements, components, ADRs) -- Phase 2 exploration results (if executed) -- Phase 3 clarification answers (if collected) -- Relevant feature-map and tech-registry doc excerpts - -### 4.3 Execute Planning - -For **Low complexity** (direct): -``` -Generate plan.json + TASK-*.json directly based on assembled context. -``` - -For **Medium/High complexity**: -``` -Agent(subagent_type="cli-lite-planning-agent", prompt=" - Task: {user task description} - - ## Doc-Index Impact Map - {Phase 1 results} - - ## Exploration Context - {Phase 2 results summary} - - ## Clarification Answers - {Phase 3 answers} - - ## Architecture Constraints - {ADR excerpts} - - Generate plan following plan-overview-base-schema. - Generate tasks following task-schema. - Include doc_context in both plan.json and each TASK-*.json. -") -``` - -### 4.3.1 Populate Task Artifacts (TASK-002) - -After task generation, enrich each TASK-*.json with artifacts[] field: - -1. Load doc-index.json from `.workflow/.doc-index/doc-index.json` -2. For each task, extract feature_ids from task.doc_context -3. Filter doc-index features/requirements matching task scope: - - Match by feature_ids in task.doc_context.feature_ids - - Include linked requirements via requirementIds - - Include linked components via componentIds -4. Populate task.artifacts[] with filtered references: - -```json -{ - "artifacts": [ - { - "type": "feature_spec", - "source": "doc-index", - "path": ".workflow/.doc-index/feature-maps/auth.md", - "feature_id": "feat-auth", - "usage": "Reference for authentication requirements" - }, - { - "type": "requirement", - "source": "doc-index", - "path": ".workflow/.doc-index/doc-index.json#requirements[0]", - "feature_id": "feat-auth", - "requirement_id": "REQ-001", - "usage": "Acceptance criteria source" - }, - { - "type": "component_doc", - "source": "doc-index", - "path": ".workflow/.doc-index/tech-registry/auth-service.md", - "component_id": "tech-auth-service", - "usage": "Implementation reference" - } - ] -} -``` - -**Loading pattern** (following brainstorm pattern from action-planning-agent.md:200-214): -- Load doc-index.json once for catalog -- Filter by task-relevant feature IDs (1-3 per task) -- Only include artifacts directly referenced in task scope -- Use relative paths from task file location - -### 4.3.2 Populate Context Package Path (TASK-001) - -Set context_package_path field in each TASK-*.json: - -```json -{ - "context_package_path": "../.process/doc-context-package.json" -} -``` - -Relative path from `.task/TASK-*.json` to `.process/doc-context-package.json`. - -### 4.3.3 Add Navigation Links Block (TASK-003) - -Add links{} navigation block to each TASK-*.json for improved discoverability: - -```json -{ - "links": { - "plan": "../plan.json", - "doc_index": "../../../doc-index.json", - "feature_maps": [ - "../../../feature-maps/auth.md" - ], - "related_tasks": [ - "TASK-002.json", - "TASK-003.json" - ] - } -} -``` - -**Path computation**: -- `plan`: Relative path from `.task/TASK-*.json` to `plan.json` (sibling of .task/) -- `doc_index`: Relative path to `.workflow/.doc-index/doc-index.json` -- `feature_maps`: Paths to feature-map docs from task.doc_context.feature_docs -- `related_tasks`: Task IDs from task.depends_on or tasks sharing same feature_ids - -**Backward compatibility**: links{} is optional field (task-schema allows additionalProperties). - -### 4.4 Output Schema: plan.json - -Follows `plan-overview-base-schema` with ddd-specific `doc_context` extension: - -```json -{ - "summary": "...", - "approach": "...", - "task_ids": ["TASK-001", "TASK-002"], - "task_count": 2, - "complexity": "Medium", - "doc_context": { - "affected_features": ["feat-auth"], - "affected_requirements": ["REQ-001", "REQ-002"], - "affected_components": ["tech-auth-service"], - "architecture_constraints": ["ADR-001"], - "index_path": ".workflow/.doc-index/doc-index.json", - "symbol_docs": [ - { - "symbol_urn": "deepwiki:symbol:#L-L", - "name": "SymbolName", - "type": "class|function|method", - "doc_summary": "Generated documentation summary...", - "source_path": "src/path/to/file.ts", - "doc_path": ".deepwiki/file.md", - "freshness": "fresh|stale|unknown" - } - ] - }, - "_metadata": { - "timestamp": "ISO8601", - "source": "cli-lite-planning-agent", - "plan_type": "feature", - "schema_version": "2.0", - "exploration_angles": ["patterns", "security"] - } -} -``` - -### 4.5 Output Schema: TASK-*.json - -Follows `task-schema` with ddd-specific `doc_context` extension: - -```json -{ - "id": "TASK-001", - "title": "Add rate limiting middleware", - "description": "...", - "depends_on": [], - "convergence": { - "criteria": ["Rate limiter middleware exists and is registered", "Tests pass"], - "verification": "npm test -- --grep rate-limit", - "definition_of_done": "API endpoints enforce rate limits per ADR-001 specifications" - }, - "doc_context": { - "feature_ids": ["feat-auth"], - "requirement_ids": ["REQ-001"], - "component_ids": ["tech-auth-service"], - "adr_ids": ["ADR-001"], - "feature_docs": ["feature-maps/auth.md"], - "component_docs": ["tech-registry/auth-service.md"], - "symbol_docs": [ - { - "symbol_urn": "deepwiki:symbol:#L-L", - "name": "SymbolName", - "type": "class|function|method", - "doc_summary": "Generated documentation summary...", - "source_path": "src/path/to/file.ts", - "doc_path": ".deepwiki/file.md", - "freshness": "fresh|stale|unknown" - } - ] - }, - "files": [...], - "implementation": [...] -} -``` - -### 4.6 Enrichment Rules - -Each task is enriched with: -- `feature_ids`, `requirement_ids`, `component_ids`, `adr_ids` — traced from Phase 1 -- Relevant feature-map and tech-registry doc paths -- Requirement acceptance criteria as convergence criteria source -- ADR decisions as implementation constraints - ---- - -## Phase 5: Confirmation & Handoff Selection - -### 5.1 Display Plan Summary - -Show: -- Plan overview (summary, approach, complexity) -- Task list with dependencies -- Doc-index impact: which features/requirements/components will be affected -- Estimated scope - -### 5.2 Handoff Options - -| Option | Description | When | -|--------|-------------|------| -| **ddd:execute** | Document-aware execution (recommended) | Default for ddd workflow | -| **lite-execute** | Standard execution (no doc awareness) | When doc traceability not needed | -| **direct** | Output context, manual work | User prefers manual coding | -| **stop** | Planning only, no execution | Research/analysis tasks | - -### 5.3 Auto-Selection - -With `-y`: auto-select `ddd:execute`. - -Without `-y`: present options via AskUserQuestion. - ---- - -## Phase 6: Handoff - -### 6.1 Build Execution Context - -Build `executionContext` compatible with lite-execute format: - -```json -{ - "plan_path": ".workflow/.doc-index/planning/{slug}/plan.json", - "task_dir": ".workflow/.doc-index/planning/{slug}/.task/", - "doc_index_path": ".workflow/.doc-index/doc-index.json", - "exploration_manifest": ".workflow/.doc-index/planning/{slug}/explorations-manifest.json", - "original_input": "user's task description" -} -``` - -### 6.2 Invoke Selected Engine - -| Selection | Action | -|-----------|--------| -| `ddd:execute` | Invoke `/ddd:execute --in-memory` with executionContext | -| `lite-execute` | Invoke `/workflow:lite-execute` with plan.json path | -| `direct` | Display context package + file list for manual work | -| `stop` | Output plan summary, end here | - ---- - -## Flags - -| Flag | Effect | -|------|--------| -| `-y, --yes` | Skip clarification, auto-select ddd:execute | -| `--explore` | Force Phase 2 exploration even for Low complexity | -| `--skip-explore` | Skip Phase 2 (doc-index-guided exploration) | -| `--skip-clarify` | Skip Phase 3 (clarification) only | - -## Output - -- **Primary**: plan.json + TASK-*.json in session folder -- **Secondary**: planning-context.md (legacy format) -- **Exploration**: exploration-{angle}.json files (if Phase 2 ran) -- **Console**: Plan summary with doc-index impact - -## Integration Points - -- **Input from**: `doc-index.json` (built by `/ddd:index-build` or `/ddd:scan`) -- **Output to**: `/ddd:execute`, `/workflow:lite-execute`, `/ddd:sync` post-task -- **Schemas**: `plan-overview-ddd-schema.json` (plan output), `task-schema.json` + `task-ddd-extension-schema.json` (task output), `explore-json-schema.json` -- **Triggers**: Before any development task in ddd workflow diff --git a/.claude/commands/ddd/scan.md b/.claude/commands/ddd/scan.md deleted file mode 100644 index ac253b93..00000000 --- a/.claude/commands/ddd/scan.md +++ /dev/null @@ -1,365 +0,0 @@ ---- -name: scan -description: Scan existing codebase to build document index without specs. Analyzes code structure, infers features, discovers components, and reverse-engineers project knowledge graph. -argument-hint: "[-y|--yes] [--from-scratch] [--scope ] \"optional project description\"" -allowed-tools: TodoWrite(*), Agent(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*), mcp__ace-tool__search_context(*) ---- - -## Auto Mode - -When `--yes` or `-y`: Auto-confirm feature groupings, component naming, skip interactive review. - -# DDD Scan Command (/ddd:scan) - -## Purpose - -For **existing projects without specifications**: analyze codebase to construct the document index by reverse-engineering project structure. This is the code-first entry point — no spec-generator required. - -``` -Codebase → Components → Features (inferred) → Requirements (inferred) → doc-index.json -``` - -## When to Use - -- Existing project, no spec-generator outputs -- Want to start using doc-driven workflow on a legacy codebase -- Quick project mapping for onboarding or audit - -## Prerequisite - -- A codebase must exist (src/, lib/, app/, or similar source directories) -- Git repository recommended (for action history seeding) - -## Storage Location - -``` -.workflow/.doc-index/ -├── doc-index.json ← Central index (primary output) -├── feature-maps/ ← Inferred feature documentation -│ ├── _index.md -│ └── {feature-slug}.md -├── tech-registry/ ← Discovered component documentation -│ ├── _index.md -│ └── {component-slug}.md -└── action-logs/ ← Git history seeds - ├── _index.md - └── {act-hash}.md -``` - -## Phase 1: Project Structure Analysis - -### 1.1 Framework & Stack Detection - -```bash -ccw cli -p "PURPOSE: Analyze project structure, tech stack, and architecture for documentation indexing. -TASK: -• Detect language/framework from manifest files (package.json, go.mod, Cargo.toml, requirements.txt, etc.) -• Map directory structure: source dirs, test dirs, config dirs, entry points -• Identify architectural pattern: monolith, microservices, monorepo, library, CLI tool -• Detect key dependencies and their roles (ORM, HTTP framework, auth library, etc.) -• List all major source directories with brief purpose description -MODE: analysis -CONTEXT: @**/* -EXPECTED: JSON with: { - project_name, language, framework, architecture_pattern, - source_dirs: [{ path, purpose, file_count }], - dependencies: [{ name, role }], - entry_points: [{ path, description }] -} -CONSTRAINTS: Prioritize source directories | Ignore node_modules, dist, build, vendor" --tool gemini --mode analysis -``` - -### 1.2 Merge with project-tech.json - -If `.workflow/project-tech.json` exists, merge to reduce redundant analysis. - -## Phase 2: Component Discovery - -### 2.1 Deep Module Scan - -```bash -ccw cli -p "PURPOSE: Discover all significant code components/modules for documentation indexing. -TASK: -• For each source directory, identify distinct modules/components -• For each component extract: - - Name (class name, module name, or logical group) - - Type: service | controller | model | util | hook | route | config | middleware | component - - File paths (primary file + related files) - - Exported symbols (public API: classes, functions, types, constants) - - Internal dependencies: what other modules it imports from within the project - - Responsibility: one-line description of what it does -• Group small utility files under parent module when they share domain -MODE: analysis -CONTEXT: @{source_dirs from Phase 1} -EXPECTED: JSON array: [{ name, type, files, symbols, depends_on, responsibility }] -CONSTRAINTS: Focus on business logic | Min threshold: components with 2+ exports or clear domain purpose | Group utilities under parent domain" --tool gemini --mode analysis -``` - -### 2.2 Generate Component IDs - -For each discovered component: -- ID: `tech-{kebab-case-name}` (e.g., `tech-auth-service`, `tech-user-model`) -- Validate uniqueness, append counter on collision - -### 2.3 Build Dependency Graph - -From `depends_on` fields, construct internal dependency edges: -``` -tech-auth-service → tech-user-model -tech-auth-service → tech-jwt-util -tech-order-controller → tech-auth-service -``` - -## Phase 3: Feature Inference - -**Key step: group components into logical features without formal specs.** - -### 3.1 Inference Strategy (priority order) - -``` -Strategy 1 — Directory grouping: - src/auth/** → feat-auth - src/orders/** → feat-orders - src/payments/** → feat-payments - -Strategy 2 — Route/endpoint grouping (web apps): - /api/users/* → feat-user-management - /api/orders/* → feat-order-management - -Strategy 3 — Dependency clustering: - Components that heavily import each other → same feature - -Strategy 4 — Domain keyword extraction: - Class names + file names → domain terms → feature names -``` - -### 3.2 Gemini Feature Synthesis - -```bash -ccw cli -p "PURPOSE: Infer high-level features from discovered code components. This project has no formal specification. -TASK: -Given these discovered components: -{component list from Phase 2: names, types, files, responsibilities, dependencies} - -• Group them into logical features (3-10 features for a typical project) -• For each feature: - - name: human-readable (Chinese OK) - - component_ids: which components belong - - description: what the feature does (inferred from code) - - inferred_requirements: what this feature needs to accomplish (1-3 per feature) - - status: 'implemented' (code complete) or 'partial' (incomplete patterns) - - tags: search keywords -• Identify cross-cutting concerns (logging, auth middleware, error handling) as separate features -MODE: analysis -CONTEXT: {component list JSON} -EXPECTED: JSON: { features: [{ name, description, component_ids, inferred_requirements: [{ id, title }], status, tags }] } -CONSTRAINTS: Every component must belong to at least 1 feature | Prefer fewer broad features over many narrow ones" --tool gemini --mode analysis -``` - -### 3.3 Interactive Feature Review (unless -y) - -Present inferred features to user: -- Allow renaming, merging, splitting -- Allow reassigning components between features -- Confirm final feature list - -## Phase 4: Implicit Requirement & Architecture Extraction - -### 4.1 Inferred Requirements - -For each feature, generate lightweight requirement entries from its components: - -``` -Feature: feat-auth (User Authentication) - → IREQ-001: "Users can log in with email and password" (from LoginController) - → IREQ-002: "JWT tokens for session management" (from AuthMiddleware + jwt dep) - → IREQ-003: "Password reset via email" (from PasswordResetService) -``` - -**ID Convention**: `IREQ-NNN` — distinguishes inferred from formal `REQ-NNN`. - -### 4.2 Inferred Architecture Decisions - -Detect patterns from code + dependencies: - -``` -Express.js + JWT middleware → IADR-001: "REST API with JWT authentication" -Prisma ORM + PostgreSQL → IADR-002: "PostgreSQL via Prisma ORM" -React + Redux → IADR-003: "React frontend with Redux state" -``` - -**ID Convention**: `IADR-NNN` — distinguishes inferred from formal `ADR-NNN`. - -### 4.3 Glossary Generation - -Extract domain terms from: -- Class/function names (CamelCase → terms) -- Key business terms in comments and strings -- Framework-specific terminology - -Write to `.workflow/.doc-index/glossary.json`. - -## Phase 5: Git History Seeds - -```bash -git log --oneline --since="3 months ago" --no-merges --format="%H|%s|%ai" | head -30 -``` - -For each significant commit: -- Match changed files to discovered components -- Create action entry with `type: "historical"` - -## Phase 6: Assemble doc-index.json - -Write the index with code-first markers: - -```json -{ - "version": "1.0", - "project": "{project-name}", - "build_path": "code-first", - "spec_session": null, - "last_updated": "ISO8601", - "glossary": [...], - "features": [{ - "id": "feat-{slug}", - "name": "Feature Name", - "epicId": null, - "status": "implemented|partial", - "docPath": "feature-maps/{slug}.md", - "requirementIds": ["IREQ-NNN"], - "tags": ["tag"] - }], - "requirements": [{ - "id": "IREQ-NNN", - "title": "Inferred requirement", - "source": "inferred", - "priority": "inferred", - "sourcePath": null, - "techComponentIds": ["tech-{slug}"], - "featureId": "feat-{slug}" - }], - "technicalComponents": [{ - "id": "tech-{slug}", - "name": "ComponentName", - "type": "service|controller|model|...", - "responsibility": "One-line description", - "adrId": "IADR-NNN|null", - "docPath": "tech-registry/{slug}.md", - "codeLocations": [{ "path": "src/...", "symbols": [...] }], - "dependsOn": ["tech-{other}"], - "featureIds": ["feat-{slug}"], - "actionIds": [] - }], - "architectureDecisions": [{ - "id": "IADR-NNN", - "title": "Inferred decision", - "source": "inferred", - "sourcePath": null, - "componentIds": ["tech-{slug}"] - }], - "actions": [{ - "id": "act-{short-hash}", - "description": "Commit message", - "type": "historical", - "status": "historical", - "affectedComponents": ["tech-{slug}"], - "relatedCommit": "full-hash", - "timestamp": "ISO8601" - }], - "freshness": { - "thresholds": { "warning": 0.3, "stale": 0.7 }, - "weights": { "time": 0.1, "churn": 0.4, "symbol": 0.5 }, - "time_decay_k": 0.05, - "auto_regenerate": false - }, - "deepwiki_feature_to_symbol_index": {} -} -``` - - -## Phase 7: Build DeepWiki Feature-to-Symbol Index - -If DeepWiki is available (`.codexlens/deepwiki_index.db` exists): - -1. Collect all `codeLocations[].path` from `technicalComponents[]` -2. Query DeepWiki: `POST /api/deepwiki/symbols-for-paths { paths: [...] }` -3. Build `deepwiki_feature_to_symbol_index` by traversing: - `feature → requirementIds → techComponentIds → codeLocations → symbols` - -```json -"deepwiki_feature_to_symbol_index": { - "feat-auth": [ - "deepwiki:symbol:src/auth/jwt.ts#L30-L55", - "deepwiki:symbol:src/models/user.ts#L12-L40" - ] -} -``` - -**Symbol URN format**: `deepwiki:symbol:#L-L` - -**Graceful degradation**: If DeepWiki is unavailable, set `deepwiki_feature_to_symbol_index: {}` and log warning. - -## Phase 8: Generate Documents - -Delegate all document generation to `/ddd:doc-generate`: - -``` -Invoke /ddd:doc-generate [-y] -``` - -This generates the complete document tree (Layer 3 → 2 → 1): -- `tech-registry/{slug}.md` — component docs (Layer 3) -- `feature-maps/{slug}.md` — feature docs (Layer 2) -- `_index.md`, `README.md`, `ARCHITECTURE.md`, `SCHEMA.md` — index/overview docs (Layer 1) - -See `/ddd:doc-generate` for full details on generation strategy and flags. - -## Phase 9: Validation & Report - -``` -Scan Report - -Project: {name} ({language}/{framework}) -Architecture: {pattern} -Source dirs: {N} - -Discovered: - Components: {N} ({by type breakdown}) - Features: {N} (inferred) - Requirements: {N} (IREQ, inferred) - Architecture Decisions: {N} (IADR, inferred) - Historical Actions: {N} (from git) - -Coverage: - Components → Features: {%} - Dependencies mapped: {%} - -Recommendations: - - Run /spec-generator to formalize {N} inferred requirements - - {N} components have unclear responsibility — review tech-registry docs - - Use /ddd:plan to start planning tasks with this index -``` - -## Flags - -| Flag | Effect | -|------|--------| -| `-y, --yes` | Auto-confirm all decisions | -| `--from-scratch` | Delete existing index and rebuild | -| `--scope ` | Limit scan to specific directory (e.g., `--scope src/auth`) | - -## Upgrade Path: scan → spec - -When a scanned project later runs `spec-generator` + `/ddd:index-build`: -- `/ddd:index-build` detects existing code-first index -- Merges: `IREQ-NNN` → `REQ-NNN`, `IADR-NNN` → `ADR-NNN` where content overlaps -- Updates `build_path` to `"spec-first"` -- Preserves all `tech-*` and `feat-*` entries (updates links only) - -## Integration Points - -- **Input from**: Codebase, git history, `project-tech.json` -- **Delegates to**: `/ddd:doc-generate` (Phase 8, full document generation) -- **Output to**: `ddd:plan`, `ddd:sync`, `ddd:update`, `ddd:index-build` (upgrade) -- **Standalone**: Can be used independently on any project diff --git a/.claude/commands/ddd/sync.md b/.claude/commands/ddd/sync.md deleted file mode 100644 index f8ec6b00..00000000 --- a/.claude/commands/ddd/sync.md +++ /dev/null @@ -1,353 +0,0 @@ ---- -name: sync -description: Post-task synchronization - update document index, generate action log, and refresh feature/component docs after completing a development task. -argument-hint: "[-y|--yes] [--dry-run] [--from-manifest ] [--task-id ] [--commit ] \"task summary\"" -allowed-tools: TodoWrite(*), Agent(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*), mcp__ace-tool__search_context(*) ---- - -## Auto Mode - -When `--yes` or `-y`: Auto-detect changes, auto-update all docs, skip review prompts. - -# DDD Sync Command (/ddd:sync) - -## Purpose - -After completing a development task, synchronize the document index with actual code changes: -1. **Analyze** what changed (git diff) -2. **Trace** which features/requirements/components are affected -3. **Update** index entries (status, code locations, links) -4. **Generate** action log entry -5. **Refresh** feature-map and tech-registry documents - -## When to Use: sync vs update - -| Scenario | Use | -|----------|-----| -| Task completed, ready to commit | **ddd:sync** — full post-task reconciliation | -| Mid-development, quick impact check | ddd:update | -| Pre-commit validation | ddd:update --check-only | -| Auto-triggered after ddd:execute | **ddd:sync** (automatic) | -| Periodic index refresh during refactoring | ddd:update | - -**Rule of thumb**: `sync` = task boundary (done something), `update` = development pulse (doing something). - -## Prerequisite - -- `doc-index.json` must exist -- Git repository with committed or staged changes - -## Phase 0: Consistency Validation - -Before processing changes, verify that `doc-index.json` entries are consistent with actual code state. - -### 0.1 Validate Code Locations - -For each `technicalComponents[].codeLocations[]`: -- Verify file exists on disk -- If file was deleted/moved → flag for removal or update -- If file exists → verify listed `symbols[]` still exist (quick grep/AST check) - -### 0.2 Validate Symbols - -For components with `codeLocations[].symbols[]`: -- Check each symbol still exists in the referenced file -- Detect new exported symbols not yet tracked -- Report: `{N} stale symbols, {N} untracked symbols` - -### 0.3 Validation Report - -``` -Consistency Check: - Components validated: {N} - Files verified: {N} - Stale references: {N} (files missing or symbols removed) - Untracked symbols: {N} (new exports not in index) -``` - -If stale references found: warn and auto-fix during Phase 3 updates. -If `--dry-run`: report only, no fixes. - -## Phase 1: Change Detection - -### 1.0.1 Schema Version Check - -Before processing changes, verify doc-index.json schema compatibility: - -```javascript -const docIndex = JSON.parse(Read('.workflow/.doc-index/doc-index.json')); -const schemaVersion = docIndex.schema_version || '0.0'; // Default for legacy - -if (schemaVersion !== '1.0') { - console.warn(`Schema version mismatch: found ${schemaVersion}, expected 1.0`); - console.warn('Consider running schema migration or regenerating doc-index with /ddd:scan'); - // Continue with degraded functionality - may encounter missing fields -} -``` - -**Graceful degradation**: If version mismatch detected → log warning → continue with caution (some features may not work as expected). - -### 1.0 Data Source Selection - -``` -IF --from-manifest : - Load execution-manifest.json - → files_modified[] provides precise file list + action type + task attribution - → TASK-*.result.json provides symbol-level changes + convergence results - → Skip Phase 1.1/1.2 (already classified by execute) - → Proceed directly to Phase 2 with manifest data -ELSE: - → Fall through to Phase 1.1 (git-based discovery) -``` - -**`--from-manifest` advantages** (used automatically by ddd:execute): -- Precise file → task attribution (which task modified which file) -- Symbol-level change tracking (not just file-level) -- Convergence verification results carried forward to action-log -- Survives process interruptions (manifest is persisted to disk) - -### 1.1 Identify Changes (git-based fallback) - -```bash -# If --commit provided: -git diff --name-only {commit}^..{commit} -git diff --stat {commit}^..{commit} - -# If --task-id provided, find related commits: -git log --oneline --grep="task-{id}" | head -10 - -# Otherwise: changes since last ddd:sync -git diff --name-only HEAD~1..HEAD -``` - -### 1.2 Classify Changes (git-based fallback) - -For each changed file, determine: -- **Type**: added | modified | deleted | renamed -- **Category**: source | test | config | docs | other -- **Symbols affected**: parse diff for changed functions/classes (use Gemini if complex) - -## Phase 2: Impact Tracing (Layer-Based, TASK-004) - -**Strategy**: Trace impact through layers (files → components → features → indexes) following memory-manage pattern. - -### 2.1 Match to Index - -For each changed file path: - -``` -Search doc-index.json.technicalComponents[].codeLocations[].path -→ Find matching component IDs (Layer 3) -→ From components, find linked featureIds (Layer 2) -→ From features, find linked requirementIds (Layer 2) -``` - -### 2.2 Discover New Components - -If changed files don't match any existing component: -- Flag as potential new component -- Ask user if it should be registered (or auto-register with `-y`) - -### 2.3 Build Impact Report - -```markdown -## Impact Summary - -### Changed Files (5) -- src/services/auth.ts (modified) → tech-auth-service → feat-auth -- src/models/user.ts (modified) → tech-user-model → feat-auth -- src/routes/login.ts (added) → NEW COMPONENT → feat-auth -- src/tests/auth.test.ts (modified) → [test file, skip] -- package.json (modified) → [config, skip] - -### Affected Features -- feat-auth: User Authentication (2 components modified, 1 new) - -### Affected Requirements -- REQ-001: Email login (implementation updated) -- REQ-002: JWT token generation (implementation updated) -``` - -## Phase 2.4: DeepWiki Freshness Check - -If DeepWiki integration is configured (`doc-index.json.freshness` exists): - -### 2.4.1 Identify Modified Files -From `execution-manifest.json` or git diff, collect `files_modified[]` with `action == "modified"`. - -### 2.4.2 Check Staleness -Query DeepWiki: `POST /api/deepwiki/stale-files { files: [{path, hash}] }` - -For each stale file's symbols, calculate staleness score: -``` -S(symbol) = min(1.0, w_t × T + w_c × C + w_s × M) -``` -Where weights come from `doc-index.json.freshness.weights`. - -### 2.4.3 Score Propagation (max aggregation) -``` -S_file = max(S_symbol_1, S_symbol_2, ...) -S_component = max(S_file_1, S_file_2, ...) -S_feature = max(S_component_1, S_component_2, ...) -``` - -### 2.4.4 Status Assignment -Using thresholds from `doc-index.json.freshness.thresholds`: -- `fresh`: score in [0, warning_threshold) -- `warning`: score in [warning_threshold, stale_threshold) -- `stale`: score in [stale_threshold, 1.0] - -### 2.4.5 Update Records -- Update `deepwiki_symbols.staleness_score` and `deepwiki_files.staleness_score` in DeepWiki SQLite -- Update `tech-registry/{slug}.md` YAML frontmatter with freshness block -- Update `feature-maps/{slug}.md` YAML frontmatter with freshness block -- Update `deepwiki_feature_to_symbol_index` in doc-index.json - -### 2.4.6 Staleness Report -Add to action-log: -- Number of stale symbols/files/components -- Top-5 most stale items with scores -- Auto-regeneration candidates (if `auto_regenerate: true` and score >= stale threshold) - -## Phase 3: Update Index - -### 3.0 Dry-Run Gate - -If `--dry-run` is set: -- Execute Phase 3 analysis (determine what would change) -- Display planned modifications as a preview report -- Skip all file writes (Phase 3.1-3.5 and Phase 4) -- Output: "Dry-run complete. Run without --dry-run to apply changes." - -### 3.0.1 Backup Index - -Before any modifications, create backup: -- Copy `doc-index.json` → `doc-index.json.bak` -- On failure: restore from `.bak` and report error -- On success: remove `.bak` - -### 3.1 Update Technical Components - -For each affected component in `doc-index.json`: -- Update `codeLocations` if file paths or line ranges changed -- Update `symbols` if new exports were added -- Add new `actionIds` entry -- **Auto-update `responsibility`**: If symbols changed (new methods/exports added or removed), re-infer responsibility from current symbols list using Gemini analysis. This prevents stale descriptions (e.g., responsibility still says "登录、注册" after adding logout support) - -### 3.2 Register New Components - -For newly discovered components: -- Generate `tech-{slug}` ID -- Create entry in `technicalComponents[]` -- Link to appropriate features -- Generate new `tech-registry/{slug}.md` document - -### 3.3 Update Feature Status - -For each affected feature: -- If all requirements now have mapped components → `status: "implemented"` -- If some requirements still unmapped → `status: "in-progress"` - -### 3.4 Add Action Entry - -```json -{ - "id": "task-{id}", - "description": "{task summary from user}", - "type": "feature|bugfix|refactor", - "status": "completed", - "affectedFeatures": ["feat-auth"], - "affectedComponents": ["tech-auth-service", "tech-user-model"], - "changedFiles": [ - { "path": "src/services/auth.ts", "action": "modified", "task_id": "TASK-001" }, - { "path": "src/models/user.ts", "action": "modified", "task_id": "TASK-001" } - ], - "symbolsChanged": ["AuthService.validate", "UserModel.toJSON"], - "convergenceResults": { - "passed": 2, - "total": 2, - "details": ["Rate limiter middleware exists", "Config accepts per-route limits"] - }, - "verifyGate": "PASS|WARN|FAIL|skipped", - "relatedCommit": "{commit hash}", - "manifestPath": "{execution-manifest.json path | null}", - "timestamp": "ISO8601" -} -``` - -### 3.5 Update Timestamp - -Set `doc-index.json.last_updated` to current time. - -## Phase 4: Refresh Documents & Action Log - -### 4.1 Delegate Document Refresh to /ddd:doc-refresh - -From Phase 2 impact tracing, collect affected component and feature IDs, then delegate: - -``` -Invoke /ddd:doc-refresh [-y] --components {affected_component_ids} --features {affected_feature_ids} -``` - -This handles Layer 3 → 2 → 1 selective document refresh. See `/ddd:doc-refresh` for full details. - -### 4.2 Generate Action Log Entry - -Create `.workflow/.doc-index/action-logs/{task-id}.md`: - -```markdown ---- -id: task-{id} -type: feature|bugfix|refactor -status: completed -features: [feat-auth] -components: [tech-auth-service, tech-user-model] -commit: {hash} -timestamp: ISO8601 ---- - -# Task: {summary} - -## Changes -| File | Type | Component | -|------|------|-----------| -| src/services/auth.ts | modified | tech-auth-service | - -## Impact -- Features affected: feat-auth -- Requirements addressed: REQ-001, REQ-002 - -## Staleness (if DeepWiki freshness enabled) -| Item | Type | Score | Status | -|------|------|-------|--------| -| {symbol/file/component} | {type} | {score} | {fresh/warning/stale} | - -## Notes -{any user-provided notes} -``` - -## Phase 5: Confirmation (unless -y) - -Present update summary to user: -- Files updated in doc-index -- New documents created -- Status changes -- Ask for confirmation before writing - -## Flags - -| Flag | Effect | -|------|--------| -| `-y, --yes` | Auto-confirm all updates | -| `--dry-run` | Preview all changes without modifying any files | -| `--from-manifest ` | Use execution-manifest.json as data source (auto-set by ddd:execute) | -| `--task-id ` | Associate with specific task ID | -| `--commit ` | Analyze specific commit | - -## Integration Points - -- **Input from**: `execution-manifest.json` (preferred, from ddd:execute) OR Git history (fallback), `doc-index.json`, `/ddd:plan` output -- **Delegates to**: `/ddd:doc-refresh` (Phase 4.1, selective document refresh) -- **Output to**: Updated `doc-index.json`, feature-maps/, tech-registry/, action-logs/ -- **Triggers**: After completing any development task -- **Data source priority**: `--from-manifest` > `--commit` > `--task-id` > git diff HEAD~1 diff --git a/.claude/commands/ddd/update.md b/.claude/commands/ddd/update.md deleted file mode 100644 index 05caa18e..00000000 --- a/.claude/commands/ddd/update.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -name: update -description: Incremental index update - detect code changes and trace impact to related features/requirements. Lightweight alternative to full sync. -argument-hint: "[-y|--yes] [--files ] [--staged] [--check-only]" -allowed-tools: TodoWrite(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*), mcp__ace-tool__search_context(*) ---- - -## Auto Mode - -When `--yes` or `-y`: Auto-update index without confirmation prompts. - -# DDD Update Command (/ddd:update) - -## Purpose - -Lightweight incremental update: given a set of changed files, trace their impact through the document index and update affected entries. Unlike `/ddd:sync` (full post-task sync), this command focuses on keeping the index fresh during development. - -## When to Use: update vs sync - -| Scenario | Use | -|----------|-----| -| Quick impact check during development | **ddd:update** | -| Preview what sync would change | **ddd:update --check-only** | -| Task completed, full reconciliation | ddd:sync | -| Register new components + update all docs | ddd:sync | - -**Rule of thumb**: `update` = lightweight pulse (during work), `sync` = full checkpoint (after work). - -## Use Cases - -1. **During development**: Quick check which docs are affected by current changes -2. **Pre-commit check**: Ensure index is up-to-date before committing -3. **Periodic refresh**: Update stale code locations after refactoring - -## Prerequisite - -- `doc-index.json` must exist at `.workflow/.doc-index/doc-index.json` - -## Phase 1: Identify Changed Files - -### Source Priority - -``` -1. --files → Explicit file list -2. --staged → git diff --cached --name-only -3. (default) → git diff --name-only (unstaged changes) -``` - -### Output - -List of changed file paths with change type (added/modified/deleted/renamed). - -## Phase 2: Trace Impact - -### 2.1 Forward Lookup (Code → Components → Features) - -For each changed file: - -``` -doc-index.json.technicalComponents[] - .codeLocations[].path MATCH changed_file - → component_ids[] - -doc-index.json.technicalComponents[component_ids] - .featureIds[] - → feature_ids[] - -doc-index.json.features[feature_ids] - .requirementIds[] - → requirement_ids[] -``` - -### 2.2 Orphan Detection - -Files not matching any component → flag as: -- **Potential new component**: if in src/ directory -- **Ignorable**: if in test/, docs/, config/ directories - -### 2.3 Impact Report - -``` -Impact Analysis for 3 changed files: - - src/services/auth.ts (modified) - → Component: tech-auth-service (AuthService) - → Feature: feat-auth (User Authentication) - → Requirements: REQ-001, REQ-002 - - src/middleware/rate-limit.ts (added) - → No matching component (new file) - → Suggested: Register as new component - - src/utils/hash.ts (modified) - → Component: tech-hash-util - → Features: feat-auth, feat-password-reset - → Requirements: REQ-001, REQ-005 -``` - -## Phase 3: Update Index (unless --check-only) - -### 3.1 Update Code Locations - -For matched components: -- If file was renamed → update `codeLocations[].path` -- If file was deleted → remove code location entry -- If symbols changed → update `symbols` list (requires AST or Gemini analysis) - -### 3.2 Register New Components (interactive unless -y) - -For orphan files in src/: -- Prompt user for component name and type -- Or auto-generate with `-y`: derive name from file path -- Create `technicalComponents[]` entry -- Ask which feature it belongs to (or auto-link by directory structure) - -### 3.3 Update Timestamps - -- Update `technicalComponents[].docPath` last_updated in corresponding .md -- Update `doc-index.json.last_updated` - -## Phase 4: Refresh Documents (if updates were made) - -### 4.1 Delegate to /ddd:doc-refresh - -From Phase 2 impact tracing, collect affected component and feature IDs, then delegate: - -``` -Invoke /ddd:doc-refresh [-y] --minimal --components {affected_component_ids} --features {affected_feature_ids} -``` - -The `--minimal` flag ensures only metadata/frontmatter is updated (code locations, timestamps), skipping full content regeneration. This keeps the update lightweight. - -See `/ddd:doc-refresh` for full details. - -### 4.2 Skip If --check-only - -With `--check-only`, skip Phase 3 and Phase 4 entirely — only output the impact report. - -## Flags - -| Flag | Effect | -|------|--------| -| `-y, --yes` | Auto-confirm updates | -| `--files ` | Explicit comma-separated file list | -| `--staged` | Analyze staged (git cached) files | -| `--check-only` | Report impact without modifying index | - -## Output - -- **Console**: Impact report showing affected features/requirements -- **Updated**: `doc-index.json` (if not --check-only) -- **Updated**: Affected tech-registry/ and feature-maps/ docs - -## Integration Points - -- **Input from**: Git working tree, `doc-index.json` -- **Delegates to**: `/ddd:doc-refresh` (Phase 4.1, incremental document refresh with --minimal) -- **Output to**: Updated `doc-index.json`, impact report -- **Triggers**: During development, pre-commit, or periodic refresh -- **Can chain to**: `/ddd:sync` for full post-task synchronization diff --git a/.claude/commands/idaw/add.md b/.claude/commands/idaw/add.md deleted file mode 100644 index 6434b7a4..00000000 --- a/.claude/commands/idaw/add.md +++ /dev/null @@ -1,287 +0,0 @@ ---- -name: add -description: Add IDAW tasks - manual creation or import from ccw issue -argument-hint: "[-y|--yes] [--from-issue [,,...]] \"description\" [--type ] [--priority <1-5>]" -allowed-tools: AskUserQuestion(*), Read(*), Bash(*), Write(*), Glob(*) ---- - -# IDAW Add Command (/idaw:add) - -## Auto Mode - -When `--yes` or `-y`: Skip clarification questions, create task with inferred details. - -## IDAW Task Schema - -```json -{ - "id": "IDAW-001", - "title": "string", - "description": "string", - "status": "pending", - "priority": 2, - "task_type": null, - "skill_chain": null, - "context": { - "affected_files": [], - "acceptance_criteria": [], - "constraints": [], - "references": [] - }, - "source": { - "type": "manual|import-issue", - "issue_id": null, - "issue_snapshot": null - }, - "execution": { - "session_id": null, - "started_at": null, - "completed_at": null, - "skill_results": [], - "git_commit": null, - "error": null - }, - "created_at": "ISO", - "updated_at": "ISO" -} -``` - -**Valid task_type values**: `bugfix|bugfix-hotfix|feature|feature-complex|refactor|tdd|test|test-fix|review|docs` - -## Implementation - -### Phase 1: Parse Arguments - -```javascript -const args = $ARGUMENTS; -const autoYes = /(-y|--yes)\b/.test(args); -const fromIssue = args.match(/--from-issue\s+([\w,-]+)/)?.[1]; -const typeFlag = args.match(/--type\s+([\w-]+)/)?.[1]; -const priorityFlag = args.match(/--priority\s+(\d)/)?.[1]; - -// Extract description: content inside quotes (preferred), or fallback to stripping flags -const quotedMatch = args.match(/(?:^|\s)["']([^"']+)["']/); -const description = quotedMatch - ? quotedMatch[1].trim() - : args.replace(/(-y|--yes|--from-issue\s+[\w,-]+|--type\s+[\w-]+|--priority\s+\d)/g, '').trim(); -``` - -### Phase 2: Route — Import or Manual - -``` ---from-issue present? - ├─ YES → Import Mode (Phase 3A) - └─ NO → Manual Mode (Phase 3B) -``` - -### Phase 3A: Import Mode (from ccw issue) - -```javascript -const issueIds = fromIssue.split(','); - -// Fetch all issues once (outside loop) -let issues = []; -try { - const issueJson = Bash(`ccw issue list --json`); - issues = JSON.parse(issueJson).issues || []; -} catch (e) { - console.log(`Error fetching CCW issues: ${e.message || e}`); - console.log('Ensure ccw is installed and issues exist. Use /issue:new to create issues first.'); - return; -} - -for (const issueId of issueIds) { - // 1. Find issue data - const issue = issues.find(i => i.id === issueId.trim()); - if (!issue) { - console.log(`Warning: Issue ${issueId} not found, skipping`); - continue; - } - - // 2. Check duplicate (same issue_id already imported) - const existing = Glob('.workflow/.idaw/tasks/IDAW-*.json'); - for (const f of existing) { - const data = JSON.parse(Read(f)); - if (data.source?.issue_id === issueId.trim()) { - console.log(`Warning: Issue ${issueId} already imported as ${data.id}, skipping`); - continue; // skip to next issue - } - } - - // 3. Generate next IDAW ID - const nextId = generateNextId(); - - // 4. Map issue → IDAW task - const task = { - id: nextId, - title: issue.title, - description: issue.context || issue.title, - status: 'pending', - priority: parseInt(priorityFlag) || issue.priority || 3, - task_type: typeFlag || inferTaskType(issue.title, issue.context || ''), - skill_chain: null, - context: { - affected_files: issue.affected_components || [], - acceptance_criteria: [], - constraints: [], - references: issue.source_url ? [issue.source_url] : [] - }, - source: { - type: 'import-issue', - issue_id: issue.id, - issue_snapshot: { - id: issue.id, - title: issue.title, - status: issue.status, - context: issue.context, - priority: issue.priority, - created_at: issue.created_at - } - }, - execution: { - session_id: null, - started_at: null, - completed_at: null, - skill_results: [], - git_commit: null, - error: null - }, - created_at: new Date().toISOString(), - updated_at: new Date().toISOString() - }; - - // 5. Write task file - Bash('mkdir -p .workflow/.idaw/tasks'); - Write(`.workflow/.idaw/tasks/${nextId}.json`, JSON.stringify(task, null, 2)); - console.log(`Created ${nextId} from issue ${issueId}: ${issue.title}`); -} -``` - -### Phase 3B: Manual Mode - -```javascript -// 1. Validate description -if (!description && !autoYes) { - const answer = AskUserQuestion({ - questions: [{ - question: 'Please provide a task description:', - header: 'Task', - multiSelect: false, - options: [ - { label: 'Provide description', description: 'What needs to be done?' } - ] - }] - }); - // Use custom text from "Other" - description = answer.customText || ''; -} - -if (!description) { - console.log('Error: No description provided. Usage: /idaw:add "task description"'); - return; -} - -// 2. Generate next IDAW ID -const nextId = generateNextId(); - -// 3. Build title from first sentence -const title = description.split(/[.\n]/)[0].substring(0, 80).trim(); - -// 4. Determine task_type -const taskType = typeFlag || null; // null → inferred at run time - -// 5. Create task -const task = { - id: nextId, - title: title, - description: description, - status: 'pending', - priority: parseInt(priorityFlag) || 3, - task_type: taskType, - skill_chain: null, - context: { - affected_files: [], - acceptance_criteria: [], - constraints: [], - references: [] - }, - source: { - type: 'manual', - issue_id: null, - issue_snapshot: null - }, - execution: { - session_id: null, - started_at: null, - completed_at: null, - skill_results: [], - git_commit: null, - error: null - }, - created_at: new Date().toISOString(), - updated_at: new Date().toISOString() -}; - -Bash('mkdir -p .workflow/.idaw/tasks'); -Write(`.workflow/.idaw/tasks/${nextId}.json`, JSON.stringify(task, null, 2)); -console.log(`Created ${nextId}: ${title}`); -``` - -## Helper Functions - -### ID Generation - -```javascript -function generateNextId() { - const files = Glob('.workflow/.idaw/tasks/IDAW-*.json') || []; - if (files.length === 0) return 'IDAW-001'; - - const maxNum = files - .map(f => parseInt(f.match(/IDAW-(\d+)/)?.[1] || '0')) - .reduce((max, n) => Math.max(max, n), 0); - - return `IDAW-${String(maxNum + 1).padStart(3, '0')}`; -} -``` - -### Task Type Inference (deferred — used at run time if task_type is null) - -```javascript -function inferTaskType(title, description) { - const text = `${title} ${description}`.toLowerCase(); - if (/urgent|production|critical/.test(text) && /fix|bug/.test(text)) return 'bugfix-hotfix'; - if (/refactor|重构|tech.*debt/.test(text)) return 'refactor'; - if (/tdd|test-driven|test first/.test(text)) return 'tdd'; - if (/test fail|fix test|failing test/.test(text)) return 'test-fix'; - if (/generate test|写测试|add test/.test(text)) return 'test'; - if (/review|code review/.test(text)) return 'review'; - if (/docs|documentation|readme/.test(text)) return 'docs'; - if (/fix|bug|error|crash|fail/.test(text)) return 'bugfix'; - if (/complex|multi-module|architecture/.test(text)) return 'feature-complex'; - return 'feature'; -} -``` - -## Examples - -```bash -# Manual creation -/idaw:add "Fix login timeout bug" --type bugfix --priority 2 -/idaw:add "Add rate limiting to API endpoints" --priority 1 -/idaw:add "Refactor auth module to use strategy pattern" - -# Import from ccw issue -/idaw:add --from-issue ISS-20260128-001 -/idaw:add --from-issue ISS-20260128-001,ISS-20260128-002 --priority 1 - -# Auto mode (skip clarification) -/idaw:add -y "Quick fix for typo in header" -``` - -## Output - -``` -Created IDAW-001: Fix login timeout bug - Type: bugfix | Priority: 2 | Source: manual - → Next: /idaw:run or /idaw:status -``` diff --git a/.claude/commands/idaw/resume.md b/.claude/commands/idaw/resume.md deleted file mode 100644 index 05ec4d7c..00000000 --- a/.claude/commands/idaw/resume.md +++ /dev/null @@ -1,442 +0,0 @@ ---- -name: resume -description: Resume interrupted IDAW session from last checkpoint -argument-hint: "[-y|--yes] [session-id]" -allowed-tools: Skill(*), TodoWrite(*), AskUserQuestion(*), Read(*), Write(*), Bash(*), Glob(*) ---- - -# IDAW Resume Command (/idaw:resume) - -## Auto Mode - -When `--yes` or `-y`: Auto-skip interrupted task, continue with remaining. - -## Skill Chain Mapping - -```javascript -const SKILL_CHAIN_MAP = { - 'bugfix': ['workflow-lite-plan', 'workflow-test-fix'], - 'bugfix-hotfix': ['workflow-lite-plan'], - 'feature': ['workflow-lite-plan', 'workflow-test-fix'], - 'feature-complex': ['workflow-plan', 'workflow-execute', 'workflow-test-fix'], - 'refactor': ['workflow:refactor-cycle'], - 'tdd': ['workflow-tdd-plan', 'workflow-execute'], - 'test': ['workflow-test-fix'], - 'test-fix': ['workflow-test-fix'], - 'review': ['review-cycle'], - 'docs': ['workflow-lite-plan'] -}; -``` - -## Task Type Inference - -```javascript -function inferTaskType(title, description) { - const text = `${title} ${description}`.toLowerCase(); - if (/urgent|production|critical/.test(text) && /fix|bug/.test(text)) return 'bugfix-hotfix'; - if (/refactor|重构|tech.*debt/.test(text)) return 'refactor'; - if (/tdd|test-driven|test first/.test(text)) return 'tdd'; - if (/test fail|fix test|failing test/.test(text)) return 'test-fix'; - if (/generate test|写测试|add test/.test(text)) return 'test'; - if (/review|code review/.test(text)) return 'review'; - if (/docs|documentation|readme/.test(text)) return 'docs'; - if (/fix|bug|error|crash|fail/.test(text)) return 'bugfix'; - if (/complex|multi-module|architecture/.test(text)) return 'feature-complex'; - return 'feature'; -} -``` - -## Implementation - -### Phase 1: Find Resumable Session - -```javascript -const args = $ARGUMENTS; -const autoYes = /(-y|--yes)/.test(args); -const targetSessionId = args.replace(/(-y|--yes)/g, '').trim(); - -let session = null; -let sessionDir = null; - -if (targetSessionId) { - // Load specific session - sessionDir = `.workflow/.idaw/sessions/${targetSessionId}`; - try { - session = JSON.parse(Read(`${sessionDir}/session.json`)); - } catch { - console.log(`Session "${targetSessionId}" not found.`); - console.log('Use /idaw:status to list sessions, or /idaw:run to start a new one.'); - return; - } -} else { - // Find most recent running session - const sessionFiles = Glob('.workflow/.idaw/sessions/IDA-*/session.json') || []; - - for (const f of sessionFiles) { - try { - const s = JSON.parse(Read(f)); - if (s.status === 'running') { - session = s; - sessionDir = f.replace(/\/session\.json$/, '').replace(/\\session\.json$/, ''); - break; - } - } catch { - // Skip malformed - } - } - - if (!session) { - console.log('No running sessions found to resume.'); - console.log('Use /idaw:run to start a new execution.'); - return; - } -} - -console.log(`Resuming session: ${session.session_id}`); -``` - -### Phase 2: Handle Interrupted Task - -```javascript -// Find the task that was in_progress when interrupted -let currentTaskId = session.current_task; -let currentTask = null; - -if (currentTaskId) { - try { - currentTask = JSON.parse(Read(`.workflow/.idaw/tasks/${currentTaskId}.json`)); - } catch { - console.log(`Warning: Could not read task ${currentTaskId}`); - currentTaskId = null; - } -} - -if (currentTask && currentTask.status === 'in_progress') { - if (autoYes) { - // Auto: skip interrupted task - currentTask.status = 'skipped'; - currentTask.execution.error = 'Skipped on resume (auto mode)'; - currentTask.execution.completed_at = new Date().toISOString(); - currentTask.updated_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${currentTaskId}.json`, JSON.stringify(currentTask, null, 2)); - session.skipped.push(currentTaskId); - console.log(`Skipped interrupted task: ${currentTaskId}`); - } else { - const answer = AskUserQuestion({ - questions: [{ - question: `Task ${currentTaskId} was interrupted: "${currentTask.title}". How to proceed?`, - header: 'Resume', - multiSelect: false, - options: [ - { label: 'Retry', description: 'Reset to pending, re-execute from beginning' }, - { label: 'Skip', description: 'Mark as skipped, move to next task' } - ] - }] - }); - - if (answer.answers?.Resume === 'Skip') { - currentTask.status = 'skipped'; - currentTask.execution.error = 'Skipped on resume (user choice)'; - currentTask.execution.completed_at = new Date().toISOString(); - currentTask.updated_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${currentTaskId}.json`, JSON.stringify(currentTask, null, 2)); - session.skipped.push(currentTaskId); - } else { - // Retry: reset to pending - currentTask.status = 'pending'; - currentTask.execution.started_at = null; - currentTask.execution.completed_at = null; - currentTask.execution.skill_results = []; - currentTask.execution.error = null; - currentTask.updated_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${currentTaskId}.json`, JSON.stringify(currentTask, null, 2)); - } - } -} -``` - -### Phase 3: Build Remaining Task Queue - -```javascript -// Collect remaining tasks (pending, or the retried current task) -const allTaskIds = session.tasks; -const completedSet = new Set([...session.completed, ...session.failed, ...session.skipped]); - -const remainingTasks = []; -for (const taskId of allTaskIds) { - if (completedSet.has(taskId)) continue; - try { - const task = JSON.parse(Read(`.workflow/.idaw/tasks/${taskId}.json`)); - if (task.status === 'pending') { - remainingTasks.push(task); - } - } catch { - console.log(`Warning: Could not read task ${taskId}, skipping`); - } -} - -if (remainingTasks.length === 0) { - console.log('No remaining tasks to execute. Session complete.'); - session.status = 'completed'; - session.current_task = null; - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - return; -} - -// Sort: priority ASC, then ID ASC -remainingTasks.sort((a, b) => { - if (a.priority !== b.priority) return a.priority - b.priority; - return a.id.localeCompare(b.id); -}); - -console.log(`Remaining tasks: ${remainingTasks.length}`); - -// Append resume marker to progress.md -const progressFile = `${sessionDir}/progress.md`; -try { - const currentProgress = Read(progressFile); - Write(progressFile, currentProgress + `\n---\n**Resumed**: ${new Date().toISOString()}\n\n`); -} catch { - Write(progressFile, `# IDAW Progress — ${session.session_id}\n\n---\n**Resumed**: ${new Date().toISOString()}\n\n`); -} - -// Update TodoWrite -TodoWrite({ - todos: remainingTasks.map((t, i) => ({ - content: `IDAW:[${i + 1}/${remainingTasks.length}] ${t.title}`, - status: i === 0 ? 'in_progress' : 'pending', - activeForm: `Executing ${t.title}` - })) -}); -``` - -### Phase 4-6: Execute Remaining (reuse run.md main loop) - -Execute remaining tasks using the same Phase 4-6 logic from `/idaw:run`: - -```javascript -// Phase 4: Main Loop — identical to run.md Phase 4 -for (let taskIdx = 0; taskIdx < remainingTasks.length; taskIdx++) { - const task = remainingTasks[taskIdx]; - - // Resolve skill chain - const resolvedType = task.task_type || inferTaskType(task.title, task.description); - const chain = task.skill_chain || SKILL_CHAIN_MAP[resolvedType] || SKILL_CHAIN_MAP['feature']; - - // Update task → in_progress - task.status = 'in_progress'; - task.task_type = resolvedType; - task.execution.started_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2)); - - session.current_task = task.id; - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - - console.log(`\n--- [${taskIdx + 1}/${remainingTasks.length}] ${task.id}: ${task.title} ---`); - console.log(`Chain: ${chain.join(' → ')}`); - - // ━━━ Pre-Task CLI Context Analysis (for complex/bugfix tasks) ━━━ - if (['bugfix', 'bugfix-hotfix', 'feature-complex'].includes(resolvedType)) { - console.log(` Pre-analysis: gathering context for ${resolvedType} task...`); - const affectedFiles = (task.context?.affected_files || []).join(', '); - const preAnalysisPrompt = `PURPOSE: Pre-analyze codebase context for IDAW task before execution. -TASK: • Understand current state of: ${affectedFiles || 'files related to: ' + task.title} • Identify dependencies and risk areas • Note existing patterns to follow -MODE: analysis -CONTEXT: @**/* -EXPECTED: Brief context summary (affected modules, dependencies, risk areas) in 3-5 bullet points -CONSTRAINTS: Keep concise | Focus on execution-relevant context`; - const preAnalysis = Bash(`ccw cli -p '${preAnalysisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis 2>&1 || echo "Pre-analysis skipped"`); - task.execution.skill_results.push({ - skill: 'cli-pre-analysis', - status: 'completed', - context_summary: preAnalysis?.substring(0, 500), - timestamp: new Date().toISOString() - }); - } - - // Execute skill chain - let previousResult = null; - let taskFailed = false; - - for (let skillIdx = 0; skillIdx < chain.length; skillIdx++) { - const skillName = chain[skillIdx]; - const skillArgs = assembleSkillArgs(skillName, task, previousResult, autoYes, skillIdx === 0); - - console.log(` [${skillIdx + 1}/${chain.length}] ${skillName}`); - - try { - const result = Skill({ skill: skillName, args: skillArgs }); - previousResult = result; - task.execution.skill_results.push({ - skill: skillName, - status: 'completed', - timestamp: new Date().toISOString() - }); - } catch (error) { - // ━━━ CLI-Assisted Error Recovery ━━━ - console.log(` Diagnosing failure: ${skillName}...`); - const diagnosisPrompt = `PURPOSE: Diagnose why skill "${skillName}" failed during IDAW task execution. -TASK: • Analyze error: ${String(error).substring(0, 300)} • Check affected files: ${(task.context?.affected_files || []).join(', ') || 'unknown'} • Identify root cause • Suggest fix strategy -MODE: analysis -CONTEXT: @**/* | Memory: IDAW task ${task.id}: ${task.title} -EXPECTED: Root cause + actionable fix recommendation (1-2 sentences) -CONSTRAINTS: Focus on actionable diagnosis`; - const diagnosisResult = Bash(`ccw cli -p '${diagnosisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause 2>&1 || echo "CLI diagnosis unavailable"`); - - task.execution.skill_results.push({ - skill: `cli-diagnosis:${skillName}`, - status: 'completed', - diagnosis: diagnosisResult?.substring(0, 500), - timestamp: new Date().toISOString() - }); - - // Retry with diagnosis context - console.log(` Retry with diagnosis: ${skillName}`); - try { - const retryResult = Skill({ skill: skillName, args: skillArgs }); - previousResult = retryResult; - task.execution.skill_results.push({ - skill: skillName, - status: 'completed-retry-with-diagnosis', - timestamp: new Date().toISOString() - }); - } catch (retryError) { - task.execution.skill_results.push({ - skill: skillName, - status: 'failed', - error: String(retryError).substring(0, 200), - timestamp: new Date().toISOString() - }); - - if (autoYes) { - taskFailed = true; - break; - } - - const answer = AskUserQuestion({ - questions: [{ - question: `${skillName} failed after CLI diagnosis + retry: ${String(retryError).substring(0, 100)}`, - header: 'Error', - multiSelect: false, - options: [ - { label: 'Skip task', description: 'Mark as failed, continue' }, - { label: 'Abort', description: 'Stop run' } - ] - }] - }); - - if (answer.answers?.Error === 'Abort') { - task.status = 'failed'; - task.execution.error = String(retryError).substring(0, 200); - Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2)); - session.failed.push(task.id); - session.status = 'failed'; - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - return; - } - taskFailed = true; - break; - } - } - } - - // Phase 5: Checkpoint - if (taskFailed) { - task.status = 'failed'; - task.execution.error = 'Skill chain failed after retry'; - task.execution.completed_at = new Date().toISOString(); - session.failed.push(task.id); - } else { - // Git commit - const commitMsg = `feat(idaw): ${task.title} [${task.id}]`; - const diffCheck = Bash('git diff --stat HEAD 2>/dev/null || echo ""'); - const untrackedCheck = Bash('git ls-files --others --exclude-standard 2>/dev/null || echo ""'); - - if (diffCheck?.trim() || untrackedCheck?.trim()) { - Bash('git add -A'); - Bash(`git commit -m "$(cat <<'EOF'\n${commitMsg}\nEOF\n)"`); - const commitHash = Bash('git rev-parse --short HEAD 2>/dev/null')?.trim(); - task.execution.git_commit = commitHash; - } else { - task.execution.git_commit = 'no-commit'; - } - - task.status = 'completed'; - task.execution.completed_at = new Date().toISOString(); - session.completed.push(task.id); - } - - task.updated_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2)); - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - - // Append progress - const chain_str = chain.join(' → '); - const progressEntry = `## ${task.id} — ${task.title}\n- Status: ${task.status}\n- Chain: ${chain_str}\n- Commit: ${task.execution.git_commit || '-'}\n\n`; - const currentProgress = Read(`${sessionDir}/progress.md`); - Write(`${sessionDir}/progress.md`, currentProgress + progressEntry); -} - -// Phase 6: Report -session.status = session.failed.length > 0 && session.completed.length === 0 ? 'failed' : 'completed'; -session.current_task = null; -session.updated_at = new Date().toISOString(); -Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - -const summary = `\n---\n## Summary (Resumed)\n- Completed: ${session.completed.length}\n- Failed: ${session.failed.length}\n- Skipped: ${session.skipped.length}\n`; -const finalProgress = Read(`${sessionDir}/progress.md`); -Write(`${sessionDir}/progress.md`, finalProgress + summary); - -console.log('\n=== IDAW Resume Complete ==='); -console.log(`Session: ${session.session_id}`); -console.log(`Completed: ${session.completed.length} | Failed: ${session.failed.length} | Skipped: ${session.skipped.length}`); -``` - -## Helper Functions - -### assembleSkillArgs - -```javascript -function assembleSkillArgs(skillName, task, previousResult, autoYes, isFirst) { - let args = ''; - - if (isFirst) { - // Sanitize for shell safety - const goal = `${task.title}\n${task.description}` - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\$/g, '\\$') - .replace(/`/g, '\\`'); - args = `"${goal}"`; - if (task.task_type === 'bugfix-hotfix') args += ' --hotfix'; - } else if (previousResult?.session_id) { - args = `--session="${previousResult.session_id}"`; - } - - if (autoYes && !args.includes('-y') && !args.includes('--yes')) { - args = args ? `${args} -y` : '-y'; - } - - return args; -} -``` - -## Examples - -```bash -# Resume most recent running session (interactive) -/idaw:resume - -# Resume specific session -/idaw:resume IDA-auth-fix-20260301 - -# Resume with auto mode (skip interrupted, continue) -/idaw:resume -y - -# Resume specific session with auto mode -/idaw:resume -y IDA-auth-fix-20260301 -``` diff --git a/.claude/commands/idaw/run-coordinate.md b/.claude/commands/idaw/run-coordinate.md deleted file mode 100644 index 1ae42eb5..00000000 --- a/.claude/commands/idaw/run-coordinate.md +++ /dev/null @@ -1,648 +0,0 @@ ---- -name: run-coordinate -description: IDAW coordinator - execute task skill chains via external CLI with hook callbacks and git checkpoints -argument-hint: "[-y|--yes] [--task [,,...]] [--dry-run] [--tool ]" -allowed-tools: Agent(*), AskUserQuestion(*), Read(*), Write(*), Bash(*), Glob(*), Grep(*) ---- - -# IDAW Run Coordinate Command (/idaw:run-coordinate) - -Coordinator variant of `/idaw:run`: external CLI execution with background tasks and hook callbacks. - -**Execution Model**: `ccw cli -p "..." --tool --mode write` in background → hook callback → next step. - -**vs `/idaw:run`**: Direct `Skill()` calls (blocking, main process) vs `ccw cli` (background, external process). - -## When to Use - -| Scenario | Use | -|----------|-----| -| Standard IDAW execution (main process) | `/idaw:run` | -| External CLI execution (background, hook-driven) | `/idaw:run-coordinate` | -| Need `claude` or `gemini` as execution tool | `/idaw:run-coordinate --tool claude` | -| Long-running tasks, avoid context window pressure | `/idaw:run-coordinate` | - -## Skill Chain Mapping - -```javascript -const SKILL_CHAIN_MAP = { - 'bugfix': ['workflow-lite-plan', 'workflow-test-fix'], - 'bugfix-hotfix': ['workflow-lite-plan'], - 'feature': ['workflow-lite-plan', 'workflow-test-fix'], - 'feature-complex': ['workflow-plan', 'workflow-execute', 'workflow-test-fix'], - 'refactor': ['workflow:refactor-cycle'], - 'tdd': ['workflow-tdd-plan', 'workflow-execute'], - 'test': ['workflow-test-fix'], - 'test-fix': ['workflow-test-fix'], - 'review': ['review-cycle'], - 'docs': ['workflow-lite-plan'] -}; -``` - -## Task Type Inference - -```javascript -function inferTaskType(title, description) { - const text = `${title} ${description}`.toLowerCase(); - if (/urgent|production|critical/.test(text) && /fix|bug/.test(text)) return 'bugfix-hotfix'; - if (/refactor|重构|tech.*debt/.test(text)) return 'refactor'; - if (/tdd|test-driven|test first/.test(text)) return 'tdd'; - if (/test fail|fix test|failing test/.test(text)) return 'test-fix'; - if (/generate test|写测试|add test/.test(text)) return 'test'; - if (/review|code review/.test(text)) return 'review'; - if (/docs|documentation|readme/.test(text)) return 'docs'; - if (/fix|bug|error|crash|fail/.test(text)) return 'bugfix'; - if (/complex|multi-module|architecture/.test(text)) return 'feature-complex'; - return 'feature'; -} -``` - -## 6-Phase Execution (Coordinator Model) - -### Phase 1: Load Tasks - -```javascript -const args = $ARGUMENTS; -const autoYes = /(-y|--yes)/.test(args); -const dryRun = /--dry-run/.test(args); -const taskFilter = args.match(/--task\s+([\w,-]+)/)?.[1]?.split(',') || null; -const cliTool = args.match(/--tool\s+(\w+)/)?.[1] || 'claude'; - -// Load task files -const taskFiles = Glob('.workflow/.idaw/tasks/IDAW-*.json') || []; - -if (taskFiles.length === 0) { - console.log('No IDAW tasks found. Use /idaw:add to create tasks.'); - return; -} - -// Parse and filter -let tasks = taskFiles.map(f => JSON.parse(Read(f))); - -if (taskFilter) { - tasks = tasks.filter(t => taskFilter.includes(t.id)); -} else { - tasks = tasks.filter(t => t.status === 'pending'); -} - -if (tasks.length === 0) { - console.log('No pending tasks to execute. Use /idaw:add to add tasks or --task to specify IDs.'); - return; -} - -// Sort: priority ASC (1=critical first), then ID ASC -tasks.sort((a, b) => { - if (a.priority !== b.priority) return a.priority - b.priority; - return a.id.localeCompare(b.id); -}); -``` - -### Phase 2: Session Setup - -```javascript -// Generate session ID: IDA-{slug}-YYYYMMDD -const slug = tasks[0].title - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .substring(0, 20) - .replace(/-$/, ''); -const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, ''); -let sessionId = `IDA-${slug}-${dateStr}`; - -// Check collision -const existingSession = Glob(`.workflow/.idaw/sessions/${sessionId}/session.json`); -if (existingSession?.length > 0) { - sessionId = `${sessionId}-2`; -} - -const sessionDir = `.workflow/.idaw/sessions/${sessionId}`; -Bash(`mkdir -p "${sessionDir}"`); - -const session = { - session_id: sessionId, - mode: 'coordinate', // ★ Marks this as coordinator-mode session - cli_tool: cliTool, - status: 'running', - created_at: new Date().toISOString(), - updated_at: new Date().toISOString(), - tasks: tasks.map(t => t.id), - current_task: null, - current_skill_index: 0, - completed: [], - failed: [], - skipped: [], - prompts_used: [] -}; - -Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - -// Initialize progress.md -const progressHeader = `# IDAW Progress — ${sessionId} (coordinate mode)\nStarted: ${session.created_at}\nCLI Tool: ${cliTool}\n\n`; -Write(`${sessionDir}/progress.md`, progressHeader); -``` - -### Phase 3: Startup Protocol - -```javascript -// Check for existing running sessions -const runningSessions = Glob('.workflow/.idaw/sessions/IDA-*/session.json') - ?.map(f => { try { return JSON.parse(Read(f)); } catch { return null; } }) - .filter(s => s && s.status === 'running' && s.session_id !== sessionId) || []; - -if (runningSessions.length > 0 && !autoYes) { - const answer = AskUserQuestion({ - questions: [{ - question: `Found running session: ${runningSessions[0].session_id}. How to proceed?`, - header: 'Conflict', - multiSelect: false, - options: [ - { label: 'Resume existing', description: 'Use /idaw:resume instead' }, - { label: 'Start fresh', description: 'Continue with new session' }, - { label: 'Abort', description: 'Cancel this run' } - ] - }] - }); - if (answer.answers?.Conflict === 'Resume existing') { - console.log(`Use: /idaw:resume ${runningSessions[0].session_id}`); - return; - } - if (answer.answers?.Conflict === 'Abort') return; -} - -// Check git status -const gitStatus = Bash('git status --porcelain 2>/dev/null'); -if (gitStatus?.trim() && !autoYes) { - const answer = AskUserQuestion({ - questions: [{ - question: 'Working tree has uncommitted changes. How to proceed?', - header: 'Git', - multiSelect: false, - options: [ - { label: 'Continue', description: 'Proceed with dirty tree' }, - { label: 'Stash', description: 'git stash before running' }, - { label: 'Abort', description: 'Stop and handle manually' } - ] - }] - }); - if (answer.answers?.Git === 'Stash') Bash('git stash push -m "idaw-pre-run"'); - if (answer.answers?.Git === 'Abort') return; -} - -// Dry run -if (dryRun) { - console.log(`# Dry Run — ${sessionId} (coordinate mode, tool: ${cliTool})\n`); - for (const task of tasks) { - const taskType = task.task_type || inferTaskType(task.title, task.description); - const chain = task.skill_chain || SKILL_CHAIN_MAP[taskType] || SKILL_CHAIN_MAP['feature']; - console.log(`## ${task.id}: ${task.title}`); - console.log(` Type: ${taskType} | Priority: ${task.priority}`); - console.log(` Chain: ${chain.join(' → ')}`); - console.log(` CLI: ccw cli --tool ${cliTool} --mode write\n`); - } - console.log(`Total: ${tasks.length} tasks`); - return; -} -``` - -### Phase 4: Launch First Task (then wait for hook) - -```javascript -// Start with the first task, first skill -const firstTask = tasks[0]; -const resolvedType = firstTask.task_type || inferTaskType(firstTask.title, firstTask.description); -const chain = firstTask.skill_chain || SKILL_CHAIN_MAP[resolvedType] || SKILL_CHAIN_MAP['feature']; - -// Update task → in_progress -firstTask.status = 'in_progress'; -firstTask.task_type = resolvedType; -firstTask.execution.started_at = new Date().toISOString(); -Write(`.workflow/.idaw/tasks/${firstTask.id}.json`, JSON.stringify(firstAgent, null, 2)); - -// Update session -session.current_task = firstTask.id; -session.current_skill_index = 0; -session.updated_at = new Date().toISOString(); -Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - -// ━━━ Pre-Task CLI Context Analysis (for complex/bugfix tasks) ━━━ -if (['bugfix', 'bugfix-hotfix', 'feature-complex'].includes(resolvedType)) { - console.log(`Pre-analysis: gathering context for ${resolvedType} task...`); - const affectedFiles = (firstTask.context?.affected_files || []).join(', '); - const preAnalysisPrompt = `PURPOSE: Pre-analyze codebase context for IDAW task. -TASK: • Understand current state of: ${affectedFiles || 'files related to: ' + firstTask.title} • Identify dependencies and risk areas -MODE: analysis -CONTEXT: @**/* -EXPECTED: Brief context summary in 3-5 bullet points -CONSTRAINTS: Keep concise`; - Bash(`ccw cli -p '${preAnalysisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis 2>&1 || echo "Pre-analysis skipped"`); -} - -// Assemble prompt for first skill -const skillName = chain[0]; -const prompt = assembleCliPrompt(skillName, firstAgent, null, autoYes); - -session.prompts_used.push({ - task_id: firstTask.id, - skill_index: 0, - skill: skillName, - prompt: prompt, - timestamp: new Date().toISOString() -}); -session.updated_at = new Date().toISOString(); -Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - -// Launch via ccw cli in background -console.log(`[1/${tasks.length}] ${firstTask.id}: ${firstTask.title}`); -console.log(` Chain: ${chain.join(' → ')}`); -console.log(` Launching: ${skillName} via ccw cli --tool ${cliTool}`); - -Bash( - `ccw cli -p "${escapeForShell(prompt)}" --tool ${cliTool} --mode write`, - { run_in_background: true } -); - -// ★ STOP HERE — wait for hook callback -// Hook callback will trigger handleStepCompletion() below -``` - -### Phase 5: Hook Callback Handler (per-step completion) - -```javascript -// Called by hook when background CLI completes -async function handleStepCompletion(sessionId, cliOutput) { - const sessionDir = `.workflow/.idaw/sessions/${sessionId}`; - const session = JSON.parse(Read(`${sessionDir}/session.json`)); - - const taskId = session.current_task; - const task = JSON.parse(Read(`.workflow/.idaw/tasks/${taskId}.json`)); - - const resolvedType = task.task_type || inferTaskType(task.title, task.description); - const chain = task.skill_chain || SKILL_CHAIN_MAP[resolvedType] || SKILL_CHAIN_MAP['feature']; - const skillIdx = session.current_skill_index; - const skillName = chain[skillIdx]; - - // Parse CLI output for session ID - const parsedOutput = parseCliOutput(cliOutput); - - // Record skill result - task.execution.skill_results.push({ - skill: skillName, - status: parsedOutput.success ? 'completed' : 'failed', - session_id: parsedOutput.sessionId, - timestamp: new Date().toISOString() - }); - - // ━━━ Handle failure with CLI diagnosis ━━━ - if (!parsedOutput.success) { - console.log(` ${skillName} failed. Running CLI diagnosis...`); - const diagnosisPrompt = `PURPOSE: Diagnose why skill "${skillName}" failed during IDAW task. -TASK: • Analyze error output • Check affected files: ${(task.context?.affected_files || []).join(', ') || 'unknown'} -MODE: analysis -CONTEXT: @**/* | Memory: IDAW task ${task.id}: ${task.title} -EXPECTED: Root cause + fix recommendation -CONSTRAINTS: Actionable diagnosis`; - Bash(`ccw cli -p '${diagnosisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause 2>&1 || true`); - - task.execution.skill_results.push({ - skill: `cli-diagnosis:${skillName}`, - status: 'completed', - timestamp: new Date().toISOString() - }); - - // Retry once - console.log(` Retrying: ${skillName}`); - const retryPrompt = assembleCliPrompt(skillName, task, parsedOutput, true); - session.prompts_used.push({ - task_id: taskId, - skill_index: skillIdx, - skill: `${skillName}-retry`, - prompt: retryPrompt, - timestamp: new Date().toISOString() - }); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - Write(`.workflow/.idaw/tasks/${taskId}.json`, JSON.stringify(task, null, 2)); - - Bash( - `ccw cli -p "${escapeForShell(retryPrompt)}" --tool ${session.cli_tool} --mode write`, - { run_in_background: true } - ); - return; // Wait for retry hook - } - - // ━━━ Skill succeeded — advance ━━━ - const nextSkillIdx = skillIdx + 1; - - if (nextSkillIdx < chain.length) { - // More skills in this task's chain → launch next skill - session.current_skill_index = nextSkillIdx; - session.updated_at = new Date().toISOString(); - - const nextSkill = chain[nextSkillIdx]; - const nextPrompt = assembleCliPrompt(nextSkill, task, parsedOutput, true); - - session.prompts_used.push({ - task_id: taskId, - skill_index: nextSkillIdx, - skill: nextSkill, - prompt: nextPrompt, - timestamp: new Date().toISOString() - }); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - Write(`.workflow/.idaw/tasks/${taskId}.json`, JSON.stringify(task, null, 2)); - - console.log(` Next skill: ${nextSkill}`); - Bash( - `ccw cli -p "${escapeForShell(nextPrompt)}" --tool ${session.cli_tool} --mode write`, - { run_in_background: true } - ); - return; // Wait for next hook - } - - // ━━━ Task chain complete — git checkpoint ━━━ - const commitMsg = `feat(idaw): ${task.title} [${task.id}]`; - const diffCheck = Bash('git diff --stat HEAD 2>/dev/null || echo ""'); - const untrackedCheck = Bash('git ls-files --others --exclude-standard 2>/dev/null || echo ""'); - - if (diffCheck?.trim() || untrackedCheck?.trim()) { - Bash('git add -A'); - Bash(`git commit -m "$(cat <<'EOF'\n${commitMsg}\nEOF\n)"`); - const commitHash = Bash('git rev-parse --short HEAD 2>/dev/null')?.trim(); - task.execution.git_commit = commitHash; - } else { - task.execution.git_commit = 'no-commit'; - } - - task.status = 'completed'; - task.execution.completed_at = new Date().toISOString(); - task.updated_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${taskId}.json`, JSON.stringify(task, null, 2)); - - session.completed.push(taskId); - - // Append progress - const progressEntry = `## ${task.id} — ${task.title}\n` + - `- Status: completed\n` + - `- Type: ${task.task_type}\n` + - `- Chain: ${chain.join(' → ')}\n` + - `- Commit: ${task.execution.git_commit || '-'}\n` + - `- Mode: coordinate (${session.cli_tool})\n\n`; - const currentProgress = Read(`${sessionDir}/progress.md`); - Write(`${sessionDir}/progress.md`, currentProgress + progressEntry); - - // ━━━ Advance to next task ━━━ - const allTaskIds = session.tasks; - const completedSet = new Set([...session.completed, ...session.failed, ...session.skipped]); - const nextTaskId = allTaskIds.find(id => !completedSet.has(id)); - - if (nextTaskId) { - // Load next task - const nextTask = JSON.parse(Read(`.workflow/.idaw/tasks/${nextTaskId}.json`)); - const nextType = nextTask.task_type || inferTaskType(nextTask.title, nextTask.description); - const nextChain = nextTask.skill_chain || SKILL_CHAIN_MAP[nextType] || SKILL_CHAIN_MAP['feature']; - - nextTask.status = 'in_progress'; - nextTask.task_type = nextType; - nextTask.execution.started_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${nextTaskId}.json`, JSON.stringify(nextAgent, null, 2)); - - session.current_task = nextTaskId; - session.current_skill_index = 0; - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - - // Pre-analysis for complex tasks - if (['bugfix', 'bugfix-hotfix', 'feature-complex'].includes(nextType)) { - const affectedFiles = (nextTask.context?.affected_files || []).join(', '); - Bash(`ccw cli -p 'PURPOSE: Pre-analyze context for ${nextTask.title}. TASK: Check ${affectedFiles || "related files"}. MODE: analysis. EXPECTED: 3-5 bullet points.' --tool gemini --mode analysis 2>&1 || true`); - } - - const nextSkillName = nextChain[0]; - const nextPrompt = assembleCliPrompt(nextSkillName, nextAgent, null, true); - - session.prompts_used.push({ - task_id: nextTaskId, - skill_index: 0, - skill: nextSkillName, - prompt: nextPrompt, - timestamp: new Date().toISOString() - }); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - - const taskNum = session.completed.length + 1; - const totalTasks = session.tasks.length; - console.log(`\n[${taskNum}/${totalTasks}] ${nextTaskId}: ${nextTask.title}`); - console.log(` Chain: ${nextChain.join(' → ')}`); - - Bash( - `ccw cli -p "${escapeForShell(nextPrompt)}" --tool ${session.cli_tool} --mode write`, - { run_in_background: true } - ); - return; // Wait for hook - } - - // ━━━ All tasks complete — Phase 6: Report ━━━ - session.status = session.failed.length > 0 && session.completed.length === 0 ? 'failed' : 'completed'; - session.current_task = null; - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - - const summary = `\n---\n## Summary (coordinate mode)\n` + - `- CLI Tool: ${session.cli_tool}\n` + - `- Completed: ${session.completed.length}\n` + - `- Failed: ${session.failed.length}\n` + - `- Skipped: ${session.skipped.length}\n` + - `- Total: ${session.tasks.length}\n`; - const finalProgress = Read(`${sessionDir}/progress.md`); - Write(`${sessionDir}/progress.md`, finalProgress + summary); - - console.log('\n=== IDAW Coordinate Complete ==='); - console.log(`Session: ${sessionId}`); - console.log(`Completed: ${session.completed.length}/${session.tasks.length}`); - if (session.failed.length > 0) console.log(`Failed: ${session.failed.join(', ')}`); -} -``` - -## Helper Functions - -### assembleCliPrompt - -```javascript -function assembleCliPrompt(skillName, task, previousResult, autoYes) { - let prompt = ''; - const yFlag = autoYes ? ' -y' : ''; - - // Map skill to command invocation - if (skillName === 'workflow-lite-plan') { - const goal = sanitize(`${task.title}\n${task.description}`); - prompt = `/workflow-lite-plan${yFlag} "${goal}"`; - if (task.task_type === 'bugfix') prompt = `/workflow-lite-plan${yFlag} --bugfix "${goal}"`; - if (task.task_type === 'bugfix-hotfix') prompt = `/workflow-lite-plan${yFlag} --hotfix "${goal}"`; - - } else if (skillName === 'workflow-plan') { - prompt = `/workflow-plan${yFlag} "${sanitize(task.title)}"`; - - } else if (skillName === 'workflow-execute') { - if (previousResult?.sessionId) { - prompt = `/workflow-execute${yFlag} --resume-session="${previousResult.sessionId}"`; - } else { - prompt = `/workflow-execute${yFlag}`; - } - - } else if (skillName === 'workflow-test-fix') { - if (previousResult?.sessionId) { - prompt = `/workflow-test-fix${yFlag} "${previousResult.sessionId}"`; - } else { - prompt = `/workflow-test-fix${yFlag} "${sanitize(task.title)}"`; - } - - } else if (skillName === 'workflow-tdd-plan') { - prompt = `/workflow-tdd-plan${yFlag} "${sanitize(task.title)}"`; - - } else if (skillName === 'workflow:refactor-cycle') { - prompt = `/workflow:refactor-cycle${yFlag} "${sanitize(task.title)}"`; - - } else if (skillName === 'review-cycle') { - if (previousResult?.sessionId) { - prompt = `/review-cycle${yFlag} --session="${previousResult.sessionId}"`; - } else { - prompt = `/review-cycle${yFlag}`; - } - - } else { - // Generic fallback - prompt = `/${skillName}${yFlag} "${sanitize(task.title)}"`; - } - - // Append task context - prompt += `\n\nTask: ${task.title}\nDescription: ${task.description}`; - if (task.context?.affected_files?.length > 0) { - prompt += `\nAffected files: ${task.context.affected_files.join(', ')}`; - } - if (task.context?.acceptance_criteria?.length > 0) { - prompt += `\nAcceptance criteria: ${task.context.acceptance_criteria.join('; ')}`; - } - - return prompt; -} -``` - -### sanitize & escapeForShell - -```javascript -function sanitize(text) { - return text - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\$/g, '\\$') - .replace(/`/g, '\\`'); -} - -function escapeForShell(prompt) { - return prompt.replace(/'/g, "'\\''"); -} -``` - -### parseCliOutput - -```javascript -function parseCliOutput(output) { - // Extract session ID from CLI output (e.g., WFS-xxx, session-xxx) - const sessionMatch = output.match(/(?:session|WFS|Session ID)[:\s]*([\w-]+)/i); - const success = !/(?:error|failed|fatal)/i.test(output) || /completed|success/i.test(output); - - return { - success, - sessionId: sessionMatch?.[1] || null, - raw: output?.substring(0, 500) - }; -} -``` - -## CLI-Assisted Analysis - -Same as `/idaw:run` — integrated at two points: - -### Pre-Task Context Analysis -For `bugfix`, `bugfix-hotfix`, `feature-complex` tasks: auto-invoke `ccw cli --tool gemini --mode analysis` before launching skill chain. - -### Error Recovery with CLI Diagnosis -When a skill's CLI execution fails: invoke diagnosis → retry once → if still fails, mark failed and advance. - -``` -Skill CLI fails → CLI diagnosis (gemini) → Retry CLI → Still fails → mark failed → next task -``` - -## State Flow - -``` -Phase 4: Launch first skill - ↓ - ccw cli --tool claude --mode write (background) - ↓ - ★ STOP — wait for hook callback - ↓ -Phase 5: handleStepCompletion() - ├─ Skill succeeded + more in chain → launch next skill → STOP - ├─ Skill succeeded + chain complete → git checkpoint → next task → STOP - ├─ Skill failed → CLI diagnosis → retry → STOP - └─ All tasks done → Phase 6: Report -``` - -## Session State (session.json) - -```json -{ - "session_id": "IDA-fix-login-20260301", - "mode": "coordinate", - "cli_tool": "claude", - "status": "running|waiting|completed|failed", - "created_at": "ISO", - "updated_at": "ISO", - "tasks": ["IDAW-001", "IDAW-002"], - "current_task": "IDAW-001", - "current_skill_index": 0, - "completed": [], - "failed": [], - "skipped": [], - "prompts_used": [ - { - "task_id": "IDAW-001", - "skill_index": 0, - "skill": "workflow-lite-plan", - "prompt": "/workflow-lite-plan -y \"Fix login timeout\"", - "timestamp": "ISO" - } - ] -} -``` - -## Differences from /idaw:run - -| Aspect | /idaw:run | /idaw:run-coordinate | -|--------|-----------|---------------------| -| Execution | `Skill()` blocking in main process | `ccw cli` background + hook callback | -| Context window | Shared (each skill uses main context) | Isolated (each CLI gets fresh context) | -| Concurrency | Sequential blocking | Sequential non-blocking (hook-driven) | -| State tracking | session.json + task.json | session.json + task.json + prompts_used | -| Tool selection | N/A (Skill native) | `--tool claude\|gemini\|qwen` | -| Resume | Via `/idaw:resume` (same) | Via `/idaw:resume` (same, detects mode) | -| Best for | Short chains, interactive | Long chains, autonomous, context-heavy | - -## Examples - -```bash -# Execute all pending tasks via claude CLI -/idaw:run-coordinate -y - -# Use specific CLI tool -/idaw:run-coordinate -y --tool gemini - -# Execute specific tasks -/idaw:run-coordinate --task IDAW-001,IDAW-003 --tool claude - -# Dry run (show plan without executing) -/idaw:run-coordinate --dry-run - -# Interactive mode -/idaw:run-coordinate -``` diff --git a/.claude/commands/idaw/run.md b/.claude/commands/idaw/run.md deleted file mode 100644 index 2b71e449..00000000 --- a/.claude/commands/idaw/run.md +++ /dev/null @@ -1,539 +0,0 @@ ---- -name: run -description: IDAW orchestrator - execute task skill chains serially with git checkpoints -argument-hint: "[-y|--yes] [--task [,,...]] [--dry-run]" -allowed-tools: Skill(*), TodoWrite(*), AskUserQuestion(*), Read(*), Write(*), Bash(*), Glob(*) ---- - -# IDAW Run Command (/idaw:run) - -## Auto Mode - -When `--yes` or `-y`: Skip all confirmations, auto-skip on failure, proceed with dirty git. - -## Skill Chain Mapping - -```javascript -const SKILL_CHAIN_MAP = { - 'bugfix': ['workflow-lite-plan', 'workflow-test-fix'], - 'bugfix-hotfix': ['workflow-lite-plan'], - 'feature': ['workflow-lite-plan', 'workflow-test-fix'], - 'feature-complex': ['workflow-plan', 'workflow-execute', 'workflow-test-fix'], - 'refactor': ['workflow:refactor-cycle'], - 'tdd': ['workflow-tdd-plan', 'workflow-execute'], - 'test': ['workflow-test-fix'], - 'test-fix': ['workflow-test-fix'], - 'review': ['review-cycle'], - 'docs': ['workflow-lite-plan'] -}; -``` - -## Task Type Inference - -```javascript -function inferTaskType(title, description) { - const text = `${title} ${description}`.toLowerCase(); - if (/urgent|production|critical/.test(text) && /fix|bug/.test(text)) return 'bugfix-hotfix'; - if (/refactor|重构|tech.*debt/.test(text)) return 'refactor'; - if (/tdd|test-driven|test first/.test(text)) return 'tdd'; - if (/test fail|fix test|failing test/.test(text)) return 'test-fix'; - if (/generate test|写测试|add test/.test(text)) return 'test'; - if (/review|code review/.test(text)) return 'review'; - if (/docs|documentation|readme/.test(text)) return 'docs'; - if (/fix|bug|error|crash|fail/.test(text)) return 'bugfix'; - if (/complex|multi-module|architecture/.test(text)) return 'feature-complex'; - return 'feature'; -} -``` - -## 6-Phase Execution - -### Phase 1: Load Tasks - -```javascript -const args = $ARGUMENTS; -const autoYes = /(-y|--yes)/.test(args); -const dryRun = /--dry-run/.test(args); -const taskFilter = args.match(/--task\s+([\w,-]+)/)?.[1]?.split(',') || null; - -// Load task files -const taskFiles = Glob('.workflow/.idaw/tasks/IDAW-*.json') || []; - -if (taskFiles.length === 0) { - console.log('No IDAW tasks found. Use /idaw:add to create tasks.'); - return; -} - -// Parse and filter -let tasks = taskFiles.map(f => JSON.parse(Read(f))); - -if (taskFilter) { - tasks = tasks.filter(t => taskFilter.includes(t.id)); -} else { - tasks = tasks.filter(t => t.status === 'pending'); -} - -if (tasks.length === 0) { - console.log('No pending tasks to execute. Use /idaw:add to add tasks or --task to specify IDs.'); - return; -} - -// Sort: priority ASC (1=critical first), then ID ASC -tasks.sort((a, b) => { - if (a.priority !== b.priority) return a.priority - b.priority; - return a.id.localeCompare(b.id); -}); -``` - -### Phase 2: Session Setup - -```javascript -// Generate session ID: IDA-{slug}-YYYYMMDD -const slug = tasks[0].title - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .substring(0, 20) - .replace(/-$/, ''); -const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, ''); -let sessionId = `IDA-${slug}-${dateStr}`; - -// Check collision -const existingSession = Glob(`.workflow/.idaw/sessions/${sessionId}/session.json`); -if (existingSession?.length > 0) { - sessionId = `${sessionId}-2`; -} - -const sessionDir = `.workflow/.idaw/sessions/${sessionId}`; -Bash(`mkdir -p "${sessionDir}"`); - -const session = { - session_id: sessionId, - status: 'running', - created_at: new Date().toISOString(), - updated_at: new Date().toISOString(), - tasks: tasks.map(t => t.id), - current_task: null, - completed: [], - failed: [], - skipped: [] -}; - -Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - -// Initialize progress.md -const progressHeader = `# IDAW Progress — ${sessionId}\nStarted: ${session.created_at}\n\n`; -Write(`${sessionDir}/progress.md`, progressHeader); - -// TodoWrite -TodoWrite({ - todos: tasks.map((t, i) => ({ - content: `IDAW:[${i + 1}/${tasks.length}] ${t.title}`, - status: i === 0 ? 'in_progress' : 'pending', - activeForm: `Executing ${t.title}` - })) -}); -``` - -### Phase 3: Startup Protocol - -```javascript -// Check for existing running sessions -const runningSessions = Glob('.workflow/.idaw/sessions/IDA-*/session.json') - ?.map(f => JSON.parse(Read(f))) - .filter(s => s.status === 'running' && s.session_id !== sessionId) || []; - -if (runningSessions.length > 0) { - if (!autoYes) { - const answer = AskUserQuestion({ - questions: [{ - question: `Found running session: ${runningSessions[0].session_id}. How to proceed?`, - header: 'Conflict', - multiSelect: false, - options: [ - { label: 'Resume existing', description: 'Use /idaw:resume instead' }, - { label: 'Start fresh', description: 'Continue with new session' }, - { label: 'Abort', description: 'Cancel this run' } - ] - }] - }); - if (answer.answers?.Conflict === 'Resume existing') { - console.log(`Use: /idaw:resume ${runningSessions[0].session_id}`); - return; - } - if (answer.answers?.Conflict === 'Abort') return; - } - // autoYes or "Start fresh": proceed -} - -// Check git status -const gitStatus = Bash('git status --porcelain 2>/dev/null'); -if (gitStatus?.trim()) { - if (!autoYes) { - const answer = AskUserQuestion({ - questions: [{ - question: 'Working tree has uncommitted changes. How to proceed?', - header: 'Git', - multiSelect: false, - options: [ - { label: 'Continue', description: 'Proceed with dirty tree' }, - { label: 'Stash', description: 'git stash before running' }, - { label: 'Abort', description: 'Stop and handle manually' } - ] - }] - }); - if (answer.answers?.Git === 'Stash') { - Bash('git stash push -m "idaw-pre-run"'); - } - if (answer.answers?.Git === 'Abort') return; - } - // autoYes: proceed silently -} - -// Dry run: show plan and exit -if (dryRun) { - console.log(`# Dry Run — ${sessionId}\n`); - for (const task of tasks) { - const taskType = task.task_type || inferTaskType(task.title, task.description); - const chain = task.skill_chain || SKILL_CHAIN_MAP[taskType] || SKILL_CHAIN_MAP['feature']; - console.log(`## ${task.id}: ${task.title}`); - console.log(` Type: ${taskType} | Priority: ${task.priority}`); - console.log(` Chain: ${chain.join(' → ')}\n`); - } - console.log(`Total: ${tasks.length} tasks`); - return; -} -``` - -### Phase 4: Main Loop (serial, one task at a time) - -```javascript -for (let taskIdx = 0; taskIdx < tasks.length; taskIdx++) { - const task = tasks[taskIdx]; - - // Skip completed/failed/skipped - if (['completed', 'failed', 'skipped'].includes(task.status)) continue; - - // Resolve skill chain - const resolvedType = task.task_type || inferTaskType(task.title, task.description); - const chain = task.skill_chain || SKILL_CHAIN_MAP[resolvedType] || SKILL_CHAIN_MAP['feature']; - - // Update task status → in_progress - task.status = 'in_progress'; - task.task_type = resolvedType; // persist inferred type - task.execution.started_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2)); - - // Update session - session.current_task = task.id; - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - - console.log(`\n--- [${taskIdx + 1}/${tasks.length}] ${task.id}: ${task.title} ---`); - console.log(`Chain: ${chain.join(' → ')}`); - - // ━━━ Pre-Task CLI Context Analysis (for complex/bugfix tasks) ━━━ - if (['bugfix', 'bugfix-hotfix', 'feature-complex'].includes(resolvedType)) { - console.log(` Pre-analysis: gathering context for ${resolvedType} task...`); - const affectedFiles = (task.context?.affected_files || []).join(', '); - const preAnalysisPrompt = `PURPOSE: Pre-analyze codebase context for IDAW task before execution. -TASK: • Understand current state of: ${affectedFiles || 'files related to: ' + task.title} • Identify dependencies and risk areas • Note existing patterns to follow -MODE: analysis -CONTEXT: @**/* -EXPECTED: Brief context summary (affected modules, dependencies, risk areas) in 3-5 bullet points -CONSTRAINTS: Keep concise | Focus on execution-relevant context`; - const preAnalysis = Bash(`ccw cli -p '${preAnalysisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis 2>&1 || echo "Pre-analysis skipped"`); - task.execution.skill_results.push({ - skill: 'cli-pre-analysis', - status: 'completed', - context_summary: preAnalysis?.substring(0, 500), - timestamp: new Date().toISOString() - }); - } - - // Execute each skill in chain - let previousResult = null; - let taskFailed = false; - - for (let skillIdx = 0; skillIdx < chain.length; skillIdx++) { - const skillName = chain[skillIdx]; - const skillArgs = assembleSkillArgs(skillName, task, previousResult, autoYes, skillIdx === 0); - - console.log(` [${skillIdx + 1}/${chain.length}] ${skillName}`); - - try { - const result = Skill({ skill: skillName, args: skillArgs }); - previousResult = result; - task.execution.skill_results.push({ - skill: skillName, - status: 'completed', - timestamp: new Date().toISOString() - }); - } catch (error) { - // ━━━ CLI-Assisted Error Recovery ━━━ - // Step 1: Invoke CLI diagnosis (auto-invoke trigger: self-repair fails) - console.log(` Diagnosing failure: ${skillName}...`); - const diagnosisPrompt = `PURPOSE: Diagnose why skill "${skillName}" failed during IDAW task execution. -TASK: • Analyze error: ${String(error).substring(0, 300)} • Check affected files: ${(task.context?.affected_files || []).join(', ') || 'unknown'} • Identify root cause • Suggest fix strategy -MODE: analysis -CONTEXT: @**/* | Memory: IDAW task ${task.id}: ${task.title} -EXPECTED: Root cause + actionable fix recommendation (1-2 sentences) -CONSTRAINTS: Focus on actionable diagnosis`; - const diagnosisResult = Bash(`ccw cli -p '${diagnosisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause 2>&1 || echo "CLI diagnosis unavailable"`); - - task.execution.skill_results.push({ - skill: `cli-diagnosis:${skillName}`, - status: 'completed', - diagnosis: diagnosisResult?.substring(0, 500), - timestamp: new Date().toISOString() - }); - - // Step 2: Retry with diagnosis context - console.log(` Retry with diagnosis: ${skillName}`); - try { - const retryResult = Skill({ skill: skillName, args: skillArgs }); - previousResult = retryResult; - task.execution.skill_results.push({ - skill: skillName, - status: 'completed-retry-with-diagnosis', - timestamp: new Date().toISOString() - }); - } catch (retryError) { - // Step 3: Failed after CLI-assisted retry - task.execution.skill_results.push({ - skill: skillName, - status: 'failed', - error: String(retryError).substring(0, 200), - timestamp: new Date().toISOString() - }); - - if (autoYes) { - taskFailed = true; - break; - } else { - const answer = AskUserQuestion({ - questions: [{ - question: `${skillName} failed after CLI diagnosis + retry: ${String(retryError).substring(0, 100)}. How to proceed?`, - header: 'Error', - multiSelect: false, - options: [ - { label: 'Skip task', description: 'Mark task as failed, continue to next' }, - { label: 'Abort', description: 'Stop entire run' } - ] - }] - }); - if (answer.answers?.Error === 'Abort') { - task.status = 'failed'; - task.execution.error = String(retryError).substring(0, 200); - Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2)); - session.failed.push(task.id); - session.status = 'failed'; - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - return; - } - taskFailed = true; - break; - } - } - } - } - - // Phase 5: Checkpoint (per task) — inline - if (taskFailed) { - task.status = 'failed'; - task.execution.error = 'Skill chain failed after retry'; - task.execution.completed_at = new Date().toISOString(); - session.failed.push(task.id); - } else { - // Git commit checkpoint - const commitMsg = `feat(idaw): ${task.title} [${task.id}]`; - const diffCheck = Bash('git diff --stat HEAD 2>/dev/null || echo ""'); - const untrackedCheck = Bash('git ls-files --others --exclude-standard 2>/dev/null || echo ""'); - - if (diffCheck?.trim() || untrackedCheck?.trim()) { - Bash('git add -A'); - const commitResult = Bash(`git commit -m "$(cat <<'EOF'\n${commitMsg}\nEOF\n)"`); - const commitHash = Bash('git rev-parse --short HEAD 2>/dev/null')?.trim(); - task.execution.git_commit = commitHash; - } else { - task.execution.git_commit = 'no-commit'; - } - - task.status = 'completed'; - task.execution.completed_at = new Date().toISOString(); - session.completed.push(task.id); - } - - // Write task + session state - task.updated_at = new Date().toISOString(); - Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2)); - - session.updated_at = new Date().toISOString(); - Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - - // Append to progress.md - const duration = task.execution.started_at && task.execution.completed_at - ? formatDuration(new Date(task.execution.completed_at) - new Date(task.execution.started_at)) - : 'unknown'; - - const progressEntry = `## ${task.id} — ${task.title}\n` + - `- Status: ${task.status}\n` + - `- Type: ${task.task_type}\n` + - `- Chain: ${chain.join(' → ')}\n` + - `- Commit: ${task.execution.git_commit || '-'}\n` + - `- Duration: ${duration}\n\n`; - - const currentProgress = Read(`${sessionDir}/progress.md`); - Write(`${sessionDir}/progress.md`, currentProgress + progressEntry); - - // Update TodoWrite - if (taskIdx + 1 < tasks.length) { - TodoWrite({ - todos: tasks.map((t, i) => ({ - content: `IDAW:[${i + 1}/${tasks.length}] ${t.title}`, - status: i < taskIdx + 1 ? 'completed' : (i === taskIdx + 1 ? 'in_progress' : 'pending'), - activeForm: `Executing ${t.title}` - })) - }); - } -} -``` - -### Phase 6: Report - -```javascript -session.status = session.failed.length > 0 && session.completed.length === 0 ? 'failed' : 'completed'; -session.current_task = null; -session.updated_at = new Date().toISOString(); -Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2)); - -// Final progress summary -const summary = `\n---\n## Summary\n` + - `- Completed: ${session.completed.length}\n` + - `- Failed: ${session.failed.length}\n` + - `- Skipped: ${session.skipped.length}\n` + - `- Total: ${tasks.length}\n`; - -const finalProgress = Read(`${sessionDir}/progress.md`); -Write(`${sessionDir}/progress.md`, finalProgress + summary); - -// Display report -console.log('\n=== IDAW Run Complete ==='); -console.log(`Session: ${sessionId}`); -console.log(`Completed: ${session.completed.length}/${tasks.length}`); -if (session.failed.length > 0) console.log(`Failed: ${session.failed.join(', ')}`); -if (session.skipped.length > 0) console.log(`Skipped: ${session.skipped.join(', ')}`); - -// List git commits -for (const taskId of session.completed) { - const t = JSON.parse(Read(`.workflow/.idaw/tasks/${taskId}.json`)); - if (t.execution.git_commit && t.execution.git_commit !== 'no-commit') { - console.log(` ${t.execution.git_commit} ${t.title}`); - } -} -``` - -## Helper Functions - -### assembleSkillArgs - -```javascript -function assembleSkillArgs(skillName, task, previousResult, autoYes, isFirst) { - let args = ''; - - if (isFirst) { - // First skill: pass task goal — sanitize for shell safety - const goal = `${task.title}\n${task.description}` - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\$/g, '\\$') - .replace(/`/g, '\\`'); - args = `"${goal}"`; - - // bugfix-hotfix: add --hotfix - if (task.task_type === 'bugfix-hotfix') { - args += ' --hotfix'; - } - } else if (previousResult?.session_id) { - // Subsequent skills: chain session - args = `--session="${previousResult.session_id}"`; - } - - // Propagate -y - if (autoYes && !args.includes('-y') && !args.includes('--yes')) { - args = args ? `${args} -y` : '-y'; - } - - return args; -} -``` - -### formatDuration - -```javascript -function formatDuration(ms) { - const seconds = Math.floor(ms / 1000); - const minutes = Math.floor(seconds / 60); - const remainingSeconds = seconds % 60; - if (minutes > 0) return `${minutes}m ${remainingSeconds}s`; - return `${seconds}s`; -} -``` - -## CLI-Assisted Analysis - -IDAW integrates `ccw cli` (Gemini) for intelligent analysis at two key points: - -### Pre-Task Context Analysis - -For `bugfix`, `bugfix-hotfix`, and `feature-complex` tasks, IDAW automatically invokes CLI analysis **before** executing the skill chain to gather codebase context: - -``` -Task starts → CLI pre-analysis (gemini) → Context gathered → Skill chain executes -``` - -- Identifies dependencies and risk areas -- Notes existing patterns to follow -- Results stored in `task.execution.skill_results` as `cli-pre-analysis` - -### Error Recovery with CLI Diagnosis - -When a skill fails, instead of blind retry, IDAW uses CLI-assisted diagnosis: - -``` -Skill fails → CLI diagnosis (gemini, analysis-diagnose-bug-root-cause) - → Root cause identified → Retry with diagnosis context - → Still fails → Skip (autoYes) or Ask user (interactive) -``` - -- Uses `--rule analysis-diagnose-bug-root-cause` template -- Diagnosis results stored in `task.execution.skill_results` as `cli-diagnosis:{skill}` -- Follows CLAUDE.md auto-invoke trigger pattern: "self-repair fails → invoke CLI analysis" - -### Execution Flow (with CLI analysis) - -``` -Phase 4 Main Loop (per task): - ├─ [bugfix/complex only] CLI pre-analysis → context summary - ├─ Skill 1: execute - │ ├─ Success → next skill - │ └─ Failure → CLI diagnosis → retry → success/fail - ├─ Skill 2: execute ... - └─ Phase 5: git checkpoint -``` - -## Examples - -```bash -# Execute all pending tasks -/idaw:run -y - -# Execute specific tasks -/idaw:run --task IDAW-001,IDAW-003 - -# Dry run (show plan without executing) -/idaw:run --dry-run - -# Interactive mode (confirm at each step) -/idaw:run -``` diff --git a/.claude/commands/idaw/status.md b/.claude/commands/idaw/status.md deleted file mode 100644 index b551b577..00000000 --- a/.claude/commands/idaw/status.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -name: status -description: View IDAW task and session progress -argument-hint: "[session-id]" -allowed-tools: Read(*), Glob(*), Bash(*) ---- - -# IDAW Status Command (/idaw:status) - -## Overview - -Read-only command to view IDAW task queue and execution session progress. - -## Implementation - -### Phase 1: Determine View Mode - -```javascript -const sessionId = $ARGUMENTS?.trim(); - -if (sessionId) { - // Specific session view - showSession(sessionId); -} else { - // Overview: pending tasks + latest session - showOverview(); -} -``` - -### Phase 2: Show Overview - -```javascript -function showOverview() { - // 1. Load all tasks - const taskFiles = Glob('.workflow/.idaw/tasks/IDAW-*.json') || []; - - if (taskFiles.length === 0) { - console.log('No IDAW tasks found. Use /idaw:add to create tasks.'); - return; - } - - const tasks = taskFiles.map(f => JSON.parse(Read(f))); - - // 2. Group by status - const byStatus = { - pending: tasks.filter(t => t.status === 'pending'), - in_progress: tasks.filter(t => t.status === 'in_progress'), - completed: tasks.filter(t => t.status === 'completed'), - failed: tasks.filter(t => t.status === 'failed'), - skipped: tasks.filter(t => t.status === 'skipped') - }; - - // 3. Display task summary table - console.log('# IDAW Tasks\n'); - console.log('| ID | Title | Type | Priority | Status |'); - console.log('|----|-------|------|----------|--------|'); - - // Sort: priority ASC, then ID ASC - const sorted = [...tasks].sort((a, b) => { - if (a.priority !== b.priority) return a.priority - b.priority; - return a.id.localeCompare(b.id); - }); - - for (const t of sorted) { - const type = t.task_type || '(infer)'; - console.log(`| ${t.id} | ${t.title.substring(0, 40)} | ${type} | ${t.priority} | ${t.status} |`); - } - - console.log(`\nTotal: ${tasks.length} | Pending: ${byStatus.pending.length} | Completed: ${byStatus.completed.length} | Failed: ${byStatus.failed.length}`); - - // 4. Show latest session (if any) - const sessionDirs = Glob('.workflow/.idaw/sessions/IDA-*/session.json') || []; - if (sessionDirs.length > 0) { - // Sort by modification time (newest first) — Glob returns sorted by mtime - const latestSessionFile = sessionDirs[0]; - const session = JSON.parse(Read(latestSessionFile)); - console.log(`\n## Latest Session: ${session.session_id}`); - console.log(`Status: ${session.status} | Tasks: ${session.tasks?.length || 0}`); - console.log(`Completed: ${session.completed?.length || 0} | Failed: ${session.failed?.length || 0} | Skipped: ${session.skipped?.length || 0}`); - } -} -``` - -### Phase 3: Show Specific Session - -```javascript -function showSession(sessionId) { - const sessionFile = `.workflow/.idaw/sessions/${sessionId}/session.json`; - const progressFile = `.workflow/.idaw/sessions/${sessionId}/progress.md`; - - // Try reading session - try { - const session = JSON.parse(Read(sessionFile)); - - console.log(`# IDAW Session: ${session.session_id}\n`); - console.log(`Status: ${session.status}`); - console.log(`Created: ${session.created_at}`); - console.log(`Updated: ${session.updated_at}`); - console.log(`Current Task: ${session.current_task || 'none'}\n`); - - // Task detail table - console.log('| ID | Title | Status | Commit |'); - console.log('|----|-------|--------|--------|'); - - for (const taskId of session.tasks) { - const taskFile = `.workflow/.idaw/tasks/${taskId}.json`; - try { - const task = JSON.parse(Read(taskFile)); - const commit = task.execution?.git_commit?.substring(0, 7) || '-'; - console.log(`| ${task.id} | ${task.title.substring(0, 40)} | ${task.status} | ${commit} |`); - } catch { - console.log(`| ${taskId} | (file not found) | unknown | - |`); - } - } - - console.log(`\nCompleted: ${session.completed?.length || 0} | Failed: ${session.failed?.length || 0} | Skipped: ${session.skipped?.length || 0}`); - - // Show progress.md if exists - try { - const progress = Read(progressFile); - console.log('\n---\n'); - console.log(progress); - } catch { - // No progress file yet - } - - } catch { - // Session not found — try listing all sessions - console.log(`Session "${sessionId}" not found.\n`); - listSessions(); - } -} -``` - -### Phase 4: List All Sessions - -```javascript -function listSessions() { - const sessionFiles = Glob('.workflow/.idaw/sessions/IDA-*/session.json') || []; - - if (sessionFiles.length === 0) { - console.log('No IDAW sessions found. Use /idaw:run to start execution.'); - return; - } - - console.log('# IDAW Sessions\n'); - console.log('| Session ID | Status | Tasks | Completed | Failed |'); - console.log('|------------|--------|-------|-----------|--------|'); - - for (const f of sessionFiles) { - try { - const session = JSON.parse(Read(f)); - console.log(`| ${session.session_id} | ${session.status} | ${session.tasks?.length || 0} | ${session.completed?.length || 0} | ${session.failed?.length || 0} |`); - } catch { - // Skip malformed - } - } - - console.log('\nUse /idaw:status for details.'); -} -``` - -## Examples - -```bash -# Show overview (pending tasks + latest session) -/idaw:status - -# Show specific session details -/idaw:status IDA-auth-fix-20260301 - -# Output example: -# IDAW Tasks -# -# | ID | Title | Type | Priority | Status | -# |----------|------------------------------------|--------|----------|-----------| -# | IDAW-001 | Fix auth token refresh | bugfix | 1 | completed | -# | IDAW-002 | Add rate limiting | feature| 2 | pending | -# | IDAW-003 | Refactor payment module | refact | 3 | pending | -# -# Total: 3 | Pending: 2 | Completed: 1 | Failed: 0 -```