diff --git a/.claude/agents/issue-plan-agent.md b/.claude/agents/issue-plan-agent.md index bc436241..7b3bab58 100644 --- a/.claude/agents/issue-plan-agent.md +++ b/.claude/agents/issue-plan-agent.md @@ -180,10 +180,23 @@ function decomposeTasks(issue, exploration) { - Task validation (all 5 phases present) - Conflict detection (cross-issue file modifications) -**Solution Registration**: -```bash -# Write solution and register via CLI -ccw issue bind --solution /tmp/sol.json +**Solution Registration** (CRITICAL: check solution count first): +```javascript +for (const issue of issues) { + const solutions = generatedSolutions[issue.id]; + + if (solutions.length === 1) { + // Single solution → auto-bind + Bash(`ccw issue bind ${issue.id} --solution ${solutions[0].file}`); + bound.push({ issue_id: issue.id, solution_id: solutions[0].id, task_count: solutions[0].tasks.length }); + } else { + // Multiple solutions → DO NOT BIND, return for user selection + pending_selection.push({ + issue_id: issue.id, + solutions: solutions.map(s => ({ id: s.id, description: s.description, task_count: s.tasks.length })) + }); + } +} ``` --- @@ -255,7 +268,7 @@ Each line is a solution JSON containing tasks. Schema: `cat .claude/workflows/cl 2. Use vague criteria ("works correctly", "good performance") 3. Create circular dependencies 4. Generate more than 10 tasks per issue -5. Bind when multiple solutions exist +5. **Bind when multiple solutions exist** - MUST check `solutions.length === 1` before calling `ccw issue bind` **OUTPUT**: 1. Register solutions via `ccw issue bind --solution ` diff --git a/.claude/agents/issue-queue-agent.md b/.claude/agents/issue-queue-agent.md index 167bf0a0..d902265c 100644 --- a/.claude/agents/issue-queue-agent.md +++ b/.claude/agents/issue-queue-agent.md @@ -244,4 +244,7 @@ Queue Item ID format: `S-N` (S-1, S-2, S-3, ...) **OUTPUT**: 1. Write `.workflow/issues/queues/{queue-id}.json` 2. Update `.workflow/issues/queues/index.json` -3. Return summary with `queue_id`, `total_solutions`, `total_tasks`, `execution_groups`, `conflicts_resolved`, `issues_queued` +3. **CRITICAL**: Final return MUST be PURE JSON only (no markdown, no explanation, no prose): + ```json + {"queue_id":"QUE-xxx","total_solutions":N,"total_tasks":N,"execution_groups":[...],"conflicts_resolved":N,"issues_queued":["ISS-xxx"]} + ``` diff --git a/.claude/commands/issue/plan.md b/.claude/commands/issue/plan.md index 23c76b54..703c9cbd 100644 --- a/.claude/commands/issue/plan.md +++ b/.claude/commands/issue/plan.md @@ -252,7 +252,11 @@ for (let i = 0; i < agentTasks.length; i += MAX_PARALLEL) { for (const item of summary.bound || []) { console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks)`); } - pendingSelections.push(...(summary.pending_selection || [])); + // Collect and notify pending selections + for (const pending of summary.pending_selection || []) { + console.log(`⏳ ${pending.issue_id}: ${pending.solutions.length} solutions → awaiting selection`); + pendingSelections.push(pending); + } if (summary.conflicts?.length > 0) { console.log(`⚠ Conflicts: ${summary.conflicts.map(c => c.file).join(', ')}`); } @@ -261,11 +265,13 @@ for (let i = 0; i < agentTasks.length; i += MAX_PARALLEL) { } ``` -### Phase 3: Multi-Solution Selection +### Phase 3: Multi-Solution Selection (MANDATORY when pendingSelections > 0) ```javascript -// Only handle issues where agent generated multiple solutions +// MUST trigger user selection when multiple solutions exist if (pendingSelections.length > 0) { + console.log(`\n## User Selection Required: ${pendingSelections.length} issue(s) have multiple solutions\n`); + const answer = AskUserQuestion({ questions: pendingSelections.map(({ issue_id, solutions }) => ({ question: `Select solution for ${issue_id}:`, diff --git a/.claude/commands/issue/queue.md b/.claude/commands/issue/queue.md index 65666724..5cbf9b4b 100644 --- a/.claude/commands/issue/queue.md +++ b/.claude/commands/issue/queue.md @@ -199,6 +199,8 @@ Phase 5: Queue Output ### Phase 1: Solution Loading +**NOTE**: Execute code directly. DO NOT pre-read solution files - Bash cat handles all reading. + ```javascript // Load issues.jsonl const issuesPath = '.workflow/issues/issues.jsonl'; diff --git a/.codex/prompts/issue-plan.md b/.codex/prompts/issue-plan.md new file mode 100644 index 00000000..3930fa6a --- /dev/null +++ b/.codex/prompts/issue-plan.md @@ -0,0 +1,106 @@ +--- +description: Plan issue(s) into bound solutions (writes solutions JSONL via ccw issue bind) +argument-hint: "[,,...] [--all-pending] [--batch-size 3]" +--- + +# Issue Plan (Codex Version) + +## Goal + +Create executable solution(s) for issue(s) and bind the selected solution to each issue using `ccw issue bind`. + +This workflow is **planning + registration** (no implementation): it explores the codebase just enough to produce a high-quality task breakdown that can be executed later (e.g., by `issue-execute.md`). + +## Inputs + +- **Explicit issues**: comma-separated IDs, e.g. `ISS-123,ISS-124` +- **All pending**: `--all-pending` → plan all issues in `registered` status +- **Batch size**: `--batch-size N` (default `3`) → max issues per batch + +## Output Requirements + +For each issue: +- Register at least one solution and bind one solution to the issue (updates `.workflow/issues/issues.jsonl` and appends to `.workflow/issues/solutions/{issue-id}.jsonl`). +- Ensure tasks conform to `.claude/workflows/cli-templates/schemas/solution-schema.json`. +- Each task includes quantified `acceptance.criteria` and concrete `acceptance.verification`. + +Return a final summary JSON: +```json +{ + "bound": [{ "issue_id": "...", "solution_id": "...", "task_count": 0 }], + "pending_selection": [{ "issue_id": "...", "solutions": [{ "id": "...", "task_count": 0, "description": "..." }] }], + "conflicts": [{ "file": "...", "issues": ["..."] }] +} +``` + +## Workflow + +### Step 1: Resolve issue list + +- If `--all-pending`: + - Run `ccw issue list --status registered --json` and plan all returned issues. +- Else: + - Parse IDs from user input (split by `,`), and ensure each issue exists: + - `ccw issue init --title "Issue "` (safe if already exists) + +### Step 2: Load issue details + +For each issue ID: +- `ccw issue status --json` +- Extract the issue title/context/labels and any discovery hints (affected files, snippets, etc. if present). + +### Step 3: Minimal exploration (evidence-based) + +- If issue context names specific files or symbols: open them first. +- Otherwise: + - Use `rg` to locate relevant code paths by keywords from the title/context. + - Read 3+ similar patterns before proposing refactors or API changes. + +### Step 4: Draft solutions and tasks (schema-driven) + +Default to **one** solution per issue unless there are genuinely different approaches. + +Task rules (from schema): +- `id`: `T1`, `T2`, ... +- `action`: one of `Create|Update|Implement|Refactor|Add|Delete|Configure|Test|Fix` +- `implementation`: step-by-step, executable instructions +- `test.commands`: include at least one command per task when feasible +- `acceptance.criteria`: testable statements +- `acceptance.verification`: concrete steps/commands mapping to criteria +- Prefer small, independently testable tasks; encode dependencies in `depends_on`. + +### Step 5: Register & bind solutions via CLI + +Create an import JSON file per solution (NOT JSONL), then bind it: + +1. Write a file (example path): + - `.workflow/issues/solutions/_imports/-.json` +2. File contents shape (minimum): + ```json + { + "description": "High-level summary", + "approach": "Technical approach", + "tasks": [] + } + ``` +3. Register+bind in one step: + - `ccw issue bind --solution ` + +If you intentionally generated multiple solutions for the same issue: +- Register each via `ccw issue bind --solution ` (do NOT bind yet). +- Present the alternatives in `pending_selection` and stop for user choice. +- Bind chosen solution with: `ccw issue bind `. + +### Step 6: Detect cross-issue file conflicts (best-effort) + +Across the issues planned in this run: +- Build a set of touched files from each solution’s `modification_points.file` (and/or task `scope` when explicit files are missing). +- If the same file appears in multiple issues, add it to `conflicts` with all involved issue IDs. +- Recommend a safe execution order (sequential) when conflicts exist. + +## Done Criteria + +- A bound solution exists for each issue unless explicitly deferred for user selection. +- All tasks validate against the solution schema fields (especially acceptance criteria + verification). +- The final summary JSON matches the required shape. +