From 267e46c5cf58dc1a392a932744a54b86ae627da5 Mon Sep 17 00:00:00 2001 From: Dean Sharon Date: Sat, 28 Mar 2026 02:15:44 +0300 Subject: [PATCH 1/3] docs: update social preview for v1.8.3 --- .github/assets/social-preview.png | Bin 102564 -> 102574 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.github/assets/social-preview.png b/.github/assets/social-preview.png index d64726c89974b91ab2186b0737bb24d796473fe8..058a53106946e661aaeab0f6b8071d1f51ff5487 100644 GIT binary patch literal 102574 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 oye{^QAheMeKWo4GpZ~uFH%!t&9S1z0aq=G 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 Date: Sat, 28 Mar 2026 11:36:57 +0300 Subject: [PATCH 2/3] feat: incremental reviews, timestamped dirs, worktree discovery Add timestamped review directories with incremental diff tracking via .last-review-head. Auto-discover git worktrees and process all reviewable branches in parallel. Update agent/skill documentation for multi-agent parallel workflows. --- CLAUDE.md | 13 +- .../commands/code-review-teams.md | 138 ++++++++++++---- .../commands/code-review.md | 149 +++++++++++++----- .../devflow-resolve/commands/resolve-teams.md | 109 ++++++++++--- plugins/devflow-resolve/commands/resolve.md | 106 ++++++++++--- scripts/hooks/ambient-prompt | 1 + shared/agents/coder.md | 8 + shared/agents/git.md | 38 +++-- shared/agents/resolver.md | 8 + shared/agents/reviewer.md | 11 +- shared/agents/scrutinizer.md | 7 + shared/agents/shepherd.md | 7 + shared/agents/simplifier.md | 7 + shared/agents/synthesizer.md | 10 +- shared/agents/validator.md | 8 + shared/skills/ambient-router/SKILL.md | 5 + .../references/skill-catalog.md | 13 ++ shared/skills/debug-orchestration/SKILL.md | 4 + shared/skills/docs-framework/SKILL.md | 20 ++- .../docs-framework/references/patterns.md | 59 +++++-- .../implementation-orchestration/SKILL.md | 4 + shared/skills/plan-orchestration/SKILL.md | 4 + 22 files changed, 576 insertions(+), 153 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5318ce48..b830f807 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -90,8 +90,13 @@ All generated docs live under `.docs/` in the project root: ``` .docs/ -├── reviews/{branch-slug}/ # Review reports per branch -└── design/ # Implementation plans +├── reviews/{branch-slug}/ # Review reports per branch +│ ├── .last-review-head # HEAD SHA for incremental reviews +│ └── {timestamp}/ # Timestamped review directory +│ ├── {focus}.md # Reviewer reports (security.md, etc.) +│ ├── review-summary.md # Synthesizer output +│ └── resolution-summary.md # Written by /resolve +└── design/ # Implementation plans ``` Working memory files live in a dedicated `.memory/` directory: @@ -117,7 +122,9 @@ Working memory files live in a dedicated `.memory/` directory: **Naming conventions**: Timestamps as `YYYY-MM-DD_HHMM`, branch slugs replace `/` with `-`, topic slugs are lowercase-dashes. -**Persisting agents**: Reviewer → `.docs/reviews/`, Synthesizer → `.docs/reviews/` (review mode), Working Memory → `.memory/WORKING-MEMORY.md` (automatic) +**Persisting agents**: Reviewer → `.docs/reviews/{branch-slug}/{timestamp}/{focus}.md`, Synthesizer → `.docs/reviews/{branch-slug}/{timestamp}/review-summary.md` (review mode), Resolver → `.docs/reviews/{branch-slug}/{timestamp}/resolution-summary.md`, Working Memory → `.memory/WORKING-MEMORY.md` (automatic) + +**Incremental Reviews**: `/code-review` writes reports into timestamped subdirectories (`YYYY-MM-DD_HHMM`) and tracks HEAD SHA in `.last-review-head` for incremental diffs. Second review only diffs from last reviewed commit. `/resolve` defaults to latest timestamped directory. Both commands auto-discover git worktrees and process all reviewable branches in parallel. ## Agent & Command Roster diff --git a/plugins/devflow-code-review/commands/code-review-teams.md b/plugins/devflow-code-review/commands/code-review-teams.md index def2ca72..be3250a1 100644 --- a/plugins/devflow-code-review/commands/code-review-teams.md +++ b/plugins/devflow-code-review/commands/code-review-teams.md @@ -4,37 +4,70 @@ description: Comprehensive branch review using agent teams for adversarial peer # Code Review Command -Run a comprehensive code review of the current branch by spawning a review team where agents debate findings, then synthesize consensus results into PR comments. +Run a comprehensive code review of the current branch by spawning a review team where agents debate findings, then synthesize consensus results into PR comments. Supports incremental reviews, timestamped report directories, and multi-worktree auto-discovery. ## Usage ``` -/code-review (review current branch) +/code-review (review current branch — or all worktrees if multiple found) /code-review #42 (review specific PR) +/code-review --full (force full-branch review, ignore previous review state) +/code-review --path /path/to/worktree (review a specific worktree only) ``` ## Phases -### Phase 0: Pre-Flight (Git Agent) +### Phase 0: Worktree Discovery & Pre-Flight -Spawn Git agent to validate and prepare branch: +#### Step 0a: Discover Worktrees + +1. Run `git worktree list --porcelain` to discover all worktrees +2. For each worktree, extract path and branch +3. **Filter to reviewable worktrees:** + - Must be on a named branch (skip detached HEAD) + - Must NOT be on a protected branch (main, master, develop, release/*, staging, production) + - Must NOT be mid-rebase or mid-merge (check `git -C {path} status` for "rebase in progress" / "merging") +4. **If `--path` flag provided:** use only that worktree, skip discovery +5. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change +6. **If multiple reviewable worktrees:** report "Found N worktrees with reviewable branches: {list with paths and branches}" and proceed with multi-worktree flow +7. **Deduplicate by branch:** if two worktrees are on the same branch, use only the first worktree's path + +#### Step 0b: Per-Worktree Pre-Flight (Git Agent) + +For each reviewable worktree, spawn Git agent: ``` Task(subagent_type="Git", run_in_background=false): "OPERATION: ensure-pr-ready +WORKTREE_PATH: {worktree_path} (omit if cwd) Validate branch, commit if needed, push, create PR if needed. Return: branch, base_branch, branch-slug, PR#" ``` -**If BLOCKED:** Stop and report the blocker to user. +In multi-worktree mode, spawn all pre-flight agents **in a single message** (parallel). + +**If BLOCKED:** In single-worktree mode, stop and report. In multi-worktree mode, report the failure but continue with other worktrees. -**Extract from response:** `branch`, `base_branch`, `branch_slug`, `pr_number` for use in subsequent phases. +**Extract from response:** `branch`, `base_branch`, `branch_slug`, `pr_number` per worktree. +#### Step 0c: Incremental Detection & Timestamp Setup +For each worktree: + +1. Generate timestamp: `YYYY-MM-DD_HHMM`. If directory already exists (same-minute collision), append seconds (`YYYY-MM-DD_HHMMSS`). +2. Create timestamped review directory: `mkdir -p {worktree}/.docs/reviews/{branch-slug}/{timestamp}/` +3. Check if `{worktree}/.docs/reviews/{branch-slug}/.last-review-head` exists: + - **If yes AND `--full` NOT set:** + - Read the SHA from the file + - Verify reachable: `git -C {worktree} cat-file -t {sha}` (handles rebases — if unreachable, fallback to full) + - Check if SHA == current HEAD → if so, skip review: "No new commits since last review. Use --full for a full re-review." + - Set `DIFF_RANGE` to `{last-review-sha}...HEAD` + - **If no (first review), or `--full`:** + - Set `DIFF_RANGE` to `{base_branch}...HEAD` ### Phase 1: Analyze Changed Files -Detect file types in diff to determine conditional reviews: +Per worktree, detect file types in diff using `DIFF_RANGE` to determine conditional reviews: | Condition | Adds Perspective | |-----------|-----------------| @@ -54,7 +87,9 @@ Detect file types in diff to determine conditional reviews: ### Phase 2: Spawn Review Team -Create an agent team for adversarial review. Always include 4 core perspectives; conditionally add more based on Phase 1 analysis. +**Per worktree**, create an agent team for adversarial review. Always include 4 core perspectives; conditionally add more based on Phase 1 analysis. + +**Note**: In multi-worktree mode, process worktrees sequentially for Agent Teams (one team per session constraint). Each worktree gets its own team lifecycle: create → debate → synthesize → cleanup. **Core perspectives (always):** - **Security**: vulnerabilities, injection, auth, crypto issues @@ -83,48 +118,52 @@ Spawn review teammates with self-contained prompts: - Name: "security-reviewer" Prompt: | You are reviewing PR #{pr_number} on branch {branch} (base: {base_branch}). + WORKTREE_PATH: {worktree_path} (omit if cwd) 1. Read your skill: `Read ~/.claude/skills/security-patterns/SKILL.md` 2. Read review methodology: `Read ~/.claude/skills/review-methodology/SKILL.md` 3. Read `.memory/knowledge/pitfalls.md` if it exists. Check for known pitfall patterns in the diff. - 4. Get the diff: `git diff {base_branch}...HEAD` + 4. Get the diff: `git {-C worktree_path} diff {DIFF_RANGE}` 5. Apply the 6-step review process from review-methodology 6. Focus: injection, auth bypass, crypto misuse, OWASP vulnerabilities 7. Classify each finding: 🔴 BLOCKING / ⚠️ SHOULD-FIX / ℹ️ PRE-EXISTING 8. Include file:line references for every finding - 9. Write your report: `Write to .docs/reviews/{branch_slug}/security.md` + 9. Write your report: `Write to {worktree_path}/.docs/reviews/{branch_slug}/{timestamp}/security.md` 10. Report completion: SendMessage(type: "message", recipient: "team-lead", summary: "Security review done") - Name: "architecture-reviewer" Prompt: | You are reviewing PR #{pr_number} on branch {branch} (base: {base_branch}). + WORKTREE_PATH: {worktree_path} (omit if cwd) 1. Read your skill: `Read ~/.claude/skills/architecture-patterns/SKILL.md` 2. Read review methodology: `Read ~/.claude/skills/review-methodology/SKILL.md` 3. Read `.memory/knowledge/pitfalls.md` if it exists. Check for known pitfall patterns in the diff. - 4. Get the diff: `git diff {base_branch}...HEAD` + 4. Get the diff: `git {-C worktree_path} diff {DIFF_RANGE}` 5. Apply the 6-step review process from review-methodology 6. Focus: SOLID violations, coupling, layering issues, modularity problems 7. Classify each finding: 🔴 BLOCKING / ⚠️ SHOULD-FIX / ℹ️ PRE-EXISTING 8. Include file:line references for every finding - 9. Write your report: `Write to .docs/reviews/{branch_slug}/architecture.md` + 9. Write your report: `Write to {worktree_path}/.docs/reviews/{branch_slug}/{timestamp}/architecture.md` 10. Report completion: SendMessage(type: "message", recipient: "team-lead", summary: "Architecture review done") - Name: "performance-reviewer" Prompt: | You are reviewing PR #{pr_number} on branch {branch} (base: {base_branch}). + WORKTREE_PATH: {worktree_path} (omit if cwd) 1. Read your skill: `Read ~/.claude/skills/performance-patterns/SKILL.md` 2. Read review methodology: `Read ~/.claude/skills/review-methodology/SKILL.md` 3. Read `.memory/knowledge/pitfalls.md` if it exists. Check for known pitfall patterns in the diff. - 4. Get the diff: `git diff {base_branch}...HEAD` + 4. Get the diff: `git {-C worktree_path} diff {DIFF_RANGE}` 5. Apply the 6-step review process from review-methodology 6. Focus: N+1 queries, memory leaks, algorithm issues, I/O bottlenecks 7. Classify each finding: 🔴 BLOCKING / ⚠️ SHOULD-FIX / ℹ️ PRE-EXISTING 8. Include file:line references for every finding - 9. Write your report: `Write to .docs/reviews/{branch_slug}/performance.md` + 9. Write your report: `Write to {worktree_path}/.docs/reviews/{branch_slug}/{timestamp}/performance.md` 10. Report completion: SendMessage(type: "message", recipient: "team-lead", summary: "Performance review done") - Name: "quality-reviewer" Prompt: | You are reviewing PR #{pr_number} on branch {branch} (base: {base_branch}). + WORKTREE_PATH: {worktree_path} (omit if cwd) 1. Read your skills: - `Read ~/.claude/skills/complexity-patterns/SKILL.md` - `Read ~/.claude/skills/consistency-patterns/SKILL.md` @@ -132,16 +171,16 @@ Spawn review teammates with self-contained prompts: - `Read ~/.claude/skills/regression-patterns/SKILL.md` 2. Read review methodology: `Read ~/.claude/skills/review-methodology/SKILL.md` 3. Read `.memory/knowledge/pitfalls.md` if it exists. Check for known pitfall patterns in the diff. - 4. Get the diff: `git diff {base_branch}...HEAD` + 4. Get the diff: `git {-C worktree_path} diff {DIFF_RANGE}` 5. Apply the 6-step review process from review-methodology 6. Focus: complexity, test gaps, pattern violations, regressions, naming 7. Classify each finding: 🔴 BLOCKING / ⚠️ SHOULD-FIX / ℹ️ PRE-EXISTING 8. Include file:line references for every finding - 9. Write your report: `Write to .docs/reviews/{branch_slug}/quality.md` + 9. Write your report: `Write to {worktree_path}/.docs/reviews/{branch_slug}/{timestamp}/quality.md` 10. Report completion: SendMessage(type: "message", recipient: "team-lead", summary: "Quality review done") [Add conditional perspectives based on Phase 1 — follow same pattern: - explicit skill path, diff command, output path, SendMessage for completion] + explicit skill path, diff command with DIFF_RANGE, output path in timestamped dir, SendMessage for completion] ``` ### Phase 3: Debate Round @@ -184,13 +223,15 @@ Spawn 2 agents **in a single message**: ``` Task(subagent_type="Git", run_in_background=false): "OPERATION: comment-pr -Read reviews from .docs/reviews/{branch_slug}/ +WORKTREE_PATH: {worktree_path} (omit if cwd) +Read reviews from {worktree_path}/.docs/reviews/{branch_slug}/{timestamp}/ Create inline PR comments. Deduplicate overlapping findings. Consolidate skipped findings into summary comment. -Include confidence levels from debate consensus." +Include confidence levels from debate consensus. +Check for existing inline comments at same file:line before creating new ones." ``` -**Lead synthesizes review summary** (written to `.docs/reviews/{branch_slug}/review-summary.{timestamp}.md`): +**Lead synthesizes review summary** (written to `{worktree_path}/.docs/reviews/{branch_slug}/{timestamp}/review-summary.md`): ```markdown ## Review Summary: {branch} @@ -216,14 +257,21 @@ Include confidence levels from debate consensus." {Key exchanges that changed findings} ``` -### Phase 5: Record Pitfalls (if blocking issues found) +### Phase 5: Write Review Head Marker + +Per worktree, after successful completion: +1. Write current HEAD SHA to `{worktree_path}/.docs/reviews/{branch-slug}/.last-review-head` + +### Phase 6: Record Pitfalls (Sequential) -If the review summary contains CRITICAL or HIGH blocking issues: +**IMPORTANT**: Run sequentially across all worktrees (not in parallel) to avoid GitHub API conflicts. + +Per worktree, if the review summary contains CRITICAL or HIGH blocking issues: 1. Read `~/.claude/skills/knowledge-persistence/SKILL.md` and follow its extraction procedure to record pitfalls to `.memory/knowledge/pitfalls.md` 2. Source field: `/code-review {branch}` 3. Skip entirely if no CRITICAL/HIGH blocking issues -### Phase 6: Cleanup and Report +### Phase 7: Cleanup and Report Shut down all review teammates explicitly: @@ -243,18 +291,22 @@ Display results: - Key debate highlights - Artifact paths +In multi-worktree mode, report results per worktree with aggregate summary. + ## Architecture ``` /code-review (orchestrator - creates team, coordinates debate) │ -├─ Phase 0: Pre-flight -│ └─ Git agent (ensure-pr-ready) +├─ Phase 0: Worktree Discovery & Pre-flight +│ ├─ Step 0a: git worktree list → filter reviewable +│ ├─ Step 0b: Git agent (ensure-pr-ready) per worktree [parallel] +│ └─ Step 0c: Incremental detection + timestamp setup per worktree │ -├─ Phase 1: Analyze changed files +├─ Phase 1: Analyze changed files per worktree │ └─ Detect file types for conditional perspectives │ -├─ Phase 2: Spawn review team +├─ Phase 2: Spawn review team (per worktree, sequential for teams) │ ├─ Security Reviewer (teammate) │ ├─ Architecture Reviewer (teammate) │ ├─ Performance Reviewer (teammate) @@ -265,14 +317,37 @@ Display results: │ └─ Reviewers challenge each other (max 2 rounds) │ ├─ Phase 4: Synthesis -│ ├─ Git agent (comment-pr with consensus findings) +│ ├─ Git agent (comment-pr with consensus findings + dedup) │ └─ Lead writes review-summary with confidence levels │ -├─ Phase 5: Record Pitfalls (inline, if blocking issues) +├─ Phase 5: Write .last-review-head per worktree │ -└─ Phase 6: Cleanup and display results +├─ Phase 6: Record Pitfalls (SEQUENTIAL across worktrees) +│ +└─ Phase 7: Cleanup and display results ``` +## Edge Cases + +| Case | Handling | +|------|----------| +| No new commits since last review | Skip review, report: "No new commits since last review. Use --full for a full re-review." | +| Rebase invalidates `.last-review-head` SHA | `git cat-file -t` check fails → fallback to full diff | +| Same-minute review collision | `mkdir` fails → retry with seconds appended (`YYYY-MM-DD_HHMMSS`) | +| Worktree in detached HEAD | Filtered out (no branch name → not reviewable) | +| Worktree mid-rebase or mid-merge | Filtered out by status check | +| Two worktrees on same branch | Deduplicate by branch — review once, use first worktree's path | +| Worktree on protected branch | Filtered out (not reviewable) | +| Worktree pre-flight fails | Report failure, continue with other worktrees | +| `--full` in multi-worktree mode | Applies to all worktrees (global modifier) | +| Multi-worktree with Agent Teams | Process worktrees sequentially (one team per session) | +| Duplicate PR comments | Git agent checks for existing comments at same file:line | + +## Backwards Compatibility + +- **Single worktree**: Auto-discovery finds only one worktree → proceeds exactly as before. Zero behavior change. +- **Legacy flat layout**: New runs create timestamped subdirectories. Old flat files remain untouched. + ## Principles 1. **Adversarial review** - Reviewers challenge each other's findings, not just report independently @@ -282,4 +357,5 @@ Display results: 5. **Bounded debate** - Max 2 exchange rounds, then converge 6. **Honest reporting** - Report disagreements with evidence, don't paper over conflicts 7. **Cleanup always** - Team resources released even on failure - +8. **Incremental by default** - Only review new changes unless `--full` specified +9. **Auto-discover worktrees** - One command handles all reviewable branches diff --git a/plugins/devflow-code-review/commands/code-review.md b/plugins/devflow-code-review/commands/code-review.md index af7d2747..41ac1bb3 100644 --- a/plugins/devflow-code-review/commands/code-review.md +++ b/plugins/devflow-code-review/commands/code-review.md @@ -4,37 +4,70 @@ description: Comprehensive branch review using specialized sub-agents for PR rea # Code Review Command -Run a comprehensive code review of the current branch by spawning parallel review agents, then synthesizing results into PR comments. +Run a comprehensive code review of the current branch by spawning parallel review agents, then synthesizing results into PR comments. Supports incremental reviews, timestamped report directories, and multi-worktree auto-discovery. ## Usage ``` -/code-review (review current branch) +/code-review (review current branch — or all worktrees if multiple found) /code-review #42 (review specific PR) +/code-review --full (force full-branch review, ignore previous review state) +/code-review --path /path/to/worktree (review a specific worktree only) ``` ## Phases -### Phase 0: Pre-Flight (Git Agent) +### Phase 0: Worktree Discovery & Pre-Flight -Spawn Git agent to validate and prepare branch: +#### Step 0a: Discover Worktrees + +1. Run `git worktree list --porcelain` to discover all worktrees +2. For each worktree, extract path and branch +3. **Filter to reviewable worktrees:** + - Must be on a named branch (skip detached HEAD) + - Must NOT be on a protected branch (main, master, develop, release/*, staging, production) + - Must NOT be mid-rebase or mid-merge (check `git -C {path} status` for "rebase in progress" / "merging") +4. **If `--path` flag provided:** use only that worktree, skip discovery +5. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change +6. **If multiple reviewable worktrees:** report "Found N worktrees with reviewable branches: {list with paths and branches}" and proceed with multi-worktree flow +7. **Deduplicate by branch:** if two worktrees are on the same branch, use only the first worktree's path + +#### Step 0b: Per-Worktree Pre-Flight (Git Agent) + +For each reviewable worktree, spawn Git agent: ``` Task(subagent_type="Git", run_in_background=false): "OPERATION: ensure-pr-ready +WORKTREE_PATH: {worktree_path} (omit if cwd) Validate branch, commit if needed, push, create PR if needed. Return: branch, base_branch, branch-slug, PR#" ``` -**If BLOCKED:** Stop and report the blocker to user. +In multi-worktree mode, spawn all pre-flight agents **in a single message** (parallel). -**Extract from response:** `branch`, `base_branch`, `branch_slug`, `pr_number` for use in subsequent phases. +**If BLOCKED:** In single-worktree mode, stop and report. In multi-worktree mode, report the failure but continue with other worktrees. +**Extract from response:** `branch`, `base_branch`, `branch_slug`, `pr_number` per worktree. +#### Step 0c: Incremental Detection & Timestamp Setup + +For each worktree: + +1. Generate timestamp: `YYYY-MM-DD_HHMM`. If directory already exists (same-minute collision), append seconds (`YYYY-MM-DD_HHMMSS`). +2. Create timestamped review directory: `mkdir -p {worktree}/.docs/reviews/{branch-slug}/{timestamp}/` +3. Check if `{worktree}/.docs/reviews/{branch-slug}/.last-review-head` exists: + - **If yes AND `--full` NOT set:** + - Read the SHA from the file + - Verify reachable: `git -C {worktree} cat-file -t {sha}` (handles rebases — if unreachable, fallback to full) + - Check if SHA == current HEAD → if so, skip review: "No new commits since last review. Use --full for a full re-review." + - Set `DIFF_RANGE` to `{last-review-sha}...HEAD` + - **If no (first review), or `--full`:** + - Set `DIFF_RANGE` to `{base_branch}...HEAD` ### Phase 1: Analyze Changed Files -Detect file types in diff to determine conditional reviews: +Per worktree, detect file types in diff using `DIFF_RANGE` to determine conditional reviews: | Condition | Adds Review | |-----------|-------------| @@ -83,43 +116,58 @@ Task(subagent_type="Reviewer", run_in_background=false): "Review focusing on {focus}. Apply {focus}-patterns. Follow 6-step process from review-methodology. PR: #{pr_number}, Base: {base_branch} -IMPORTANT: Write report to .docs/reviews/{branch-slug}/{focus}.md using Write tool" +WORKTREE_PATH: {worktree_path} (omit if cwd) +DIFF_COMMAND: git diff {DIFF_RANGE} (use this instead of default base_branch...HEAD) +IMPORTANT: Write report to {worktree_path}/.docs/reviews/{branch-slug}/{timestamp}/{focus}.md using Write tool" ``` +In multi-worktree mode, spawn ALL reviewers for ALL worktrees in one parallel message. + ### Phase 3: Synthesis (Parallel) -**WAIT** for Phase 2, then spawn 3 agents **in a single message**: +**WAIT** for Phase 2, then spawn agents per worktree **in a single message**: -**Git Agent (PR Comments)**: +**Git Agent (PR Comments)** per worktree: ``` Task(subagent_type="Git", run_in_background=false): "OPERATION: comment-pr -Read reviews from .docs/reviews/{branch-slug}/ +WORKTREE_PATH: {worktree_path} (omit if cwd) +Read reviews from {worktree_path}/.docs/reviews/{branch-slug}/{timestamp}/ Create inline PR comments for findings with ≥80% confidence only. Lower-confidence suggestions (60-79%) go in the summary comment, not as inline comments. -Deduplicate findings across reviewers, consolidate skipped into summary." +Deduplicate findings across reviewers, consolidate skipped into summary. +Check for existing inline comments at same file:line before creating new ones to avoid duplicates." ``` -**Synthesizer Agent**: +**Synthesizer Agent** per worktree: ``` Task(subagent_type="Synthesizer", run_in_background=false): "Mode: review +WORKTREE_PATH: {worktree_path} (omit if cwd) +REVIEW_BASE_DIR: {worktree_path}/.docs/reviews/{branch-slug}/{timestamp} +TIMESTAMP: {timestamp} Aggregate findings, determine merge recommendation -Output: .docs/reviews/{branch-slug}/review-summary.{timestamp}.md" +Output: {worktree_path}/.docs/reviews/{branch-slug}/{timestamp}/review-summary.md" ``` -### Phase 4: Report +### Phase 4: Write Review Head Marker & Report -Display results from all agents: -- Merge recommendation (from Synthesizer) -- Issue counts by category (🔴 blocking / ⚠️ should-fix / ℹ️ pre-existing) -- PR comments created/skipped (from Git) -- Artifact paths +Per worktree, after successful completion: +1. Write current HEAD SHA to `{worktree_path}/.docs/reviews/{branch-slug}/.last-review-head` +2. Display results from all agents: + - Merge recommendation (from Synthesizer) + - Issue counts by category (🔴 blocking / ⚠️ should-fix / ℹ️ pre-existing) + - PR comments created/skipped (from Git) + - Artifact paths -### Phase 5: Record Pitfalls (if blocking issues found) +In multi-worktree mode, report results per worktree. -If the review summary contains CRITICAL or HIGH blocking issues: +### Phase 5: Record Pitfalls (Sequential) + +**IMPORTANT**: Run sequentially across all worktrees (not in parallel) to avoid GitHub API conflicts. + +Per worktree, if the review summary contains CRITICAL or HIGH blocking issues: 1. Read `~/.claude/skills/knowledge-persistence/SKILL.md` and follow its extraction procedure to record pitfalls to `.memory/knowledge/pitfalls.md` 2. Source field: `/code-review {branch}` 3. Skip entirely if no CRITICAL/HIGH blocking issues @@ -129,31 +177,54 @@ If the review summary contains CRITICAL or HIGH blocking issues: ``` /code-review (orchestrator - spawns agents only) │ -├─ Phase 0: Pre-flight -│ └─ Git agent (ensure-pr-ready) +├─ Phase 0: Worktree Discovery & Pre-flight +│ ├─ Step 0a: git worktree list → filter reviewable +│ ├─ Step 0b: Git agent (ensure-pr-ready) per worktree [parallel] +│ └─ Step 0c: Incremental detection + timestamp setup per worktree │ -├─ Phase 1: Analyze changed files +├─ Phase 1: Analyze changed files per worktree │ └─ Detect file types for conditional reviews │ -├─ Phase 2: Reviews (PARALLEL) -│ ├─ Reviewer: security -│ ├─ Reviewer: architecture -│ ├─ Reviewer: performance -│ ├─ Reviewer: complexity -│ ├─ Reviewer: consistency -│ ├─ Reviewer: regression -│ ├─ Reviewer: tests -│ └─ Reviewer: [conditional: typescript, react, a11y, design, go, java, python, rust, database, deps, docs] +├─ Phase 2: Reviews (PARALLEL — all worktrees in one message) +│ ├─ Reviewer: security (per worktree) +│ ├─ Reviewer: architecture (per worktree) +│ ├─ Reviewer: performance (per worktree) +│ ├─ Reviewer: complexity (per worktree) +│ ├─ Reviewer: consistency (per worktree) +│ ├─ Reviewer: regression (per worktree) +│ ├─ Reviewer: tests (per worktree) +│ └─ Reviewer: [conditional per worktree] │ -├─ Phase 3: Synthesis (PARALLEL) -│ ├─ Git agent (comment-pr) +├─ Phase 3: Synthesis (PARALLEL per worktree) +│ ├─ Git agent (comment-pr with dedup) │ └─ Synthesizer agent (mode: review) │ -├─ Phase 4: Display results +├─ Phase 4: Write .last-review-head + display results per worktree │ -└─ Phase 5: Record Pitfalls (inline, if blocking issues) +└─ Phase 5: Record Pitfalls (SEQUENTIAL across worktrees) ``` +## Edge Cases + +| Case | Handling | +|------|----------| +| No new commits since last review | Skip review, report: "No new commits since last review. Use --full for a full re-review." | +| Rebase invalidates `.last-review-head` SHA | `git cat-file -t` check fails → fallback to full diff | +| Same-minute review collision | `mkdir` fails → retry with seconds appended (`YYYY-MM-DD_HHMMSS`) | +| Worktree in detached HEAD | Filtered out (no branch name → not reviewable) | +| Worktree mid-rebase or mid-merge | Filtered out by status check | +| Two worktrees on same branch | Deduplicate by branch — review once, use first worktree's path | +| Worktree on protected branch | Filtered out (not reviewable) | +| Worktree pre-flight fails | Report failure, continue with other worktrees | +| `--full` in multi-worktree mode | Applies to all worktrees (global modifier) | +| Many worktrees (5+) | Report count and proceed — user manages their worktree count | +| Duplicate PR comments | Git agent checks for existing comments at same file:line before creating | + +## Backwards Compatibility + +- **Single worktree**: Auto-discovery finds only one worktree → proceeds exactly as before. Zero behavior change. +- **Legacy flat layout**: If `.docs/reviews/{branch-slug}/` contains flat `*.md` files (no timestamped subdirectories), new runs create timestamped subdirectories. Old flat files remain untouched. + ## Principles 1. **Orchestration only** - Command spawns agents, doesn't do git/review work itself @@ -161,3 +232,5 @@ If the review summary contains CRITICAL or HIGH blocking issues: 3. **Git agent for git work** - All git operations go through Git agent 4. **Clear ownership** - Each agent owns its output completely 5. **Honest reporting** - Display agent outputs directly +6. **Incremental by default** - Only review new changes unless `--full` specified +7. **Auto-discover worktrees** - One command handles all reviewable branches diff --git a/plugins/devflow-resolve/commands/resolve-teams.md b/plugins/devflow-resolve/commands/resolve-teams.md index efb81da8..d347740e 100644 --- a/plugins/devflow-resolve/commands/resolve-teams.md +++ b/plugins/devflow-resolve/commands/resolve-teams.md @@ -4,35 +4,70 @@ description: Process review issues using agent teams with cross-validation debat # Resolve Command -Process issues from code review reports: validate them (false positive check), assess risk for FIX vs TECH_DEBT decision, and implement fixes for low-risk issues. +Process issues from code review reports: validate them (false positive check), assess risk for FIX vs TECH_DEBT decision, and implement fixes for low-risk issues. Defaults to the latest timestamped review directory. Supports multi-worktree auto-discovery. ## Usage ``` -/resolve (resolve issues on current branch) -/resolve #42 (resolve issues for specific PR) +/resolve (resolve latest review on current branch — or all worktrees) +/resolve #42 (resolve issues for specific PR) +/resolve --review 2026-03-28_0900 (resolve a specific review run by timestamp) +/resolve --path /path/to/worktree (resolve a specific worktree only) ``` ## Phases -### Phase 0: Pre-Flight (Git Agent) +### Phase 0: Worktree Discovery & Pre-Flight -Spawn Git agent to validate branch state: +#### Step 0a: Discover Worktrees + +1. Run `git worktree list --porcelain` to discover all worktrees +2. For each worktree, extract path and branch +3. **Filter to resolvable worktrees:** + - Must be on a named branch (skip detached HEAD) + - Must NOT be on a protected branch (main, master, develop, release/*, staging, production) + - Must have unresolved reviews (latest review directory has no `resolution-summary.md`) +4. **If `--path` flag provided:** use only that worktree, skip discovery +5. **If only 1 resolvable worktree** (the common case): proceed as single-worktree flow — zero behavior change +6. **If multiple resolvable worktrees:** report "Found N worktrees with unresolved reviews: {list}" and proceed with multi-worktree flow + +#### Step 0b: Per-Worktree Pre-Flight (Git Agent) + +For each resolvable worktree, spawn Git agent: ``` Task(subagent_type="Git", run_in_background=false): "OPERATION: validate-branch +WORKTREE_PATH: {worktree_path} (omit if cwd) Check feature branch, clean working directory, reviews exist. Return: branch, branch-slug, PR#, review count" ``` -**If BLOCKED:** Stop and report the blocker to user. If no reviews found, suggest `/code-review` first. +In multi-worktree mode, spawn all pre-flight agents **in a single message** (parallel). + +**If BLOCKED:** In single-worktree mode, stop and report. In multi-worktree mode, report failure, continue with other worktrees. + +**Extract from response:** `branch`, `branch_slug`, `pr_number`, `review_count` per worktree. + +#### Step 0c: Target Review Directory + +For each worktree: -**Extract from response:** `branch`, `branch_slug`, `pr_number`, `review_count` for use in subsequent phases. +1. List directories in `{worktree}/.docs/reviews/{branch-slug}/` +2. **If `--review {timestamp}` provided:** use that specific directory (not supported in multi-worktree mode) +3. **Otherwise:** sort directories by name (timestamps are naturally sortable), select the latest that contains `review-summary.md` (complete review) +4. **If latest directory already has `resolution-summary.md`:** skip worktree — already resolved +5. **Legacy fallback:** if no timestamped subdirectories exist but flat `*.md` files do, read them directly (backwards compatible) + +Set `TARGET_DIR` to the selected review directory path. ### Phase 1: Parse Issues -Read all review reports from `.docs/reviews/{branch-slug}/*.md` and extract: +Read review reports from `{TARGET_DIR}/*.md` and extract: + +**Exclude from issue extraction:** +- `review-summary.md` (synthesizer output, not individual findings) +- `resolution-summary.md` (if it exists from a previous partial run) **Include only:** - Blocking issues (CRITICAL, HIGH) @@ -72,6 +107,8 @@ Create execution plan: **With Agent Teams:** +**Note**: In multi-worktree mode, process worktrees sequentially for Agent Teams (one team per session constraint). + Create a resolution team for cross-validated fixes: ``` @@ -82,11 +119,12 @@ Spawn resolver teammates with self-contained prompts (one per independent batch) - Name: "resolver-batch-1" Prompt: | You are resolving review issues on branch {branch} (PR #{pr_number}). + WORKTREE_PATH: {worktree_path} (omit if cwd) 1. Read your skill: `Read ~/.claude/skills/implementation-patterns/SKILL.md` 2. Your issues to resolve: {batch 1 issues — full structured list with id, file, line, severity, type, description, suggested_fix} 3. For each issue: - a. Read the code context around file:line + a. Read the code context around file:line (use WORKTREE_PATH prefix if provided) b. Validate: is this a real issue or false positive? c. If real: assess risk (LOW → FIX now, HIGH → defer to TECH_DEBT) d. If FIX: implement the fix, commit with descriptive message @@ -98,11 +136,12 @@ Spawn resolver teammates with self-contained prompts (one per independent batch) - Name: "resolver-batch-2" Prompt: | You are resolving review issues on branch {branch} (PR #{pr_number}). + WORKTREE_PATH: {worktree_path} (omit if cwd) 1. Read your skill: `Read ~/.claude/skills/implementation-patterns/SKILL.md` 2. Your issues to resolve: {batch 2 issues — full structured list with id, file, line, severity, type, description, suggested_fix} 3. For each issue: - a. Read the code context around file:line + a. Read the code context around file:line (use WORKTREE_PATH prefix if provided) b. Validate: is this a real issue or false positive? c. If real: assess risk (LOW → FIX now, HIGH → defer to TECH_DEBT) d. If FIX: implement the fix, commit with descriptive message @@ -150,7 +189,9 @@ Aggregate from all Resolvers: - **Deferred**: High-risk issues marked for tech debt - **Blocked**: Issues that couldn't be fixed -### Phase 6: Record Pitfalls (from tech debt deferrals) +### Phase 6: Record Pitfalls (Sequential) + +**IMPORTANT**: Run sequentially across all worktrees (not in parallel) to avoid GitHub API conflicts. For each issue deferred as TECH_DEBT: 1. Read `~/.claude/skills/knowledge-persistence/SKILL.md` and follow its extraction procedure to record pitfalls to `.memory/knowledge/pitfalls.md` @@ -164,31 +205,35 @@ If any fixes were made, spawn Simplifier agent to refine the changed code: ``` Task(subagent_type="Simplifier", run_in_background=false): "TASK_DESCRIPTION: Issue resolution fixes +WORKTREE_PATH: {worktree_path} (omit if cwd) FILES_CHANGED: {list of files modified by Resolvers} Simplify and refine the fixes for clarity and consistency" ``` -### Phase 8: Manage Tech Debt +### Phase 8: Manage Tech Debt (Sequential) + +**IMPORTANT**: Run sequentially across all worktrees (not in parallel) to avoid GitHub API conflicts. If any issues were deferred, spawn Git agent: ``` Task(subagent_type="Git"): "OPERATION: manage-debt -REVIEW_DIR: .docs/reviews/{branch-slug}/ +WORKTREE_PATH: {worktree_path} (omit if cwd) +REVIEW_DIR: {TARGET_DIR} TIMESTAMP: {timestamp} -Note: Deferred issues from resolution are already in resolution-summary.{timestamp}.md" +Note: Deferred issues from resolution are already in resolution-summary.md" ``` ### Phase 9: Report -**Write the resolution summary** to `.docs/reviews/{branch-slug}/resolution-summary.{timestamp}.md` using Write tool, then display: +**Write the resolution summary** to `{TARGET_DIR}/resolution-summary.md` using Write tool, then display: ``` ## Resolution Summary **Branch**: {branch} -**Reviews Processed**: {n} reports +**Reviews Processed**: {n} reports from {TARGET_DIR} **Total Issues**: {n} ### Results @@ -206,19 +251,23 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta - {n} items added to backlog ### Artifacts -- Resolution report: .docs/reviews/{branch}/resolution-summary.{timestamp}.md +- Resolution report: {TARGET_DIR}/resolution-summary.md ``` +In multi-worktree mode, report results per worktree with aggregate summary. + ## Architecture ``` /resolve (orchestrator - spawns teams and agents) │ -├─ Phase 0: Pre-flight -│ └─ Git agent (validate-branch) +├─ Phase 0: Worktree Discovery & Pre-flight +│ ├─ Step 0a: git worktree list → filter resolvable +│ ├─ Step 0b: Git agent (validate-branch) per worktree [parallel] +│ └─ Step 0c: Target latest review directory per worktree │ -├─ Phase 1: Parse issues -│ └─ Extract Blocking + Should-Fix (skip Pre-existing) +├─ Phase 1: Parse issues from TARGET_DIR +│ └─ Extract Blocking + Should-Fix (skip Pre-existing, exclude summaries) │ ├─ Phase 2: Analyze dependencies │ └─ Build dependency graph @@ -226,7 +275,7 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta ├─ Phase 3: Plan batches │ └─ Group issues, determine parallel vs sequential │ -├─ Phase 4: Resolve (Agent Teams with cross-validation) +├─ Phase 4: Resolve (Agent Teams with cross-validation, per worktree sequential) │ ├─ Resolver: Batch 1 (teammate) │ ├─ Resolver: Batch 2 (teammate) │ ├─ Resolver: Batch 3 (teammate, waits if depends on 1 or 2) @@ -235,15 +284,15 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta ├─ Phase 5: Collect results │ └─ Aggregate fixed, false positives, deferred, blocked │ -├─ Phase 6: Record Pitfalls (inline, from tech debt deferrals) +├─ Phase 6: Record Pitfalls (SEQUENTIAL across worktrees) │ ├─ Phase 7: Simplify │ └─ Simplifier agent (refine fixes) │ -├─ Phase 8: Git agent (manage-debt) +├─ Phase 8: Git agent (manage-debt) — SEQUENTIAL across worktrees │ └─ Add deferred items to Tech Debt Backlog │ -└─ Phase 9: Display resolution summary +└─ Phase 9: Write resolution-summary.md + display results ``` ## Edge Cases @@ -255,6 +304,11 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta | Fix attempt fails | Revert changes, mark BLOCKED, continue others | | Issue dependencies | Sequential chain, skip dependents if predecessor blocked | | No actionable issues | Report "No issues to resolve" (all were pre-existing or LOW) | +| Incomplete review directory | Skip — resolve only targets complete reviews | +| Latest review already resolved | Skip worktree, suggest /code-review first | +| Legacy flat layout | Read flat *.md files directly (backwards compatible) | +| `--review` in multi-worktree mode | Not supported — use `--path` + `--review` for specific worktree | +| Multi-worktree with Agent Teams | Process worktrees sequentially (one team per session) | ## Principles @@ -264,16 +318,19 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta 4. **Conservative risk** - When Resolvers are unsure, defer to tech debt 5. **Honest reporting** - Display agent outputs directly 6. **Complete tracking** - Every issue gets a decision recorded +7. **Latest review by default** - Only process the most recent complete review +8. **Auto-discover worktrees** - One command handles all resolvable branches ## Output Artifact -Written by orchestrator in Phase 9 to `.docs/reviews/{branch-slug}/resolution-summary.{timestamp}.md`: +Written by orchestrator in Phase 9 to `{TARGET_DIR}/resolution-summary.md`: ```markdown # Resolution Summary **Branch**: {branch} -> {base} **Date**: {timestamp} +**Review**: {TARGET_DIR} **Command**: /resolve ## Statistics diff --git a/plugins/devflow-resolve/commands/resolve.md b/plugins/devflow-resolve/commands/resolve.md index 37e78289..92426411 100644 --- a/plugins/devflow-resolve/commands/resolve.md +++ b/plugins/devflow-resolve/commands/resolve.md @@ -4,35 +4,70 @@ description: Process review issues - validate, assess risk, fix low-risk issues, # Resolve Command -Process issues from code review reports: validate them (false positive check), assess risk for FIX vs TECH_DEBT decision, and implement fixes for low-risk issues. +Process issues from code review reports: validate them (false positive check), assess risk for FIX vs TECH_DEBT decision, and implement fixes for low-risk issues. Defaults to the latest timestamped review directory. Supports multi-worktree auto-discovery. ## Usage ``` -/resolve (resolve issues on current branch) -/resolve #42 (resolve issues for specific PR) +/resolve (resolve latest review on current branch — or all worktrees) +/resolve #42 (resolve issues for specific PR) +/resolve --review 2026-03-28_0900 (resolve a specific review run by timestamp) +/resolve --path /path/to/worktree (resolve a specific worktree only) ``` ## Phases -### Phase 0: Pre-Flight (Git Agent) +### Phase 0: Worktree Discovery & Pre-Flight -Spawn Git agent to validate branch state: +#### Step 0a: Discover Worktrees + +1. Run `git worktree list --porcelain` to discover all worktrees +2. For each worktree, extract path and branch +3. **Filter to resolvable worktrees:** + - Must be on a named branch (skip detached HEAD) + - Must NOT be on a protected branch (main, master, develop, release/*, staging, production) + - Must have unresolved reviews (latest review directory has no `resolution-summary.md`) +4. **If `--path` flag provided:** use only that worktree, skip discovery +5. **If only 1 resolvable worktree** (the common case): proceed as single-worktree flow — zero behavior change +6. **If multiple resolvable worktrees:** report "Found N worktrees with unresolved reviews: {list}" and proceed with multi-worktree flow + +#### Step 0b: Per-Worktree Pre-Flight (Git Agent) + +For each resolvable worktree, spawn Git agent: ``` Task(subagent_type="Git", run_in_background=false): "OPERATION: validate-branch +WORKTREE_PATH: {worktree_path} (omit if cwd) Check feature branch, clean working directory, reviews exist. Return: branch, branch-slug, PR#, review count" ``` -**If BLOCKED:** Stop and report the blocker to user. If no reviews found, suggest `/code-review` first. +In multi-worktree mode, spawn all pre-flight agents **in a single message** (parallel). + +**If BLOCKED:** In single-worktree mode, stop and report the blocker to user. If no reviews found, suggest `/code-review` first. In multi-worktree mode, report the failure but continue with other worktrees. + +**Extract from response:** `branch`, `branch_slug`, `pr_number`, `review_count` per worktree. + +#### Step 0c: Target Review Directory + +For each worktree: -**Extract from response:** `branch`, `branch_slug`, `pr_number`, `review_count` for use in subsequent phases. +1. List directories in `{worktree}/.docs/reviews/{branch-slug}/` +2. **If `--review {timestamp}` provided:** use that specific directory (not supported in multi-worktree mode) +3. **Otherwise:** sort directories by name (timestamps are naturally sortable), select the latest that contains `review-summary.md` (complete review) +4. **If latest directory already has `resolution-summary.md`:** skip worktree — already resolved. Report: "Latest review already resolved. Run /code-review for a new review first." +5. **Legacy fallback:** if no timestamped subdirectories exist but flat `*.md` files do in `{worktree}/.docs/reviews/{branch-slug}/`, read them directly (backwards compatible) + +Set `TARGET_DIR` to the selected review directory path. ### Phase 1: Parse Issues -Read all review reports from `.docs/reviews/{branch-slug}/*.md` and extract: +Read review reports from `{TARGET_DIR}/*.md` and extract: + +**Exclude from issue extraction:** +- `review-summary.md` (synthesizer output, not individual findings) +- `resolution-summary.md` (if it exists from a previous partial run) **Include only:** - Blocking issues (CRITICAL, HIGH) @@ -77,6 +112,7 @@ Task(subagent_type="Resolver"): "ISSUES: [{issue1}, {issue2}, ...] BRANCH: {branch-slug} BATCH_ID: batch-{n} +WORKTREE_PATH: {worktree_path} (omit if cwd) Validate, decide FIX vs TECH_DEBT, implement fixes" ``` @@ -90,7 +126,9 @@ Aggregate from all Resolvers: - **Deferred**: High-risk issues marked for tech debt - **Blocked**: Issues that couldn't be fixed -### Phase 6: Record Pitfalls (from tech debt deferrals) +### Phase 6: Record Pitfalls (Sequential) + +**IMPORTANT**: Run sequentially across all worktrees (not in parallel) to avoid GitHub API conflicts. For each issue deferred as TECH_DEBT: 1. Read `~/.claude/skills/knowledge-persistence/SKILL.md` and follow its extraction procedure to record pitfalls to `.memory/knowledge/pitfalls.md` @@ -104,31 +142,35 @@ If any fixes were made, spawn Simplifier agent to refine the changed code: ``` Task(subagent_type="Simplifier", run_in_background=false): "TASK_DESCRIPTION: Issue resolution fixes +WORKTREE_PATH: {worktree_path} (omit if cwd) FILES_CHANGED: {list of files modified by Resolvers} Simplify and refine the fixes for clarity and consistency" ``` -### Phase 8: Manage Tech Debt +### Phase 8: Manage Tech Debt (Sequential) + +**IMPORTANT**: Run sequentially across all worktrees (not in parallel) to avoid GitHub API conflicts. If any issues were deferred, spawn Git agent: ``` Task(subagent_type="Git"): "OPERATION: manage-debt -REVIEW_DIR: .docs/reviews/{branch-slug}/ +WORKTREE_PATH: {worktree_path} (omit if cwd) +REVIEW_DIR: {TARGET_DIR} TIMESTAMP: {timestamp} -Note: Deferred issues from resolution are already in resolution-summary.{timestamp}.md" +Note: Deferred issues from resolution are already in resolution-summary.md" ``` ### Phase 9: Report -**Write the resolution summary** to `.docs/reviews/{branch-slug}/resolution-summary.{timestamp}.md` using Write tool, then display: +**Write the resolution summary** to `{TARGET_DIR}/resolution-summary.md` using Write tool, then display: ``` ## Resolution Summary **Branch**: {branch} -**Reviews Processed**: {n} reports +**Reviews Processed**: {n} reports from {TARGET_DIR} **Total Issues**: {n} ### Results @@ -146,19 +188,23 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta - {n} items added to backlog ### Artifacts -- Resolution report: .docs/reviews/{branch}/resolution-summary.{timestamp}.md +- Resolution report: {TARGET_DIR}/resolution-summary.md ``` +In multi-worktree mode, report results per worktree with aggregate summary. + ## Architecture ``` /resolve (orchestrator - spawns agents only) │ -├─ Phase 0: Pre-flight -│ └─ Git agent (validate-branch) +├─ Phase 0: Worktree Discovery & Pre-flight +│ ├─ Step 0a: git worktree list → filter resolvable +│ ├─ Step 0b: Git agent (validate-branch) per worktree [parallel] +│ └─ Step 0c: Target latest review directory per worktree │ -├─ Phase 1: Parse issues -│ └─ Extract Blocking + Should-Fix (skip Pre-existing) +├─ Phase 1: Parse issues from TARGET_DIR +│ └─ Extract Blocking + Should-Fix (skip Pre-existing, exclude summaries) │ ├─ Phase 2: Analyze dependencies │ └─ Build dependency graph @@ -174,15 +220,15 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta ├─ Phase 5: Collect results │ └─ Aggregate fixed, false positives, deferred, blocked │ -├─ Phase 6: Record Pitfalls (inline, from tech debt deferrals) +├─ Phase 6: Record Pitfalls (SEQUENTIAL across worktrees) │ ├─ Phase 7: Simplify │ └─ Simplifier agent (refine fixes) │ -├─ Phase 8: Git agent (manage-debt) +├─ Phase 8: Git agent (manage-debt) — SEQUENTIAL across worktrees │ └─ Add deferred items to Tech Debt Backlog │ -└─ Phase 9: Display resolution summary +└─ Phase 9: Write resolution-summary.md + display results ``` ## Edge Cases @@ -194,6 +240,17 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta | Fix attempt fails | Revert changes, mark BLOCKED, continue others | | Issue dependencies | Sequential chain, skip dependents if predecessor blocked | | No actionable issues | Report "No issues to resolve" (all were pre-existing or LOW) | +| Incomplete review directory (no review-summary.md) | Skip — resolve only targets complete reviews | +| Latest review already resolved | Skip worktree, report suggestion to run /code-review first | +| Legacy flat layout (no subdirectories) | Read flat *.md files directly (backwards compatible) | +| `--review {timestamp}` in multi-worktree mode | Not supported — use `--path` + `--review` to target specific worktree + review | +| Worktree pre-flight fails | Report failure, continue with other worktrees | + +## Backwards Compatibility + +- **Single worktree**: Auto-discovery finds only one worktree → proceeds exactly as before. Zero behavior change. +- **Legacy flat layout**: If `.docs/reviews/{branch-slug}/` contains flat `*.md` files (no timestamped subdirectories), reads from flat directory (existing behavior). +- **No timestamped directories**: Falls back to reading flat `*.md` files from branch-slug directory. ## Principles @@ -203,16 +260,19 @@ Note: Deferred issues from resolution are already in resolution-summary.{timesta 4. **Conservative risk** - When Resolvers are unsure, defer to tech debt 5. **Honest reporting** - Display agent outputs directly 6. **Complete tracking** - Every issue gets a decision recorded +7. **Latest review by default** - Only process the most recent complete review +8. **Auto-discover worktrees** - One command handles all resolvable branches ## Output Artifact -Written by orchestrator in Phase 9 to `.docs/reviews/{branch-slug}/resolution-summary.{timestamp}.md`: +Written by orchestrator in Phase 9 to `{TARGET_DIR}/resolution-summary.md`: ```markdown # Resolution Summary **Branch**: {branch} -> {base} **Date**: {timestamp} +**Review**: {TARGET_DIR} **Command**: /resolve ## Statistics diff --git a/scripts/hooks/ambient-prompt b/scripts/hooks/ambient-prompt index cdecad01..f7898889 100755 --- a/scripts/hooks/ambient-prompt +++ b/scripts/hooks/ambient-prompt @@ -37,6 +37,7 @@ fi # shell-level regex was causing false positives that silently broke ambient mode. # SYNC: must match tests/ambient.test.ts preamble drift detection PREAMBLE="AMBIENT MODE: Classify depth then act. QUICK=chat/explore/git/config/trivial: respond normally. GUIDED=implement(1-2 files)/debug(clear error)/plan(focused)/review: load skills. ORCHESTRATED=implement(3+ files)/debug(vague)/architecture: load skills+agents. Prefer GUIDED for code changes. +MULTI_WORKTREE: all worktrees/branches, each worktree, review everything, resolve all → ORCHESTRATED. Follow code-review/resolve command flow (auto-discovers worktrees). GUIDED/ORCHESTRATED: Call Skill tool for ALL skills listed for intent — one Skill call per skill, before ANY text. IMPLEMENT → test-driven-development, implementation-patterns, search-first DEBUG → core-patterns, test-patterns diff --git a/shared/agents/coder.md b/shared/agents/coder.md index f5485989..4b484f82 100644 --- a/shared/agents/coder.md +++ b/shared/agents/coder.md @@ -22,6 +22,14 @@ You receive from orchestrator: **Domain hint** (optional): - **DOMAIN**: `backend` | `frontend` | `tests` | `fullstack` - Load/apply relevant domain skills +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix git commands: `git -C {WORKTREE_PATH} ...` +- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- If omitted, use cwd (default behavior unchanged). + **Sequential execution context** (when part of multi-Coder chain): - **PRIOR_PHASE_SUMMARY**: Implementation summary from previous Coder (see format below) - **FILES_FROM_PRIOR_PHASE**: Files created that must be read and understood diff --git a/shared/agents/git.md b/shared/agents/git.md index 3f718033..52ab52fa 100644 --- a/shared/agents/git.md +++ b/shared/agents/git.md @@ -15,16 +15,24 @@ The orchestrator provides: - **OPERATION**: Which task to perform - **Operation-specific parameters**: See each operation below +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix all git commands: `git -C {WORKTREE_PATH} ...` +- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- If omitted, use cwd (default behavior unchanged). + ## Operations | Operation | Purpose | Key Parameters | |-----------|---------|----------------| -| `ensure-pr-ready` | Pre-flight for /review: commit, push, create PR | - | -| `validate-branch` | Pre-flight for /resolve: check branch state | - | +| `ensure-pr-ready` | Pre-flight for /review: commit, push, create PR | `WORKTREE_PATH` (optional) | +| `validate-branch` | Pre-flight for /resolve: check branch state | `WORKTREE_PATH` (optional) | | `setup-task` | Create feature branch and fetch issue | `BASE_BRANCH`, `ISSUE_INPUT` (optional), `TASK_DESCRIPTION` (optional) | | `fetch-issue` | Fetch GitHub issue for implementation | `ISSUE_INPUT` (number or search term) | -| `comment-pr` | Create PR inline comments for review findings | `PR_NUMBER`, `REVIEW_BASE_DIR`, `TIMESTAMP` | -| `manage-debt` | Update tech debt backlog with pre-existing issues | `REVIEW_DIR`, `TIMESTAMP` | +| `comment-pr` | Create PR inline comments for review findings | `PR_NUMBER`, `REVIEW_BASE_DIR`, `TIMESTAMP`, `WORKTREE_PATH` (optional) | +| `manage-debt` | Update tech debt backlog with pre-existing issues | `REVIEW_DIR`, `TIMESTAMP`, `WORKTREE_PATH` (optional) | | `create-release` | Create GitHub release with version tag | `VERSION`, `CHANGELOG_CONTENT` | --- @@ -33,7 +41,7 @@ The orchestrator provides: Pre-flight checks and fixes for `/code-review`. Ensures branch is ready for code review. -**Input:** None (uses current branch) +**Input:** `WORKTREE_PATH` (optional) **Process:** 1. Verify on feature branch (not main/master/develop) - error if not @@ -68,14 +76,14 @@ Pre-flight checks and fixes for `/code-review`. Ensures branch is ready for code Pre-flight validation for `/resolve`. Checks branch state without modifications. -**Input:** None (uses current branch) +**Input:** `WORKTREE_PATH` (optional) **Process:** 1. Verify on feature branch (not main/master/develop) - error if not 2. Verify working directory is clean - error if uncommitted changes 3. Get current branch name 4. Derive branch-slug (replace `/` with `-`) -5. Check if reviews exist at `.docs/reviews/{branch-slug}/` +5. Check if reviews exist at `{WORKTREE_PATH}/.docs/reviews/{branch-slug}/` (or `.docs/reviews/{branch-slug}/` if no WORKTREE_PATH) 6. If PR# context provided, fetch PR details **Output:** @@ -171,16 +179,17 @@ Fetch comprehensive issue details for implementation planning. Create inline PR comments for blocking and should-fix issues from code review. -**Input:** `PR_NUMBER`, `REVIEW_BASE_DIR`, `TIMESTAMP` +**Input:** `PR_NUMBER`, `REVIEW_BASE_DIR`, `TIMESTAMP`, `WORKTREE_PATH` (optional) **Process:** 1. Get PR context (head SHA, changed files, diff) -2. Read review reports from `${REVIEW_BASE_DIR}/*.md` +2. Read review reports from `${REVIEW_BASE_DIR}/*.md` (exclude `review-summary.md` and `resolution-summary.md`) 3. Extract issues - only comment on blocking (CRITICAL/HIGH) and should-fix (HIGH/MEDIUM) 4. Skip pre-existing issues (these go to tech debt) 5. Deduplicate issues by file:line -6. Create inline comments for lines in diff; consolidate others into summary comment -7. Include 1-second delay between API calls for rate limiting +6. **Check for existing comments**: Before creating each inline comment, fetch existing PR review comments via `gh api repos/{owner}/{repo}/pulls/{pr_number}/comments`. Skip creating a new comment if an existing comment already targets the same file and line — avoids duplicate comments across incremental reviews. +7. Create inline comments for lines in diff; consolidate others into summary comment +8. Include 1-second delay between API calls for rate limiting **Output:** ```markdown @@ -189,7 +198,8 @@ Create inline PR comments for blocking and should-fix issues from code review. ### Inline Comments - Created: {n} -- Skipped: {n} (lines not in diff) +- Skipped (already exists): {n} +- Skipped (lines not in diff): {n} ### Summary Comment {Created | Not needed} @@ -201,7 +211,7 @@ Create inline PR comments for blocking and should-fix issues from code review. Update tech debt backlog with pre-existing issues from code review. -**Input:** `REVIEW_DIR`, `TIMESTAMP` +**Input:** `REVIEW_DIR`, `TIMESTAMP`, `WORKTREE_PATH` (optional) **Process:** 1. Find or create "Tech Debt Backlog" issue with `tech-debt` label @@ -257,7 +267,7 @@ Create a GitHub release with version tag. 1. **Rate limit aware** - Always throttle API calls (1s delay between comments) 2. **Fail gracefully** - Log errors but continue with remaining operations -3. **Deduplicate** - Never spam duplicate comments or issues +3. **Deduplicate** - Never spam duplicate comments or issues; check for existing comments before creating 4. **Actionable output** - Every response includes next steps 5. **Clear attribution** - Include Claude Code footer on PR comments 6. **Be decisive** - Make confident choices about categorization diff --git a/shared/agents/resolver.md b/shared/agents/resolver.md index 723c5615..dc7f15f8 100644 --- a/shared/agents/resolver.md +++ b/shared/agents/resolver.md @@ -16,6 +16,14 @@ You receive from orchestrator: - **BRANCH**: Current branch slug - **BATCH_ID**: Identifier for this batch of issues +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix git commands: `git -C {WORKTREE_PATH} ...` +- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- If omitted, use cwd (default behavior unchanged). + ## Responsibilities 1. **Validate each issue**: Read file context (30 lines around the line number). Check: diff --git a/shared/agents/reviewer.md b/shared/agents/reviewer.md index 6eac4a0b..50059b16 100644 --- a/shared/agents/reviewer.md +++ b/shared/agents/reviewer.md @@ -14,7 +14,16 @@ You are a universal code review agent. Your focus area is specified in the promp The orchestrator provides: - **Focus**: Which review type to perform - **Branch context**: What changes to review -- **Output path**: Where to save findings (e.g., `.docs/reviews/{branch}/{focus}.md`) +- **Output path**: Where to save findings (e.g., `.docs/reviews/{branch}/{timestamp}/{focus}.md`) +- **DIFF_COMMAND** (optional): Specific diff command to use (e.g., `git diff {sha}...HEAD` for incremental reviews). If not provided, default to `git diff {base_branch}...HEAD`. + +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix git commands: `git -C {WORKTREE_PATH} ...` +- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- If omitted, use cwd (default behavior unchanged). ## Focus Areas diff --git a/shared/agents/scrutinizer.md b/shared/agents/scrutinizer.md index 1e26154a..21166f98 100644 --- a/shared/agents/scrutinizer.md +++ b/shared/agents/scrutinizer.md @@ -15,6 +15,13 @@ You receive from orchestrator: - **TASK_DESCRIPTION**: What was implemented - **FILES_CHANGED**: List of modified files from Coder output +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix git commands: `git -C {WORKTREE_PATH} ...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- If omitted, use cwd (default behavior unchanged). + ## Responsibilities 1. **Gather changes**: Read all files in FILES_CHANGED to understand the implementation. diff --git a/shared/agents/shepherd.md b/shared/agents/shepherd.md index 936daa04..18650b9b 100644 --- a/shared/agents/shepherd.md +++ b/shared/agents/shepherd.md @@ -17,6 +17,13 @@ You receive from orchestrator: - **FILES_CHANGED**: List of modified files from Coder output - **ACCEPTANCE_CRITERIA**: Extracted acceptance criteria (if any) +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix git commands: `git -C {WORKTREE_PATH} ...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- If omitted, use cwd (default behavior unchanged). + ## Responsibilities 1. **Understand intent**: Read ORIGINAL_REQUEST and EXECUTION_PLAN to understand what was requested diff --git a/shared/agents/simplifier.md b/shared/agents/simplifier.md index b6a71e07..f1cd579d 100644 --- a/shared/agents/simplifier.md +++ b/shared/agents/simplifier.md @@ -15,6 +15,13 @@ You receive from orchestrator: - **TASK_DESCRIPTION**: What was implemented - **FILES_CHANGED**: List of modified files from Coder output (optional) +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix git commands: `git -C {WORKTREE_PATH} ...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- If omitted, use cwd (default behavior unchanged). + ## Responsibilities Analyze recently modified code and apply refinements that: diff --git a/shared/agents/synthesizer.md b/shared/agents/synthesizer.md index bffa931a..cd7f2001 100644 --- a/shared/agents/synthesizer.md +++ b/shared/agents/synthesizer.md @@ -16,6 +16,14 @@ The orchestrator provides: - **Agent outputs**: Results from parallel agents to synthesize - **Output path**: Where to save synthesis (if applicable) +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix git commands: `git -C {WORKTREE_PATH} ...` +- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- If omitted, use cwd (default behavior unchanged). + --- ## Mode: Exploration @@ -153,7 +161,7 @@ Synthesize outputs from multiple Reviewer agents. Apply strict merge rules. **Output:** **CRITICAL**: Write the summary to disk using the Write tool: 1. Create directory: `mkdir -p ${REVIEW_BASE_DIR}` -2. Write to `${REVIEW_BASE_DIR}/review-summary.${TIMESTAMP}.md` using Write tool +2. Write to `${REVIEW_BASE_DIR}/review-summary.md` using Write tool (the directory name provides the timestamp) 3. Confirm file written in final message Report format: diff --git a/shared/agents/validator.md b/shared/agents/validator.md index fc1be5b1..ba20e41f 100644 --- a/shared/agents/validator.md +++ b/shared/agents/validator.md @@ -15,6 +15,14 @@ You receive from orchestrator: - **FILES_CHANGED**: List of modified files - **VALIDATION_SCOPE**: `full` | `changed-only` (hints for test filtering if supported) +## Worktree Support (Optional) + +If `WORKTREE_PATH` is provided: +- Prefix git commands: `git -C {WORKTREE_PATH} ...` +- Resolve source files: `{WORKTREE_PATH}/{file}` +- Run validation commands from worktree directory: `cd {WORKTREE_PATH} && ...` +- If omitted, use cwd (default behavior unchanged). + ## Responsibilities 1. **Discover validation commands**: Check package.json scripts, Makefile, Cargo.toml, or similar for available commands diff --git a/shared/skills/ambient-router/SKILL.md b/shared/skills/ambient-router/SKILL.md index 66c2c8b9..db077d89 100644 --- a/shared/skills/ambient-router/SKILL.md +++ b/shared/skills/ambient-router/SKILL.md @@ -32,6 +32,7 @@ Determine what the user is trying to do from their prompt. | **IMPLEMENT** | "add", "create", "implement", "build", "write", "make" | "add a login form", "create an API endpoint" | | **DEBUG** | "fix", "bug", "broken", "failing", "error", "why does" | "fix the auth error", "why is this test failing" | | **REVIEW** | "check", "look at", "review", "is this ok", "any issues" | "check this function", "any issues with this?" | +| **MULTI_WORKTREE** | "all worktrees/branches", "each worktree/branch", "review everything", "resolve all" | "review all my worktrees", "resolve all branches", "review everything that needs review" | | **PLAN** | "how should", "design", "architecture", "approach", "strategy" | "how should I structure auth?", "what's the approach for caching?" | | **EXPLORE** | "what is", "where is", "find", "show me", "explain", "how does" | "where is the config?", "explain this function" | | **CHAT** | greetings, meta-questions, confirmations, short responses | "thanks", "yes", "what can you do?" | @@ -56,6 +57,7 @@ Determine how much enforcement the prompt warrants. | **DEBUG** | Clear error with known location (stack trace, specific file) | Vague/cross-cutting bug, multiple possible causes | | **PLAN** | Focused question about specific area/pattern | System-level architecture, multi-module design | | **REVIEW** | Always GUIDED | — | +| **MULTI_WORKTREE** | Always ORCHESTRATED — triggers code-review/resolve command flow | — | **Classification conservatism:** When choosing between GUIDED and ORCHESTRATED, prefer GUIDED — escalate only when scope clearly exceeds main-session capacity. When choosing between QUICK and GUIDED, prefer GUIDED if the prompt involves code changes (implement, debug, fix, add, create code). Reserve QUICK for truly zero-overhead prompts: chat, exploration, git ops, config changes, trivial edits. @@ -120,6 +122,8 @@ After loading skills via Step 3-4, execute the agent pipeline for the classified | **IMPLEMENT** | Follow implementation-orchestration skill pipeline: pre-flight → plan synthesis → Coder → quality gates | | **DEBUG** | Follow debug-orchestration skill pipeline: hypotheses → parallel Explores → convergence → report → offer fix | | **PLAN** | Follow plan-orchestration skill pipeline: Skimmer → Explores → Plan agent → gap validation | +| **MULTI_WORKTREE + REVIEW** | Follow `devflow:code-review` command flow (auto-discovers worktrees natively) | +| **MULTI_WORKTREE + RESOLVE** | Follow `devflow:resolve` command flow (auto-discovers worktrees natively) | | **EXPLORE** | No agents — respond in main session | | **CHAT** | No agents — respond in main session | @@ -144,4 +148,5 @@ After loading skills via Step 3-4, execute the agent pipeline for the classified | Prompt references specific DevFlow command | Skip ambient — the command has its own orchestration | | Scope ambiguous between GUIDED and ORCHESTRATED | Default to GUIDED; escalate if complexity emerges during work | | REVIEW intent | Always GUIDED — single Reviewer focus, no orchestration pipeline | +| MULTI_WORKTREE intent | Always ORCHESTRATED — follow code-review/resolve command flow which auto-discovers worktrees | | Multiple triggers per session | Each runs independently; context compaction handles accumulation | diff --git a/shared/skills/ambient-router/references/skill-catalog.md b/shared/skills/ambient-router/references/skill-catalog.md index f822c69c..5db34338 100644 --- a/shared/skills/ambient-router/references/skill-catalog.md +++ b/shared/skills/ambient-router/references/skill-catalog.md @@ -64,6 +64,19 @@ These skills are loaded only by explicit DevFlow commands (primarily `/code-revi - accessibility — WCAG compliance, ARIA roles, keyboard navigation - performance-patterns — N+1 queries, memory leaks, caching opportunities +## Multi-Worktree Detection + +When the user's prompt contains multi-worktree signals ("all worktrees", "all branches", "each worktree", "review everything", "resolve all"), classify as MULTI_WORKTREE intent combined with REVIEW or RESOLVE. This always routes to ORCHESTRATED depth. + +| Signal | Combined Intent | Action | +|--------|----------------|--------| +| "review all worktrees/branches" | MULTI_WORKTREE + REVIEW | Follow `devflow:code-review` command flow (auto-discovers worktrees) | +| "resolve all worktrees/branches" | MULTI_WORKTREE + RESOLVE | Follow `devflow:resolve` command flow (auto-discovers worktrees) | +| "review everything that needs review" | MULTI_WORKTREE + REVIEW | Follow `devflow:code-review` command flow | +| "run code review on each branch" | MULTI_WORKTREE + REVIEW | Follow `devflow:code-review` command flow | + +No additional skills needed — the code-review and resolve commands handle all orchestration internally, including worktree discovery, incremental detection, and parallel agent spawning. + ## Selection Limits - **Maximum 3 knowledge skills** per ambient response (primary + up to 2 secondary) diff --git a/shared/skills/debug-orchestration/SKILL.md b/shared/skills/debug-orchestration/SKILL.md index 6c52a986..a47e8102 100644 --- a/shared/skills/debug-orchestration/SKILL.md +++ b/shared/skills/debug-orchestration/SKILL.md @@ -21,6 +21,10 @@ This is a lightweight variant of `/debug` for ambient ORCHESTRATED mode. Exclude --- +## Worktree Support + +If the orchestrator receives a `WORKTREE_PATH` context (e.g., from multi-worktree workflows), pass it through to all spawned agents. Each agent's "Worktree Support" section handles path resolution. + ## Phase 1: Hypothesize Analyze the bug description, error messages, and conversation context. Generate 3-5 hypotheses that are: diff --git a/shared/skills/docs-framework/SKILL.md b/shared/skills/docs-framework/SKILL.md index c8af66d9..94ef94f4 100644 --- a/shared/skills/docs-framework/SKILL.md +++ b/shared/skills/docs-framework/SKILL.md @@ -26,8 +26,14 @@ All generated documentation lives under `.docs/` in the project root: ``` .docs/ ├── reviews/{branch-slug}/ # Code review reports per branch -│ ├── {type}-report.{timestamp}.md -│ └── review-summary.{timestamp}.md +│ ├── .last-review-head # HEAD SHA of last completed review (for incremental) +│ ├── {timestamp}/ # Timestamped review directory (YYYY-MM-DD_HHMM) +│ │ ├── {focus}.md # Reviewer report (e.g., security.md, architecture.md) +│ │ ├── review-summary.md # Synthesizer output +│ │ └── resolution-summary.md # Written by /resolve (if run) +│ └── {timestamp}/ # Second review (incremental) +│ ├── {focus}.md +│ └── review-summary.md ├── status/ # Development logs │ ├── {timestamp}.md │ ├── compact/{timestamp}.md @@ -71,7 +77,10 @@ TOPIC_SLUG=$(echo "$TOPIC" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed 's/[^ | Type | Pattern | Example | |------|---------|---------| | Special indexes | `UPPERCASE.md` | `WORKING-MEMORY.md`, `INDEX.md` | -| Reports | `{type}-report.{timestamp}.md` | `security-report.2025-12-26_1430.md` | +| Review reports | `{focus}.md` in timestamped dir | `2025-12-26_1430/security.md` | +| Review summary | `review-summary.md` in timestamped dir | `2025-12-26_1430/review-summary.md` | +| Resolution summary | `resolution-summary.md` in timestamped dir | `2025-12-26_1430/resolution-summary.md` | +| Review head marker | `.last-review-head` | Plain text file with SHA | | Status logs | `{timestamp}.md` | `2025-12-26_1430.md` | --- @@ -97,7 +106,10 @@ source .devflow/scripts/docs-helpers.sh 2>/dev/null || { | Agent | Output Location | Behavior | |-------|-----------------|----------| -| Reviewer | `.docs/reviews/{branch-slug}/{type}-report.{timestamp}.md` | Creates new | +| Reviewer | `.docs/reviews/{branch-slug}/{timestamp}/{focus}.md` | Creates new in timestamped dir | +| Synthesizer (review) | `.docs/reviews/{branch-slug}/{timestamp}/review-summary.md` | Creates new in timestamped dir | +| Resolver | `.docs/reviews/{branch-slug}/{timestamp}/resolution-summary.md` | Creates new in timestamped dir | +| Code-review cmd | `.docs/reviews/{branch-slug}/.last-review-head` | Overwrites with HEAD SHA | | Working Memory | `.memory/WORKING-MEMORY.md` | Overwrites (auto-maintained by Stop hook) | | Knowledge (decisions) | `.memory/knowledge/decisions.md` | Append-only (ADR-NNN sequential IDs) | | Knowledge (pitfalls) | `.memory/knowledge/pitfalls.md` | Append-only (PF-NNN sequential IDs) | diff --git a/shared/skills/docs-framework/references/patterns.md b/shared/skills/docs-framework/references/patterns.md index 779b03ac..8dad676b 100644 --- a/shared/skills/docs-framework/references/patterns.md +++ b/shared/skills/docs-framework/references/patterns.md @@ -11,8 +11,13 @@ Correct patterns for DevFlow documentation artifacts with templates and helper f ``` .docs/ ├── reviews/{branch-slug}/ # Code review reports per branch -│ ├── {type}-report.{timestamp}.md -│ └── review-summary.{timestamp}.md +│ ├── .last-review-head # HEAD SHA of last completed review +│ ├── {timestamp}/ # Timestamped review directory +│ │ ├── {focus}.md # Reviewer reports (security.md, architecture.md, etc.) +│ │ ├── review-summary.md # Synthesizer output +│ │ └── resolution-summary.md # Written by /resolve (if run) +│ └── {timestamp}/ # Incremental review +│ └── ... ├── design/ # Implementation plans │ └── {topic-slug}.{timestamp}.md ├── status/ # Development logs @@ -32,18 +37,45 @@ Correct patterns for DevFlow documentation artifacts with templates and helper f └── CATCH_UP.md ``` -**With Reviews:** +**With Reviews (single review):** ``` .docs/ ├── reviews/feat-auth/ -│ ├── security-report.2025-01-05_1430.md -│ └── review-summary.2025-01-05_1430.md +│ ├── .last-review-head +│ └── 2025-01-05_1430/ +│ ├── security.md +│ ├── architecture.md +│ ├── performance.md +│ ├── complexity.md +│ ├── consistency.md +│ ├── regression.md +│ ├── tests.md +│ └── review-summary.md ├── status/ │ ├── 2025-01-05_1430.md │ └── INDEX.md └── CATCH_UP.md ``` +**With Multiple Reviews (incremental):** +``` +.docs/ +├── reviews/feat-auth/ +│ ├── .last-review-head +│ ├── 2025-01-05_1430/ +│ │ ├── security.md +│ │ ├── ... +│ │ ├── review-summary.md +│ │ └── resolution-summary.md +│ └── 2025-01-06_0900/ +│ ├── security.md +│ ├── ... +│ └── review-summary.md +├── status/ +│ └── INDEX.md +└── CATCH_UP.md +``` + --- ## Naming Conventions @@ -103,13 +135,15 @@ Always UPPERCASE, overwritten or appended: - `INDEX.md` - Chronological log index - `KNOWLEDGE_BASE.md` - Searchable debug solutions -### Artifact Files (lowercase + timestamp) +### Artifact Files (lowercase) -Always lowercase with timestamp: +Always lowercase: - `2025-01-05_1430.md` - Status log -- `security-report.2025-01-05_1430.md` - Review report -- `review-summary.2025-01-05_1430.md` - Combined summary +- `security.md` - Review report (in timestamped directory) +- `review-summary.md` - Combined summary (in timestamped directory) +- `resolution-summary.md` - Resolution summary (in timestamped directory) +- `.last-review-head` - SHA marker for incremental reviews - `jwt-authentication.2025-01-05_1430.md` - Design doc --- @@ -169,14 +203,15 @@ get_status_path() { get_doc_path "status" "${timestamp}.md" } -# Create review report path +# Create timestamped review directory and return path for a focus report get_review_path() { - local type="$1" + local focus="$1" local branch_slug local timestamp branch_slug=$(get_branch_slug) timestamp=$(get_timestamp) - get_doc_path "reviews/$branch_slug" "${type}-report.${timestamp}.md" + ensure_docs_dir "reviews/$branch_slug/$timestamp" + echo ".docs/reviews/$branch_slug/$timestamp/${focus}.md" } ``` diff --git a/shared/skills/implementation-orchestration/SKILL.md b/shared/skills/implementation-orchestration/SKILL.md index b46ba3e9..eb20340b 100644 --- a/shared/skills/implementation-orchestration/SKILL.md +++ b/shared/skills/implementation-orchestration/SKILL.md @@ -38,6 +38,10 @@ Synthesize conversation context into a structured EXECUTION_PLAN for Coder: Format as structured markdown with: Goal, Steps, Files, Constraints, Decisions. +## Worktree Support + +If the orchestrator receives a `WORKTREE_PATH` context (e.g., from multi-worktree workflows), pass it through to all spawned agents. Each agent's "Worktree Support" section handles path resolution. + ## Phase 3: Coder Execution Record git SHA before first Coder: `git rev-parse HEAD` diff --git a/shared/skills/plan-orchestration/SKILL.md b/shared/skills/plan-orchestration/SKILL.md index c9e9184d..6625851e 100644 --- a/shared/skills/plan-orchestration/SKILL.md +++ b/shared/skills/plan-orchestration/SKILL.md @@ -21,6 +21,10 @@ This is a lightweight variant of the Plan phase in `/implement` for ambient ORCH --- +## Worktree Support + +If the orchestrator receives a `WORKTREE_PATH` context (e.g., from multi-worktree workflows), pass it through to all spawned agents. Each agent's "Worktree Support" section handles path resolution. + ## Phase 1: Orient Spawn `Task(subagent_type="Skimmer")` to get codebase overview relevant to the planning question: From c12c53ffc079c07b824c46018011b6594b93277c Mon Sep 17 00:00:00 2001 From: Dean Sharon Date: Sun, 29 Mar 2026 01:30:44 +0300 Subject: [PATCH 3/3] fix: resolve code review findings for PR #166 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Worktree DRY consolidation: - New worktree-support skill with canonical path resolution, 7-step discovery algorithm, and protected branch list - All 10 agents: replace inline worktree blocks with skill reference - 4 commands: replace inline discovery with skill reference - Protected branch list aligned everywhere (+ release/*, staging, production) Bug fixes: - B1: Synthesizer glob — exact-name exclusion for review/resolution summaries - B2: DIFF_COMMAND missing -C worktree prefix in non-teams variant - B3: Path traversal validation for --path flag in all commands - B7: Comment-pr batch dedup (fetch once, build lookup, skip dupes) Resolver philosophy rewrite (3-tier risk): - Standard fixes: applied directly - Careful fixes (public API, >3 files): test-first approach - Architectural overhaul: only case for tech debt deferral Cleanup: - P2: Remove rm -f .git/index.lock convention from CLAUDE.md - P3: Rate limit awareness in git agent comment-pr - S1+S10: Standardized git template syntax across commands - S2: Removed unnecessary backwards compat section - S3: Synced edge case tables between base/teams variants - S9: Added MULTI_WORKTREE preamble test assertion --- CLAUDE.md | 11 ++- .../.claude-plugin/plugin.json | 24 ++++- .../commands/code-review-teams.md | 28 +++--- .../commands/code-review.md | 19 ++-- .../devflow-resolve/commands/resolve-teams.md | 17 ++-- plugins/devflow-resolve/commands/resolve.md | 23 ++--- scripts/hooks/ambient-prompt | 11 ++- shared/agents/coder.md | 13 +-- shared/agents/git.md | 17 ++-- shared/agents/resolver.md | 57 ++++++----- shared/agents/reviewer.md | 12 +-- shared/agents/scrutinizer.md | 11 +-- shared/agents/shepherd.md | 11 +-- shared/agents/simplifier.md | 11 +-- shared/agents/skimmer.md | 6 +- shared/agents/synthesizer.md | 12 +-- shared/agents/validator.md | 10 +- shared/skills/ambient-router/SKILL.md | 28 ++++-- .../references/skill-catalog.md | 27 ++++- shared/skills/git-safety/SKILL.md | 2 +- .../skills/git-safety/references/patterns.md | 6 +- .../implementation-orchestration/SKILL.md | 4 + shared/skills/pipeline-orchestration/SKILL.md | 77 +++++++++++++++ shared/skills/resolve-orchestration/SKILL.md | 89 +++++++++++++++++ shared/skills/review-orchestration/SKILL.md | 99 +++++++++++++++++++ shared/skills/worktree-support/SKILL.md | 91 +++++++++++++++++ src/cli/commands/init.ts | 8 +- src/cli/plugins.ts | 54 ++++++++-- src/cli/utils/installer.ts | 42 ++++---- tests/ambient.test.ts | 13 +++ tests/plugins.test.ts | 47 +++++++++ tests/uninstall-logic.test.ts | 9 ++ 32 files changed, 691 insertions(+), 198 deletions(-) create mode 100644 shared/skills/pipeline-orchestration/SKILL.md create mode 100644 shared/skills/resolve-orchestration/SKILL.md create mode 100644 shared/skills/review-orchestration/SKILL.md create mode 100644 shared/skills/worktree-support/SKILL.md diff --git a/CLAUDE.md b/CLAUDE.md index b830f807..13adf5e2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -50,7 +50,7 @@ Commands with Teams Variant ship as `{name}.md` (parallel subagents) and `{name} ``` devflow/ -├── shared/skills/ # 35 skills (single source of truth) +├── shared/skills/ # 39 skills (single source of truth) ├── shared/agents/ # 10 shared agents (single source of truth) ├── plugins/devflow-*/ # 17 plugins (8 core + 9 optional language/ecosystem) ├── docs/reference/ # Detailed reference documentation @@ -126,6 +126,12 @@ Working memory files live in a dedicated `.memory/` directory: **Incremental Reviews**: `/code-review` writes reports into timestamped subdirectories (`YYYY-MM-DD_HHMM`) and tracks HEAD SHA in `.last-review-head` for incremental diffs. Second review only diffs from last reviewed commit. `/resolve` defaults to latest timestamped directory. Both commands auto-discover git worktrees and process all reviewable branches in parallel. +**Coder Handoff Artifact**: Sequential Coder phases write `.docs/handoff.md` after each phase. Survives context compaction (unlike PRIOR_PHASE_SUMMARY). Every Coder reads it on startup. Deleted by implementation-orchestration after pipeline completes. + +**Universal Skill Installation**: All skills from all plugins are always installed, regardless of plugin selection. Skills are tiny markdown files. This ensures orchestration skills (review-orchestration, resolve-orchestration) can spawn agents that depend on skills from other plugins. Only commands and agents remain plugin-specific. + +**Model Strategy**: Explicit model assignments in agent frontmatter override the user's session model. Opus for analysis agents (reviewer, scrutinizer, shepherd), Sonnet for execution agents (coder, simplifier, resolver, skimmer), Haiku for I/O agents (git, synthesizer, validator). + ## Agent & Command Roster **Orchestration commands** (spawn agents, never do agent work in main session): @@ -141,6 +147,8 @@ Working memory files live in a dedicated `.memory/` directory: **Plugin-specific agents** (1): claude-md-auditor +**Ambient orchestration skills** (6): implementation-orchestration, debug-orchestration, plan-orchestration, review-orchestration, resolve-orchestration, pipeline-orchestration. These enable the same agent pipelines as slash commands but triggered via ambient intent classification. + **Agent Teams**: 5 commands use Agent Teams (`/code-review`, `/implement`, `/debug`, `/specify`, `/resolve`). One-team-per-session constraint — must TeamDelete before creating next team. ## Key Conventions @@ -174,7 +182,6 @@ Use conventional commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore ## Critical Rules ### Git Safety -- Always use `rm -f .git/index.lock &&` before git operations - Run git commands sequentially, never in parallel - Never force push without explicit user request diff --git a/plugins/devflow-ambient/.claude-plugin/plugin.json b/plugins/devflow-ambient/.claude-plugin/plugin.json index 7deb0e44..452719d5 100644 --- a/plugins/devflow-ambient/.claude-plugin/plugin.json +++ b/plugins/devflow-ambient/.claude-plugin/plugin.json @@ -22,12 +22,32 @@ "scrutinizer", "shepherd", "skimmer", - "reviewer" + "reviewer", + "git", + "synthesizer", + "resolver" ], "skills": [ "ambient-router", "implementation-orchestration", "debug-orchestration", - "plan-orchestration" + "plan-orchestration", + "review-orchestration", + "resolve-orchestration", + "pipeline-orchestration", + "review-methodology", + "security-patterns", + "architecture-patterns", + "performance-patterns", + "complexity-patterns", + "consistency-patterns", + "regression-patterns", + "test-patterns", + "database-patterns", + "dependencies-patterns", + "documentation-patterns", + "implementation-patterns", + "knowledge-persistence", + "worktree-support" ] } diff --git a/plugins/devflow-code-review/commands/code-review-teams.md b/plugins/devflow-code-review/commands/code-review-teams.md index be3250a1..aabace72 100644 --- a/plugins/devflow-code-review/commands/code-review-teams.md +++ b/plugins/devflow-code-review/commands/code-review-teams.md @@ -21,16 +21,13 @@ Run a comprehensive code review of the current branch by spawning a review team #### Step 0a: Discover Worktrees -1. Run `git worktree list --porcelain` to discover all worktrees -2. For each worktree, extract path and branch -3. **Filter to reviewable worktrees:** - - Must be on a named branch (skip detached HEAD) - - Must NOT be on a protected branch (main, master, develop, release/*, staging, production) - - Must NOT be mid-rebase or mid-merge (check `git -C {path} status` for "rebase in progress" / "merging") -4. **If `--path` flag provided:** use only that worktree, skip discovery -5. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change -6. **If multiple reviewable worktrees:** report "Found N worktrees with reviewable branches: {list with paths and branches}" and proceed with multi-worktree flow -7. **Deduplicate by branch:** if two worktrees are on the same branch, use only the first worktree's path +1. **Discover reviewable worktrees** using the `worktree-support` skill discovery algorithm: + - Run `git worktree list --porcelain` → parse, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit + - See `~/.claude/skills/worktree-support/SKILL.md` for the full 7-step algorithm and canonical protected branch list +2. **If `--path` flag provided:** use only that worktree, skip discovery + **`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop. +3. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change +4. **If multiple reviewable worktrees:** report "Found N worktrees with reviewable branches: {list with paths and branches}" and proceed with multi-worktree flow #### Step 0b: Per-Worktree Pre-Flight (Git Agent) @@ -122,7 +119,7 @@ Spawn review teammates with self-contained prompts: 1. Read your skill: `Read ~/.claude/skills/security-patterns/SKILL.md` 2. Read review methodology: `Read ~/.claude/skills/review-methodology/SKILL.md` 3. Read `.memory/knowledge/pitfalls.md` if it exists. Check for known pitfall patterns in the diff. - 4. Get the diff: `git {-C worktree_path} diff {DIFF_RANGE}` + 4. Get the diff: `git -C {WORKTREE_PATH} diff {DIFF_RANGE}` 5. Apply the 6-step review process from review-methodology 6. Focus: injection, auth bypass, crypto misuse, OWASP vulnerabilities 7. Classify each finding: 🔴 BLOCKING / ⚠️ SHOULD-FIX / ℹ️ PRE-EXISTING @@ -137,7 +134,7 @@ Spawn review teammates with self-contained prompts: 1. Read your skill: `Read ~/.claude/skills/architecture-patterns/SKILL.md` 2. Read review methodology: `Read ~/.claude/skills/review-methodology/SKILL.md` 3. Read `.memory/knowledge/pitfalls.md` if it exists. Check for known pitfall patterns in the diff. - 4. Get the diff: `git {-C worktree_path} diff {DIFF_RANGE}` + 4. Get the diff: `git -C {WORKTREE_PATH} diff {DIFF_RANGE}` 5. Apply the 6-step review process from review-methodology 6. Focus: SOLID violations, coupling, layering issues, modularity problems 7. Classify each finding: 🔴 BLOCKING / ⚠️ SHOULD-FIX / ℹ️ PRE-EXISTING @@ -152,7 +149,7 @@ Spawn review teammates with self-contained prompts: 1. Read your skill: `Read ~/.claude/skills/performance-patterns/SKILL.md` 2. Read review methodology: `Read ~/.claude/skills/review-methodology/SKILL.md` 3. Read `.memory/knowledge/pitfalls.md` if it exists. Check for known pitfall patterns in the diff. - 4. Get the diff: `git {-C worktree_path} diff {DIFF_RANGE}` + 4. Get the diff: `git -C {WORKTREE_PATH} diff {DIFF_RANGE}` 5. Apply the 6-step review process from review-methodology 6. Focus: N+1 queries, memory leaks, algorithm issues, I/O bottlenecks 7. Classify each finding: 🔴 BLOCKING / ⚠️ SHOULD-FIX / ℹ️ PRE-EXISTING @@ -171,7 +168,7 @@ Spawn review teammates with self-contained prompts: - `Read ~/.claude/skills/regression-patterns/SKILL.md` 2. Read review methodology: `Read ~/.claude/skills/review-methodology/SKILL.md` 3. Read `.memory/knowledge/pitfalls.md` if it exists. Check for known pitfall patterns in the diff. - 4. Get the diff: `git {-C worktree_path} diff {DIFF_RANGE}` + 4. Get the diff: `git -C {WORKTREE_PATH} diff {DIFF_RANGE}` 5. Apply the 6-step review process from review-methodology 6. Focus: complexity, test gaps, pattern violations, regressions, naming 7. Classify each finding: 🔴 BLOCKING / ⚠️ SHOULD-FIX / ℹ️ PRE-EXISTING @@ -341,7 +338,8 @@ In multi-worktree mode, report results per worktree with aggregate summary. | Worktree pre-flight fails | Report failure, continue with other worktrees | | `--full` in multi-worktree mode | Applies to all worktrees (global modifier) | | Multi-worktree with Agent Teams | Process worktrees sequentially (one team per session) | -| Duplicate PR comments | Git agent checks for existing comments at same file:line | +| Many worktrees (5+) | Report count and proceed — user manages their worktree count | +| Duplicate PR comments | Git agent checks for existing comments at same file:line before creating | ## Backwards Compatibility diff --git a/plugins/devflow-code-review/commands/code-review.md b/plugins/devflow-code-review/commands/code-review.md index 41ac1bb3..bddc4f03 100644 --- a/plugins/devflow-code-review/commands/code-review.md +++ b/plugins/devflow-code-review/commands/code-review.md @@ -21,16 +21,13 @@ Run a comprehensive code review of the current branch by spawning parallel revie #### Step 0a: Discover Worktrees -1. Run `git worktree list --porcelain` to discover all worktrees -2. For each worktree, extract path and branch -3. **Filter to reviewable worktrees:** - - Must be on a named branch (skip detached HEAD) - - Must NOT be on a protected branch (main, master, develop, release/*, staging, production) - - Must NOT be mid-rebase or mid-merge (check `git -C {path} status` for "rebase in progress" / "merging") -4. **If `--path` flag provided:** use only that worktree, skip discovery -5. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change -6. **If multiple reviewable worktrees:** report "Found N worktrees with reviewable branches: {list with paths and branches}" and proceed with multi-worktree flow -7. **Deduplicate by branch:** if two worktrees are on the same branch, use only the first worktree's path +1. **Discover reviewable worktrees** using the `worktree-support` skill discovery algorithm: + - Run `git worktree list --porcelain` → parse, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit + - See `~/.claude/skills/worktree-support/SKILL.md` for the full 7-step algorithm and canonical protected branch list +2. **If `--path` flag provided:** use only that worktree, skip discovery + **`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop. +3. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change +4. **If multiple reviewable worktrees:** report "Found N worktrees with reviewable branches: {list with paths and branches}" and proceed with multi-worktree flow #### Step 0b: Per-Worktree Pre-Flight (Git Agent) @@ -117,7 +114,7 @@ Task(subagent_type="Reviewer", run_in_background=false): Follow 6-step process from review-methodology. PR: #{pr_number}, Base: {base_branch} WORKTREE_PATH: {worktree_path} (omit if cwd) -DIFF_COMMAND: git diff {DIFF_RANGE} (use this instead of default base_branch...HEAD) +DIFF_COMMAND: git -C {WORKTREE_PATH} diff {DIFF_RANGE} (omit -C flag if no WORKTREE_PATH) IMPORTANT: Write report to {worktree_path}/.docs/reviews/{branch-slug}/{timestamp}/{focus}.md using Write tool" ``` diff --git a/plugins/devflow-resolve/commands/resolve-teams.md b/plugins/devflow-resolve/commands/resolve-teams.md index d347740e..13d207a5 100644 --- a/plugins/devflow-resolve/commands/resolve-teams.md +++ b/plugins/devflow-resolve/commands/resolve-teams.md @@ -21,15 +21,14 @@ Process issues from code review reports: validate them (false positive check), a #### Step 0a: Discover Worktrees -1. Run `git worktree list --porcelain` to discover all worktrees -2. For each worktree, extract path and branch -3. **Filter to resolvable worktrees:** - - Must be on a named branch (skip detached HEAD) - - Must NOT be on a protected branch (main, master, develop, release/*, staging, production) - - Must have unresolved reviews (latest review directory has no `resolution-summary.md`) -4. **If `--path` flag provided:** use only that worktree, skip discovery -5. **If only 1 resolvable worktree** (the common case): proceed as single-worktree flow — zero behavior change -6. **If multiple resolvable worktrees:** report "Found N worktrees with unresolved reviews: {list}" and proceed with multi-worktree flow +1. **Discover resolvable worktrees** using the `worktree-support` skill discovery algorithm: + - Run `git worktree list --porcelain` → parse, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit + - See `~/.claude/skills/worktree-support/SKILL.md` for the full 7-step algorithm and canonical protected branch list + - Additional filter: must have unresolved reviews (latest review directory has no `resolution-summary.md`) +2. **If `--path` flag provided:** use only that worktree, skip discovery + **`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop. +3. **If only 1 resolvable worktree** (the common case): proceed as single-worktree flow — zero behavior change +4. **If multiple resolvable worktrees:** report "Found N worktrees with unresolved reviews: {list}" and proceed with multi-worktree flow #### Step 0b: Per-Worktree Pre-Flight (Git Agent) diff --git a/plugins/devflow-resolve/commands/resolve.md b/plugins/devflow-resolve/commands/resolve.md index 92426411..b4e75e0e 100644 --- a/plugins/devflow-resolve/commands/resolve.md +++ b/plugins/devflow-resolve/commands/resolve.md @@ -21,15 +21,14 @@ Process issues from code review reports: validate them (false positive check), a #### Step 0a: Discover Worktrees -1. Run `git worktree list --porcelain` to discover all worktrees -2. For each worktree, extract path and branch -3. **Filter to resolvable worktrees:** - - Must be on a named branch (skip detached HEAD) - - Must NOT be on a protected branch (main, master, develop, release/*, staging, production) - - Must have unresolved reviews (latest review directory has no `resolution-summary.md`) -4. **If `--path` flag provided:** use only that worktree, skip discovery -5. **If only 1 resolvable worktree** (the common case): proceed as single-worktree flow — zero behavior change -6. **If multiple resolvable worktrees:** report "Found N worktrees with unresolved reviews: {list}" and proceed with multi-worktree flow +1. **Discover resolvable worktrees** using the `worktree-support` skill discovery algorithm: + - Run `git worktree list --porcelain` → parse, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit + - See `~/.claude/skills/worktree-support/SKILL.md` for the full 7-step algorithm and canonical protected branch list + - Additional filter: must have unresolved reviews (latest review directory has no `resolution-summary.md`) +2. **If `--path` flag provided:** use only that worktree, skip discovery + **`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop. +3. **If only 1 resolvable worktree** (the common case): proceed as single-worktree flow — zero behavior change +4. **If multiple resolvable worktrees:** report "Found N worktrees with unresolved reviews: {list}" and proceed with multi-worktree flow #### Step 0b: Per-Worktree Pre-Flight (Git Agent) @@ -246,12 +245,6 @@ In multi-worktree mode, report results per worktree with aggregate summary. | `--review {timestamp}` in multi-worktree mode | Not supported — use `--path` + `--review` to target specific worktree + review | | Worktree pre-flight fails | Report failure, continue with other worktrees | -## Backwards Compatibility - -- **Single worktree**: Auto-discovery finds only one worktree → proceeds exactly as before. Zero behavior change. -- **Legacy flat layout**: If `.docs/reviews/{branch-slug}/` contains flat `*.md` files (no timestamped subdirectories), reads from flat directory (existing behavior). -- **No timestamped directories**: Falls back to reading flat `*.md` files from branch-slug directory. - ## Principles 1. **Orchestration only** - Command spawns agents, doesn't do git/resolve work itself diff --git a/scripts/hooks/ambient-prompt b/scripts/hooks/ambient-prompt index f7898889..dd9d1a1a 100755 --- a/scripts/hooks/ambient-prompt +++ b/scripts/hooks/ambient-prompt @@ -36,15 +36,20 @@ fi # No fast-path filtering — the LLM handles QUICK classification reliably and # shell-level regex was causing false positives that silently broke ambient mode. # SYNC: must match tests/ambient.test.ts preamble drift detection -PREAMBLE="AMBIENT MODE: Classify depth then act. QUICK=chat/explore/git/config/trivial: respond normally. GUIDED=implement(1-2 files)/debug(clear error)/plan(focused)/review: load skills. ORCHESTRATED=implement(3+ files)/debug(vague)/architecture: load skills+agents. Prefer GUIDED for code changes. +PREAMBLE="AMBIENT MODE: Classify depth then act. QUICK=chat/explore/git/config/trivial: respond normally. GUIDED=implement(1-2 files)/debug(clear error)/plan(focused)/review(small scope): load skills. ORCHESTRATED=implement(3+ files)/debug(vague)/architecture/review(full/branch/PR)/resolve/pipeline: load skills+agents. Prefer GUIDED for code changes. +REVIEW depth: continuation-aware (match prior IMPLEMENT depth) or signal-word based (full/branch/PR→ORCHESTRATED, check this/specific file→GUIDED). +RESOLVE: always ORCHESTRATED. PIPELINE (end-to-end/implement and review): always ORCHESTRATED. MULTI_WORKTREE: all worktrees/branches, each worktree, review everything, resolve all → ORCHESTRATED. Follow code-review/resolve command flow (auto-discovers worktrees). GUIDED/ORCHESTRATED: Call Skill tool for ALL skills listed for intent — one Skill call per skill, before ANY text. IMPLEMENT → test-driven-development, implementation-patterns, search-first DEBUG → core-patterns, test-patterns -REVIEW → self-review, core-patterns +REVIEW/GUIDED → self-review, core-patterns +REVIEW/ORCHESTRATED → review-orchestration +RESOLVE → resolve-orchestration, core-patterns +PIPELINE → pipeline-orchestration, implementation-patterns PLAN → implementation-patterns, core-patterns Also add if file type matches: typescript, react, go, java, python, rust, input-validation, security-patterns, frontend-design -ORCHESTRATED also add: implementation-orchestration / debug-orchestration / plan-orchestration +ORCHESTRATED also add: implementation-orchestration / debug-orchestration / plan-orchestration / review-orchestration / resolve-orchestration / pipeline-orchestration State: Ambient: INTENT/DEPTH. Loading: skills. Then proceed." json_prompt_output "$PREAMBLE" diff --git a/shared/agents/coder.md b/shared/agents/coder.md index 4b484f82..5a7474b5 100644 --- a/shared/agents/coder.md +++ b/shared/agents/coder.md @@ -1,8 +1,8 @@ --- name: Coder description: Autonomous task implementation on feature branch. Implements, tests, and commits. -model: inherit -skills: core-patterns, git-safety, implementation-patterns, git-workflow, test-patterns, test-driven-development, search-first, input-validation +model: sonnet +skills: core-patterns, git-safety, implementation-patterns, git-workflow, test-patterns, test-driven-development, search-first, input-validation, worktree-support --- # Coder Agent @@ -22,13 +22,7 @@ You receive from orchestrator: **Domain hint** (optional): - **DOMAIN**: `backend` | `frontend` | `tests` | `fullstack` - Load/apply relevant domain skills -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix git commands: `git -C {WORKTREE_PATH} ...` -- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. **Sequential execution context** (when part of multi-Coder chain): - **PRIOR_PHASE_SUMMARY**: Implementation summary from previous Coder (see format below) @@ -45,6 +39,7 @@ If `WORKTREE_PATH` is provided: - If PRIOR_PHASE_SUMMARY is provided, use it to validate your understanding — actual code is authoritative, summaries are supplementary - If `.memory/knowledge/decisions.md` exists, read it. Apply prior architectural decisions relevant to this task. Avoid contradicting accepted decisions without documenting a new ADR. - If `.memory/knowledge/pitfalls.md` exists, scan for pitfalls in files you're about to modify. + - If `.docs/handoff.md` exists, read it for prior phase context. Cross-reference against actual code — code is authoritative, handoff is supplementary. 2. **Load domain skills**: Based on DOMAIN hint and files in scope, dynamically load relevant language/ecosystem skills by reading their SKILL.md. Only load skills that are installed: - `backend` (TypeScript): Read `~/.claude/skills/typescript/SKILL.md`, `~/.claude/skills/input-validation/SKILL.md` diff --git a/shared/agents/git.md b/shared/agents/git.md index 52ab52fa..0c30662a 100644 --- a/shared/agents/git.md +++ b/shared/agents/git.md @@ -2,7 +2,7 @@ name: Git description: Unified agent for all git/GitHub operations - issues, PR comments, tech debt, releases model: haiku -skills: github-patterns, git-safety, git-workflow +skills: github-patterns, git-safety, git-workflow, worktree-support --- # Git Agent @@ -15,13 +15,7 @@ The orchestrator provides: - **OPERATION**: Which task to perform - **Operation-specific parameters**: See each operation below -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix all git commands: `git -C {WORKTREE_PATH} ...` -- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. ## Operations @@ -44,7 +38,7 @@ Pre-flight checks and fixes for `/code-review`. Ensures branch is ready for code **Input:** `WORKTREE_PATH` (optional) **Process:** -1. Verify on feature branch (not main/master/develop) - error if not +1. Verify on feature branch (not main/master/develop/release/*/staging/production) - error if not 2. Check for uncommitted changes - if any, create atomic commit using `git-workflow` patterns 3. Check if branch pushed to remote - if not, push with `-u` flag 4. Check if PR exists - if not, create PR using `git-workflow` patterns @@ -79,7 +73,7 @@ Pre-flight validation for `/resolve`. Checks branch state without modifications. **Input:** `WORKTREE_PATH` (optional) **Process:** -1. Verify on feature branch (not main/master/develop) - error if not +1. Verify on feature branch (not main/master/develop/release/*/staging/production) - error if not 2. Verify working directory is clean - error if uncommitted changes 3. Get current branch name 4. Derive branch-slug (replace `/` with `-`) @@ -187,9 +181,10 @@ Create inline PR comments for blocking and should-fix issues from code review. 3. Extract issues - only comment on blocking (CRITICAL/HIGH) and should-fix (HIGH/MEDIUM) 4. Skip pre-existing issues (these go to tech debt) 5. Deduplicate issues by file:line -6. **Check for existing comments**: Before creating each inline comment, fetch existing PR review comments via `gh api repos/{owner}/{repo}/pulls/{pr_number}/comments`. Skip creating a new comment if an existing comment already targets the same file and line — avoids duplicate comments across incremental reviews. +6. **Deduplicate efficiently**: Fetch all existing PR review comments once via `gh api repos/{owner}/{repo}/pulls/{pr_number}/comments`. Build a lookup set of `{path}:{line}` pairs from the response. For each new comment, check the lookup — skip if already present. This replaces per-comment checking. 7. Create inline comments for lines in diff; consolidate others into summary comment 8. Include 1-second delay between API calls for rate limiting +9. **Rate limit awareness**: Before posting a batch of comments, check `X-RateLimit-Remaining` from the last API response header. If remaining < 50: warn user and reduce posting rate (add 3s delay between calls). If remaining < 10: stop posting, report which comments were skipped due to rate limits. **Output:** ```markdown diff --git a/shared/agents/resolver.md b/shared/agents/resolver.md index dc7f15f8..04e3431a 100644 --- a/shared/agents/resolver.md +++ b/shared/agents/resolver.md @@ -1,13 +1,13 @@ --- name: Resolver -description: Validates review issues, decides FIX vs TECH_DEBT based on risk, implements fixes -model: inherit -skills: core-patterns, git-safety, implementation-patterns, git-workflow +description: Validates review issues, implements fixes with risk-proportional care. Tech debt only for architectural overhauls. +model: sonnet +skills: core-patterns, git-safety, implementation-patterns, git-workflow, worktree-support --- # Resolver Agent -You are an issue resolution specialist. You validate review issues, decide whether to fix or defer based on risk, and implement low-risk fixes. You make conservative risk assessments - when in doubt, defer to tech debt. +You are an issue resolution specialist. You validate review issues and implement fixes with risk-proportional care. You fix everything that can be fixed safely. Tech debt is the absolute last resort — only for issues requiring complete architectural redesign. ## Input Context @@ -16,13 +16,7 @@ You receive from orchestrator: - **BRANCH**: Current branch slug - **BATCH_ID**: Identifier for this batch of issues -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix git commands: `git -C {WORKTREE_PATH} ...` -- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. ## Responsibilities @@ -46,7 +40,7 @@ If `WORKTREE_PATH` is provided: ## Risk Assessment -**LOW_RISK (fix now):** +**Standard fixes** (fix directly): - Adding null checks, validation - Fixing documentation/typos - Adding error handling (no flow change) @@ -56,15 +50,22 @@ If `WORKTREE_PATH` is provided: - Improving logging - Security fixes in isolated scope -**HIGH_RISK (defer to tech debt):** -- Refactoring working functionality -- Changing function signatures with callers -- Modifying shared state/data models -- Architectural pattern changes -- Database migrations -- Multi-service changes -- Auth flow changes +**Careful fixes** (test-first approach): +- Changes to public APIs or function signatures +- Modifications to shared state or data models - Changes touching >3 files +- Core business logic modifications +- Multi-service interface changes +- Auth flow changes + +For careful fixes: write tests first covering current behavior → apply fix → verify tests still pass → commit. + +**Architectural overhaul** (defer to tech debt — LAST RESORT): +- Requires complete system redesign (e.g., fundamentally different architecture) +- Database schema migrations requiring coordinated multi-service deployment +- Changes that cannot be safely validated with tests alone + +This is the ONLY case where deferral is appropriate. "Touches many files" or "changes public API" are NOT reasons to defer — they're reasons to be careful. ## Decision Flow @@ -74,19 +75,21 @@ For each issue: ├─ Still present? NO → FALSE_POSITIVE ├─ Reviewer understood correctly? NO → FALSE_POSITIVE ├─ Code is intentional? YES → FALSE_POSITIVE (document reasoning) +├─ Understand existing design/behavior/UX before changing anything └─ Risk Assessment: - ├─ Changes public API? → HIGH_RISK → TECH_DEBT - ├─ Modifies core business logic? → HIGH_RISK → TECH_DEBT - ├─ Touches >3 files? → HIGH_RISK → TECH_DEBT - ├─ Changes data structures? → HIGH_RISK → TECH_DEBT - ├─ Requires migration? → HIGH_RISK → TECH_DEBT - └─ Otherwise → LOW_RISK → FIX + ├─ Requires complete architectural redesign? → TECH_DEBT (last resort) + ├─ Changes public API / shared state / >3 files / core logic? → CAREFUL FIX + │ ├─ Write tests covering current behavior first + │ ├─ Apply fix + │ ├─ Verify tests pass + │ └─ Commit + └─ Otherwise → STANDARD FIX → implement directly ``` ## Principles 1. **Validate before acting** - Never fix an issue without confirming it exists -2. **Conservative risk assessment** - When uncertain, defer to tech debt +2. **Risk-proportional care** - Standard fixes go fast, careful fixes get tests first, only architectural overhauls get deferred 3. **Document all decisions** - Every issue gets reasoning recorded 4. **Atomic commits** - One commit per batch with clear message 5. **Follow existing patterns** - Match codebase style exactly diff --git a/shared/agents/reviewer.md b/shared/agents/reviewer.md index 50059b16..4beb8465 100644 --- a/shared/agents/reviewer.md +++ b/shared/agents/reviewer.md @@ -1,8 +1,8 @@ --- name: Reviewer description: Universal code review agent with parameterized focus. Dynamically loads pattern skill for assigned focus area. -model: inherit -skills: review-methodology +model: opus +skills: review-methodology, worktree-support --- # Reviewer Agent @@ -17,13 +17,7 @@ The orchestrator provides: - **Output path**: Where to save findings (e.g., `.docs/reviews/{branch}/{timestamp}/{focus}.md`) - **DIFF_COMMAND** (optional): Specific diff command to use (e.g., `git diff {sha}...HEAD` for incremental reviews). If not provided, default to `git diff {base_branch}...HEAD`. -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix git commands: `git -C {WORKTREE_PATH} ...` -- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. ## Focus Areas diff --git a/shared/agents/scrutinizer.md b/shared/agents/scrutinizer.md index 21166f98..79925a58 100644 --- a/shared/agents/scrutinizer.md +++ b/shared/agents/scrutinizer.md @@ -1,8 +1,8 @@ --- name: Scrutinizer description: Self-review agent that evaluates and fixes implementation issues using 9-pillar framework. Runs in fresh context after Coder completes. -model: inherit -skills: self-review, core-patterns +model: opus +skills: self-review, core-patterns, worktree-support --- # Scrutinizer Agent @@ -15,12 +15,7 @@ You receive from orchestrator: - **TASK_DESCRIPTION**: What was implemented - **FILES_CHANGED**: List of modified files from Coder output -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix git commands: `git -C {WORKTREE_PATH} ...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. ## Responsibilities diff --git a/shared/agents/shepherd.md b/shared/agents/shepherd.md index 18650b9b..6f17c379 100644 --- a/shared/agents/shepherd.md +++ b/shared/agents/shepherd.md @@ -1,8 +1,8 @@ --- name: Shepherd description: Validates implementation aligns with original request and plan. Catches missed requirements, scope creep, and intent drift. Reports misalignments for Coder to fix. -model: inherit -skills: core-patterns +model: opus +skills: core-patterns, worktree-support --- # Shepherd Agent @@ -17,12 +17,7 @@ You receive from orchestrator: - **FILES_CHANGED**: List of modified files from Coder output - **ACCEPTANCE_CRITERIA**: Extracted acceptance criteria (if any) -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix git commands: `git -C {WORKTREE_PATH} ...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. ## Responsibilities diff --git a/shared/agents/simplifier.md b/shared/agents/simplifier.md index f1cd579d..8fefdc3d 100644 --- a/shared/agents/simplifier.md +++ b/shared/agents/simplifier.md @@ -1,8 +1,8 @@ --- name: Simplifier description: Simplifies and refines code for clarity, consistency, and maintainability while preserving all functionality. Focuses on recently modified code unless instructed otherwise. -skills: core-patterns -model: inherit +skills: core-patterns, worktree-support +model: sonnet --- # Simplifier Agent @@ -15,12 +15,7 @@ You receive from orchestrator: - **TASK_DESCRIPTION**: What was implemented - **FILES_CHANGED**: List of modified files from Coder output (optional) -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix git commands: `git -C {WORKTREE_PATH} ...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. ## Responsibilities diff --git a/shared/agents/skimmer.md b/shared/agents/skimmer.md index de6238a8..a80800d5 100644 --- a/shared/agents/skimmer.md +++ b/shared/agents/skimmer.md @@ -2,8 +2,8 @@ name: Skimmer description: Codebase orientation using rskim to identify relevant files, functions, and patterns for a feature or task tools: ["Bash", "Read"] -skills: knowledge-persistence -model: inherit +skills: knowledge-persistence, worktree-support +model: sonnet --- # Skimmer Agent @@ -15,6 +15,8 @@ You are a codebase orientation specialist. You use `npx rskim` exclusively for c You receive from orchestrator: - **TASK_DESCRIPTION**: What feature/task needs to be implemented or understood +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. + ## Workflow Execute these steps in order. Do NOT skip steps or reorder. diff --git a/shared/agents/synthesizer.md b/shared/agents/synthesizer.md index cd7f2001..56f4b573 100644 --- a/shared/agents/synthesizer.md +++ b/shared/agents/synthesizer.md @@ -2,7 +2,7 @@ name: Synthesizer description: Combines outputs from multiple agents into actionable summaries (modes: exploration, planning, review) model: haiku -skills: review-methodology, docs-framework +skills: review-methodology, docs-framework, worktree-support --- # Synthesizer Agent @@ -16,13 +16,7 @@ The orchestrator provides: - **Agent outputs**: Results from parallel agents to synthesize - **Output path**: Where to save synthesis (if applicable) -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix git commands: `git -C {WORKTREE_PATH} ...` -- Resolve `.docs/` paths: `{WORKTREE_PATH}/.docs/...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. --- @@ -136,7 +130,7 @@ Analyze 3 axes to determine strategy: Synthesize outputs from multiple Reviewer agents. Apply strict merge rules. **Process:** -1. Read all review reports from `${REVIEW_BASE_DIR}/*.md` (exclude your own output `review-summary.*.md`) +1. Read all review reports from `${REVIEW_BASE_DIR}/*.md` (exclude `review-summary.md` and `resolution-summary.md`) 2. Extract confidence percentages from each finding 3. Apply confidence-aware aggregation: when multiple reviewers flag the same file:line, boost confidence by 10% per additional reviewer (cap at 100%) diff --git a/shared/agents/validator.md b/shared/agents/validator.md index ba20e41f..6072021f 100644 --- a/shared/agents/validator.md +++ b/shared/agents/validator.md @@ -2,7 +2,7 @@ name: Validator description: Dedicated agent for running validation commands (build, typecheck, lint, test). Reports pass/fail with structured failure details - never fixes. model: haiku -skills: test-patterns +skills: test-patterns, worktree-support --- # Validator Agent @@ -15,13 +15,7 @@ You receive from orchestrator: - **FILES_CHANGED**: List of modified files - **VALIDATION_SCOPE**: `full` | `changed-only` (hints for test filtering if supported) -## Worktree Support (Optional) - -If `WORKTREE_PATH` is provided: -- Prefix git commands: `git -C {WORKTREE_PATH} ...` -- Resolve source files: `{WORKTREE_PATH}/{file}` -- Run validation commands from worktree directory: `cd {WORKTREE_PATH} && ...` -- If omitted, use cwd (default behavior unchanged). +**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `worktree-support` skill for path resolution. If omitted, use cwd. ## Responsibilities diff --git a/shared/skills/ambient-router/SKILL.md b/shared/skills/ambient-router/SKILL.md index db077d89..5851cc9e 100644 --- a/shared/skills/ambient-router/SKILL.md +++ b/shared/skills/ambient-router/SKILL.md @@ -32,6 +32,8 @@ Determine what the user is trying to do from their prompt. | **IMPLEMENT** | "add", "create", "implement", "build", "write", "make" | "add a login form", "create an API endpoint" | | **DEBUG** | "fix", "bug", "broken", "failing", "error", "why does" | "fix the auth error", "why is this test failing" | | **REVIEW** | "check", "look at", "review", "is this ok", "any issues" | "check this function", "any issues with this?" | +| **RESOLVE** | "resolve", "fix review issues", "address feedback", "fix findings" | "resolve the review issues", "fix the findings" | +| **PIPELINE** | "end to end", "implement and review", "build and review", "full pipeline" | "implement this end to end", "build and review this" | | **MULTI_WORKTREE** | "all worktrees/branches", "each worktree/branch", "review everything", "resolve all" | "review all my worktrees", "resolve all branches", "review everything that needs review" | | **PLAN** | "how should", "design", "architecture", "approach", "strategy" | "how should I structure auth?", "what's the approach for caching?" | | **EXPLORE** | "what is", "where is", "find", "show me", "explain", "how does" | "where is the config?", "explain this function" | @@ -46,8 +48,8 @@ Determine how much enforcement the prompt warrants. | Depth | Criteria | Action | |-------|----------|--------| | **QUICK** | CHAT intent. EXPLORE intent. Git/devops operations (commit, push, merge, branch, pr, deploy, reinstall). Single-word continuations. Small edits, config changes, trivial single-file tweaks. | Respond normally. Zero overhead. Do not state classification. | -| **GUIDED** | IMPLEMENT with small scope (≤2 files, single module). DEBUG with clear error location (stack trace, specific file, known function). PLAN for focused design questions (specific area/pattern). REVIEW (always GUIDED). | Load skills via Skill tool. Main session implements directly. Spawn Simplifier after code changes. State classification. | -| **ORCHESTRATED** | IMPLEMENT with larger scope (>2 files, multi-module, complex). DEBUG with vague/cross-cutting bug (no clear location, multiple possible causes). PLAN for system-level architecture (caching layer, auth system, multi-module design). | Load skills via Skill tool, then orchestrate agents per Step 5. State classification. | +| **GUIDED** | IMPLEMENT with small scope (≤2 files, single module). DEBUG with clear error location (stack trace, specific file, known function). PLAN for focused design questions (specific area/pattern). REVIEW (small scope — see below). | Load skills via Skill tool. Main session implements directly. Spawn Simplifier after code changes. State classification. | +| **ORCHESTRATED** | IMPLEMENT with larger scope (>2 files, multi-module, complex). DEBUG with vague/cross-cutting bug (no clear location, multiple possible causes). PLAN for system-level architecture (caching layer, auth system, multi-module design). REVIEW (large scope — see below). RESOLVE (always). PIPELINE (always). | Load skills via Skill tool, then orchestrate agents per Step 5. State classification. | **Scope-based decision criteria:** @@ -56,7 +58,9 @@ Determine how much enforcement the prompt warrants. | **IMPLEMENT** | ≤2 files, single module, clear task | >2 files, multi-module, complex | | **DEBUG** | Clear error with known location (stack trace, specific file) | Vague/cross-cutting bug, multiple possible causes | | **PLAN** | Focused question about specific area/pattern | System-level architecture, multi-module design | -| **REVIEW** | Always GUIDED | — | +| **REVIEW** | Continuation: match prior IMPLEMENT depth. Standalone: "check this"/"review this file" → GUIDED | Continuation: match prior IMPLEMENT depth. Standalone: "full review"/"branch review"/"PR review" → ORCHESTRATED | +| **RESOLVE** | — | Always ORCHESTRATED | +| **PIPELINE** | — | Always ORCHESTRATED | | **MULTI_WORKTREE** | Always ORCHESTRATED — triggers code-review/resolve command flow | — | **Classification conservatism:** When choosing between GUIDED and ORCHESTRATED, prefer GUIDED — escalate only when scope clearly exceeds main-session capacity. When choosing between QUICK and GUIDED, prefer GUIDED if the prompt involves code changes (implement, debug, fix, add, create code). Reserve QUICK for truly zero-overhead prompts: chat, exploration, git ops, config changes, trivial edits. @@ -81,8 +85,11 @@ Based on classified intent and depth, invoke each selected skill using the Skill | **IMPLEMENT** | implementation-orchestration, implementation-patterns | typescript (.ts), react (.tsx/.jsx), go (.go), java (.java), python (.py), rust (.rs), frontend-design (CSS/UI), input-validation (forms/API), security-patterns (auth/crypto) | | **DEBUG** | debug-orchestration, core-patterns | git-safety (if git operations involved) | | **PLAN** | plan-orchestration, implementation-patterns, core-patterns | — | +| **REVIEW** | review-orchestration | — (reviewers load their own pattern skills) | +| **RESOLVE** | resolve-orchestration, core-patterns | — | +| **PIPELINE** | pipeline-orchestration, implementation-patterns | — | -**Excluded from ambient** (review-command-only): review-methodology, complexity-patterns, consistency-patterns, database-patterns, dependencies-patterns, documentation-patterns, regression-patterns, architecture-patterns, accessibility, performance-patterns. +**Excluded from ambient loading** (loaded by agents internally): review-methodology, complexity-patterns, consistency-patterns, database-patterns, dependencies-patterns, documentation-patterns, regression-patterns, architecture-patterns, accessibility, performance-patterns. These skills are always installed (universal skill installation) but loaded by Reviewer agents at runtime, not by the router. See `references/skill-catalog.md` for the full skill-to-intent mapping with file pattern triggers. @@ -111,7 +118,7 @@ to all tools (Edit, Write, Bash, Agent, etc.) for implementation work. | **IMPLEMENT** | Implement directly with loaded skills. Follow TDD cycle. | Spawn Simplifier on changed files. | | **DEBUG** | Investigate directly — reproduce bug, diagnose from stack trace/error, fix. | Spawn Simplifier on changed files. | | **PLAN** | Explore relevant code and design directly. The area is focused enough for main session. | No Simplifier (no code changes). | -| **REVIEW** | Review directly with loaded skills. | No Simplifier. | +| **REVIEW** | Review directly with loaded skills (self-review in main session). | No Simplifier. | ## Step 5: Orchestrate Agents (ORCHESTRATED depth only) @@ -122,6 +129,9 @@ After loading skills via Step 3-4, execute the agent pipeline for the classified | **IMPLEMENT** | Follow implementation-orchestration skill pipeline: pre-flight → plan synthesis → Coder → quality gates | | **DEBUG** | Follow debug-orchestration skill pipeline: hypotheses → parallel Explores → convergence → report → offer fix | | **PLAN** | Follow plan-orchestration skill pipeline: Skimmer → Explores → Plan agent → gap validation | +| **REVIEW** | Follow review-orchestration skill pipeline: pre-flight → incremental detection → parallel reviewers → synthesis | +| **RESOLVE** | Follow resolve-orchestration skill pipeline: find review → parse issues → batch → parallel resolvers → simplify | +| **PIPELINE** | Follow pipeline-orchestration skill pipeline: implement → gate → review → gate → resolve | | **MULTI_WORKTREE + REVIEW** | Follow `devflow:code-review` command flow (auto-discovers worktrees natively) | | **MULTI_WORKTREE + RESOLVE** | Follow `devflow:resolve` command flow (auto-discovers worktrees natively) | | **EXPLORE** | No agents — respond in main session | @@ -147,6 +157,12 @@ After loading skills via Step 3-4, execute the agent pipeline for the classified | User explicitly requests no enforcement | Respect immediately — classify as QUICK | | Prompt references specific DevFlow command | Skip ambient — the command has its own orchestration | | Scope ambiguous between GUIDED and ORCHESTRATED | Default to GUIDED; escalate if complexity emerges during work | -| REVIEW intent | Always GUIDED — single Reviewer focus, no orchestration pipeline | +| REVIEW after IMPLEMENT/GUIDED | GUIDED (continuation — match prior depth) | +| REVIEW after IMPLEMENT/ORCHESTRATED | ORCHESTRATED (continuation — match prior depth) | +| REVIEW standalone, large scope ("full review", "branch", "PR") | ORCHESTRATED | +| REVIEW standalone, small scope ("check this", specific file) | GUIDED | +| REVIEW standalone, ambiguous | GUIDED (conservative) | +| RESOLVE intent | Always ORCHESTRATED | +| PIPELINE intent | Always ORCHESTRATED | | MULTI_WORKTREE intent | Always ORCHESTRATED — follow code-review/resolve command flow which auto-discovers worktrees | | Multiple triggers per session | Each runs independently; context compaction handles accumulation | diff --git a/shared/skills/ambient-router/references/skill-catalog.md b/shared/skills/ambient-router/references/skill-catalog.md index 5db34338..39abb7b7 100644 --- a/shared/skills/ambient-router/references/skill-catalog.md +++ b/shared/skills/ambient-router/references/skill-catalog.md @@ -40,6 +40,27 @@ These skills may be loaded during GUIDED and ORCHESTRATED-depth ambient routing. | self-review | Always for REVIEW | GUIDED | Any code file | | core-patterns | Always for REVIEW | GUIDED | Any code file | | test-patterns | Test files in scope | GUIDED | `*.test.*`, `*.spec.*` | +| review-orchestration | ORCHESTRATED only | ORCHESTRATED | Any — orchestrates multi-agent review pipeline | + +**REVIEW depth is continuation-aware**: If the prior classification in the same conversation was IMPLEMENT/GUIDED → REVIEW stays GUIDED. If prior was IMPLEMENT/ORCHESTRATED → REVIEW becomes ORCHESTRATED. Standalone REVIEW uses signal words: "full review"/"branch review"/"PR review" → ORCHESTRATED, "check this"/"review this file" → GUIDED. Ambiguous → GUIDED. + +### RESOLVE Intent + +| Skill | When to Load | Depth | File Patterns | +|-------|-------------|-------|---------------| +| resolve-orchestration | Always for RESOLVE | ORCHESTRATED | Any — orchestrates issue resolution pipeline | +| core-patterns | Always for RESOLVE | ORCHESTRATED | Any code file | + +RESOLVE is always ORCHESTRATED — it requires multi-agent resolution with Resolver agents and Simplifier. + +### PIPELINE Intent + +| Skill | When to Load | Depth | File Patterns | +|-------|-------------|-------|---------------| +| pipeline-orchestration | Always for PIPELINE | ORCHESTRATED | Any — meta-orchestrator for implement → review → resolve | +| implementation-patterns | Always for PIPELINE | ORCHESTRATED | Any code file | + +PIPELINE is always ORCHESTRATED — it chains multiple orchestration stages with user gates. ### PLAN Intent @@ -49,9 +70,9 @@ These skills may be loaded during GUIDED and ORCHESTRATED-depth ambient routing. | implementation-patterns | Always for PLAN | GUIDED + ORCHESTRATED | Any planning context | | core-patterns | Always for PLAN | GUIDED + ORCHESTRATED | System design discussions | -## Skills Excluded from Ambient +## Skills Excluded from Ambient Router Loading -These skills are loaded only by explicit DevFlow commands (primarily `/code-review`): +These skills are always installed (universal skill installation) but loaded by agents internally at runtime, not by the ambient router. Reviewer agents load their pattern skill based on their focus area: - review-methodology — Full review process (6-step, 3-category classification) - complexity-patterns — Cyclomatic complexity, deep nesting analysis @@ -80,7 +101,7 @@ No additional skills needed — the code-review and resolve commands handle all ## Selection Limits - **Maximum 3 knowledge skills** per ambient response (primary + up to 2 secondary) -- **Orchestration skills** (implementation-orchestration, debug-orchestration, plan-orchestration) are loaded only at ORCHESTRATED depth — they don't count toward the knowledge skill limit +- **Orchestration skills** (implementation-orchestration, debug-orchestration, plan-orchestration, review-orchestration, resolve-orchestration, pipeline-orchestration) are loaded only at ORCHESTRATED depth — they don't count toward the knowledge skill limit - **Primary skills** are always loaded for the classified intent at both GUIDED and ORCHESTRATED depth - **Secondary skills** are loaded only when file patterns match conversation context - **GUIDED depth** loads knowledge skills only (no orchestration skills) — main session works directly diff --git a/shared/skills/git-safety/SKILL.md b/shared/skills/git-safety/SKILL.md index 0beade62..6fa03037 100644 --- a/shared/skills/git-safety/SKILL.md +++ b/shared/skills/git-safety/SKILL.md @@ -77,7 +77,7 @@ Only use `--amend` when ALL conditions are met: ## Branch Safety -Never force push to: `main`, `master`, `develop` +Never force push to: `main`, `master`, `develop`, `release/*`, `staging`, `production` **Branch naming**: `feat/`, `fix/`, `release/`, `hotfix/` prefixes with short descriptions. diff --git a/shared/skills/git-safety/references/patterns.md b/shared/skills/git-safety/references/patterns.md index 54027af1..20673a0c 100644 --- a/shared/skills/git-safety/references/patterns.md +++ b/shared/skills/git-safety/references/patterns.md @@ -116,7 +116,7 @@ git push -u origin $(git branch --show-current) ## Protected Branch Check ```bash -PROTECTED_BRANCHES="main master develop" +PROTECTED_BRANCHES="main master develop staging production" check_protected_branch() { local branch="$1" @@ -126,6 +126,10 @@ check_protected_branch() { return 1 fi done + # Check release/* glob + case "$branch" in + release/*) echo "ERROR: Cannot force push to $branch"; return 1 ;; + esac return 0 } ``` diff --git a/shared/skills/implementation-orchestration/SKILL.md b/shared/skills/implementation-orchestration/SKILL.md index eb20340b..a474fad5 100644 --- a/shared/skills/implementation-orchestration/SKILL.md +++ b/shared/skills/implementation-orchestration/SKILL.md @@ -59,6 +59,8 @@ Spawn `Task(subagent_type="Coder")` with input variables: If Coder returns **BLOCKED**, halt the pipeline and report to user. +**Handoff artifact** (when HANDOFF_REQUIRED=true): After Coder completes, write the phase summary to `.docs/handoff.md` using the Write tool. The next Coder reads this on startup (see Coder agent Responsibility 1). This survives context compaction — unlike PRIOR_PHASE_SUMMARY which is context-mediated. + ## Phase 4: FILES_CHANGED Detection After Coder completes, detect changed files: @@ -83,6 +85,8 @@ If any gate exhausts retries, halt pipeline and report what passed and what fail ## Phase 6: Completion +Cleanup: delete `.docs/handoff.md` if it exists (no longer needed after pipeline completes). + Report results: - Commits created (from Coder) - Files changed diff --git a/shared/skills/pipeline-orchestration/SKILL.md b/shared/skills/pipeline-orchestration/SKILL.md new file mode 100644 index 00000000..1e22d8ad --- /dev/null +++ b/shared/skills/pipeline-orchestration/SKILL.md @@ -0,0 +1,77 @@ +--- +name: pipeline-orchestration +description: End-to-end meta-orchestrator chaining implement → review → resolve with user gates between stages +user-invocable: false +allowed-tools: Read, Grep, Glob, Bash, Task, AskUserQuestion +--- + +# Pipeline Orchestration + +Meta-orchestrator chaining implement → review → resolve with user gates between stages. For ambient PIPELINE intent ("implement this end to end", "build and review"). + +## Iron Law + +> **USER GATES BETWEEN STAGES** +> +> Never auto-chain from review to resolve without user confirmation. +> Critical findings require human judgment. Each gate is mandatory. + +--- + +## Cost Communication + +Classification statement must warn about scope: +`Ambient: PIPELINE/ORCHESTRATED. This runs implement → review → resolve (15+ agents across stages).` + +## Phase 1: Implement + +Follow implementation-orchestration pipeline (Phases 1-6). + +If implementation returns **BLOCKED**: halt entire pipeline, report blocker. + +Cleanup: delete `.docs/handoff.md` if it exists (no longer needed before review). + +## Phase 2: Gate — Review Decision + +Use AskUserQuestion: +> "Implementation complete ({n} files changed, all quality gates passed). Proceed with multi-agent review? (This spawns 7+ reviewer agents)" + +- **User says NO** → stop pipeline, report implementation results only +- **User says YES** → continue to Phase 3 + +## Phase 3: Review + +Follow review-orchestration pipeline (Phases 1-6). + +Report review results (merge recommendation, issue counts). + +## Phase 4: Gate — Resolve Decision + +If **blocking issues found**: +> Use AskUserQuestion: "Found {n} blocking issues. Auto-resolve? (Spawns resolver agents per batch)" + +If **no blocking issues**: +> "Review clean — no resolution needed." → stop pipeline with success summary + +- **User says NO** → stop pipeline, report implementation + review results +- **User says YES** → continue to Phase 5 + +## Phase 5: Resolve + +Follow resolve-orchestration pipeline (Phases 1-6). + +## Phase 6: Summary + +End-to-end report: +- **Implementation**: files changed, commits, quality gate results +- **Review**: issue counts by severity, merge recommendation +- **Resolution**: issues fixed vs deferred vs false positives +- **Final state**: branch status, remaining work (if any) + +## Error Handling + +- **Implementation BLOCKED**: Halt at Phase 1, report blocker +- **User declines gate**: Stop cleanly, report completed stages +- **Review finds no changes**: Skip review, report implementation only +- **All issues resolved**: Report full success +- **Partial resolution**: Report what was fixed and what remains diff --git a/shared/skills/resolve-orchestration/SKILL.md b/shared/skills/resolve-orchestration/SKILL.md new file mode 100644 index 00000000..d24aea99 --- /dev/null +++ b/shared/skills/resolve-orchestration/SKILL.md @@ -0,0 +1,89 @@ +--- +name: resolve-orchestration +description: Agent orchestration for RESOLVE intent in ambient mode — issue resolution from review reports +user-invocable: false +allowed-tools: Read, Grep, Glob, Bash, Task, AskUserQuestion +--- + +# Resolve Orchestration + +Agent pipeline for RESOLVE intent in ambient mode. Parses review reports, validates issues, batches resolutions, and runs Simplifier cleanup. + +This is a lightweight variant of `/resolve` for ambient mode. Excluded: pitfall recording, tech debt management, Agent Teams debate, multi-worktree flow, CLI flags. + +## Iron Law + +> **VALIDATE FIRST, FIX EVERYTHING POSSIBLE** +> +> Every issue must be validated in current file context before any fix. +> Read first, decide second, fix third. Never apply a suggested fix blindly. +> Tech debt deferral is the LAST RESORT — only for complete architectural overhauls. + +--- + +## Phase 1: Target Review Directory + +Find the latest timestamped directory under `.docs/reviews/` that: +1. Contains a `review-summary.md` (has been reviewed) +2. Does NOT contain a `resolution-summary.md` (hasn't been resolved yet) + +If no unresolved review found: halt with "No unresolved review found. Run a review first." + +Extract branch slug from the directory path. + +## Phase 2: Parse Issues + +Read all `{focus}.md` files in the timestamped directory (exclude `review-summary.md` and `resolution-summary.md`). + +Extract issues at **Blocking** and **Should-Fix** severity only. Skip Pre-existing and Suggestions. + +For each issue, extract: id (generated), file, line, severity, type (from focus), description, suggested_fix. + +If no actionable issues found: "Review is clean — no blocking or should-fix issues to resolve." → stop. + +## Phase 3: Analyze & Batch + +Group issues by file/function for efficient resolution: +- Issues in the same file → same batch +- Issues with cross-file dependencies → same batch +- Max 5 issues per batch + +Determine execution: batches with no shared files can run in parallel. + +## Phase 4: Resolve (Parallel) + +Spawn `Task(subagent_type="Resolver")` agents — one per batch, parallel where possible. + +Each receives: +- **ISSUES**: Array of issues in the batch +- **BRANCH**: Branch slug +- **BATCH_ID**: Identifier for this batch + +Resolvers follow a 3-tier risk approach: +- **Standard fixes**: Applied directly +- **Careful fixes** (public API, shared state, >3 files): Test-first — write tests covering current behavior, apply fix, verify tests pass +- **Architectural overhaul**: Defer to tech debt (LAST RESORT — only when complete system redesign required) + +## Phase 5: Collect & Simplify + +Aggregate results from all Resolver agents: +- Count: fixed, false positives, deferred + +Spawn `Task(subagent_type="Simplifier")` on all files modified by Resolvers. + +## Phase 6: Report + +Write `resolution-summary.md` to the same timestamped review directory. + +Report to user: +- Issues resolved vs deferred vs false positives +- Files modified +- Commits created +- Remaining issues (if any deferred) + +## Error Handling + +- **No review directory**: Halt, suggest running review first +- **All issues false positive**: Report findings, write resolution-summary noting no changes needed +- **Resolver BLOCKED**: Report which batch blocked, continue with remaining +- **Simplifier fails**: Resolution still valid — report that simplification was skipped diff --git a/shared/skills/review-orchestration/SKILL.md b/shared/skills/review-orchestration/SKILL.md new file mode 100644 index 00000000..ba37f699 --- /dev/null +++ b/shared/skills/review-orchestration/SKILL.md @@ -0,0 +1,99 @@ +--- +name: review-orchestration +description: Agent orchestration for REVIEW intent in ambient ORCHESTRATED mode — multi-agent code review with parallel reviewers +user-invocable: false +allowed-tools: Read, Grep, Glob, Bash, Task, AskUserQuestion +--- + +# Review Orchestration + +Agent pipeline for REVIEW intent in ambient ORCHESTRATED mode. Full multi-agent review with parallel specialized reviewers, incremental detection, and disk-persisted reports. + +This is a lightweight variant of `/code-review` for ambient ORCHESTRATED mode. Excluded: pitfall recording, tech debt management, Agent Teams debate, multi-worktree flow (routes to full command via MULTI_WORKTREE intent), CLI flag parsing. + +## Iron Law + +> **EVERY REVIEWER WRITES TO DISK** +> +> A review that exists only in agent output disappears on compaction. +> No disk artifact, no review. The Synthesizer reads from disk, not memory. + +--- + +## Phase 1: Pre-flight + +Spawn `Task(subagent_type="Git")` with action `ensure-pr-ready`: +- Extract: branch, base_branch, branch_slug, pr_number +- If BLOCKED (detached HEAD, no commits ahead of base): halt with message + +Determine base branch: use PR target if PR exists, otherwise `main`/`master`. + +## Phase 2: Incremental Detection + +Check `.docs/reviews/{branch_slug}/.last-review-head`: +- If file exists and SHA matches HEAD: "No new commits since last review. Nothing to do." → stop +- If file exists and SHA differs: set `DIFF_RANGE={sha}...HEAD` (incremental) +- If file doesn't exist: set `DIFF_RANGE={base_branch}...HEAD` (full review) + +Generate timestamp: `YYYY-MM-DD_HHMM` +Create directory: `mkdir -p .docs/reviews/{branch_slug}/{timestamp}` + +## Phase 3: File Analysis + +Run `git diff --name-only {DIFF_RANGE}` to get changed files. + +Detect conditional reviewers from file types: + +| File Pattern | Reviewer Focus | +|-------------|---------------| +| `*.ts`, `*.tsx` | typescript | +| `*.tsx`, `*.jsx` | react | +| `*.go` | go | +| `*.java` | java | +| `*.py` | python | +| `*.rs` | rust | +| `*.css`, `*.scss` | frontend-design | +| `*.tsx`, `*.jsx` (with UI) | accessibility | +| migration/schema files | database | +| `package.json`, lock files | dependencies | +| `*.md`, doc files | documentation | + +## Phase 4: Reviews (Parallel) + +Spawn all reviewers in a single message (parallel execution): + +**7 core reviewers** (always): +- security, architecture, performance, complexity, consistency, tests, regression + +**Conditional reviewers** (from Phase 3 file analysis): +- typescript, react, database, dependencies, documentation, go, java, python, rust, accessibility, frontend-design + +Each reviewer receives: +- **Focus**: Their review type +- **Branch context**: branch → base_branch +- **Output path**: `.docs/reviews/{branch_slug}/{timestamp}/{focus}.md` +- **DIFF_COMMAND**: `git diff {DIFF_RANGE}` (incremental or full) + +## Phase 5: Synthesis (Parallel) + +After all reviewers complete, spawn in parallel: + +1. `Task(subagent_type="Git")` with action `comment-pr` — post review summary as PR comment (deduplicate: check existing comments first) +2. `Task(subagent_type="Synthesizer")` in review mode — reads all `{focus}.md` files from disk, writes `review-summary.md` + +## Phase 6: Finalize + +Write HEAD SHA to `.docs/reviews/{branch_slug}/.last-review-head` for next incremental review. + +Report to user: +- Merge recommendation (from Synthesizer) +- Issue counts by severity +- Artifacts: list of report files written +- Next steps: suggest `/resolve` or `resolve the review issues` if blocking issues found + +## Error Handling + +- **Git pre-flight BLOCKED**: Halt immediately, report to user +- **No changed files**: "No changes to review." → stop +- **Reviewer fails**: Report which reviewer failed, continue with remaining +- **Synthesizer fails**: Reports are still on disk — user can read them directly diff --git a/shared/skills/worktree-support/SKILL.md b/shared/skills/worktree-support/SKILL.md new file mode 100644 index 00000000..9022d44e --- /dev/null +++ b/shared/skills/worktree-support/SKILL.md @@ -0,0 +1,91 @@ +--- +name: worktree-support +description: Canonical worktree path resolution and discovery algorithm for agents and commands +user-invocable: false +allowed-tools: Bash, Read +--- + +# Worktree Support + +Canonical patterns for worktree-aware agents and multi-worktree discovery in commands. + +## Iron Law + +> **WORKTREE_PATH IS A PREFIX, NOT A FLAG** +> +> When WORKTREE_PATH is provided, it changes how you resolve ALL paths — git commands, +> file reads, .docs/ paths. It's not a toggle; it's a coordinate system shift. + +--- + +## Agent Path Resolution + +When `WORKTREE_PATH` is provided to an agent: + +| Operation | Without WORKTREE_PATH | With WORKTREE_PATH | +|-----------|----------------------|-------------------| +| Git commands | `git ...` | `git -C {WORKTREE_PATH} ...` | +| .docs/ paths | `.docs/...` | `{WORKTREE_PATH}/.docs/...` | +| Source files | `{file}` | `{WORKTREE_PATH}/{file}` | +| Default | Use cwd | Use WORKTREE_PATH as root | + +If `WORKTREE_PATH` is omitted, behavior is unchanged (use cwd). This is the common case. + +--- + +## Worktree Discovery Algorithm (Commands) + +For commands that auto-discover worktrees (`/code-review`, `/resolve`): + +### Step 1: List Worktrees + +Run `git worktree list --porcelain` + +### Step 2: Parse Each Entry + +Extract: `worktree {path}`, `HEAD {sha}`, `branch refs/heads/{name}` + +### Step 3: Filter + +Exclude: +- **Bare worktrees** (no branch) +- **Detached HEAD** (no named branch) +- **Protected branches**: `main`, `master`, `develop`, `release/*`, `staging`, `production` +- **Mid-rebase or mid-merge**: check `git -C {path} status` for "rebase in progress" or "merging" + +### Step 4: Check for Work + +Each worktree must have commits ahead of base branch. Skip those that are clean/up-to-date. + +### Step 5: Deduplicate + +If two worktrees are on the same branch, use only the first worktree's path. + +### Step 6: Sort + +Sort by last commit date (most recent first). + +### Step 7: Return + +Return list of reviewable worktrees with path, branch, HEAD SHA. + +--- + +## Protected Branches (Canonical List) + +`main`, `master`, `develop`, `release/*`, `staging`, `production` + +All components (agents, commands, skills) must use this exact list when checking for protected branches. + +--- + +## Multi-Worktree Mode + +| Condition | Behavior | +|-----------|----------| +| 0 reviewable worktrees | Error: no reviewable branches found | +| 1 worktree (common case) | Single-worktree flow, zero behavior change | +| 2+ worktrees | Report count, process all in parallel where possible | +| 5+ worktrees | Report count and proceed — user manages their worktree count | +| `--path` flag provided | Use only that worktree, skip discovery | +| Same branch in 2 worktrees | Deduplicate — review once using first worktree's path | diff --git a/src/cli/commands/init.ts b/src/cli/commands/init.ts index 4d8e1879..5f00ce42 100644 --- a/src/cli/commands/init.ts +++ b/src/cli/commands/init.ts @@ -20,7 +20,7 @@ import { migrateMemoryFiles, type SecurityMode, } from '../utils/post-install.js'; -import { DEVFLOW_PLUGINS, LEGACY_SKILL_NAMES, LEGACY_COMMAND_NAMES, buildAssetMaps, type PluginDefinition } from '../plugins.js'; +import { DEVFLOW_PLUGINS, LEGACY_SKILL_NAMES, LEGACY_COMMAND_NAMES, buildAssetMaps, buildFullSkillsMap, type PluginDefinition } from '../plugins.js'; import { detectPlatform, detectShell, getProfilePath, getSafeDeleteInfo, hasSafeDelete } from '../utils/safe-delete.js'; import { generateSafeDeleteBlock, installToProfile, removeFromProfile, getInstalledVersion, SAFE_DELETE_BLOCK_VERSION } from '../utils/safe-delete-install.js'; import { addAmbientHook } from './ambient.js'; @@ -749,7 +749,11 @@ export const initCommand = new Command('init') pluginsToInstall.push(ambientPlugin); } - const { skillsMap, agentsMap } = buildAssetMaps(pluginsToInstall); + // Skills: install ALL from ALL plugins (skills are tiny markdown files; + // orchestration skills need skills from other plugins to function) + const skillsMap = buildFullSkillsMap(); + // Agents: install only from selected plugins + const { agentsMap } = buildAssetMaps(pluginsToInstall); // Install: try native CLI first, fall back to file copy const cliAvailable = isClaudeCliAvailable(); diff --git a/src/cli/plugins.ts b/src/cli/plugins.ts index 9e15c233..c93ebf37 100644 --- a/src/cli/plugins.ts +++ b/src/cli/plugins.ts @@ -38,42 +38,64 @@ export const DEVFLOW_PLUGINS: PluginDefinition[] = [ description: 'Complete task implementation workflow with exploration, planning, and coding', commands: ['/implement'], agents: ['git', 'skimmer', 'synthesizer', 'coder', 'simplifier', 'scrutinizer', 'shepherd', 'validator'], - skills: ['agent-teams', 'implementation-patterns', 'knowledge-persistence', 'self-review'], + skills: ['agent-teams', 'implementation-patterns', 'knowledge-persistence', 'self-review', 'worktree-support'], }, { name: 'devflow-code-review', description: 'Comprehensive code review with parallel specialized agents', commands: ['/code-review'], agents: ['git', 'reviewer', 'synthesizer'], - skills: ['agent-teams', 'architecture-patterns', 'complexity-patterns', 'consistency-patterns', 'database-patterns', 'dependencies-patterns', 'documentation-patterns', 'knowledge-persistence', 'performance-patterns', 'regression-patterns', 'review-methodology', 'security-patterns', 'test-patterns'], + skills: ['agent-teams', 'architecture-patterns', 'complexity-patterns', 'consistency-patterns', 'database-patterns', 'dependencies-patterns', 'documentation-patterns', 'knowledge-persistence', 'performance-patterns', 'regression-patterns', 'review-methodology', 'security-patterns', 'test-patterns', 'worktree-support'], }, { name: 'devflow-resolve', description: 'Process and fix code review issues with risk assessment', commands: ['/resolve'], agents: ['git', 'resolver', 'simplifier'], - skills: ['agent-teams', 'implementation-patterns', 'knowledge-persistence', 'security-patterns'], + skills: ['agent-teams', 'implementation-patterns', 'knowledge-persistence', 'security-patterns', 'worktree-support'], }, { name: 'devflow-debug', description: 'Debugging workflows with competing hypothesis investigation using agent teams', commands: ['/debug'], agents: ['git', 'synthesizer'], - skills: ['agent-teams', 'git-safety', 'knowledge-persistence'], + skills: ['agent-teams', 'git-safety', 'knowledge-persistence', 'worktree-support'], }, { name: 'devflow-self-review', description: 'Self-review workflow: Simplifier + Scrutinizer for code quality', commands: ['/self-review'], agents: ['simplifier', 'scrutinizer', 'validator'], - skills: ['self-review', 'core-patterns'], + skills: ['self-review', 'core-patterns', 'worktree-support'], }, { name: 'devflow-ambient', description: 'Ambient mode — intent classification with proportional agent orchestration', commands: ['/ambient'], - agents: ['coder', 'validator', 'simplifier', 'scrutinizer', 'shepherd', 'skimmer', 'reviewer'], - skills: ['ambient-router', 'implementation-orchestration', 'debug-orchestration', 'plan-orchestration'], + agents: ['coder', 'validator', 'simplifier', 'scrutinizer', 'shepherd', 'skimmer', 'reviewer', 'git', 'synthesizer', 'resolver'], + skills: [ + 'ambient-router', + 'implementation-orchestration', + 'debug-orchestration', + 'plan-orchestration', + 'review-orchestration', + 'resolve-orchestration', + 'pipeline-orchestration', + 'review-methodology', + 'security-patterns', + 'architecture-patterns', + 'performance-patterns', + 'complexity-patterns', + 'consistency-patterns', + 'regression-patterns', + 'test-patterns', + 'database-patterns', + 'dependencies-patterns', + 'documentation-patterns', + 'implementation-patterns', + 'knowledge-persistence', + 'worktree-support', + ], }, { name: 'devflow-audit-claude', @@ -252,3 +274,21 @@ export function buildAssetMaps(plugins: PluginDefinition[]): { } return { skillsMap, agentsMap }; } + +/** + * Build a skills map from ALL plugins (regardless of selection). + * Skills are tiny markdown files — always install all of them so orchestration + * skills (review-orchestration, resolve-orchestration) can spawn agents that + * depend on skills from other plugins. + */ +export function buildFullSkillsMap(): Map { + const skillsMap = new Map(); + for (const plugin of DEVFLOW_PLUGINS) { + for (const skill of plugin.skills) { + if (!skillsMap.has(skill)) { + skillsMap.set(skill, plugin.name); + } + } + } + return skillsMap; +} diff --git a/src/cli/utils/installer.ts b/src/cli/utils/installer.ts index 6a2b4f2d..b1ad1833 100644 --- a/src/cli/utils/installer.ts +++ b/src/cli/utils/installer.ts @@ -161,7 +161,7 @@ export async function installViaFileCopy(options: FileCopyOptions): Promise { expect(shellPreamble).toContain('IMPLEMENT'); expect(shellPreamble).toContain('DEBUG'); expect(shellPreamble).toContain('REVIEW'); + expect(shellPreamble).toContain('RESOLVE'); + expect(shellPreamble).toContain('PIPELINE'); expect(shellPreamble).toContain('PLAN'); + // Must contain multi-worktree awareness + expect(shellPreamble).toContain('MULTI_WORKTREE'); + // Must reference core skills by name expect(shellPreamble).toContain('implementation-patterns'); expect(shellPreamble).toContain('test-driven-development'); @@ -279,6 +284,14 @@ describe('preamble drift detection', () => { expect(shellPreamble).toContain('self-review'); expect(shellPreamble).toContain('search-first'); + // Must reference all 6 orchestration skills + expect(shellPreamble).toContain('implementation-orchestration'); + expect(shellPreamble).toContain('debug-orchestration'); + expect(shellPreamble).toContain('plan-orchestration'); + expect(shellPreamble).toContain('review-orchestration'); + expect(shellPreamble).toContain('resolve-orchestration'); + expect(shellPreamble).toContain('pipeline-orchestration'); + // Must instruct Skill tool invocation expect(shellPreamble).toContain('Skill tool'); diff --git a/tests/plugins.test.ts b/tests/plugins.test.ts index 9a1a7688..cf2844e5 100644 --- a/tests/plugins.test.ts +++ b/tests/plugins.test.ts @@ -4,6 +4,7 @@ import { getAllSkillNames, getAllAgentNames, buildAssetMaps, + buildFullSkillsMap, type PluginDefinition, } from '../src/cli/plugins.js'; @@ -86,6 +87,33 @@ describe('buildAssetMaps', () => { }); }); +describe('buildFullSkillsMap', () => { + it('includes skills from ALL plugins regardless of selection', () => { + const fullMap = buildFullSkillsMap(); + // Must include skills from optional plugins too + expect(fullMap.has('accessibility')).toBe(true); + expect(fullMap.has('typescript')).toBe(true); + expect(fullMap.has('go')).toBe(true); + // Must include all orchestration skills + expect(fullMap.has('review-orchestration')).toBe(true); + expect(fullMap.has('resolve-orchestration')).toBe(true); + expect(fullMap.has('pipeline-orchestration')).toBe(true); + }); + + it('covers more skills than buildAssetMaps with only non-optional plugins', () => { + const nonOptional = DEVFLOW_PLUGINS.filter(p => !p.optional); + const { skillsMap: partialMap } = buildAssetMaps(nonOptional); + const fullMap = buildFullSkillsMap(); + expect(fullMap.size).toBeGreaterThan(partialMap.size); + }); + + it('matches getAllSkillNames count', () => { + const fullMap = buildFullSkillsMap(); + const allNames = getAllSkillNames(); + expect(fullMap.size).toBe(allNames.length); + }); +}); + describe('DEVFLOW_PLUGINS integrity', () => { it('has no duplicate plugin names', () => { const names = DEVFLOW_PLUGINS.map(p => p.name); @@ -169,6 +197,25 @@ describe('optional plugin flag', () => { expect(DEVFLOW_PLUGINS.find(p => p.name === 'devflow-audit-claude')).toBeDefined(); }); + it('devflow-ambient declares review/resolve skill dependencies', () => { + const ambient = DEVFLOW_PLUGINS.find(p => p.name === 'devflow-ambient'); + expect(ambient).toBeDefined(); + // Ambient must declare review skills so uninstalling code-review doesn't break ambient review + expect(ambient!.skills).toContain('review-methodology'); + expect(ambient!.skills).toContain('security-patterns'); + // Ambient must declare orchestration skills + expect(ambient!.skills).toContain('review-orchestration'); + expect(ambient!.skills).toContain('resolve-orchestration'); + expect(ambient!.skills).toContain('pipeline-orchestration'); + // Ambient must declare resolve dependencies + expect(ambient!.skills).toContain('implementation-patterns'); + expect(ambient!.skills).toContain('knowledge-persistence'); + // Ambient must declare all needed agents + expect(ambient!.agents).toContain('git'); + expect(ambient!.agents).toContain('synthesizer'); + expect(ambient!.agents).toContain('resolver'); + }); + it('devflow-core-skills does not contain language/ecosystem skills', () => { const coreSkills = DEVFLOW_PLUGINS.find(p => p.name === 'devflow-core-skills'); expect(coreSkills).toBeDefined(); diff --git a/tests/uninstall-logic.test.ts b/tests/uninstall-logic.test.ts index 2604c173..07388fc3 100644 --- a/tests/uninstall-logic.test.ts +++ b/tests/uninstall-logic.test.ts @@ -51,6 +51,15 @@ describe('computeAssetsToRemove', () => { expect(commands.length).toBeGreaterThan(0); }); + it('retains review-methodology when code-review uninstalled (ambient declares it)', () => { + const reviewPlugin = DEVFLOW_PLUGINS.find(p => p.name === 'devflow-code-review')!; + const { skills } = computeAssetsToRemove([reviewPlugin], DEVFLOW_PLUGINS); + // review-methodology is also declared by devflow-ambient, so it must NOT be removed + expect(skills).not.toContain('review-methodology'); + // security-patterns is also declared by devflow-ambient + expect(skills).not.toContain('security-patterns'); + }); + it('handles custom plugin lists', () => { const plugins: PluginDefinition[] = [ { name: 'a', description: '', commands: ['/a'], agents: ['shared', 'only-a'], skills: ['shared-skill', 'only-a-skill'] },