← All field notes

The Tiny File That Keeps Parallel AI Sessions from Colliding

Separate worktrees protect files. A small claims file protects the shared resources around them.

Diagram separating file ownership from shared resource ownership in a session claim.

I can keep several coding sessions moving at once. Each has its own context, terminal, and often its own Git worktree. That makes parallel work feel safe.

The safety ends at the filesystem.

Worktrees isolate files. They do not isolate every resource a test or release command can touch. A simulator, a local port, a browser profile, or a lock in the same checkout can still be shared. If two sessions assume the other one knows this, the failure usually arrives later and looks unrelated to the original edit.

I learned this after a failed push. The test process survived the push and kept a checkout lock. That lock gave another session very little information about who owned it or whether the work was still useful.

The process failure was ordinary. The coordination around it was not enough.

A worktree is not a boundary for everything

The useful distinction is file ownership versus resource ownership.

Two sessions in different worktrees can usually edit different files without stepping on each other. Two sessions using the same checkout can still contend for a lock scoped to that checkout. Both sessions can also compete for a simulator or a port, even when their files are perfectly separate.

“I have my own worktree” answers where edits live. A concurrency plan also needs an owner for the environment around those edits.

The claims file

I added a small claims file that a person can read to the coordination area. Before editing, each session records the paths it owns and any shared resources it expects to use.

The shape is deliberately boring:

owner: session-a
paths:
  - web/src/image-loader.ts
resources:
  - checkout:test-lock
purpose: test the cache invalidation path

There is one claim per participant. A claim is not a permanent reservation. The session should release it when the work ends and record the files it actually touched beside it. If it discovers a second shared resource, it adds that resource before using it.

The log only grows by appending entries. It tells me what happened and when, but it does not grant permission to edit or replace a live claim. A log can be stale. A claim represents current ownership.

Make cleanup observable

When a command times out, I first ask “which process owns the lock, and is it still doing useful work?” The question is not how to remove the lock.

The recovery path now reports the owner, checks whether the process is alive, and distinguishes an empty or orphaned lock from an active run. A dead process can be cleaned up. An active process needs a decision from its owner. Removing a lock blindly can make two suites write into the same output directory and hide the original failure.

This also changed how I describe test failures. “The suite did not start” is a different event from a suite that ran and found a failing assertion. Both can block a release, but they need different next actions.

A small protocol for a team of one

The protocol is short:

  1. Write the claim before the session edits.
  2. Name shared resources, not only source files.
  3. Check the claim file before taking a lock or starting a simulator.
  4. Release the claim and list the files actually changed.

This is enough structure to let agents work in parallel without pretending that they share a brain. It gives a future session something concrete to read before it starts guessing.

The result is deliberately unglamorous: a shorter path from “something is stuck” to “this process owns that resource, this is what it was doing, and this is safe to clean up.”