Skip to content
Open
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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Invoke them by name (e.g., `/office-hours`).
| `/autoplan` | One command runs CEO → design → eng → DX review. |
| `/design-consultation` | Build a complete design system from scratch. |
| `/spec` | Turn vague intent into a precise, executable spec in five phases. Files a GitHub issue, optionally spawns a Claude Code agent in a fresh worktree, and lets `/ship` close the source issue on merge. |
| `/fanout` | Take a finished design doc and decompose it into N parallel agent tasks. Identifies Slab 0 (shared groundwork) plus 2-3 independent slabs, appends a Parallel Execution Plan section to the doc, and emits a `worktree-dispatch.sh` sidecar. v0 produces the plan and stops; user runs the script. |

### Implementation + review

Expand Down
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# Changelog

## [1.53.0.0] - 2026-05-27

**New skill: `/fanout` decomposes a finished design doc into 2-3 parallel agent tasks.**
**Worktree dispatch script generated alongside. Plan stops short of spawning agents in v0.**

After `/office-hours` + eng-review + `/design-consultation` produces a design doc, the bottleneck is execution: one agent works through the whole doc serially. `/fanout docs/designs/MY_FEATURE.md` reads the doc, identifies independent slabs of work via a 4-layer heuristic (numbered phases → implementation subsections → file-reference tables → natural seams), promotes shared groundwork to a synchronous Slab 0, builds a slab matrix with verification gates, and writes a `## Parallel Execution Plan` section back to the doc. Alongside it, a `worktree-dispatch.sh` script with Slab 0 ready to run and Slabs 1-N commented out (uncommented manually after Slab 0 lands on main).

### The shape of the win

No production benchmarks yet — this is a v0 release. The structural argument:

- Serial implementation of a 3-subsystem design doc waits on one agent finishing each subsystem in sequence.
- Parallel implementation runs three agents concurrently after a brief Slab 0 (shared groundwork) lands. Wall-clock collapses to `Slab 0 time + max(slab times)` instead of the sum.
- The 4-layer slab detection heuristic + explicit Slab 0 promotion is the structural defense against the failure mode where three parallel agents trip over the same shared type file.

Real numbers will land in v1 with the first production runs and a paid E2E eval. Until then, the win is qualitative: it turns "wait for one agent" into "wait for the slowest of three."

### What this means for builders

If your team or your single instance of Claude Code is sitting on a finished design doc that touches 3+ subsystems, `/fanout` turns it into 2-3 worktrees you can dispatch in parallel. Read the appended section, run the script, and let Slab 0 land before uncommenting the rest. Caps at 3 slabs by default because more is usually false parallelism. Pure prompt-based skill, no new binaries, no eval cost.

### Itemized changes

#### Added
- `/fanout` skill at `fanout/SKILL.md.tmpl` and generated `fanout/SKILL.md`.
- Free `bun test` fixture at `test/fanout.test.ts` validates frontmatter and section structure.
- `/fanout` routing line added to `CLAUDE.md` "Skill routing" section.
- `/fanout` entry added to `README.md` skill table and install-snippet skill list.

#### For contributors
- Design doc at [`docs/designs/FANOUT.md`](docs/designs/FANOUT.md) documents the 4-layer slab detection heuristic, Slab 0 promotion logic, conflict resolution rules, and edge cases.
- No new infrastructure: skill is auto-discovered by `setup` via the existing top-level-directory glob at [setup:620-633](setup).

## [1.52.1.0] - 2026-05-27

## **Brain-aware planning lands. Five planning skills read structured context from any personal gbrain before asking — same questions, smarter answers, no token tax.**
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ Key routing rules:
- Architecture → invoke /plan-eng-review
- Design system/plan review → invoke /design-consultation or /plan-design-review
- Full review pipeline → invoke /autoplan
- Parallel execution of finished design doc → invoke /fanout
- Bugs/errors → invoke /investigate
- QA/testing site behavior → invoke /qa or /qa-only
- Code review/diff check → invoke /review
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Fork it. Improve it. Make it yours. And if you want to hate on free open source

Open Claude Code and paste this. Claude does the rest.

> Install gstack: run **`git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/.claude/skills/gstack && cd ~/.claude/skills/gstack && ./setup`** then add a "gstack" section to CLAUDE.md that says to use the /browse skill from gstack for all web browsing, never use mcp\_\_claude-in-chrome\_\_\* tools, and lists the available skills: /office-hours, /plan-ceo-review, /plan-eng-review, /plan-design-review, /design-consultation, /design-shotgun, /design-html, /review, /ship, /land-and-deploy, /canary, /benchmark, /browse, /connect-chrome, /qa, /qa-only, /design-review, /setup-browser-cookies, /setup-deploy, /setup-gbrain, /retro, /investigate, /document-release, /document-generate, /codex, /cso, /autoplan, /plan-devex-review, /devex-review, /careful, /freeze, /guard, /unfreeze, /gstack-upgrade, /learn. Then ask the user if they also want to add gstack to the current project so teammates get it.
> Install gstack: run **`git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/.claude/skills/gstack && cd ~/.claude/skills/gstack && ./setup`** then add a "gstack" section to CLAUDE.md that says to use the /browse skill from gstack for all web browsing, never use mcp\_\_claude-in-chrome\_\_\* tools, and lists the available skills: /office-hours, /plan-ceo-review, /plan-eng-review, /plan-design-review, /design-consultation, /design-shotgun, /design-html, /review, /ship, /land-and-deploy, /canary, /benchmark, /browse, /connect-chrome, /qa, /qa-only, /design-review, /setup-browser-cookies, /setup-deploy, /setup-gbrain, /retro, /investigate, /document-release, /document-generate, /codex, /cso, /autoplan, /fanout, /plan-devex-review, /devex-review, /careful, /freeze, /guard, /unfreeze, /gstack-upgrade, /learn. Then ask the user if they also want to add gstack to the current project so teammates get it.

### Step 2: Team mode — auto-update for shared repos (recommended)

Expand Down Expand Up @@ -205,6 +205,7 @@ Each skill feeds into the next. `/office-hours` writes a design doc that `/plan-
| `/setup-browser-cookies` | **Session Manager** | Import cookies from your real browser (Chrome, Arc, Brave, Edge) into the headless session. Test authenticated pages. |
| `/autoplan` | **Review Pipeline** | One command, fully reviewed plan. Runs CEO → design → eng review automatically with encoded decision principles. Surfaces only taste decisions for your approval. |
| `/spec` | **Spec Author** | Turn vague intent into a precise, executable spec in five phases (why, scope, technical with mandatory code-reading, draft, file). Codex quality gate before file (blocks below 7/10), fail-closed secret redaction, dedupe against existing issues, archive to `$GSTACK_STATE_ROOT/projects/$SLUG/specs/` for team-corpus recall. `--execute` spawns `claude -p` in a fresh worktree; `/ship` auto-closes the source issue on merge. Plan-mode aware. |
| `/fanout` | **Multi-agent Dispatcher** | Take a finished design doc and decompose it into N parallel agent tasks. Identifies Slab 0 (shared groundwork) plus 2-3 independent slabs, writes a Parallel Execution Plan section back to the doc, and emits a `worktree-dispatch.sh` sidecar. v0 produces the plan and stops; user runs the script. |
| `/learn` | **Memory** | Manage what gstack learned across sessions. Review, search, prune, and export project-specific patterns, pitfalls, and preferences. Learnings compound across sessions so gstack gets smarter on your codebase over time. |

### Which review should I use?
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.52.1.0
1.53.0.0
199 changes: 199 additions & 0 deletions docs/designs/FANOUT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# /fanout — Design Doc

**Status:** v0 proposal (not yet implemented).
**Author:** sohmn, with AI-assisted brainstorming via Claude Opus 4.7.
**Target reviewer:** Garry Tan (PR review).
**Scope:** New gstack skill. No changes to existing skills.

## Problem

The current "vague idea → working code" path in gstack runs serially:

1. `/office-hours` explores the idea, validates it's worth building.
2. `/plan-eng-review` (or `/autoplan`) reviews architecture.
3. Author writes a design doc to `docs/designs/`.
4. A single agent picks up the design doc and implements it.

Step 4 is the bottleneck. A finished design doc with 3 independent subsystems still runs one agent at a time, end to end. Modern design docs commonly describe work that is structurally parallelizable: backend + frontend, schema migration + business logic + UI, API surface + client + CLI. The serial flow leaves wall-clock time on the table.

`/spec` already exists and handles a different shape of the problem: vague intent → filed GitHub issue → single agent via `--execute`. It does not consume an existing design doc and it does not fan out across multiple agents.

The gap: nothing in gstack takes a finished design doc and turns it into N parallel agent tasks.

## Why now

The user has run office-hours + eng-review + design enough times to feel the wall-clock cost of single-agent execution. Worktrees + multiple `claude -p` instances are already part of the gstack toolkit (used by `/ship`, `/spec --execute`, plan-review skills). The plumbing is there. What's missing is the orchestration layer that decides which slabs of a design doc are independent and emits the dispatch commands.

This is a small surface area: read a markdown file, identify slabs, write a section back to the file, write a shell script next to it. No new infrastructure, no new binaries, no eval cost.

## Scope for v0

The MVP is intentionally narrow. It produces the plan and stops. The user runs the dispatch script themselves when ready.

1. **New skill `/fanout`** in `fanout/SKILL.md.tmpl`. Generated `fanout/SKILL.md` via `bun run gen:skill-docs`.
2. **Single invocation form:** `/fanout <path-to-design-doc>`. Markdown file paths only in v0. GitHub issue URLs deferred.
3. **In-place append.** Skill writes a new `## Parallel Execution Plan` section to the bottom of the input file.
4. **Sidecar dispatch script.** Skill writes `worktree-dispatch.sh` next to the design doc, executable, with Slab 0 ready to run and Slabs 1-N commented out.
5. **No auto-execution.** v0 never calls `git worktree add` or `claude -p`. User runs the script when Slab 0 lands.
6. **Cap at 3 slabs.** Default `--max 3`. Override via `--max N`. Reasoning: more than 3 parallel agents on a single design is usually false parallelism. Coordination overhead eats the wins.

## Skill design

### Invocation

```
/fanout docs/designs/MY_FEATURE.md
/fanout docs/designs/MY_FEATURE.md --max 5
```

### Process

The skill runs as a single-phase agent prompt (no AskUserQuestion ping-pong unless a conflict needs disambiguation):

1. **Read the file.** Fail fast if the path doesn't exist or isn't markdown.
2. **Parse structure.** Look for slab candidates in this order:
- `## Phase N` / `## Part N` / `## Component N` headers
- `## Implementation Details` subsections
- "Files Reference" tables (cluster files by top-level directory)
- Natural seams (backend/frontend, schema/logic/UI, API/client/CLI)
3. **Identify Slab 0.** Scan for shared groundwork: type definitions, schema migrations, fixtures, shared constants, public interfaces. Anything referenced by 2+ slab candidates goes to Slab 0.
4. **Build slab matrix.** For each non-Slab-0 candidate, compute Writes / Reads / Public interface / Verification gate / ETA.
5. **Detect conflicts.** Any file that two slabs both write to is a conflict. Resolution order:
- If the file is type/schema/constant: promote to Slab 0.
- Otherwise: AskUserQuestion to pick which slab owns the file (or merge the two slabs).
6. **Enforce the slab cap.** If parsing yielded more slabs than `--max`, propose a merge: combine the two smallest by ETA, repeat until at or under the cap. AskUserQuestion before committing each merge so the user can veto a bad pairing.
7. **Write the section.** Append `## Parallel Execution Plan` to the design doc.
8. **Write the dispatch script.** Generate `worktree-dispatch.sh` next to the doc.
9. **Report.** One paragraph summary: N slabs identified, Slab 0 has X files, estimated wall-clock from M hours serial to K hours parallel.

### Output: `## Parallel Execution Plan` section template

```markdown
## Parallel Execution Plan

### Slab 0 — Synchronous prep

**Lands first.** One agent, single PR, ~30 min.

- **Writes:** [interfaces, types, schema migrations, fixtures, shared constants]
- **Verification gate:** [what proves Slab 0 is integratable — usually "tests pass + types compile"]

### Slab matrix

| # | Slab | Writes | Reads | Public interface | Verification gate | ETA |
|---|------|--------|-------|------------------|-------------------|-----|
| 1 | <name> | `path/a.ts`, `path/b.ts` | Slab 0: `types.ts` | exports `Foo` | `bun test path/a.test.ts` | 1h |
| 2 | <name> | `path/c.ts` | Slab 0: `types.ts` | exports `Bar` | `bun test path/c.test.ts` | 1.5h |
| 3 | <name> | `path/d.tsx` | Slab 0: `types.ts` | UI route `/x` | screenshot diff | 2h |

**Cross-slab reads (Slab N reads Slab M's output, M > 0) break parallelism.** When `/fanout` detects one, it picks one of three resolutions and asks the user to confirm: (a) promote Slab M's interface to Slab 0; (b) merge the two slabs; (c) accept the dependency and chain them in Merge order. Option (a) is the default proposal because it preserves the most parallelism.

### Conflict map

*(empty if no file is touched by 2+ slabs after Slab 0 promotion)*

### Merge order

1. Slab 0 → main (blocking).
2. Slabs 1, 2, 3 → rebase on Slab 0 after it lands. Any order.
3. Resolve CHANGELOG.md / VERSION conflicts via standard gstack queue rules.

### Dispatch

See [`worktree-dispatch.sh`](./worktree-dispatch.sh). Run Slab 0 first, wait for it to land on main, then uncomment Slabs 1-N and run in parallel.
```

### Output: `worktree-dispatch.sh` template

```bash
#!/usr/bin/env bash
# Generated by /fanout from <design-doc-path> on <date>.
# Step 1: Run Slab 0. Wait for it to land on main.
# Step 2: Uncomment Slabs 1-N. Run them in parallel.

set -e
cd "$(git rev-parse --show-toplevel)"

# Slab 0 — Synchronous prep
git worktree add ../<repo>-slab-0 -b slab-0/<topic>
(
cd ../<repo>-slab-0
claude -p "$(cat <<'EOF'
Read <design-doc-path>. Implement Slab 0 from the Parallel Execution Plan section:
- Writes: <files>
- Verification gate: <gate>
When the gate passes, commit, push, and open a PR via /ship.
EOF
)"
)

# After Slab 0 lands on main, uncomment and run these in parallel:
#
# git worktree add ../<repo>-slab-1 -b slab-1/<topic>
# (cd ../<repo>-slab-1 && claude -p "...Slab 1 prompt...") &
#
# git worktree add ../<repo>-slab-2 -b slab-2/<topic>
# (cd ../<repo>-slab-2 && claude -p "...Slab 2 prompt...") &
#
# git worktree add ../<repo>-slab-3 -b slab-3/<topic>
# (cd ../<repo>-slab-3 && claude -p "...Slab 3 prompt...") &
#
# wait
```

The commented-out lines for Slabs 1-N are intentional. Auto-running them before Slab 0 lands would have every parallel agent fighting over uncommitted shared types. The commented form makes the dependency explicit.

## Edge cases

1. **Design doc has no parsable structure.** Skill falls back to AskUserQuestion: "I couldn't auto-identify slabs. Want to walk through this interactively, or stop?"
2. **Only one slab identified.** Skill reports "this design doesn't decompose, single-agent execution recommended" and exits without writing the section or script.
3. **Slab 0 is empty.** Possible for designs where slabs share nothing. Section still gets written, Slab 0 row reads "None, no shared groundwork detected." The "lands first, blocking" semantics drop: Slabs 1-N can run in parallel from the start. Dispatch script reflects this by uncommenting Slabs 1-N immediately and omitting the Slab 0 worktree.
4. **All slabs write to one file.** Common for design docs that touch a single large file. Skill detects this and recommends "this isn't parallelizable as written. Either decompose the file first or accept single-agent execution."
5. **Design doc already has a `## Parallel Execution Plan` section.** Skill detects, AskUserQuestion: overwrite, append a v2, or abort?
6. **User passes a non-markdown file.** Hard fail with clear error.

## Out of scope (v0)

- GitHub issue URLs as input.
- Auto-spawning agents (`--execute` flag deferred to v1).
- Interactive dispatch (per-slab "spawn now?" prompts deferred to v1).
- Cross-repo slabs (all slabs assumed to be in the current repo).
- Re-running `/fanout` to update an existing plan after the design doc changes.
- Eval coverage. Skill is deterministic enough that a free `bun test` fixture is sufficient; paid E2E deferred until v1 adds dispatch.

## Files in the PR

```
fanout/
├── SKILL.md.tmpl (new)
└── SKILL.md (generated by bun run gen:skill-docs)

CHANGELOG.md (new entry at top, release-summary format)
VERSION (MINOR bump — new user-facing capability)
README.md (one-line addition to skill list)
CLAUDE.md (one-line addition to "Skill routing" section)
setup (symlink line for fanout/, matches qa/, spec/, etc.)
test/ (optional free test fixture for matrix-shape sanity)
```

No changes to `browse/`, `design/`, hosts/, or any existing skill template.

## CHANGELOG + VERSION

MINOR bump (new capability shipped, scale-aware bump per CLAUDE.md guidance). Release-summary section follows the format in CLAUDE.md: two-line bold headline, lead paragraph, "The numbers that matter" table (slabs identified per doc, estimated time saved vs serial), and "What this means for builders" closer. Itemized changes go in a separate `### Itemized changes` block below.

Voice: gstack direct, no em dashes, no AI vocabulary, real file names. Headline frames the wall-clock win, not the technical mechanism.

## Open questions

1. **Should `worktree-dispatch.sh` write to a non-default location?** Sitting next to the design doc means `docs/designs/worktree-dispatch.sh`. That directory becomes cluttered if multiple designs run `/fanout`. Alternative: `~/.gstack-dev/dispatch/<doc-name>.sh`. v0 choice: alongside the doc for visibility. Revisit if it becomes noisy.
2. **Slab naming convention.** `slab-0`, `slab-1` for branches is generic. Better to derive from the slab's content (`slab-schema-migration`, `slab-ui`). v0 choice: descriptive names derived from slab title, with `slab-` prefix.
3. **What if the user runs `/fanout` on a design doc that was authored by `/spec`?** `/spec` outputs to GitHub issues, not files. v0 only handles files. If user pulls a `/spec`-authored issue body into a markdown file first, `/fanout` works on it normally. Documented in the skill prompt.

## Definition of done

1. `/fanout docs/designs/SOMETHING.md` runs to completion on a real design doc and produces a valid Parallel Execution Plan section + dispatch script.
2. Generated SKILL.md passes `bun test` (skill validation + gen-skill-docs quality checks).
3. CHANGELOG entry follows the release-summary format. VERSION bumped MINOR.
4. README + CLAUDE.md routing lines added.
5. PR review pass via `/review`. No regressions to existing skills.
Loading