# Workstreams

> Decompose implementation tasks into parallel workstreams, analyze their dependency graph, and dispatch agents in worktree isolation. Use this skill when the user asks to 'implement these changes', 'parallelize this work', 'dispatch workstreams', or invokes '/workstreams'.

- Skill: `collinthefarmer/workstreams` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add collinthefarmer/workstreams`
- Raw SKILL.md: https://api.skillmd.com/api/skills/collinthefarmer/workstreams/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: collinthefarmer (https://skillmd.com/u/collinthefarmer)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/collinthefarmer/workstreams

---


# Workstreams — Parallel Implementation Dispatch

Decompose work items into dependency-aware workstreams, dispatch agents in worktree isolation, and coordinate merges. This is the implementation counterpart to `/critique`.

You ARE the orchestrator. Follow these phases in order.

## Setup

Resolve paths once before starting:

```
LIB=~/.claude/skills/lib/claude-lib.sh
```

## Argument Parsing

| Argument | Form | Default |
|----------|------|---------|
| source | Bare path to a file containing work items (e.g., critique output) | from conversation context |
| `--items` | Comma-separated work item seeds | from context |
| `--max-parallel` | Integer | `4` |
| `--auto-merge` | Flag | false (confirm each merge with user) |
| `--dry-run` | Flag | Phases 0-2 only, no dispatch |
| `--test-cmd` | String | auto-detect |
| `--skip-negotiation` | Flag | false |
| `--max-items-per-stream` | Integer | `5` |
| `--streams` | JSON or natural language stream definitions | skip to Phase 3 |

## Lightweight Dispatch Mode

**When `--streams` is provided, or the user's message already specifies the decomposition** (e.g., "dispatch three agents: one for X, one for Y, one for Z"), skip Phases 0–2 and jump directly to Phase 3.

In this mode:

1. Parse the stream definitions from the argument or conversation. Each stream needs at minimum: a name and a description of what to do. File lists are optional — agents will figure it out.
2. Run `workspace prune` to clear stale branches from prior sessions:
   ```bash
   bash "$LIB" workspace prune
   ```
3. If any files appear in multiple streams' descriptions, run Phase 1.5 (shared file pre-editing) before dispatch.
4. Proceed to Phase 3 (workspace setup + agent dispatch).
5. After collection, proceed to Phase 4 as normal.

This mode is for users who have already done the thinking and just want the parallelism. Don't second-guess their decomposition — dispatch what they asked for.

## Phase 0: Intake

### Step 0: Clean stale workspaces

```bash
bash "$LIB" workspace prune
```

Remove orphaned branches and worktrees from prior sessions before starting.

### Step 1: Survey the project

```bash
bash "$LIB" survey <project_root>
```

Read the JSON output for project profile.

### Step 2: Gather work items

Identify work items from one of these sources (in priority order):

1. **Conversation context** — if `/critique` was run earlier, extract its recommendations and cross-cutting themes.
2. **Source file argument** — if a file path was provided, read it and extract actionable items.
3. **`--items` flag** — use as seeds. Read the codebase to expand them into concrete changes.

### Step 3: Classify each work item

For each item, determine all of the following:

| Field | Description |
|-------|-------------|
| `id` | Short slug (e.g., `add-handler-tests`) |
| `type` | `additive` (new files only), `body` (logic changes, not signatures), `interface` (type/API changes), or `refactor` (moves, renames) |
| `reads` | Files the item imports from or depends on |
| `writes` | Files the item will create or modify |
| `description` | What changes and why (1-2 sentences) |
| `size` | `small` (<50 lines), `medium` (50-200), `large` (200+) |

Classification requires reading the actual source files to understand what kind of change each item involves. Read the target files before classifying.

**Classification parallelism:** If the total files to read for classification is under 20, classify inline or with 1-2 agents. Reserve 4+ classification agents for larger projects where the read set is genuinely large. Over-parallelizing small read sets wastes agent overhead.

**Output:** A JSON array of 3-20 classified work items.

**Time budget:** Under 60 seconds.

## Phase 1: Dependency Analysis

### Step 1: Run deps

Pipe the classified work items to the deps script:

```bash
echo '<work_items_json>' | bash "$LIB" deps
```

This returns:
- `conflicts` — pairs of items with shared writes, hard deps, or soft deps
- `suggested_streams` — items clustered by write conflicts (union-find)
- `ordering` — topologically sorted parallel groups

### Step 2: Refine the groupings

Review the script's output and adjust:

- **Conceptual cohesion** — items addressing the same theme belong together even without file conflicts.
- **Stream size** — split streams exceeding `--max-items-per-stream` (default 5).
- **Naming** — replace `stream-1` with descriptive names (`test-coverage`, `resource-cleanup`, `type-hardening`).
- **Edge overrides** — the LLM may override an edge type if it understands the change is mechanical (e.g., "this interface change is just a rename, treat as soft").

### Step 3: Finalize the DAG

Produce the final dispatch plan: named workstreams, parallel groups, ordering, and dependency rationale.

### Step 4: Prepare context seeding

Agents waste tokens re-reading files the orchestrator already read during classification. Identify each stream's read set — the files an agent will need to understand before making changes. These will be pre-seeded into each worktree during Phase 3 setup.

For each stream, build a `context` list: the files from its `reads` set, plus any shared foundational files (types, interfaces) that appear in 2+ streams. These files will be concatenated into a `.context.md` file in each worktree by `workspace setup`.

## Phase 1.5: Shared File Pre-Editing

### Purpose

Files written by multiple work items ("registry files" — e.g., index files, setup modules, token registrations) cause merge conflicts when agents edit them in parallel. Instead of serializing all writers into one stream, the orchestrator edits these files itself before dispatch, removing them from agents' write sets so the remaining work can parallelize.

This phase also **asserts Edit permissions early**. If the user's permission mode requires approval for file edits, the orchestrator triggers that approval now — not mid-agent-run where a denial wastes an agent's work.

### Step 1: Identify shared files

The `deps` output includes a `shared_files` array:

```json
{
  "shared_files": [
    {"file": "src/setup.ts", "writers": ["extract-audio", "extract-canvas", "extract-events"], "writer_count": 3}
  ]
}
```

Any file with `writer_count >= 2` is a candidate.

### Step 2: Classify the shared edits

For each shared file, read it and determine what each work item needs to add:

| Pattern | Example | Pre-edit strategy |
|---------|---------|-------------------|
| **Import + registration** | Adding a line to an index/barrel file, registering a token | Orchestrator adds all imports and registrations now |
| **Config addition** | Adding entries to a config object or array | Orchestrator adds all entries now |
| **Structural change** | Multiple items rewriting the same function body | Cannot pre-edit — force these items into one stream |

For the first two patterns, make the edits directly using the Edit tool. For the third, leave the items clustered.

### Step 3: Update write sets

After pre-editing, remove the shared file from each item's `writes` array. Then re-run `deps` with the updated items:

```bash
echo '<updated_items_json>' | bash "$LIB" deps
```

The new output will have fewer conflicts and more parallelism. Use this output for Phase 2 onward.

### Step 4: Record pre-edits

Keep a list of files the orchestrator pre-edited and what was added. Include this in each agent's prompt so they know:
- The file has already been modified — do not overwrite the orchestrator's additions
- Their service/module/component is already imported and registered — they only need to create the implementation file

## Phase 2: Plan Negotiation

**Skip this phase if `--skip-negotiation` was passed.**

Present the dispatch plan:

```
## Dispatch Plan

### Parallel Group 1 (launch immediately)

**Stream A: Test Coverage** — additive
  Items: add-handler-tests, add-extraction-tests
  Writes: tests/api/handler.test.ts, tests/extraction.test.ts
  Reads: src/api/handler.ts, src/extraction.ts

**Stream B: Resource Cleanup** — body
  Items: add-sigterm-handler, add-tempfile-cleanup
  Writes: src/server.ts, src/extraction.ts
  Reads: src/config.ts

### Parallel Group 2 (after Group 1 merges)

**Stream C: Branded Types** — interface
  Items: brand-dimension-ids, brand-manifest-ids
  Writes: src/types.ts, src/api/handler.ts, src/models/dimension.ts
  Depends on: A (hard — changes type signatures imported by A's new tests)

### Dependency Rationale
- A and B are independent: no shared write targets, additive and body types.
- C depends on A: branded types change signatures that A's new tests import.
```

**Decision points for the user:**
- Approve, merge/split streams, reorder groups, drop items
- Promote soft dep to independent (accept merge cost)
- Demote independent to sequenced (reduce risk)

**Wait for user confirmation before proceeding.**

If `--test-cmd` was not provided, also confirm the test command. Auto-detect from root files:
- `package.json` -> `npm test`
- `Makefile` with test target -> `make test`
- `pyproject.toml` -> `pytest`
- `Cargo.toml` -> `cargo test`
- `go.mod` -> `go test ./...`

Ask the user: "I'll have agents run `<detected-cmd>` to verify their work. Correct?"

If `--dry-run` was passed, **stop here**. Present the plan and exit.

## Phase 3: Dispatch

### Step 1: Create workspaces

Pass the stream definitions with their context file lists from Phase 1 Step 4:

```bash
echo '<streams_json>' | bash "$LIB" workspace setup --json
```

Input:
```json
[
  {"name": "test-coverage", "context": ["src/types.ts", "src/api/handler.ts"]},
  {"name": "resource-cleanup", "context": ["src/types.ts", "src/config.ts"]}
]
```

This creates all worktrees sequentially, write-tests each, and seeds a `.context.md` file in each worktree containing the pre-read source files. Returns JSON:

```json
{"workspaces": [{"name": "...", "path": "...", "branch": "...", "status": "ok", "context_seeded": true}], "all_ok": true}
```

If `all_ok` is false, stop and tell the user which workspace failed and why.

### Step 2: Dispatch and collect

Call the `Workflow` tool with an inline script that fans out one agent per stream in the current parallel group, using `parallel()`, and collects each stream's structured completion report in one call.

```js
export const meta = {
  name: 'workstream-dispatch',
  description: 'Dispatch implementation agents for one parallel group of workstreams',
  phases: [{ title: 'Implement' }],
}

const REPORT_SCHEMA = {
  type: 'object',
  properties: {
    filesChanged: { type: 'array', items: { type: 'string' } },
    filesAdded: { type: 'array', items: { type: 'string' } },
    testsPass: { type: 'boolean' },
    issues: { type: 'string' },
  },
  required: ['filesChanged', 'filesAdded', 'testsPass'],
}

const results = await parallel(args.streams.map(s => () => {
  const opts = { label: s.name, agentType: 'general-purpose', schema: REPORT_SCHEMA }
  if (s.model) opts.model = s.model
  if (s.effort) opts.effort = s.effort
  return agent(s.prompt, opts).then(result => result && ({ stream: s.name, ...result }))
}))

return results.filter(Boolean)
```

Pass `args: { streams: [{name, prompt, model?, effort?}, ...] }` for every stream in the current parallel group, where `prompt` is built from the template below and `model`/`effort` are set per the rule below. Do NOT pass `isolation: "worktree"` on the `agent()` calls — workspaces are already pre-created by `workspace setup` in Step 1; each stream's prompt names its own workspace path instead.

### Model selection

Set `model` and `effort` per stream using your own judgment of its difficulty — not mechanically off `size`/`type` alone. Those classifications measure change footprint, not how hard the implementation judgment is. A `size: small` stream can still be a subtle concurrency fix; a `size: large` one can be pure boilerplate.

- **Default: omit both fields.** This is correct for most streams — the session's default model/effort is the safe fallback.
- **Set `model: "haiku"` only when you're confident the stream is genuinely mechanical** — scaffolding that mirrors an existing pattern, tests that follow an established shape — not just because it's classified `small`/`additive`.
- **Set `effort: "high"` when the stream touches interfaces/refactors with wide blast radius, or where correctness is easy to get subtly wrong** — concurrency, auth, data migration, shared state — regardless of size.

Bias toward omitting `model` over downgrading it: a wrong downgrade risks a stream landing with subtle bugs and no signal anything went wrong, while a wrong effort bump just costs more for no harm.

**Agent prompt template:**

> **Context:** {2-3 sentences about the project — root path, languages, size.}
>
> **Worktree:** Your working directory is `{workspace-path}`. All file reads and writes must use paths under this directory. Do not modify files in the main repo.
>
> **Pre-seeded context:** Read `{workspace-path}/.context.md` before starting — it contains the source files you'll need for orientation. Do not re-read files that are already in the context file.
>
> **Assignment:** Implement the following changes:
> - {item 1: description, target files}
> - {item 2: description, target files}
>
> **Boundary:** You own these files (may create or modify): {write set}. If you need to modify a file outside your boundary, note it in your report and stop.
>
> **Pre-edited files (do not overwrite):** {If Phase 1.5 pre-edited files, list them here with a summary of what was added. E.g.: "The orchestrator already added `import { AudioMixService } from './audio-mix.service'` and registered the token in `setup.ts`. Do not modify `setup.ts` — just create the implementation file." Omit this section if no pre-edits were made.}
>
> **Verification:** Run `cd {workspace-path} && {test-cmd}` before reporting. Populate `testsPass` truthfully — never report `testsPass: true` with failing tests.
>
> **Commit:** Before reporting completion, stage and commit your changes:
> `cd {workspace-path} && git add -A && git commit -m "workstream: {stream-name}"`
>
> **Completion report:** Populate `filesChanged`, `filesAdded`, `testsPass`, and `issues` (empty string if none).

**Dispatch rules:**
- Never include more than `--max-parallel` streams (default 4) in one `args.streams` call.
- Never dispatch two streams writing to the same file.
- Always include the workspace path and test command in each stream's prompt.

Tell the user briefly: "Dispatched N agents for this group." The call runs in the background — wait for its task notification, then read the returned array before moving to per-agent validation in Phase 4.

## Phase 4: Collection & Merge

### Per-agent on completion

1. Read each stream's structured completion report from the Workflow result (`filesChanged`, `filesAdded`, `testsPass`, `issues`).
2. Validate the workspace:
   ```bash
   bash "$LIB" workspace check <stream-name>
   ```
   If `exists` is false, mark the stream as failed — do not trust the agent's report.
3. Report to user with the diff stats from the check output.

### Handling failures

- **Agent fails tests:** Report the failure. User chooses: fix, abandon, or take over.
- **Agent times out:** Mark as incomplete. Offer narrower re-dispatch.
- **Workspace missing:** Mark as failed. Offer re-dispatch.

### Per-group merge

Present each stream's check results. Propose merge order from `deps` output (`merge_order` field). **Wait for user confirmation before each merge** (unless `--auto-merge`).

For each confirmed stream:

```bash
bash "$LIB" workspace merge <stream-name> --test-cmd "<test-cmd>"
```

This merges the branch, runs tests, and cleans up the worktree on success — one call per stream. If the merge output shows `tests_pass: false` or `merged: false`, stop and surface the error.

### Partial group advancement

If some streams succeed and others fail, merge the successful ones and advance to the next group — but only if the next group's dependencies are satisfied. Failed streams must be resolved before the pipeline ends.

### Between groups

Once the current group is merged and tests pass, loop back to Phase 3 for the next group.

## Phase 5: Reconciliation

After all groups are merged (or failed streams resolved):

1. Run the full test suite: `{test-cmd}`
2. Run type checking if applicable (infer from survey).
3. Clean up any orphaned workspaces:
   ```bash
   bash "$LIB" workspace cleanup
   ```
4. Produce the delta report:

```markdown
## Workstream Results

### Stream A: {Name} — {COMPLETE|FAILED|ABANDONED}
- {Added/Modified}: {file count} ({line count} lines)
- Changes: {1-line summary}
- Issues: {none, or description}

### Integration
- Full test suite: {PASS|FAIL (details)}
- Type check: {PASS|FAIL|N/A}
- Failed streams: {count and names, or "none"}
```

## Error Recovery

| Situation | Response |
|-----------|----------|
| `workspace setup` reports `all_ok: false` | Check which workspace failed. Fix permissions or fall back to sequential execution. |
| Agent denied Write/Edit mid-run | The agent did useful research. Use its output to drive changes in the main conversation. |
| `workspace check` reports `exists: false` | Workspace lost — mark stream as failed, offer re-dispatch. |
| `workspace merge` reports `merged: false` | Merge conflict. Show error, attempt mechanical resolution, ask user if non-trivial. |
| `workspace merge` reports `tests_pass: false` | Tests broke after merge. Bisect or revert and investigate. |
| Survey or deps script fails | Fall back to manual classification. |
| All agents fail | Tell the user. No empty reconciliation report. |
| User interrupts while the Workflow dispatch is running | Workflow calls run to completion in the background; merge whatever streams have reported once it returns, note incomplete ones. |
| Orphaned workspaces after crash | `workspace cleanup` in Phase 5 catches these. |

