What an external test pass looks like.

A library that promises data safety only matters if someone has tested it under conditions that look like reality. Here is the methodology, the numbers, and the gaps for iso-code v0.1.1 — reproducible end-to-end in 90 seconds against any repository of your choice.

This is the methodology companion to the post that headlines the bugs we found. If you're evaluating whether to depend on iso-code for a tool you're building, this is the page you want.

What we tested against

The PRD names the target market explicitly: AI coding orchestrators (Claude Code, Cursor, Claude Squad, OpenCode, VS Code Copilot) and the developers who run them on real codebases. The test set therefore had to look like what those tools actually point agents at — not famous OSS infrastructure repos.

RepoSizeWhy included
bat45 MBSmallest baseline · Rust CLI · fast iteration
flask15 MBConfirms behavior is not Rust-specific · Python · default branch main
shadcn-ui153 MBTypeScript pnpm monorepo · pnpm-workspace.yaml
git/git377 MBHas sha1collisiondetection as a real submodule
next.js2.7 GBHeadline target · large pnpm monorepo · default branch canary

Five repos · four languages · three default-branch names · sizes spanning 180×.

The 15-check lifecycle suite

Each repo was subjected to identical checks. Every check is asserting one specific iso-code surface — not "does this work" in general, but "does this specific guarantee hold."

Smoke (8 checks)

Establishes the happy path. If smoke fails, nothing else is meaningful.

Stretch (7 checks)

Exercises the safety invariants — the parts that distinguish iso-code from a thin wrapper around git worktree.

Results

All five repos passed all 15 checks. The performance was consistent — create time scales with checkout size, not git-history size, because git worktree add shares the .git/ directory between worktrees instead of copying it.

RepoWorking treeCreateDeleteMulti ×3
flask2.4 MB164 ms504 ms570 ms
bat10 MB242 ms714 ms851 ms
git/git58 MB590 ms1,285 ms2,046 ms
shadcn-ui90 MB884 ms1,701 ms2,952 ms
next.js246 MB3,483 ms4,429 ms12,824 ms

Multi-create scales near-linearly. Delete consistently runs about 1.5–2× slower than create — that's a filesystem-bound recursive remove, not iso-code overhead. There were no non-linear blowups at any size we tested.

Fixtures: the safety paths no public repo can exercise

Three of iso-code's promised safety guards can't be triggered by cloning anything off GitHub — public repos either don't have unmerged commits, or aren't shaped the right way, or aren't encrypted. So we wrote fixtures.

The headline scenario: 4,972 symlinks

The single most important test in the pass — and the one that validates the bug class iso-code's README is built around.

On shadcn-ui, we created a worktree and ran pnpm install inside it. pnpm uses a global content-addressable store outside the worktree, with thousands of symlinks pointing into it from each project's node_modules. The setup:

MetricValue
Worktree size on disk1.3 GB
Top-level node_modules1.2 GB
node_modules directories4
Symlinks in worktree4,972
pnpm global store size1.1 GB

Then wt delete:

MetricPrePost
Worktree on disk1.3 GBremoved
pnpm global store1.1 GB1.1 GB unchanged
active_worktrees10
Wall time12.4 s

This is exactly where other orchestrators have shipped data-loss bugs: a worktree's node_modules is thousands of symlinks pointing into a single shared directory outside the worktree. A naive "follow symlinks during delete" implementation eats the shared store, breaking every other project on the machine. iso-code cleaned 4,972 symlinks in 12 seconds without touching a single byte of the global store.

What we deliberately didn't test

An honest test pass names its gaps. These are the surfaces that aren't yet validated and that an adopter should know about.

SurfaceWhy not yet
git-crypt locked-repo guardFixture exists; git-crypt not installed on this machine
Concurrent create from two shellsSingle-shell harness; needs a 2-terminal coordinator
MCP integration with Claude Code / CursorTested via CLI; not yet wired through a real MCP client
EcosystemAdapter / DefaultAdapterNo adapter configured in any test
Force-delete of unmerged branchHinted at by guard error; not yet exercised
Disk-limit enforcementCreateOptions::ignore_disk_limit never set
Port-lease allocationCreateOptions::allocate_port never set
Crash-safe state-file write under induced crashLogic verified by inspection; not stress-tested
Windows platformmacOS-only test pass · per PRD, Windows is M3

Reproduce it yourself

The whole pipeline is scripted. Anything you read above can be regenerated end-to-end in 90 seconds (after the initial repo clones). The harness is idempotent — it cleans up its own worktrees and branches at start and end, and never touches your main checkout.

# Prerequisites: wt (iso-code-cli) on PATH, git, python3
git clone https://github.com/sharkdp/bat.git
cd bat
./test-lifecycle.sh .         # 15 checks, sub-3s on most repos

Expected output:

[smoke]
  [PASS] list_initial                  (1 entries)
  [PASS] create                        (242ms)
  [PASS] list_post_create              (2 entries)
  [PASS] state_json_valid
  [PASS] worktree_on_disk              (10132KB)
  [PASS] delete                        (714ms)
  [PASS] list_post_delete
  [PASS] gc_dry_run

[stretch]
  [PASS] multi_create_x3               (851ms)
  [PASS] state_count_after_multi       (3 active)
  [PASS] external_remove_reconciled    (active=2 stale=2)
  [PASS] lock_protection               (dir preserved)
  [PASS] attach_external
  [PASS] duplicate_branch_error
  [PASS] missing_path_error

------------------------------------------
summary: 15 passed, 0 failed, 3s wall

Exit code is zero on all-pass, non-zero otherwise. Drop it into CI verbatim.

Findings filed back

Three issues were filed against the iso-code repo during this pass. The headline post covers them in detail. They are public, with repros and exact patches:

The bottom line: 80 of 80 lifecycle checks passed. Three guards verified by fixture (unmerged-commit, shallow, bare). One headline scenario verified end-to-end (1.3 GB / 4,972 symlinks deleted, 1.1 GB shared store untouched). Three issues filed. One safety guard remains unverified pending brew install git-crypt. Anyone can reproduce these numbers locally.
← back to all posts