Skip to content

Repository files navigation

claude-plan-composer

The problem: LLM plans look good but have blind spots

Ask Claude to write an implementation plan and you'll get something impressive — well-structured, thorough-looking, and confident. Ship it to a developer and the cracks appear:

Monoculture thinking. The model gravitates toward the same patterns every time. Ask for a CLI? It picks Click. Config management? Pydantic-settings. Project structure? The same src/ layout. These aren't wrong choices, but they crowd out alternatives that might fit your constraints better. You get one perspective presented as the only reasonable option.

Under-specification of operational details. Plans describe what to deploy but hand-wave how. "Deploy to Kubernetes" without the helm flags, resource quotas, node selectors, and PVC setup that make or break a real deployment. The gap between "deploy to K8s" and a working helm install command is where most projects stall.

Over-engineering. A single session tends to add abstractions "for flexibility" — plugin systems, configuration layers, factory patterns — that increase complexity without solving the immediate problem. With no adversarial pressure, every component survives the plan review.

Training data bias. The model's knowledge is shaped by what's popular on GitHub, not what's correct for your domain. Niche tools, internal APIs, and domain-specific deployment patterns get less attention than they deserve, while well-documented mainstream tools get over-represented.

These aren't bugs in the model. They're structural consequences of generating a plan from a single perspective. A human architect doesn't produce a plan in isolation either — they get feedback, defend trade-offs, and iterate against competing views.

The approach: parallel sessions with prompt variation, then structured merge

This project forces multiple perspectives by running parallel Claude Code sessions, each with a different prompt variant that demands different trade-offs, then merging the best elements through structured comparison.

                          ┌─────────────────────┐
                          │   Your prompt file   │
                          │   (my-prompt.md)     │
                          └──────────┬──────────┘
                                     │
              ┌──────────────┬───────┼───────┬──────────────┐
              ▼              ▼       ▼       ▼              ▼
        ┌──────────┐  ┌──────────┐ ┌──────────┐  ┌──────────────┐
        │ baseline │  │simplicity│ │  depth   │  │   breadth    │
        │(no extra │  │(minimal  │ │ (deep    │  │  (wide view, │
        │ guidance)│  │  scope)  │ │ details) │  │  trade-offs) │
        └────┬─────┘  └────┬─────┘ └────┬─────┘  └──────┬───────┘
              │              │       │       │              │
              └──────────────┴───────┼───────┴──────────────┘
                                     ▼
                          ┌──────────────────────┐
                          │   Evaluate (optional)│
                          │   convergence check  │
                          │   + gap detection    │
                          └──────────┬───────────┘
                                     ▼
                          ┌──────────────────────┐
                          │     Merge phase      │
                          │     (agent-team      │
                          │      debate or       │
                          │      automated)      │
                          └──────────┬───────────┘
                                     ▼
                          ┌──────────────────────┐
                          │   Verify (optional)  │
                          │   quality gates:     │
                          │   consistency,       │
                          │   completeness,      │
                          │   actionability      │
                          └──────────┬───────────┘
                                     ▼
                          ┌──────────────────────┐
                          │    merged-plan.md    │
                          │    (human review)    │
                          └──────────────────────┘

Phase 1 — Generate. Multiple claude -p sessions run in parallel (default: 4, configurable in config.yaml), each receiving the same base prompt plus a variant instruction that forces a specific lens:

  • Baseline: No extra guidance — the model's default interpretation
  • Simplicity: "Find the smallest possible scope. Question whether each element is needed."
  • Depth: "Go deep on specifics. Show detailed examples, exact steps, concrete patterns."
  • Breadth: "Take a wide view. Consider alternative approaches, trade-offs, and second-order effects."

Optional: --auto-lenses generates task-specific lenses via LLM instead of using config variants. --sequential-diversity runs variants in two waves — wave 2 gets skeleton outlines from wave 1 as a structural diversity constraint.

Phase 2 — Evaluate (optional). evaluate-plans.sh analyzes generated plans before merging. A zero-cost convergence check computes pairwise Jaccard similarity of section headings. An optional LLM pass (default: haiku) produces a coverage matrix and gap detection.

Phase 3 — Merge. A separate Claude session (or an Agent Teams debate with competing advocates) compares all plans dimension by dimension and synthesizes a merged plan. The merge uses a 3-phase prompt: Analysis (with conflict classification), Synthesis (with minority insight scanning), and Constitutional Review against quality principles. Supports holistic comparison (default) or pairwise tournament scoring.

Phase 4 — Verify (optional). verify-plan.sh runs the merged plan through three quality gates: consistency (no internal contradictions), completeness (no content lost from source plans), and actionability (concrete next steps in every section). Optional --pre-mortem flag adds failure scenario analysis.

Phase 5 — Review. The merged plan is a file on disk. A human reads it, iterates, and adopts it.

The critical insight: diversity comes from prompt variation, not from repetition. Running the same prompt 10 times produces 10 similar plans with correlated errors. Running N variants (default: 4) that force different trade-offs produces genuinely different perspectives.

Why this works (grounded in research)

This isn't a heuristic — the approach is grounded in specific findings from LLM ensemble research:

Same-model runs share blind spots. Correlated Errors in Large Language Models (2025) found that models from the same architecture agree on 60% of their errors. Running the same prompt N times is like polling twins, not strangers. The "wisdom of crowds" only works when evaluators make independent errors — same-model LLM runs don't qualify.

Diminishing returns from repetition, not from variation. Best-of-N sampling follows a logarithmic curve: N=3-4 captures ~80% of the total possible gain, while N=8+ adds mostly noise. Self-MoA (Li et al., 2025, Princeton) showed that multiple runs of the single best model outperforms mixing different models by 6.6% on AlpacaEval — quality beats diversity from weaker sources. This justifies using 4 Opus sessions rather than mixing Opus + Sonnet + Haiku.

Prompt variation manufactures the diversity the model can't produce on its own. Doshi et al. (2024) found that "different prompts shift the model's attention to various aspects of the input, influencing the final output." Simplicity vs. depth vs. breadth aren't cosmetic differences — they force the model into genuinely different trade-off spaces.

There's a hard ceiling on same-prompt diversity. A PNAS study on structural diversity in LLM outputs found that LLM-generated text contains repetitive combinations of structural elements. After 3-4 runs of the same prompt, you've exhausted the space of meaningfully different structural choices.

Merge complexity explodes beyond 4-6 plans. Comparing 4 plans requires 6 pairwise comparisons (manageable for a human or LLM). 8 plans = 28 pairs. 10 plans = 45 pairs. The merge quality degrades as N increases, even if individual plans are good. 4 variants is the sweet spot: enough diversity, still mergeable.

Parallel Claude at scale is proven. Anthropic's own engineering team used 16 parallel Claude agents across 2000 sessions to build a C compiler. The incident.io team documented shipping faster with parallel Claude Code and git worktrees. This project applies the same principle to planning, not coding.

What's in this repo

Five bash scripts, a test suite, and a research directory:

File Purpose
generate-plans.sh Launches parallel claude -p sessions with prompt variants (default: 4, configurable). Supports --auto-lenses and --sequential-diversity.
evaluate-plans.sh Pre-merge plan analysis: zero-cost convergence check (Jaccard similarity) + optional LLM evaluation (coverage matrix, gap detection).
merge-plans.sh Merges generated plans. Agent Teams debate (default) or headless merge. Supports holistic or pairwise tournament comparison.
verify-plan.sh Post-merge quality gates: consistency, completeness, actionability. Optional --pre-mortem failure analysis.
monitor-sessions.sh Real-time dashboard for running sessions — tracks PIDs, token usage, context window, subagents, tool calls, and last action.
examples/ Example prompts: CLI tool, REST migration, docs overhaul. Includes a sample merged plan.
test/ 44 unit tests (bats) + e2e pipeline test. Unit tests are fast and free; e2e calls the Claude API.
research/ Analysis documents that informed the design decisions (optimal N, methodology improvements with 50+ references).
AGENTS.md Detailed usage reference for working with this project in Claude Code.

Prerequisites

Dependency Purpose Install
Claude Code CLI Runs plan-generation sessions npm install -g @anthropic-ai/claude-code
Python 3 + PyYAML Config file parsing pip install pyyaml
bash 4+ Associative arrays in scripts macOS: brew install bash
GNU coreutils timeout command macOS: brew install coreutils

Verify your setup:

claude --version && python3 -c "import yaml; print('PyYAML OK')" && echo "bash ${BASH_VERSION}"

Quick start

# 1. Write your prompt (or use the included test prompt)
cat test-prompt.md

# 2. Generate plan variants (use --debug for a quick single-variant test)
./generate-plans.sh --debug test-prompt.md

# 3. Merge the results
MERGE_MODE=simple ./merge-plans.sh generated-plans/test-prompt/latest

Full pipeline with all variants (Opus, default 4, ~15-25 min, ~$20-60):

./generate-plans.sh my-prompt.md
./monitor-sessions.sh --watch          # watch progress in another terminal
./evaluate-plans.sh generated-plans/my-prompt/latest           # check convergence + gaps
./merge-plans.sh generated-plans/my-prompt/latest              # interactive agent-team merge
./verify-plan.sh generated-plans/my-prompt/latest              # quality gates on merged plan

See AGENTS.md for all options, environment variables, and output structure.

All scripts support --help for full usage details (e.g., ./generate-plans.sh --help).

What the output looks like

The merged plan starts with a dimension comparison table showing which variant won each category, then synthesizes the best elements into a standalone plan:

| Dimension              | Winner     | Justification                                      |
|------------------------|------------|-----------------------------------------------------|
| Approach and strategy  | depth      | Most concrete module breakdown                      |
| Scope and priorities   | simplicity | Correctly identifies MVP scope; defers schema to v2 |
| Risk assessment        | breadth    | Only plan to address encoding detection failures    |

See examples/sample-output/merged-plan-excerpt.md for a full excerpt from a real run.

Running e2e tests

The e2e test runs the full pipeline (generate → evaluate → merge) with real Claude API calls using the examples/csv-to-json-cli.md prompt:

make test-e2e                 # ~$2-4, ~5 min, requires Claude CLI with API access
MODEL=haiku make test-e2e     # cheaper (~$1) but less reliable

This is separate from make check (which runs fast unit tests, no API calls).

Adapting to your own project

The scripts are domain-agnostic — all domain-specific content lives in your prompt file and config.

Single-file mode: Write a prompt, customize variants in config.yaml, run ./generate-plans.sh your-prompt.md. The default variants (baseline, simplicity, depth, breadth) work for any domain. Edit them to match yours — swap "depth" for "API design" or "database schema" or whatever dimension matters most.

Multi-file mode: Write separate prompt files for each perspective, optionally with a shared context file: ./generate-plans.sh --context=shared.md prompt-a.md prompt-b.md prompt-c.md prompt-d.md.

File access: Set work_dir in config.yaml to a directory containing the repos Claude should access. Leave it empty for plans that don't need codebase access (strategy, architecture, non-technical topics).

Merge dimensions: Customize comparison dimensions in merge-config.yaml to match your domain. Use weighted dimensions ({name, weight}) to prioritize what matters. Set comparison_method: pairwise for more reliable comparison with 4+ plans. Add custom constitution principles to enforce your quality standards.

Auto-lenses: Use --auto-lenses to let the LLM generate task-specific variant perspectives from your prompt, instead of using generic config variants. Good for one-off prompts where domain-specific lenses add value.

Sequential diversity: Use --sequential-diversity to run variants in two waves. Wave 1 runs first; wave 2 receives skeleton outlines of wave 1 plans as a structural diversity constraint. This reduces convergence between plans at zero extra LLM cost for the skeleton extraction.

Lens strategies: The default variants (baseline/simplicity/depth/breadth) are analytical lenses — they vary how the model thinks. For domain-specific work, consider alternatives:

  • Persona lenses — shift who is thinking: architect, pragmatist, skeptic, visionary. Different personas attend to different aspects of the same problem (82% to 91% accuracy on reasoning benchmarks per Hegazy, 2024).
  • Constraint lenses — force different solution spaces: "2-week deadline," "team of 1," "10x scale," "zero breaking changes." Same problem, genuinely different trade-offs.
  • Adversarial lens — one contrarian variant that must differ structurally from the obvious approach. Counteracts Degeneration-of-Thought, where same-model runs converge.
  • Model cascade — use Sonnet for generation, Opus for merge. The merge aggregator's quality matters more than individual proposers (Self-MoA, Li et al., 2025). ~48% cost savings vs. all-Opus.

See config.yaml for commented examples of each strategy, or mix elements across strategies.

The key requirement is that your prompt file gives Claude enough context to produce a substantive plan — point it at files to read, decisions to make, and trade-offs to consider. See AGENTS.md for the full configuration reference.

Limitations

  • Bash scripts, not a library. This is a configurable toolkit, not a polished SDK. It's intentionally simple — shell scripts you can read, modify, and extend.
  • Cost: ~$20-60 per run. Default 4 Opus sessions plus a merge session. Use --debug mode (single Sonnet session) to iterate on prompts cheaply before a full run.
  • Same-model correlation is reducible, not eliminable. Prompt variation reduces correlated blind spots but doesn't remove them entirely. Three mitigations help: (1) per-variant model overrides in config.yaml — different model sizes have different biases, (2) work_dir and add_dirs give Claude access to your codebase so it can read internal APIs directly, (3) mcp_config connects Claude to external knowledge sources (internal docs, wikis, search indexes) it wasn't trained on.
  • The merge step has its own biases, but they're steerable. The LLM doing the merge may favor familiar patterns. Mitigations: configurable comparison dimensions and role in merge-config.yaml steer what gets prioritized; Agent Teams debate forces advocates to concede weaknesses and acknowledge competing strengths; interactive mode lets the human redirect the synthesis in real time; and you can use a different model for merge than generation (e.g., MODEL=sonnet ./merge-plans.sh).
  • Quality assessment is ultimately human. Automated scoring of plans is an unsolved research problem — there's no reliable programmatic "plan quality score," and LLM-as-judge has the same model biases the pipeline is trying to overcome. The toolkit includes evaluate-plans.sh (pre-merge convergence and gap detection) and verify-plan.sh (post-merge quality gates) as automated sanity checks, but these supplement — not replace — human judgment. The final call is yours, by design.
  • Requires Claude Code CLI with API access (Max plan or direct API key). Sessions share org-level rate limits.

License

MIT

About

Orchestrates parallel Claude Code sessions with prompt variation to generate better implementation plans — research shows same-model runs share 60% of errors, so diversity must come from forcing different trade-offs, not repetition

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages