We tested iso-code on the repos AI agents actually work on. Here's what broke.
Before celebrating the v0.1.1 release, we pointed iso-code at five real-world repositories and ran eighty lifecycle checks against the binaries we'd just published. Three things broke. We filed them against ourselves before announcing anything.
The whole pitch behind iso-code is that every major AI coding orchestrator — Claude Code, Cursor, Claude Squad, OpenCode, VS Code Copilot — has independently shipped worktree-management bugs that lose data. So before we put a library on crates.io claiming to fix that class of bug, we wanted external validation that the library itself doesn't ship its own version of the same problem.
This is the result of that test pass. The headline: the safety guarantees the README promises hold up end-to-end. But our own bug-finding standards uncovered three real issues, all now filed at github.com/snehith01001110/ISO-Framework/issues. They're public, they have repros, they have the exact patches, and one of them is the exact category we built iso-code to prevent.
The setup
We cloned five repositories that span the languages and shapes AI agents are actually pointed at: bat (small Rust CLI), flask (Python web framework), shadcn-ui (TypeScript pnpm monorepo), git/git itself (C, with a real submodule), and next.js (a 2.7 GB pnpm monorepo). Five repos · four languages · three default-branch names (master, main, canary) · sizes from 15 MB to 2.7 GB.
Against each, we ran a 15-check lifecycle suite covering the smoke path (create, list, delete, gc) and the stretch path (multi-worktree state consistency, external-drift reconciliation, lock protection, attach, error messages). On top of that, we built three fixtures for safety paths no public clone can exercise: an unmerged-commit branch to trigger the 5-step pre-delete guard, shallow and bare clones, and a git-crypt locked repo. Plus one stress scenario: install a real node_modules in a worktree, then delete the worktree.
All 80 lifecycle checks passed. All three runnable fixtures passed. The pnpm stress scenario passed. The library does what it says it does.
Then we found three things to fix.
Bug 1: a misleading error message turned a quoting mistake into a 20-minute debug
An external user ran wt create feature/auth /Users/kg/Documents/Documents - kg/projects/foo with an unquoted path. The shell split it into four arguments. wt create took the first as the path (which happened to exist on the user's machine) and silently discarded the rest. The error message read "worktree path already exists" — pointing at completely the wrong problem.
Root cause: arg validation in iso-code-cli/src/main.rs uses a lower-bound check (args.len() < 2) instead of an exact match. Extras are accepted and ignored. Same pattern in run_create, run_delete, and run_attach.
Fix: three lines, change < to != in the right places. The CLI now rejects extra args with a usage message, surfacing the quoting mistake immediately.
Bug 2: an Option leaked into a user-facing string
Lock protection works correctly — wt delete on a locked worktree refuses, and the directory is preserved. But the error message rendered as worktree is locked: None. The literal string "None" is the Rust Option::None Debug formatter leaking through. Lock with a reason and you'd see worktree is locked: Some("in-flight build"). Same root cause; equally wrong.
This reproduced on every single one of the five repos we tested — it's not edge-case noise, it's a bug that ships every time a worktree is locked without a reason.
Fix: change {reason:?} to a closure-form attribute on WorktreeError::WorktreeLocked that branches on Some / None. Cosmetic, but in a security-adjacent surface — error messages users read when something refuses to delete their data — cosmetic matters.
Bug 3: the one we built iso-code to prevent
When iso-code creates a worktree on a repository that uses git submodules, the submodule directories show up in the new worktree as empty folders. The .gitmodules file is there. The directory is there. The contents are not.
This is git worktree add's default behavior, and iso-code inherits it. But for the audience iso-code targets — AI coding agents that get handed a fresh worktree and asked to work in it — this is exactly the class of silent correctness gap the README headlines. The agent runs the project's build, it fails because a dependency directory is empty, and the agent has no signal explaining why.
How we found it: we ran the lifecycle suite on git/git, which has sha1collisiondetection as a real submodule. The new worktree's submodule directory was empty. git submodule status showed the leading - meaning uninitialized.
Fix: add CreateOptions::recurse_submodules: bool (the struct is already #[non_exhaustive], so it's a non-breaking addition). When true, pass --recurse-submodules on git ≥ 2.38, fall back to a post-create git submodule update on older git, and honor the existing partial-worktree-cleanup invariant on failure.
This wasn't on the project roadmap. We checked. Two existing submodule-related items handle different scenarios — neither addresses worktree-creation-time initialization. So this is a real gap, and one that would have shipped to v1.0 if we hadn't tested against a real submodule repo.
What worked
Everything else. The list of safety guarantees the README promises mapped almost one-to-one onto checks we ran:
- 5-step unmerged-commit guard: against a fixture branch with three unpushed, unmerged commits,
wt deleterefused with a clear error. The worktree directory was preserved on disk. Even with no remote configured (degraded mode), the four remaining steps still ran and protected the data. - Lock protection: a
git worktree lock'd worktree survived bothwt deleteandwt gc --run --force --max-age-days 0. Other worktrees in the same gc pass were correctly evicted; the locked one was left alone. - Reconciliation: when a worktree was removed externally with raw
git worktree remove, the nextwt listmoved its state.json entry tostale_worktreeswith an eviction reason and a 30-day TTL — instead of silently lying about the worktree still existing. - The 4,972-symlink test: we installed a real pnpm
node_modulesin a shadcn-ui worktree (1.3 GB on disk, 4,972 symlinks pointing into a 1.1 GB shared global store), then ranwt delete. The worktree was cleaned in 12 seconds. The global store remained byte-for-byte identical. This is the bug pattern the iso-code README headlines, and it's demonstrably prevented.
The point
If a library promises safety, the obligation to validate that promise sits with the library's authors, not its users. The most useful thing a v0.1 release can do is make its own bugs visible early, with repros, in public, before any adopter has to find them.
Three issues filed against ourselves before announcing the release. The full test pass — methodology, per-repo timings, coverage matrix, what we still don't test — is in the next post. The whole pipeline is scripted; you can run it against any repo of yours in 90 seconds with ./fixtures/test-lifecycle.sh /path/to/your/repo.