diff --git a/.claude/commands/issue/execute.md b/.claude/commands/issue/execute.md index bda1d960..f590ea6e 100644 --- a/.claude/commands/issue/execute.md +++ b/.claude/commands/issue/execute.md @@ -1,6 +1,6 @@ --- name: execute -description: Execute queue with codex using DAG-based parallel orchestration (delegates task lookup to executors) +description: Execute queue with codex using DAG-based parallel orchestration (read-only task fetch) argument-hint: "[--parallel ] [--executor codex|gemini|agent]" allowed-tools: TodoWrite(*), Bash(*), Read(*), AskUserQuestion(*) --- @@ -9,13 +9,13 @@ allowed-tools: TodoWrite(*), Bash(*), Read(*), AskUserQuestion(*) ## Overview -Minimal orchestrator that dispatches task IDs to executors. **Does NOT read task details** - delegates all task lookup to the executor via `ccw issue next `. +Minimal orchestrator that dispatches task IDs to executors. Uses read-only `detail` command for parallel-safe task fetching. **Design Principles:** -- **DAG-driven**: Uses `ccw issue queue dag` to get parallel execution plan -- **ID-only dispatch**: Only passes `item_id` to executors -- **Executor responsibility**: Codex/Agent fetches task details via `ccw issue next ` -- **Parallel execution**: Launches multiple executors concurrently based on DAG batches +- `queue dag` → returns parallel batches with task IDs +- `detail ` → READ-ONLY task fetch (no status modification) +- `done ` → update completion status +- No race conditions: status changes only via `done` ## Usage @@ -37,20 +37,18 @@ Minimal orchestrator that dispatches task IDs to executors. **Does NOT read task ``` Phase 1: Get DAG - └─ ccw issue queue dag → { parallel_batches, nodes, ready_count } + └─ ccw issue queue dag → { parallel_batches: [["T-1","T-2","T-3"], ...] } -Phase 2: Dispatch Batches - ├─ For each batch in parallel_batches: - │ ├─ Launch N executors (up to --parallel limit) - │ ├─ Each executor receives: item_id only - │ ├─ Executor calls: ccw issue next +Phase 2: Dispatch Parallel Batch + ├─ For each ID in batch (parallel): + │ ├─ Executor calls: ccw issue detail (READ-ONLY) │ ├─ Executor gets full task definition │ ├─ Executor implements + tests + commits - │ └─ Executor calls: ccw issue done - └─ Wait for batch completion before next batch + │ └─ Executor calls: ccw issue done + └─ Wait for batch completion -Phase 3: Summary - └─ ccw issue queue dag → updated status +Phase 3: Next Batch + └─ ccw issue queue dag → check for newly-ready tasks ``` ## Implementation @@ -74,13 +72,12 @@ console.log(` - Total: ${dag.total} - Ready: ${dag.ready_count} - Completed: ${dag.completed_count} -- Batches: ${dag.parallel_batches.length} -- Max parallel: ${dag._summary.can_parallel} +- Parallel in batch 1: ${dag.parallel_batches[0]?.length || 0} `); // Dry run mode if (flags.dryRun) { - console.log('### Parallel Batches (would execute):\n'); + console.log('### Parallel Batches:\n'); dag.parallel_batches.forEach((batch, i) => { console.log(`Batch ${i + 1}: ${batch.join(', ')}`); }); @@ -88,71 +85,69 @@ if (flags.dryRun) { } ``` -### Phase 2: Dispatch Batches +### Phase 2: Dispatch Parallel Batch ```javascript const parallelLimit = flags.parallel || 3; const executor = flags.executor || 'codex'; -// Initialize TodoWrite for tracking -const allTasks = dag.parallel_batches.flat(); +// Process first batch (all can run in parallel) +const batch = dag.parallel_batches[0] || []; + +// Initialize TodoWrite TodoWrite({ - todos: allTasks.map(id => ({ + todos: batch.map(id => ({ content: `Execute ${id}`, status: 'pending', activeForm: `Executing ${id}` })) }); -// Process each batch -for (const [batchIndex, batch] of dag.parallel_batches.entries()) { - console.log(`\n### Batch ${batchIndex + 1}/${dag.parallel_batches.length}`); - console.log(`Tasks: ${batch.join(', ')}`); +// Dispatch all in parallel (up to limit) +const chunks = []; +for (let i = 0; i < batch.length; i += parallelLimit) { + chunks.push(batch.slice(i, i + parallelLimit)); +} - // Dispatch batch with parallelism limit - const chunks = []; - for (let i = 0; i < batch.length; i += parallelLimit) { - chunks.push(batch.slice(i, i + parallelLimit)); - } +for (const chunk of chunks) { + console.log(`\n### Executing: ${chunk.join(', ')}`); - for (const chunk of chunks) { - // Launch executors in parallel - const executions = chunk.map(itemId => { - updateTodo(itemId, 'in_progress'); - return dispatchExecutor(itemId, executor); - }); + // Launch all in parallel + const executions = chunk.map(itemId => { + updateTodo(itemId, 'in_progress'); + return dispatchExecutor(itemId, executor); + }); - await Promise.all(executions); - chunk.forEach(id => updateTodo(id, 'completed')); - } - - // Refresh DAG for next batch (dependencies may now be satisfied) - const refreshedDag = JSON.parse(Bash(`ccw issue queue dag`).trim()); - if (refreshedDag.ready_count === 0) break; + await Promise.all(executions); + chunk.forEach(id => updateTodo(id, 'completed')); } ``` -### Executor Dispatch (Minimal Prompt) +### Executor Dispatch ```javascript function dispatchExecutor(itemId, executorType) { - // Minimal prompt - executor fetches its own task + // Executor fetches task via READ-ONLY detail command + // Then reports completion via done command const prompt = ` ## Execute Task ${itemId} -### Step 1: Fetch Task +### Step 1: Get Task (read-only) \`\`\`bash -ccw issue next ${itemId} +ccw issue detail ${itemId} \`\`\` ### Step 2: Execute -Follow the task definition returned by the command above. -The JSON includes: implementation steps, test commands, acceptance criteria, commit spec. +Follow the task definition returned above: +- task.implementation: Implementation steps +- task.test: Test commands +- task.acceptance: Acceptance criteria +- task.commit: Commit specification -### Step 3: Report +### Step 3: Report Completion When done: \`\`\`bash -ccw issue done ${itemId} --result '{"summary": "..."}' +ccw issue done ${itemId} --result '{"summary": "...", "files_modified": [...]}' \`\`\` If failed: @@ -182,32 +177,51 @@ ccw issue done ${itemId} --fail --reason "..." } ``` -### Phase 3: Summary +### Phase 3: Check Next Batch ```javascript -// Get final status -const finalDag = JSON.parse(Bash(`ccw issue queue dag`).trim()); +// Refresh DAG after batch completes +const refreshedDag = JSON.parse(Bash(`ccw issue queue dag`).trim()); console.log(` -## Execution Complete +## Batch Complete -- Completed: ${finalDag.completed_count}/${finalDag.total} -- Remaining: ${finalDag.ready_count} - -### Task Status -${finalDag.nodes.map(n => { - const icon = n.status === 'completed' ? '✓' : - n.status === 'failed' ? '✗' : - n.status === 'executing' ? '⟳' : '○'; - return `${icon} ${n.id} [${n.issue_id}:${n.task_id}] - ${n.status}`; -}).join('\n')} +- Completed: ${refreshedDag.completed_count}/${refreshedDag.total} +- Next ready: ${refreshedDag.ready_count} `); -if (finalDag.ready_count > 0) { - console.log('\nRun `/issue:execute` again for remaining tasks.'); +if (refreshedDag.ready_count > 0) { + console.log('Run `/issue:execute` again for next batch.'); } ``` +## Parallel Execution Model + +``` +┌─────────────────────────────────────────────────────────┐ +│ Orchestrator │ +├─────────────────────────────────────────────────────────┤ +│ 1. ccw issue queue dag │ +│ → { parallel_batches: [["T-1","T-2","T-3"], ["T-4"]] │ +│ │ +│ 2. Dispatch batch 1 (parallel): │ +│ ┌────────────────┐ ┌────────────────┐ ┌────────────┐│ +│ │ Executor 1 │ │ Executor 2 │ │ Executor 3 ││ +│ │ detail T-1 │ │ detail T-2 │ │ detail T-3 ││ +│ │ [work] │ │ [work] │ │ [work] ││ +│ │ done T-1 │ │ done T-2 │ │ done T-3 ││ +│ └────────────────┘ └────────────────┘ └────────────┘│ +│ │ +│ 3. ccw issue queue dag (refresh) │ +│ → T-4 now ready (dependencies T-1,T-2 completed) │ +└─────────────────────────────────────────────────────────┘ +``` + +**Why this works for parallel:** +- `detail ` is READ-ONLY → no race conditions +- `done ` updates only its own task status +- `queue dag` recalculates ready tasks after each batch + ## CLI Endpoint Contract ### `ccw issue queue dag` @@ -219,25 +233,24 @@ Returns dependency graph with parallel batches: "ready_count": 3, "completed_count": 2, "nodes": [{ "id": "T-1", "status": "pending", "ready": true, ... }], - "edges": [{ "from": "T-1", "to": "T-2" }], - "parallel_batches": [["T-1", "T-3"], ["T-2"]], - "_summary": { "can_parallel": 2, "batches_needed": 2 } + "parallel_batches": [["T-1", "T-2", "T-3"], ["T-4", "T-5"]] } ``` -### `ccw issue next ` -Returns full task definition for the specified item: +### `ccw issue detail ` +Returns full task definition (READ-ONLY): ```json { "item_id": "T-1", "issue_id": "GH-123", - "task": { "id": "T1", "title": "...", "implementation": [...], ... }, + "status": "pending", + "task": { "id": "T1", "implementation": [...], "test": {...}, ... }, "context": { "relevant_files": [...] } } ``` ### `ccw issue done ` -Marks task completed/failed and updates queue state. +Marks task completed/failed, updates queue state, checks for queue completion. ## Error Handling @@ -245,28 +258,13 @@ Marks task completed/failed and updates queue state. |-------|------------| | No queue | Run /issue:queue first | | No ready tasks | Dependencies blocked, check DAG | -| Executor timeout | Marked as executing, can resume | +| Executor timeout | Task not marked done, can retry | | Task failure | Use `ccw issue retry` to reset | -## Troubleshooting - -### Check DAG Status -```bash -ccw issue queue dag | jq '.parallel_batches' -``` - -### Resume Interrupted Execution -Executors in `executing` status will be resumed automatically when calling `ccw issue next `. - -### Retry Failed Tasks -```bash -ccw issue retry # Reset all failed to pending -/issue:execute # Re-execute -``` - ## Related Commands - `/issue:plan` - Plan issues with solutions - `/issue:queue` - Form execution queue - `ccw issue queue dag` - View dependency graph +- `ccw issue detail ` - View task details - `ccw issue retry` - Reset failed tasks diff --git a/.claude/commands/issue/plan.md b/.claude/commands/issue/plan.md index e2a0473e..4ced15a2 100644 --- a/.claude/commands/issue/plan.md +++ b/.claude/commands/issue/plan.md @@ -193,10 +193,17 @@ ${issueList} **Project Root**: ${process.cwd()} +### Project Context (MANDATORY - Read Both Files First) +1. Read: .workflow/project-tech.json (technology stack, architecture, key components) +2. Read: .workflow/project-guidelines.json (user-defined constraints and conventions) + +**CRITICAL**: All solution tasks MUST comply with constraints in project-guidelines.json + ### Steps 1. Fetch: \`ccw issue status --json\` -2. Explore (ACE) → Plan solution -3. Register & bind: \`ccw issue bind --solution \` +2. Load project context (project-tech.json + project-guidelines.json) +3. Explore (ACE) → Plan solution (respecting guidelines) +4. Register & bind: \`ccw issue bind --solution \` ### Generate Files \`.workflow/issues/solutions/{issue-id}.jsonl\` - Solution with tasks (schema: cat .claude/workflows/cli-templates/schemas/solution-schema.json) diff --git a/.claude/commands/workflow/init.md b/.claude/commands/workflow/init.md index 98bb2647..cd817d11 100644 --- a/.claude/commands/workflow/init.md +++ b/.claude/commands/workflow/init.md @@ -10,7 +10,11 @@ examples: # Workflow Init Command (/workflow:init) ## Overview -Initialize `.workflow/project.json` with comprehensive project understanding by delegating analysis to **cli-explore-agent**. +Initialize `.workflow/project-tech.json` and `.workflow/project-guidelines.json` with comprehensive project understanding by delegating analysis to **cli-explore-agent**. + +**Dual File System**: +- `project-tech.json`: Auto-generated technical analysis (stack, architecture, components) +- `project-guidelines.json`: User-maintained rules and constraints (created as scaffold) **Note**: This command may be called by other workflow commands. Upon completion, return immediately to continue the calling workflow without interrupting the task flow. @@ -27,7 +31,7 @@ Input Parsing: └─ Parse --regenerate flag → regenerate = true | false Decision: - ├─ EXISTS + no --regenerate → Exit: "Already initialized" + ├─ BOTH_EXIST + no --regenerate → Exit: "Already initialized" ├─ EXISTS + --regenerate → Backup existing → Continue analysis └─ NOT_FOUND → Continue analysis @@ -37,11 +41,14 @@ Analysis Flow: │ ├─ Structural scan (get_modules_by_depth.sh, find, wc) │ ├─ Semantic analysis (Gemini CLI) │ ├─ Synthesis and merge - │ └─ Write .workflow/project.json + │ └─ Write .workflow/project-tech.json + ├─ Create guidelines scaffold (if not exists) + │ └─ Write .workflow/project-guidelines.json (empty structure) └─ Display summary Output: - └─ .workflow/project.json (+ .backup if regenerate) + ├─ .workflow/project-tech.json (+ .backup if regenerate) + └─ .workflow/project-guidelines.json (scaffold if new) ``` ## Implementation @@ -56,13 +63,18 @@ const regenerate = $ARGUMENTS.includes('--regenerate') **Check existing state**: ```bash -bash(test -f .workflow/project.json && echo "EXISTS" || echo "NOT_FOUND") +bash(test -f .workflow/project-tech.json && echo "TECH_EXISTS" || echo "TECH_NOT_FOUND") +bash(test -f .workflow/project-guidelines.json && echo "GUIDELINES_EXISTS" || echo "GUIDELINES_NOT_FOUND") ``` -**If EXISTS and no --regenerate**: Exit early +**If BOTH_EXIST and no --regenerate**: Exit early ``` -Project already initialized at .workflow/project.json -Use /workflow:init --regenerate to rebuild +Project already initialized: +- Tech analysis: .workflow/project-tech.json +- Guidelines: .workflow/project-guidelines.json + +Use /workflow:init --regenerate to rebuild tech analysis +Use /workflow:session:solidify to add guidelines Use /workflow:status --project to view state ``` @@ -78,7 +90,7 @@ bash(mkdir -p .workflow) **For --regenerate**: Backup and preserve existing data ```bash -bash(cp .workflow/project.json .workflow/project.json.backup) +bash(cp .workflow/project-tech.json .workflow/project-tech.json.backup) ``` **Delegate analysis to agent**: @@ -89,20 +101,17 @@ Task( run_in_background=false, description="Deep project analysis", prompt=` -Analyze project for workflow initialization and generate .workflow/project.json. +Analyze project for workflow initialization and generate .workflow/project-tech.json. ## MANDATORY FIRST STEPS -1. Execute: cat ~/.claude/workflows/cli-templates/schemas/project-json-schema.json (get schema reference) +1. Execute: cat ~/.claude/workflows/cli-templates/schemas/project-tech-schema.json (get schema reference) 2. Execute: ccw tool exec get_modules_by_depth '{}' (get project structure) ## Task -Generate complete project.json with: -- project_name: ${projectName} -- initialized_at: current ISO timestamp -- overview: {description, technology_stack, architecture, key_components} -- features: ${regenerate ? 'preserve from backup' : '[] (empty)'} -- development_index: ${regenerate ? 'preserve from backup' : '{feature: [], enhancement: [], bugfix: [], refactor: [], docs: []}'} -- statistics: ${regenerate ? 'preserve from backup' : '{total_features: 0, total_sessions: 0, last_updated}'} +Generate complete project-tech.json with: +- project_metadata: {name: ${projectName}, root_path: ${projectRoot}, initialized_at, updated_at} +- technology_analysis: {description, languages, frameworks, build_tools, test_frameworks, architecture, key_components, dependencies} +- development_status: ${regenerate ? 'preserve from backup' : '{completed_features: [], development_index: {feature: [], enhancement: [], bugfix: [], refactor: [], docs: []}, statistics: {total_features: 0, total_sessions: 0, last_updated}}'} - _metadata: {initialized_by: "cli-explore-agent", analysis_timestamp, analysis_mode} ## Analysis Requirements @@ -123,8 +132,8 @@ Generate complete project.json with: 1. Structural scan: get_modules_by_depth.sh, find, wc -l 2. Semantic analysis: Gemini for patterns/architecture 3. Synthesis: Merge findings -4. ${regenerate ? 'Merge with preserved features/development_index/statistics from .workflow/project.json.backup' : ''} -5. Write JSON: Write('.workflow/project.json', jsonContent) +4. ${regenerate ? 'Merge with preserved development_status from .workflow/project-tech.json.backup' : ''} +5. Write JSON: Write('.workflow/project-tech.json', jsonContent) 6. Report: Return brief completion summary Project root: ${projectRoot} @@ -132,29 +141,66 @@ Project root: ${projectRoot} ) ``` +### Step 3.5: Create Guidelines Scaffold (if not exists) + +```javascript +// Only create if not exists (never overwrite user guidelines) +if (!file_exists('.workflow/project-guidelines.json')) { + const guidelinesScaffold = { + conventions: { + coding_style: [], + naming_patterns: [], + file_structure: [], + documentation: [] + }, + constraints: { + architecture: [], + tech_stack: [], + performance: [], + security: [] + }, + quality_rules: [], + learnings: [], + _metadata: { + created_at: new Date().toISOString(), + version: "1.0.0" + } + }; + + Write('.workflow/project-guidelines.json', JSON.stringify(guidelinesScaffold, null, 2)); +} +``` + ### Step 4: Display Summary ```javascript -const projectJson = JSON.parse(Read('.workflow/project.json')); +const projectTech = JSON.parse(Read('.workflow/project-tech.json')); +const guidelinesExists = file_exists('.workflow/project-guidelines.json'); console.log(` ✓ Project initialized successfully ## Project Overview -Name: ${projectJson.project_name} -Description: ${projectJson.overview.description} +Name: ${projectTech.project_metadata.name} +Description: ${projectTech.technology_analysis.description} ### Technology Stack -Languages: ${projectJson.overview.technology_stack.languages.map(l => l.name).join(', ')} -Frameworks: ${projectJson.overview.technology_stack.frameworks.join(', ')} +Languages: ${projectTech.technology_analysis.languages.map(l => l.name).join(', ')} +Frameworks: ${projectTech.technology_analysis.frameworks.join(', ')} ### Architecture -Style: ${projectJson.overview.architecture.style} -Components: ${projectJson.overview.key_components.length} core modules +Style: ${projectTech.technology_analysis.architecture.style} +Components: ${projectTech.technology_analysis.key_components.length} core modules --- -Project state: .workflow/project.json -${regenerate ? 'Backup: .workflow/project.json.backup' : ''} +Files created: +- Tech analysis: .workflow/project-tech.json +- Guidelines: .workflow/project-guidelines.json ${guidelinesExists ? '(scaffold)' : ''} +${regenerate ? '- Backup: .workflow/project-tech.json.backup' : ''} + +Next steps: +- Use /workflow:session:solidify to add project guidelines +- Use /workflow:plan to start planning `); ``` diff --git a/.claude/commands/workflow/lite-fix.md b/.claude/commands/workflow/lite-fix.md index f5a65879..89a8a3f5 100644 --- a/.claude/commands/workflow/lite-fix.md +++ b/.claude/commands/workflow/lite-fix.md @@ -181,6 +181,8 @@ Execute **${angle}** diagnosis for bug root cause analysis. Analyze codebase fro 1. Run: ccw tool exec get_modules_by_depth '{}' (project structure) 2. Run: rg -l "{error_keyword_from_bug}" --type ts (locate relevant files) 3. Execute: cat ~/.claude/workflows/cli-templates/schemas/diagnosis-json-schema.json (get output schema reference) +4. Read: .workflow/project-tech.json (technology stack and architecture context) +5. Read: .workflow/project-guidelines.json (user-defined constraints and conventions) ## Diagnosis Strategy (${angle} focus) @@ -409,6 +411,12 @@ Generate fix plan and write fix-plan.json. ## Output Schema Reference Execute: cat ~/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json (get schema reference before generating plan) +## Project Context (MANDATORY - Read Both Files) +1. Read: .workflow/project-tech.json (technology stack, architecture, key components) +2. Read: .workflow/project-guidelines.json (user-defined constraints and conventions) + +**CRITICAL**: All fix tasks MUST comply with constraints in project-guidelines.json + ## Bug Description ${bug_description} diff --git a/.claude/commands/workflow/lite-plan.md b/.claude/commands/workflow/lite-plan.md index 24a3446c..0b675968 100644 --- a/.claude/commands/workflow/lite-plan.md +++ b/.claude/commands/workflow/lite-plan.md @@ -184,6 +184,8 @@ Execute **${angle}** exploration for task planning context. Analyze codebase fro 1. Run: ccw tool exec get_modules_by_depth '{}' (project structure) 2. Run: rg -l "{keyword_from_task}" --type ts (locate relevant files) 3. Execute: cat ~/.claude/workflows/cli-templates/schemas/explore-json-schema.json (get output schema reference) +4. Read: .workflow/project-tech.json (technology stack and architecture context) +5. Read: .workflow/project-guidelines.json (user-defined constraints and conventions) ## Exploration Strategy (${angle} focus) @@ -416,6 +418,12 @@ Generate implementation plan and write plan.json. ## Output Schema Reference Execute: cat ~/.claude/workflows/cli-templates/schemas/plan-json-schema.json (get schema reference before generating plan) +## Project Context (MANDATORY - Read Both Files) +1. Read: .workflow/project-tech.json (technology stack, architecture, key components) +2. Read: .workflow/project-guidelines.json (user-defined constraints and conventions) + +**CRITICAL**: All generated tasks MUST comply with constraints in project-guidelines.json + ## Task Description ${task_description} diff --git a/.claude/commands/workflow/review-module-cycle.md b/.claude/commands/workflow/review-module-cycle.md index eb85038f..ab996850 100644 --- a/.claude/commands/workflow/review-module-cycle.md +++ b/.claude/commands/workflow/review-module-cycle.md @@ -409,6 +409,8 @@ Task( 2. Get target files: Read resolved_files from review-state.json 3. Validate file access: bash(ls -la ${targetFiles.join(' ')}) 4. Execute: cat ~/.claude/workflows/cli-templates/schemas/review-dimension-results-schema.json (get output schema reference) + 5. Read: .workflow/project-tech.json (technology stack and architecture context) + 6. Read: .workflow/project-guidelines.json (user-defined constraints and conventions to validate against) ## Review Context - Review Type: module (independent) @@ -511,6 +513,8 @@ Task( 3. Identify related code: bash(grep -r "import.*${basename(file)}" ${projectDir}/src --include="*.ts") 4. Read test files: bash(find ${projectDir}/tests -name "*${basename(file, '.ts')}*" -type f) 5. Execute: cat ~/.claude/workflows/cli-templates/schemas/review-deep-dive-results-schema.json (get output schema reference) + 6. Read: .workflow/project-tech.json (technology stack and architecture context) + 7. Read: .workflow/project-guidelines.json (user-defined constraints for remediation compliance) ## CLI Configuration - Tool Priority: gemini → qwen → codex diff --git a/.claude/commands/workflow/review-session-cycle.md b/.claude/commands/workflow/review-session-cycle.md index a7d5215f..f4315622 100644 --- a/.claude/commands/workflow/review-session-cycle.md +++ b/.claude/commands/workflow/review-session-cycle.md @@ -420,6 +420,8 @@ Task( 3. Get changed files: bash(cd ${workflowDir} && git log --since="${sessionCreatedAt}" --name-only --pretty=format: | sort -u) 4. Read review state: ${reviewStateJsonPath} 5. Execute: cat ~/.claude/workflows/cli-templates/schemas/review-dimension-results-schema.json (get output schema reference) + 6. Read: .workflow/project-tech.json (technology stack and architecture context) + 7. Read: .workflow/project-guidelines.json (user-defined constraints and conventions to validate against) ## Session Context - Session ID: ${sessionId} @@ -522,6 +524,8 @@ Task( 3. Identify related code: bash(grep -r "import.*${basename(file)}" ${workflowDir}/src --include="*.ts") 4. Read test files: bash(find ${workflowDir}/tests -name "*${basename(file, '.ts')}*" -type f) 5. Execute: cat ~/.claude/workflows/cli-templates/schemas/review-deep-dive-results-schema.json (get output schema reference) + 6. Read: .workflow/project-tech.json (technology stack and architecture context) + 7. Read: .workflow/project-guidelines.json (user-defined constraints for remediation compliance) ## CLI Configuration - Tool Priority: gemini → qwen → codex diff --git a/.claude/commands/workflow/review.md b/.claude/commands/workflow/review.md index faf6aa65..efbb424f 100644 --- a/.claude/commands/workflow/review.md +++ b/.claude/commands/workflow/review.md @@ -139,7 +139,7 @@ After bash validation, the model takes control to: ccw cli -p " PURPOSE: Security audit of completed implementation TASK: Review code for security vulnerabilities, insecure patterns, auth/authz issues - CONTEXT: @.summaries/IMPL-*.md,../.. @../../CLAUDE.md + CONTEXT: @.summaries/IMPL-*.md,../.. @../../project-tech.json @../../project-guidelines.json EXPECTED: Security findings report with severity levels RULES: Focus on OWASP Top 10, authentication, authorization, data validation, injection risks " --tool gemini --mode write --cd .workflow/active/${sessionId} @@ -151,7 +151,7 @@ After bash validation, the model takes control to: ccw cli -p " PURPOSE: Architecture compliance review TASK: Evaluate adherence to architectural patterns, identify technical debt, review design decisions - CONTEXT: @.summaries/IMPL-*.md,../.. @../../CLAUDE.md + CONTEXT: @.summaries/IMPL-*.md,../.. @../../project-tech.json @../../project-guidelines.json EXPECTED: Architecture assessment with recommendations RULES: Check for patterns, separation of concerns, modularity, scalability " --tool qwen --mode write --cd .workflow/active/${sessionId} @@ -163,7 +163,7 @@ After bash validation, the model takes control to: ccw cli -p " PURPOSE: Code quality and best practices review TASK: Assess code readability, maintainability, adherence to best practices - CONTEXT: @.summaries/IMPL-*.md,../.. @../../CLAUDE.md + CONTEXT: @.summaries/IMPL-*.md,../.. @../../project-tech.json @../../project-guidelines.json EXPECTED: Quality assessment with improvement suggestions RULES: Check for code smells, duplication, complexity, naming conventions " --tool gemini --mode write --cd .workflow/active/${sessionId} @@ -185,7 +185,7 @@ After bash validation, the model takes control to: ccw cli -p " PURPOSE: Verify all requirements and acceptance criteria are met TASK: Cross-check implementation summaries against original requirements - CONTEXT: @.task/IMPL-*.json,.summaries/IMPL-*.md,../.. @../../CLAUDE.md + CONTEXT: @.task/IMPL-*.json,.summaries/IMPL-*.md,../.. @../../project-tech.json @../../project-guidelines.json EXPECTED: - Requirements coverage matrix - Acceptance criteria verification diff --git a/.claude/commands/workflow/session/solidify.md b/.claude/commands/workflow/session/solidify.md new file mode 100644 index 00000000..dc1f004c --- /dev/null +++ b/.claude/commands/workflow/session/solidify.md @@ -0,0 +1,299 @@ +--- +name: solidify +description: Crystallize session learnings and user-defined constraints into permanent project guidelines +argument-hint: "[--type ] [--category ] \"rule or insight\"" +examples: + - /workflow:session:solidify "Use functional components for all React code" --type convention + - /workflow:session:solidify "No direct DB access from controllers" --type constraint --category architecture + - /workflow:session:solidify "Cache invalidation requires event sourcing" --type learning --category architecture + - /workflow:session:solidify --interactive +--- + +# Session Solidify Command (/workflow:session:solidify) + +## Overview + +Crystallizes ephemeral session context (insights, decisions, constraints) into permanent project guidelines stored in `.workflow/project-guidelines.json`. This ensures valuable learnings persist across sessions and inform future planning. + +## Use Cases + +1. **During Session**: Capture important decisions as they're made +2. **After Session**: Reflect on lessons learned before archiving +3. **Proactive**: Add team conventions or architectural rules + +## Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `rule` | string | ✅ (unless --interactive) | The rule, convention, or insight to solidify | +| `--type` | enum | ❌ | Type: `convention`, `constraint`, `learning` (default: auto-detect) | +| `--category` | string | ❌ | Category for organization (see categories below) | +| `--interactive` | flag | ❌ | Launch guided wizard for adding rules | + +### Type Categories + +**convention** → Coding style preferences (goes to `conventions` section) +- Subcategories: `coding_style`, `naming_patterns`, `file_structure`, `documentation` + +**constraint** → Hard rules that must not be violated (goes to `constraints` section) +- Subcategories: `architecture`, `tech_stack`, `performance`, `security` + +**learning** → Session-specific insights (goes to `learnings` array) +- Subcategories: `architecture`, `performance`, `security`, `testing`, `process`, `other` + +## Execution Process + +``` +Input Parsing: + ├─ Parse: rule text (required unless --interactive) + ├─ Parse: --type (convention|constraint|learning) + ├─ Parse: --category (subcategory) + └─ Parse: --interactive (flag) + +Step 1: Ensure Guidelines File Exists + └─ If not exists → Create with empty structure + +Step 2: Auto-detect Type (if not specified) + └─ Analyze rule text for keywords + +Step 3: Validate and Format Entry + └─ Build entry object based on type + +Step 4: Update Guidelines File + └─ Add entry to appropriate section + +Step 5: Display Confirmation + └─ Show what was added and where +``` + +## Implementation + +### Step 1: Ensure Guidelines File Exists + +```bash +bash(test -f .workflow/project-guidelines.json && echo "EXISTS" || echo "NOT_FOUND") +``` + +**If NOT_FOUND**, create scaffold: + +```javascript +const scaffold = { + conventions: { + coding_style: [], + naming_patterns: [], + file_structure: [], + documentation: [] + }, + constraints: { + architecture: [], + tech_stack: [], + performance: [], + security: [] + }, + quality_rules: [], + learnings: [], + _metadata: { + created_at: new Date().toISOString(), + version: "1.0.0" + } +}; + +Write('.workflow/project-guidelines.json', JSON.stringify(scaffold, null, 2)); +``` + +### Step 2: Auto-detect Type (if not specified) + +```javascript +function detectType(ruleText) { + const text = ruleText.toLowerCase(); + + // Constraint indicators + if (/\b(no|never|must not|forbidden|prohibited|always must)\b/.test(text)) { + return 'constraint'; + } + + // Learning indicators + if (/\b(learned|discovered|realized|found that|turns out)\b/.test(text)) { + return 'learning'; + } + + // Default to convention + return 'convention'; +} + +function detectCategory(ruleText, type) { + const text = ruleText.toLowerCase(); + + if (type === 'constraint' || type === 'learning') { + if (/\b(architecture|layer|module|dependency|circular)\b/.test(text)) return 'architecture'; + if (/\b(security|auth|permission|sanitize|xss|sql)\b/.test(text)) return 'security'; + if (/\b(performance|cache|lazy|async|sync|slow)\b/.test(text)) return 'performance'; + if (/\b(test|coverage|mock|stub)\b/.test(text)) return 'testing'; + } + + if (type === 'convention') { + if (/\b(name|naming|prefix|suffix|camel|pascal)\b/.test(text)) return 'naming_patterns'; + if (/\b(file|folder|directory|structure|organize)\b/.test(text)) return 'file_structure'; + if (/\b(doc|comment|jsdoc|readme)\b/.test(text)) return 'documentation'; + return 'coding_style'; + } + + return type === 'constraint' ? 'tech_stack' : 'other'; +} +``` + +### Step 3: Build Entry + +```javascript +function buildEntry(rule, type, category, sessionId) { + if (type === 'learning') { + return { + date: new Date().toISOString().split('T')[0], + session_id: sessionId || null, + insight: rule, + category: category, + context: null + }; + } + + // For conventions and constraints, just return the rule string + return rule; +} +``` + +### Step 4: Update Guidelines File + +```javascript +const guidelines = JSON.parse(Read('.workflow/project-guidelines.json')); + +if (type === 'convention') { + if (!guidelines.conventions[category]) { + guidelines.conventions[category] = []; + } + if (!guidelines.conventions[category].includes(rule)) { + guidelines.conventions[category].push(rule); + } +} else if (type === 'constraint') { + if (!guidelines.constraints[category]) { + guidelines.constraints[category] = []; + } + if (!guidelines.constraints[category].includes(rule)) { + guidelines.constraints[category].push(rule); + } +} else if (type === 'learning') { + guidelines.learnings.push(buildEntry(rule, type, category, sessionId)); +} + +guidelines._metadata.updated_at = new Date().toISOString(); +guidelines._metadata.last_solidified_by = sessionId; + +Write('.workflow/project-guidelines.json', JSON.stringify(guidelines, null, 2)); +``` + +### Step 5: Display Confirmation + +``` +✓ Guideline solidified + +Type: ${type} +Category: ${category} +Rule: "${rule}" + +Location: .workflow/project-guidelines.json → ${type}s.${category} + +Total ${type}s in ${category}: ${count} +``` + +## Interactive Mode + +When `--interactive` flag is provided: + +```javascript +AskUserQuestion({ + questions: [ + { + question: "What type of guideline are you adding?", + header: "Type", + multiSelect: false, + options: [ + { label: "Convention", description: "Coding style preference (e.g., use functional components)" }, + { label: "Constraint", description: "Hard rule that must not be violated (e.g., no direct DB access)" }, + { label: "Learning", description: "Insight from this session (e.g., cache invalidation needs events)" } + ] + } + ] +}); + +// Follow-up based on type selection... +``` + +## Examples + +### Add a Convention +```bash +/workflow:session:solidify "Use async/await instead of callbacks" --type convention --category coding_style +``` + +Result in `project-guidelines.json`: +```json +{ + "conventions": { + "coding_style": ["Use async/await instead of callbacks"] + } +} +``` + +### Add an Architectural Constraint +```bash +/workflow:session:solidify "No direct DB access from controllers" --type constraint --category architecture +``` + +Result: +```json +{ + "constraints": { + "architecture": ["No direct DB access from controllers"] + } +} +``` + +### Capture a Session Learning +```bash +/workflow:session:solidify "Cache invalidation requires event sourcing for consistency" --type learning +``` + +Result: +```json +{ + "learnings": [ + { + "date": "2024-12-28", + "session_id": "WFS-auth-feature", + "insight": "Cache invalidation requires event sourcing for consistency", + "category": "architecture" + } + ] +} +``` + +## Integration with Planning + +The `project-guidelines.json` is consumed by: + +1. **`/workflow:tools:context-gather`**: Loads guidelines into context-package.json +2. **`/workflow:plan`**: Passes guidelines to task generation agent +3. **`task-generate-agent`**: Includes guidelines as "CRITICAL CONSTRAINTS" in system prompt + +This ensures all future planning respects solidified rules without users needing to re-state them. + +## Error Handling + +- **Duplicate Rule**: Warn and skip if exact rule already exists +- **Invalid Category**: Suggest valid categories for the type +- **File Corruption**: Backup existing file before modification + +## Related Commands + +- `/workflow:session:start` - Start a session (may prompt for solidify at end) +- `/workflow:session:complete` - Complete session (prompts for learnings to solidify) +- `/workflow:init` - Creates project-guidelines.json scaffold if missing diff --git a/.claude/commands/workflow/session/start.md b/.claude/commands/workflow/session/start.md index 7837d6f0..a09c3bc7 100644 --- a/.claude/commands/workflow/session/start.md +++ b/.claude/commands/workflow/session/start.md @@ -38,26 +38,29 @@ ERROR: Invalid session type. Valid types: workflow, review, tdd, test, docs ## Step 0: Initialize Project State (First-time Only) -**Executed before all modes** - Ensures project-level state file exists by calling `/workflow:init`. +**Executed before all modes** - Ensures project-level state files exist by calling `/workflow:init`. ### Check and Initialize ```bash -# Check if project state exists -bash(test -f .workflow/project.json && echo "EXISTS" || echo "NOT_FOUND") +# Check if project state exists (both files required) +bash(test -f .workflow/project-tech.json && echo "TECH_EXISTS" || echo "TECH_NOT_FOUND") +bash(test -f .workflow/project-guidelines.json && echo "GUIDELINES_EXISTS" || echo "GUIDELINES_NOT_FOUND") ``` -**If NOT_FOUND**, delegate to `/workflow:init`: +**If either NOT_FOUND**, delegate to `/workflow:init`: ```javascript // Call workflow:init for intelligent project analysis SlashCommand({command: "/workflow:init"}); // Wait for init completion -// project.json will be created with comprehensive project overview +// project-tech.json and project-guidelines.json will be created ``` **Output**: -- If EXISTS: `PROJECT_STATE: initialized` -- If NOT_FOUND: Calls `/workflow:init` → creates `.workflow/project.json` with full project analysis +- If BOTH_EXIST: `PROJECT_STATE: initialized` +- If NOT_FOUND: Calls `/workflow:init` → creates: + - `.workflow/project-tech.json` with full technical analysis + - `.workflow/project-guidelines.json` with empty scaffold **Note**: `/workflow:init` uses cli-explore-agent to build comprehensive project understanding (technology stack, architecture, key components). This step runs once per project. Subsequent executions skip initialization. diff --git a/.claude/commands/workflow/tools/context-gather.md b/.claude/commands/workflow/tools/context-gather.md index 764f89a2..ac9efff5 100644 --- a/.claude/commands/workflow/tools/context-gather.md +++ b/.claude/commands/workflow/tools/context-gather.md @@ -236,7 +236,10 @@ Task( Execute complete context-search-agent workflow for implementation planning: ### Phase 1: Initialization & Pre-Analysis -1. **Project State Loading**: Read and parse `.workflow/project.json`. Use its `overview` section as the foundational `project_context`. This is your primary source for architecture, tech stack, and key components. If file doesn't exist, proceed with fresh analysis. +1. **Project State Loading**: + - Read and parse `.workflow/project-tech.json`. Use its `technology_analysis` section as the foundational `project_context`. This is your primary source for architecture, tech stack, and key components. + - Read and parse `.workflow/project-guidelines.json`. Load `conventions`, `constraints`, and `learnings` into a `project_guidelines` section. + - If files don't exist, proceed with fresh analysis. 2. **Detection**: Check for existing context-package (early exit if valid) 3. **Foundation**: Initialize CodexLens, get project structure, load docs 4. **Analysis**: Extract keywords, determine scope, classify complexity based on task description and project state @@ -251,17 +254,19 @@ Execute all discovery tracks: ### Phase 3: Synthesis, Assessment & Packaging 1. Apply relevance scoring and build dependency graph -2. **Synthesize 4-source data**: Merge findings from all sources (archive > docs > code > web). **Prioritize the context from `project.json`** for architecture and tech stack unless code analysis reveals it's outdated. -3. **Populate `project_context`**: Directly use the `overview` from `project.json` to fill the `project_context` section of the output `context-package.json`. Include description, technology_stack, architecture, and key_components. -4. Integrate brainstorm artifacts (if .brainstorming/ exists, read content) -5. Perform conflict detection with risk assessment -6. **Inject historical conflicts** from archive analysis into conflict_detection -7. Generate and validate context-package.json +2. **Synthesize 4-source data**: Merge findings from all sources (archive > docs > code > web). **Prioritize the context from `project-tech.json`** for architecture and tech stack unless code analysis reveals it's outdated. +3. **Populate `project_context`**: Directly use the `technology_analysis` from `project-tech.json` to fill the `project_context` section. Include description, technology_stack, architecture, and key_components. +4. **Populate `project_guidelines`**: Load conventions, constraints, and learnings from `project-guidelines.json` into a dedicated section. +5. Integrate brainstorm artifacts (if .brainstorming/ exists, read content) +6. Perform conflict detection with risk assessment +7. **Inject historical conflicts** from archive analysis into conflict_detection +8. Generate and validate context-package.json ## Output Requirements Complete context-package.json with: - **metadata**: task_description, keywords, complexity, tech_stack, session_id -- **project_context**: description, technology_stack, architecture, key_components (sourced from `project.json` overview) +- **project_context**: description, technology_stack, architecture, key_components (sourced from `project-tech.json`) +- **project_guidelines**: {conventions, constraints, quality_rules, learnings} (sourced from `project-guidelines.json`) - **assets**: {documentation[], source_code[], config[], tests[]} with relevance scores - **dependencies**: {internal[], external[]} with dependency graph - **brainstorm_artifacts**: {guidance_specification, role_analyses[], synthesis_output} with content @@ -314,7 +319,8 @@ Refer to `context-search-agent.md` Phase 3.7 for complete `context-package.json` **Key Sections**: - **metadata**: Session info, keywords, complexity, tech stack -- **project_context**: Architecture patterns, conventions, tech stack (populated from `project.json` overview) +- **project_context**: Architecture patterns, conventions, tech stack (populated from `project-tech.json`) +- **project_guidelines**: Conventions, constraints, quality rules, learnings (populated from `project-guidelines.json`) - **assets**: Categorized files with relevance scores (documentation, source_code, config, tests) - **dependencies**: Internal and external dependency graphs - **brainstorm_artifacts**: Brainstorm documents with full content (if exists) @@ -429,6 +435,7 @@ if (historicalConflicts.length > 0 && currentRisk === "low") { ## Notes - **Detection-first**: Always check for existing package before invoking agent -- **Project.json integration**: Agent reads `.workflow/project.json` as primary source for project context, avoiding redundant analysis +- **Dual project file integration**: Agent reads both `.workflow/project-tech.json` (tech analysis) and `.workflow/project-guidelines.json` (user constraints) as primary sources +- **Guidelines injection**: Project guidelines are included in context-package to ensure task generation respects user-defined constraints - **No redundancy**: This command is a thin orchestrator, all logic in agent - **Plan-specific**: Use this for implementation planning; brainstorm mode uses direct agent call diff --git a/ccw/src/commands/issue.ts b/ccw/src/commands/issue.ts index 3a29ea58..c0a5ba30 100644 --- a/ccw/src/commands/issue.ts +++ b/ccw/src/commands/issue.ts @@ -1192,6 +1192,48 @@ async function nextAction(itemId: string | undefined, options: IssueOptions): Pr }, null, 2)); } +/** + * detail - Get task details by item_id (READ-ONLY, does NOT change status) + * Used for parallel execution: orchestrator gets dag, then dispatches with detail + */ +async function detailAction(itemId: string | undefined, options: IssueOptions): Promise { + if (!itemId) { + console.log(JSON.stringify({ status: 'error', message: 'item_id is required' })); + return; + } + + const queue = readActiveQueue(); + const queueItem = queue.tasks.find(t => t.item_id === itemId); + + if (!queueItem) { + console.log(JSON.stringify({ status: 'error', message: `Task ${itemId} not found` })); + return; + } + + // Load task definition from solution + const solution = findSolution(queueItem.issue_id, queueItem.solution_id); + const taskDef = solution?.tasks.find(t => t.id === queueItem.task_id); + + if (!taskDef) { + console.log(JSON.stringify({ status: 'error', message: 'Task definition not found in solution' })); + return; + } + + // Return full task info (READ-ONLY - no status update) + console.log(JSON.stringify({ + item_id: queueItem.item_id, + issue_id: queueItem.issue_id, + solution_id: queueItem.solution_id, + status: queueItem.status, + task: taskDef, + context: solution?.exploration_context || {}, + execution_hints: { + executor: queueItem.assigned_executor, + estimated_minutes: taskDef.estimated_minutes || 30 + } + }, null, 2)); +} + /** * done - Mark task completed or failed */ @@ -1333,6 +1375,9 @@ export async function issueCommand( case 'next': await nextAction(argsArray[0], options); break; + case 'detail': + await detailAction(argsArray[0], options); + break; case 'done': await doneAction(argsArray[0], options); break; @@ -1370,7 +1415,8 @@ export async function issueCommand( console.log(chalk.gray(' retry [issue-id] Retry failed tasks')); console.log(); console.log(chalk.bold('Execution Endpoints:')); - console.log(chalk.gray(' next [item-id] Get task by ID or next ready task (JSON)')); + console.log(chalk.gray(' next [item-id] Get & mark task executing (JSON)')); + console.log(chalk.gray(' detail Get task details (READ-ONLY, for parallel)')); console.log(chalk.gray(' done Mark task completed')); console.log(chalk.gray(' done --fail Mark task failed')); console.log();