Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion plugins/project-setup-jj/scripts/jj-workspace-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ input=$(cat)
name=$(echo "$input" | jq -r '.name')
cwd=$(echo "$input" | jq -r '.cwd')

DIR="$cwd/.claude/workspaces/$name"
# Create workspace OUTSIDE the repo to prevent jj's auto-snapshotting in the
# default workspace from attributing workspace file edits to @.
# Using /tmp ensures the workspace directory is not under the repo root.
DIR="/tmp/jj-workspaces/$(basename "$cwd")/$name"
mkdir -p "$(dirname "$DIR")"

# Pin workspace to the current working copy's parents (not the working copy itself).
Expand Down
2 changes: 1 addition & 1 deletion plugins/workspace-jj/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Provides the **fan-flames** skill β€” a parallel task orchestrator that dispatch

## How It Works

- **WorktreeCreate**: Runs `jj workspace add --revision @-` to create an isolated workspace at `.claude/workspaces/<name>/`, pinned to the parent revision for independent branching
- **WorktreeCreate**: Runs `jj workspace add --revision @-` to create an isolated workspace at `/tmp/jj-workspaces/<project>/<name>/`, pinned to the parent revision for independent branching. Workspaces are created outside the repo to prevent jj's auto-snapshotting from attributing workspace edits to the default workspace's `@`.
- **WorktreeRemove**: Runs `jj workspace forget` and removes the directory on cleanup

Workspaces share the same repository store (lightweight, fast to create) but each gets an independent working copy pinned to the same parent revision.
Expand Down
47 changes: 45 additions & 2 deletions plugins/workspace-jj/commands/fan-flames.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ Wave assignment:

**Overlaps detected:** Present wave plan, wait for user confirmation.

### Parallelism Threshold

After computing waves, calculate the parallelism ratio: tasks in the largest wave / total tasks. If less than 40% of tasks can run in parallel (e.g., 2 of 9 tasks in the largest wave), warn the user:

```
⚠️ Low parallelism: only N/M tasks can run in parallel (largest wave: W tasks).
File overlaps make most tasks sequential. The overhead of workspace setup,
spec review, and squash ceremony may exceed the time saved.

Options:
a) Proceed with fan-flames anyway
b) Switch to single-agent sequential execution (superpowers:executing-plans)
```

Wait for user decision.

5. **Recommend** 3-5 concurrent workspaces per wave.

## Phase 2: FAN OUT πŸͺ­ β€” Dispatch
Expand Down Expand Up @@ -156,6 +172,23 @@ Agent tool:

**Workspaces remain alive** through the REVIEW phase so fix subagents can be dispatched if spec review fails.

### Workspace Integrity Check

After collecting results, verify each subagent's changes actually landed in its workspace, not in the default workspace's `@`:

```bash
# Check if default workspace @ has unexpected changes
jj diff -r @ --stat
```

If the default workspace's `@` shows changes that belong to a subagent task, workspace isolation failed (**Pattern C**). Handle by:
1. Report the issue: "Workspace isolation failure β€” Task N's edits landed in the default workspace instead of its workspace."
2. Skip squash for that task (changes are already in `@`)
3. Verify the content is correct by diffing against the task spec
4. Continue with remaining tasks normally

This is a known edge case β€” the WorktreeCreate hook creates the jj workspace, but the agent may resolve file paths to the main repo instead of the workspace copy.

### Recovery: Missing Change IDs

```bash
Expand All @@ -166,7 +199,17 @@ jj log -r 'description("Task N: <short description>")' --no-graph -T 'change_id'

**Skip this phase if `--skip-spec-review` is set.** Clean up workspaces and proceed to FAN IN.

For each DONE/DONE_WITH_CONCERNS task, dispatch a spec reviewer subagent (read-only, no isolation needed). All reviewers run in parallel.
### Tiered Review

Not all tasks need a full reviewer agent. Before dispatching, assess each task's complexity:

**Trivial tasks** (< 10 lines changed, no logic/control flow changes β€” e.g., visibility modifiers, import reordering, renaming): Verify inline by reading the diff yourself. Report: "Task N: trivial change (N lines), verified inline β€” PASS." No reviewer agent needed.

**Non-trivial tasks** (logic changes, new functions, structural modifications): Dispatch a spec reviewer subagent as below.

### Spec Reviewer Dispatch

For each non-trivial DONE/DONE_WITH_CONCERNS task, dispatch a spec reviewer subagent (read-only, no isolation needed). All reviewers run in parallel.

Read the spec reviewer template at: `plugins/workspace-jj/skills/fan-flames-spec-reviewer.md`

Expand Down Expand Up @@ -204,7 +247,7 @@ jj log -r 'ancestors(@) & (<change-id-1> | <change-id-2>)' --no-graph -T 'change
### Pattern B: Independent branches β€” squash each into @, smallest diff first:

```bash
jj squash --from <change-id> --into @
JJ_EDITOR=true jj squash --from <change-id> --into @
jj resolve --list # check for conflicts
```

Expand Down
5 changes: 4 additions & 1 deletion plugins/workspace-jj/scripts/jj-workspace-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ input=$(cat)
name=$(echo "$input" | jq -r '.name')
cwd=$(echo "$input" | jq -r '.cwd')

DIR="$cwd/.claude/workspaces/$name"
# Create workspace OUTSIDE the repo to prevent jj's auto-snapshotting in the
# default workspace from attributing workspace file edits to @.
# Using /tmp ensures the workspace directory is not under the repo root.
DIR="/tmp/jj-workspaces/$(basename "$cwd")/$name"
mkdir -p "$(dirname "$DIR")"

# Pin workspace to the current working copy's parents (not the working copy itself).
Expand Down
47 changes: 44 additions & 3 deletions plugins/workspace-jj/skills/fan-flames.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,22 @@ Proceed with this wave plan? (or restructure)

Wait for user confirmation before proceeding.

### Parallelism Threshold

After computing waves, calculate the parallelism ratio: tasks in the largest wave / total tasks. If less than 40% of tasks can run in parallel (e.g., 2 of 9 tasks in the largest wave), warn the user:

```
⚠️ Low parallelism: only N/M tasks can run in parallel (largest wave: W tasks).
File overlaps make most tasks sequential. The overhead of workspace setup,
spec review, and squash ceremony may exceed the time saved.

Options:
a) Proceed with fan-flames anyway
b) Switch to single-agent sequential execution (superpowers:executing-plans)
```

Wait for user decision.

5. **Recommend** 3-5 concurrent workspaces per wave for most tasks. Note the recommendation but do not block dispatch if more are requested.

## Phase 2: FAN OUT πŸͺ­ β€” Create Workspaces and Dispatch
Expand Down Expand Up @@ -215,6 +231,23 @@ As subagents return, classify each result:

Track which tasks succeeded and which failed. **Capture the change ID and workspace directory name from each subagent's report** β€” change IDs are needed for fan-in squash, workspace names for cleanup.

### Workspace Integrity Check

After collecting results, verify each subagent's changes actually landed in its workspace, not in the default workspace's `@`:

```bash
# Check if default workspace @ has unexpected changes
jj diff -r @ --stat
```

If the default workspace's `@` shows changes that belong to a subagent task, workspace isolation failed (**Pattern C**). Handle by:
1. Report the issue: "Workspace isolation failure β€” Task N's edits landed in the default workspace instead of its workspace."
2. Skip squash for that task (changes are already in `@`)
3. Verify the content is correct by diffing against the task spec
4. Continue with remaining tasks normally

This is a known edge case β€” the WorktreeCreate hook creates the jj workspace, but the agent may resolve file paths to the main repo instead of the workspace copy.

### Recovery: Missing Change IDs

If a subagent crashes or times out before reporting its change ID, the change still exists in jj's DAG β€” it's just not referenced. Recover it by searching for the task description:
Expand All @@ -233,9 +266,17 @@ In v1, workspaces survived COLLECT and were cleaned up during FAN IN (after each

Runs once per wave, after COLLECT and before FAN IN.

### Tiered Review

Not all tasks need a full reviewer agent. Before dispatching, assess each task's complexity:

**Trivial tasks** (< 10 lines changed, no logic/control flow changes β€” e.g., visibility modifiers, import reordering, renaming): Verify inline by reading the diff yourself. Report: "Task N: trivial change (N lines), verified inline β€” PASS." No reviewer agent needed.

**Non-trivial tasks** (logic changes, new functions, structural modifications): Dispatch a spec reviewer subagent as below.

### Spec Reviewer Dispatch

For each DONE or DONE_WITH_CONCERNS task, dispatch a spec reviewer subagent. Spec reviewers run in the orchestrator's context (no `isolation: "worktree"`) β€” they are read-only, using `jj diff -r` and `jj file show -r` to inspect changes by change ID. All reviewers for the wave run in parallel and cannot conflict.
For each non-trivial DONE or DONE_WITH_CONCERNS task, dispatch a spec reviewer subagent. Spec reviewers run in the orchestrator's context (no `isolation: "worktree"`) β€” they are read-only, using `jj diff -r` and `jj file show -r` to inspect changes by change ID. All reviewers for the wave run in parallel and cannot conflict.

Use the template at `./fan-flames-spec-reviewer.md` to construct each reviewer prompt. Fill in:
- `[FULL TEXT of task requirements from plan]` β€” the complete task text
Expand All @@ -253,7 +294,7 @@ Use the template at `./fan-flames-spec-reviewer.md` to construct each reviewer p

When a spec reviewer returns FAIL:

1. Dispatch fix subagent **without** `isolation: "worktree"` (the workspace already exists β€” `isolation` would create a new one). Tell the subagent to work in the existing workspace directory path (e.g., `.claude/workspaces/<task-name>/`) and provide the reviewer's specific findings
1. Dispatch fix subagent **without** `isolation: "worktree"` (the workspace already exists β€” `isolation` would create a new one). Tell the subagent to work in the existing workspace directory path (e.g., `/tmp/jj-workspaces/<project>/<task-name>/`) and provide the reviewer's specific findings
2. Fix subagent uses the same implementer protocol (DONE / BLOCKED / NEEDS_CONTEXT)
3. Re-dispatch spec reviewer for that task only (same template, updated implementer report)
4. Repeat until PASS
Expand Down Expand Up @@ -341,7 +382,7 @@ jj workspace list # default workspace should be marked
1. **Squash into the default workspace:**

```bash
jj squash --from <change-id> --into @
JJ_EDITOR=true jj squash --from <change-id> --into @
```

2. **Check for conflicts:**
Expand Down
Loading