Skip to content
Code Recycle

Component · for humans & their agents

Lane Guard

verified · first-partyactively maintained$0 during beta (was $69)

Two agents, one checkout: agent B's commit silently contains agent A's unfinished work.

by Code Recycle

Get it free — beta

Every claim on this page is refundable if it is untrue — refund policy.

Verified: 77 tests · 6/6 mutations caught

Two coding agents in one checkout. A is mid-task with work in progress; B finishes and runs git add -A && git commit -m "agent B: only my change". B's commit contains BOTH edits -- agent A's unfinished work is committed, under B's name, on B's branch. Nothing threw, and no tool reported a conflict, because there was none: there was only ever one working tree. Both that run and the fixed one are reproduced in the test suite rather than described.

Two coding agents in one checkout. A is mid-task with work in progress; B finishes and runs git add -A && git commit -m "agent B: only my change". B's commit contains BOTH edits -- agent A's unfinished work is committed, under B's name, on B's branch. Nothing threw, and no tool reported a conflict, because there was none: there was only ever one working tree. Both that run and the fixed one are reproduced in the test suite rather than described.

git worktree add is one command and it is not the product. What it does not do is everything here.

CONTAINMENT, THE CHECK EVERY AGENT SANDBOX WRITES BY HAND. A task in lane foo may only touch paths under lane foo. Easy to state; the obvious implementations are all wrong, measured by execution on macOS/APFS with a real symlink and a real sibling directory. A startsWith check permits /lanes/foo-evil because the string genuinely starts with /lanes/foo -- and siblings collide by accident far more often than by attack, because lanes get named after branches and branches share prefixes. Adding path.sep fixes that and still permits a symlink out of the lane: confirmed by reading through one, which resolved to /private/tmp/cont/secret/keys.txt and returned its contents. Both checks also refuse a legitimate case-variant spelling.

CASE-FOLDING IS THE ONE THAT SURPRISES PEOPLE. On a case-insensitive volume /lanes/FOO and /lanes/foo are ONE DIRECTORY -- verified by writing through the upper-case spelling and finding the file under the lower-case one. Two lanes whose names differ only in case share a working tree while the manager believes they are isolated, and nothing reports it, because at the filesystem level only one directory was ever created. Allocation refuses the second lane for exactly that reason. Case sensitivity is PROBED, not inferred from process.platform, which is wrong in both directions: macOS formats APFS case-sensitive on request and ext4 has a casefold flag.

THE HARD CASE IS A FILE THAT DOES NOT EXIST YET. An agent about to create a file asks about a path with no inode. realpath throws on it, so the tempting fallback is path.resolve -- which reopens the symlink hole exactly when it matters, because <lane>/escape/new.txt resolves textually inside the lane and writes outside it. The test proves the write lands in the wrong directory. Resolution walks to the deepest ancestor that does exist and re-attaches the remainder, since a component that does not exist cannot be a symlink.

RELEASE REFUSES TO DESTROY WORK. A scheduler reclaiming lanes after a task reports success is where agent output gets thrown away, because succeeded and committed are different claims. Release refuses a lane with uncommitted work and returns the paths that would be lost, so the decision is made with the information rather than by reaching for --force.

WHAT IT DOES NOT CLAIM: containment is a decision, not an atomic guarantee. Between the answer and the write a symlink can be swapped in. Closing that needs openat/O_NOFOLLOW, which Node does not expose; the read path narrows the window to one statement and re-verifies through the opened handle, but does not eliminate the race. This is isolation for cooperating agents, not a security boundary against hostile code. Stated plainly because a sandbox that overstates its guarantee is more dangerous than one that does not make the claim.

VERIFIED: 77 tests, 6 deliberate defects applied to the real source, all 6 caught (the set ships in mutations.json, including the unicode-normalisation case a sweep found untested). Zero runtime dependencies.

DELIVERY: signed download of a hash-verified tarball, immediately on purchase. Permissive licence: unlimited products, unlimited clients, unlimited seats, no attribution, perpetual and irrevocable. One restriction, do not republish the source as source.

Interface

What you call, and what comes back. Types and signatures only — the implementation ships with the source.

  export function isCaseInsensitive(dir: string): boolean;
  export function clearCaseCache(): void;
  export function resolveDeepest(p: string): string;
  export function laneContains(laneRoot: unknown, candidate: unknown): ContainmentResult;
  export function assertInLane(laneRoot: string, candidate: string): string;
  export function lanesCollide(parentDir: string, a: string, b: string): boolean;
  export function validateLaneName(name: unknown):;
  export function allocateLane(repo: string, name: string, opts: AllocateOptions = {}): AllocateResult;
  export function listLanes(parentDir: string): Array<;
  export function releaseLane(lane: Lane, opts: { force?: boolean } = {}): ReleaseResult;
  export function readInLane(lane: Lane, candidate: string): string;

01Capabilities

Does

  • + Path traversal prevention
  • + Secure file path handling
  • + Sandboxing and isolation

Doesn’t

  • No exclusions declared

02Requirements & stack

Depends on

No declared dependencies

Credentials needed

None declared

Stack

typescript

03Community

No endorsements yet

No verified confirmations yet — be the first.

Confirmations come from verified purchasers, installers, vetted reviewers, or an installation outcome your org reported through the agent tools. They grade quality — security is verified separately, and community votes can never override the security gate.

Open an issue

Sign in to confirm — weight comes from verified usage, not vote count.

0 open · 0 answered · 0 fixed · 1 said it worked

04Trust Passport

Full passport →
–/100

0/0 automated components pass. An automated score is never a security guarantee.

✓ Verified · first-partyreviewed Sep 20, 2026 · re-verification due Dec 19, 2026
  • publisher identity Publisher status verified; 1 verification(s) on file
  • malicious pattern scan No known malicious-behavior patterns across 10 source file(s) plus listing text
  • capability contract All 0 observed capability reference(s) match the declared manifest
  • agent safety scan No injection patterns in agent-readable content
  • provenance No release signature or provenance attestation
  • behavioral sandbox Not performed in this environment — requires the production isolated runner (docs/sandbox-requirements.md). No untrusted code is ever executed on the application host.

Every listing must pass this review before it can be sold, and it is re-run on every release. Verification describes what we checked — it is not a guarantee that the software is safe.

VersionChannelReleasedNotes
1.0.0stableAug 3, 2026First public release.