0Pricing
Claude Architect · Lesson

Multi-Pass Decomposition

Per-file local pass, then a cross-file integration pass.

Multi-Pass Decomposition is a free Claude Architect lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Claude Architect learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why One Pass Isn't Enough

When you ask Claude to review a changeset spanning many files in a single pass, attention gets diluted. The model spreads finite focus across every file at once, so subtle per-file bugs slip through and genuine cross-file issues get buried.

The architect's answer is multi-pass decomposition: split the work into a per-file local pass first, then a separate cross-file integration pass. Each pass has one clear job, so attention stays sharp.

Two Different Questions

The two passes ask fundamentally different questions, which is exactly why they shouldn't be merged:

  • Local pass: "Is THIS file internally correct?" — logic errors, null handling, naming, dead code, style within the file's own boundary.
  • Integration pass: "Do these files work TOGETHER?" — mismatched function signatures, broken contracts, inconsistent assumptions across module boundaries.

Single-pass review forces both questions into one diluted prompt. Two passes keep each focused.

Pass 1 — Find the Files

The local pass starts with discovery. Use Claude Code's built-in tools incrementally: Glob to find files by pattern, then Read each one in isolation.

Reviewing one file per request keeps the context small and the attention concentrated. This is the opposite of dumping the whole diff into a single prompt.

# Discover changed source files, review each on its own
glob '**/*.py'  | grep -Ff <(git diff --name-only main)

# Then, per file, a focused review request:
claude -p "Review ONLY src/billing/refund.py for local correctness: \
  logic errors, null handling, edge cases. Do not assume anything \
  about other files." --output-format json

One File, One Request

In the local pass, give Claude a tight, explicit boundary: review only this file, and judge it on its own terms. Vague instructions like "be thorough" underperform; explicit criteria win.

State exactly what counts as a finding so the model doesn't drift into speculation about files it hasn't seen.

from anthropic import Anthropic
client = Anthropic()

def local_pass(path, source):
    return client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1500,
        system=("You review ONE file in isolation. Flag a finding ONLY "
                "when the code is internally wrong, never on guesses "
                "about unseen files."),
        messages=[{"role": "user",
                   "content": f"File: {path}\n\n{source}"}],
    )

Structured Findings Per File

Have each local pass emit structured output so findings are machine-mergeable for the next pass. Use tool_choice with a schema-backed tool to guarantee well-formed JSON.

Critically: mark a field required only if it is always present. Never require a field that may be absent — the model will fabricate a value to satisfy the schema.

tools = [{
    "name": "report_findings",
    "description": "Record local-pass findings for a single file.",
    "input_schema": {
        "type": "object",
        "properties": {
            "file": {"type": "string"},
            "findings": {"type": "array", "items": {"type": "string"}},
        },
        "required": ["file", "findings"],  # always present
    },
}]
# force structured output -> no free-text parsing
resp = client.messages.create(model="claude-sonnet-4-5", max_tokens=1500,
    tools=tools, tool_choice={"type": "tool", "name": "report_findings"},
    messages=[{"role": "user", "content": file_blob}])

Pass 2 — Cross-File Integration

Once every file passes its local review, run a separate integration pass. Now the goal flips: you deliberately load the relevant files together and ask whether their contracts line up.

Typical integration defects:

  • A caller passes three arguments; the callee now expects four.
  • One module returns None on "not found"; the consumer treats it as an empty list.
  • A renamed enum value still referenced by a sibling file.

Tracing the Seams

The integration pass mirrors incremental investigation. Start at the boundaries and follow the wiring: Grep for a changed function's name to find every call site, then Read those consumers.

This way the integration pass concentrates on the seams between files — the exact place single-pass review tends to miss.

# Find everyone who calls the changed function, then read them
claude -p "Cross-file pass. process_refund() signature changed in \
  refund.py. Grep its call sites, Read each consumer, and report \
  ONLY mismatched arguments, return-type assumptions, or broken \
  contracts across files." --output-format json

Why Order Matters

Run local before integration, not the reverse. If a file is internally broken, integration findings about it are noise — you'd flag a contract mismatch that disappears once the local bug is fixed.

Clean each file in isolation first, then the integration pass can trust that every file is locally sound and focus purely on how they fit together.

Fixed Pipeline, Not Improvised

Because the steps are known and sequential — discover, local pass, integration pass, report — this is a job for a fixed pipeline (prompt chaining), not adaptive, open-ended exploration.

Reserve adaptive decomposition for genuinely open investigations ("why is this flaky?"). Multi-pass review has a defined shape, so encode that shape.

def review_changeset(files):
    # Stage 1: local pass, one request per file
    local = {f: local_pass(f, read(f)) for f in files}
    # Stage 2: integration pass over the seams
    integration = cross_file_pass(files, local)
    return merge(local, integration)

Run It in an Isolated Session

Run each review pass in a fresh, isolated session, separate from whatever session generated the code. Independent review beats same-session self-review: an author retains its own reasoning and won't challenge its own assumptions.

In CI, drive this non-interactively with -p / --print and --output-format json so results are parseable. When re-running, feed in prior results and report only new or still-unfixed issues.

# CI: isolated, non-interactive, machine-readable
claude -p "$LOCAL_PASS_PROMPT" --output-format json > local.json
claude -p "$INTEGRATION_PROMPT" --output-format json > integ.json
# fresh process each pass -> no generation-context bias

Scaling with Subagents

For large changesets, fan out the local pass across subagents in a hub-and-spoke pattern: the coordinator splits files among parallel workers, then runs the integration pass itself once results return.

Remember the rule: subagents do not inherit the coordinator's history. Each subagent prompt must carry all the context it needs explicitly. Multiple Task calls in one response run in parallel.

# Coordinator: parallel local passes, then one integration pass
# (each Task gets full context — subagents inherit no history)
Task(subagent="reviewer", prompt=local_prompt_for("refund.py"))
Task(subagent="reviewer", prompt=local_prompt_for("ledger.py"))
# ...both run in parallel; coordinator aggregates, then integrates

Quick Check

An architect must review a 9-file pull request and wants the highest-quality findings. What is the soundest decomposition?

Recap

Multi-pass decomposition, distilled:

  • Two passes, two questions: local = is each file internally correct; integration = do the files work together.
  • Local first, then integration — a broken file makes integration findings noise.
  • One file per local request to keep attention sharp; emit structured output for clean merging.
  • Fixed pipeline (discover → local → integration → report), not adaptive improvisation.
  • Isolated/fresh sessions beat same-session self-review; in CI use -p and --output-format json.
  • Scale the local pass across parallel subagents — each one needs context passed explicitly.

Single-pass multi-file review is the anti-pattern. Decompose, and your reviews get sharper, not just longer.

Frequently asked questions

Is the “Multi-Pass Decomposition” lesson free?

Yes — the full text of “Multi-Pass Decomposition” is free to read here on the web, and the Claude Architect course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Claude Architect course, upgrade to CoddyKit PRO.

What will I learn in “Multi-Pass Decomposition”?

Per-file local pass, then a cross-file integration pass. You practise Claude Architect with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Claude Architect?

No prior experience is required. Claude Architect on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Multi-Pass Decomposition” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Claude Architect lesson?

Yes. Every Claude Architect lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Fixed Pipelines vs Adaptive Decomposition
  2. Multi-Pass Decomposition
  3. Session Management
  4. Stale Context & Starting Fresh
← Back to Claude Architect