Back
Kevin Riedl

8 min read · 6 Sep 2026
Last reviewed

Next
Made on your device, with no Instagram connection. We copy the post link for Instagram’s Link sticker.

Atomic Multi-File Edits for AI Coding Agents: The Semaprax Lesson

If an AI coding agent changes several dependent files, replacing each file safely is not enough. The project needs one publication boundary. Otherwise a build process, language server, test watcher or second agent can read half of the old program and half of the new one.

We met this problem while developing Semaprax, our experimental agent-native systems language. The useful lesson is broader than the language: prepare a complete immutable generation, verify it, then switch one small active pointer. This article explains the pattern, its limits and the questions a technical buyer should ask before trusting any claim of “atomic” agent edits.

What is an atomic multi-file edit?

An atomic multi-file edit makes one complete old state or one complete new state visible to its defined readers, never an in-between mixture. The phrase is incomplete until the system names those readers, the files in scope, the commit point and the failure model.

Consider a two-file change that renames an exported function and updates its caller. If the definition changes first, a watcher can observe a caller for the old name with a definition for the new name. If the caller changes first, it sees the opposite mismatch. Both files may be valid text. The combined program is not valid at that instant.

The learning: publish generations, not a sequence of writes

Semaprax initially needed a bounded way to publish verified changes across several source files. Its architecture decision rejects sequential replacement because a reader can observe a mixed generation. The accepted design keeps complete source generations immutable and selects one through a single ACTIVE record. The pinned Semaprax architecture decision records both the decision and the rejected alternatives.

.semaprax-workspace/
  ACTIVE
  generations/
    <old-workspace-revision>/
    <candidate-workspace-revision>/

The write path has five distinct stages:

  1. Bind the proposal to a base revision. Reject it if the selected workspace has moved.
  2. Preflight every changed file. Resolve all operations against one authenticated base before writing a candidate.
  3. Build the whole candidate separately. Include unchanged files too, so the candidate is a complete generation rather than a bag of patches.
  4. Verify the complete candidate. Check formats, identities, limits, digests and the invariants the protocol actually claims.
  5. Switch one pointer. After final rechecks, replace only ACTIVE. A cooperating reader resolves that pointer and reads one immutable generation.

Why is one atomic file rename not enough?

Writing a temporary file and renaming it over the destination is a valuable single-file pattern. Rust documents std::fs::rename as one rename operation and also lists platform-specific behavior and cross-mount failure. It does not offer a portable transaction over an arbitrary set of paths. See the Rust standard library rename contract.

Repeating that operation for five files creates five publication moments. If a reader can run between moments two and three, the overall program is still exposed as a mixture. Atomicity at the file level does not automatically compose into atomicity at the project level.

Doesn’t Git already make multi-file changes atomic?

A Git commit identifies one complete tree, but that does not make every live working-tree transition atomic to editors, watchers or other processes. The distinction is between publishing repository history and changing the files that active tools read.

Git itself illustrates how precise the boundary must be. git update-ref can verify an expected old object ID and queue ref changes in a transaction. Its documentation also warns that a concurrent reader may still see a subset of multiple ref modifications even though individual refs are updated atomically. The official Git update-ref documentation is a useful model for expected-version checks and explicit transaction states.

Use branches, worktrees and commits for collaboration, review and recovery. Add a managed publication layer only when running consumers must observe one coherent application snapshot during a change.

Why immutable generations are a practical pattern

Immutable generations move most risk before the commit point. A candidate can be built, inspected and rejected without modifying the selected state. The final operation is small because it changes a pointer, not every payload file.

This is not unique to agent tooling. Nix explains atomic upgrades in similar terms: packages are not overwritten in place, and a profile moves to a new generation, avoiding a window with some old and some new files. The official Nix architecture guide provides a mature example of the broader generation pattern.

The agent-specific addition is evidence. A fluent model response should not be the commit authority. The system should preserve the base revision, proposed operations, candidate digest, validation results and final pivot outcome so another component can check what happened.

What Semaprax actually implements, and what it does not

At the audited commit, Semaprax defines a bounded transaction for 2 to 16 managed .spx files. Writers take an exclusive lock, construct or authenticate a complete candidate generation, perform final checks and replace ACTIVE. Cooperating readers take a shared lock and resolve the selected immutable generation. The pinned workspace transaction specification defines the wire format, limits, diagnostics, evidence and nonclaims.

The boundary matters more than the headline. The protocol does not make raw source paths, Git, editors or noncooperating readers atomic. It does not claim network filesystem behavior, power-loss durability, automatic rollback, general repository semantics or arbitrary multi-file repair. Semaprax remains pre-alpha research, and this article does not turn its bounded evidence into a production-readiness claim.

Build or buy: eight questions for agent tooling vendors

  1. Who are the protected readers? Ask whether the guarantee covers only the tool’s API, the working tree, language servers, builds and external processes.
  2. What is the base revision? Every proposal needs an expected version and a clear stale-rejection path.
  3. What is the commit point? “We use temp files” is not an answer for a multi-file change.
  4. Is validation run on the complete candidate? Per-file syntax checks miss cross-file breakage.
  5. Who owns write authority? Model output, review evidence and approval tokens should not silently become reusable commit power.
  6. What happens before and after the pivot? Pre-pivot rejection and post-pivot ambiguity require different recovery procedures.
  7. Which durability claim is tested? Process crash, operating-system crash, power loss and network storage are different failure models.
  8. Can you reproduce the evidence? Ask for hostile tests, fixed fixtures, limits and exact versions, not only a polished demo.

When do you need this architecture?

You probably do not need a managed generation protocol for an agent that proposes a patch, stops and waits for a human to review a normal Git diff. You should consider it when autonomous work changes several coupled files while builds, services or other agents read the workspace continuously, and a mixed state can trigger deployment, code generation, migration or an irreversible action.

Start one layer earlier if the agent cannot identify the right program entities. Our Semaprax engineering note on semantic identity explains why stable declaration IDs and revision-bound patches are safer than stale line offsets. The AI agent harness guide places publication inside the larger context, policy, tool, verification and observability system.

Frequently asked questions

Are Git commits atomic?

A commit names one complete repository tree. That is not the same as guaranteeing that live readers of a changing working directory never observe intermediate file states.

Is atomic write the same as rollback?

No. Atomic publication defines what becomes visible at the pivot. Rollback, cleanup and recovery after a crash are separate contracts and need separate evidence.

Do immutable generations prevent merge conflicts?

No. They control publication visibility for cooperating readers. Branch coordination, semantic conflicts and human review remain separate concerns.

What is the minimum useful design?

Define the protected readers, bind the proposal to a base revision, validate a complete candidate outside the active state and make one small authenticated switch. Then document everything the switch does not guarantee.

Production AI help

Building an AI product and worried about inference cost, architecture, or production readiness? Wavect helps founders turn AI prototypes into reliable production systems.

Explore the service path:

Editorial disclosure: OpenAI Codex assisted with research, drafting and translation. Wavect checked the technical claims against Semaprax commit 942ed70 and the linked primary documentation on 6 September 2026. No performance or production-readiness claim is inferred from model output.

Final thoughts

The most important word in an atomic-edit claim is not atomic. It is scope. A safe design says who reads, what version the proposal targets, which state is verified and exactly where publication happens.

Semaprax taught us to stop treating several safe file writes as one safe program change. Build the complete generation first, verify it, then switch one pointer. Keep the nonclaims as explicit as the happy path.

Production AI help

Building an AI product and worried about inference cost, architecture, or production readiness? Wavect helps founders turn AI prototypes into reliable production systems.

Explore the service path:

Inbox, without the noise

Follow the work that matters to you

Get a short email when we publish something new. Follow the whole blog or only the problems you care about.

What would you like to receive?
Choose your topics

Free, double opt-in, no tracking pixels.

Back
Kevin Riedl

8 min read · 6 Sep 2026
Last reviewed

Next

Get the next AI and agents field note

One concise email when we publish. No tracking pixels, and no inbox filler.

Free, double opt-in, no tracking pixels.