BXUP Track progress & test yourself — free
Software Engineering · Playbook · Advanced · ~5 min read
SOFTWARE ENGINEERING · PLAYBOOK · ADVANCED

Repo-Wide Pattern Refactor via Decomposition and Parallel Agents

A cross-cutting change — swap the logging API in 40 files, replace a deprecated HTTP client everywhere, thread a tenant-id through every handler — is too big for one agent session and too boring for a team.

Tier: Advanced · Workflow area: Refactoring & Migration

The pattern proven by Stripe-style agent-fleet harnesses: decompose into independently verifiable subtasks, run agents in parallel with a written spec, verify each shard mechanically, and aggregate into human-reviewable PRs. The engineering skill being trained here is the decomposition and the verification harness, not the prompting.

When to use

  • One repeated transformation across tens-to-hundreds of files, too context-heavy for a single session, too irregular for a pure codemod (call sites need local judgment).
  • You can define done per file mechanically (greps, tests, compile) — if you cannot, the aggregation step will drown you.
  • A codemod alone gets you 60–80% but the rest needs semantics (varied argument shapes, local error-handling differences).

If a codemod can do it all, use pb-23's approach instead — determinism beats parallelism.

Prerequisites

  • An agent runtime supporting parallel isolated runs: Claude Code subagents or multiple worktree sessions, a Copilot coding-agent fleet on separate issues, or a scripted harness looping claude -p/API calls.
  • Green baseline CI, and per-shard test commands that run in minutes, not hours.
  • git worktree familiarity — parallel agents editing one checkout corrupt each other; one worktree+branch per shard.

The workflow

  1. Write the transformation spec once, with before/after pairs. This is the contract every agent gets verbatim:

    # SPEC: migrate logger.* to structlog
    - `logger.info("msg %s", x)`  →  `log.info("msg", value=x)`
    - `logger.exception("...")`    →  `log.error("...", exc_info=True)` inside except blocks
    - Module setup: replace `logging.getLogger(__name__)` with `structlog.get_logger()`
    - DO NOT change log message text, log levels, or surrounding logic.
    - DO NOT touch files outside your assigned list.
    - If a call site doesn't match any pattern above, leave it and append it
      to UNRESOLVED.md with file:line and reason.
    

    The UNRESOLVED escape hatch is what keeps agents from inventing creative interpretations at weird call sites.

  2. Shard by natural seams, sized for verification. Group by directory/package so each shard compiles and tests independently; 5–15 files per shard is the sweet spot (big enough to amortize context, small enough to review). Generate the assignment mechanically:

    grep -rln "logging.getLogger" src/ | sort > /tmp/targets.txt   # 43 files
    # shard by top-level package
    awk -F/ '{print $2}' /tmp/targets.txt | sort | uniq -c
    
  3. Launch parallel agents, one worktree each. Scripted form:

    for shard in api workers billing ingest; do
      git worktree add ../wt-$shard -b refactor/structlog-$shard
      (cd ../wt-$shard && claude -p "Apply SPEC.md to exactly these files: $(cat shards/$shard.txt). \
         Then run: pytest tests/$shard -x. Fix failures within the spec's rules only. \
         Output UNRESOLVED.md entries for anything the spec doesn't cover." \
         --allowedTools "Edit,Bash(pytest*),Bash(git diff*)" ) &
    done; wait
    

    Equivalent flows: Claude Code subagents fanned out from one session, or one GitHub issue per shard assigned to the Copilot coding agent. Cap parallelism at what you can review the same day.

  4. Verify each shard mechanically before any human reading. The aggregator is a script, not vibes — per shard:

    # 1. Scope: only assigned files touched
    git diff --name-only main | diff - shards/$shard.txt
    # 2. Completeness: no old-API stragglers in assigned files
    grep -n "logging.getLogger\|logger\." $(cat shards/$shard.txt) || echo CLEAN
    # 3. Behavior: shard tests + full-suite smoke
    pytest tests/$shard && pytest -m smoke
    # 4. No collateral edits: diff contains only spec-shaped hunks (spot pattern)
    git diff main -- $(cat shards/$shard.txt) | grep '^-' | grep -v "logger\|getLogger" || true
    

    Check 4 is the agent-specific one: it surfaces drive-by "improvements" outside the spec. Any check fails → the shard goes back to its agent with the failure, or you fix it; it does not proceed to review.

  5. Aggregate for human review, merge shard-wise. Collate all UNRESOLVED.md entries first — resolve them yourself or extend the spec and re-run affected shards (spec extensions re-run everywhere relevant, or your codebase ends half-migrated in two styles). Open one PR per shard (reviewable) rather than one 40-file PR (not), each carrying its verification log in the description. Land a repo-wide final gate in CI: grep -rn "logging.getLogger" src/ && exit 1 so the old pattern can never return.

Key Takeaway:

Parallel agents don't remove the verification burden — they batch it. The harness (scope check, completeness grep, tests, collateral-edit scan) is the deliverable that makes 40 files of agent output trustworthy; without it you have 40 files of plausible diffs.

Tool variants

  • Claude Code subagents/worktrees: richest control (allowed-tools restriction, hooks running the verifier after each edit); best when you want the harness local and scripted.
  • Copilot coding agent fleet: create one issue per shard with SPEC.md pasted; each agent PRs against CI independently — GitHub-native aggregation, good on Copilot Pro pricing.
  • Harness-over-API (Stripe-minions style): a Python loop calling the model API per shard with spec + files, applying patches, running the verifier — most work, fully auditable, no per-seat tooling; the pattern to know for platform-team interviews.

Verification

  • Per-shard: scope check exact, completeness grep clean, shard + smoke tests green, collateral-edit scan explained-or-empty.
  • Global: repo-wide grep for the old pattern returns zero outside explicitly deferred files; CI gate merged.
  • UNRESOLVED entries all dispositioned (hand-fixed, spec-extended + re-run, or documented exception).
  • Sampled human review per shard PR (every file in high-risk shards; sampling elsewhere) found no spec violations the harness missed — if it did, add that check to the harness and re-verify all shards.

Pitfalls

  • Sharding by file count instead of seams. Ten files from five packages don't test independently; verification becomes all-or-nothing and the parallelism gains evaporate.
  • Agents sharing a checkout. Two agents in one working tree produce interleaved garbage; worktrees or separate clones, always.
  • Spec drift mid-flight. Fixing the spec after shard 3 without re-running shards 1–2 ships two dialects of the new pattern. Version the spec; re-run on change.
  • Reviewing the aggregate diff top-to-bottom. 40 files of near-identical hunks anesthetizes reviewers into missing the one weird hunk — that is exactly what the mechanical collateral-edit scan is for; let humans review the exceptions and samples.
  • Unbounded parallelism. Twelve shards you can't review today become twelve stale branches tomorrow. Launch what you can land.

Restricted-environment variant

  • The harness (sharding, scope/completeness/collateral checks, CI gate) is pure git+grep+tests — fully local. Under client restrictions, run agents via the sanctioned route (Copilot Business coding agent, client-tenant models) or downgrade gracefully: codemod for the mechanical share, humans for the residue, same harness verifying both.
  • Local-model fleets (Ollama looped over shards) handle highly regular specs at $0 — verification catches their higher miss rate, which is the point of building it; expect more UNRESOLVED and re-runs.
  • The spec + harness + shard-PR structure is also the correct shape for distributing the work across junior engineers instead of agents — identical artifacts, human executors, no data leaves anywhere.

Success criteria

  • The full pattern change lands in days with per-shard evidence logs, versus the weeks-long hand-migration it replaced.
  • Zero old-pattern occurrences post-merge, enforced by a CI gate — the change is permanent, not statistical.
  • Your spec, shard map, and verifier script are reusable for the next repo-wide change with only content edits — you own a harness now, not a one-off.
This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in