Skip to content

Mutations

omnifs today is a read projection: upstream services appear as local paths, and the read tree never changes unless the upstream does. Writes will extend that model rather than replace it. The core invariant stays intact: the paths you cat today will not mutate behind you.

When mutation support lands, every write will stage into a draft namespace that sits beside the live read tree, not inside it. The live tree stays untouched. A draft namespace is scoped to a session or an explicit named draft; you can have several open at once.

A staged write might look like this:

Terminal window
# future syntax, not yet implemented
omnifs draft new my-fix
omnifs draft write /github/my-org/my-repo/_issues/open/42/state my-fix <<< "closed"

The draft records the intended change at the same path the read tree would serve. Nothing reaches the upstream API at this point.

Because staged writes live at the same path structure as the read tree, diffing is straightforward: the draft namespace acts as a shadow tree, and any tool that can diff two directory trees will work.

Terminal window
# future syntax, not yet implemented
omnifs draft diff my-fix

The output would be a unified diff against the live read paths. You inspect it the same way you inspect any diff: grep, less, patch viewers. No special client needed.

Applying a draft commits all staged changes as a single transaction. If the upstream rejects any operation in the set (permission error, conflict, validation failure), the whole transaction rolls back and the live tree remains unchanged.

Terminal window
# future syntax, not yet implemented
omnifs draft apply my-fix

After a successful apply, the live read paths reflect the upstream state, the draft is discarded, and the host cache invalidates the affected entries.

Staging before applying keeps two properties that would be hard to recover if writes were fire-and-forget:

  • Atomicity. A set of related changes (close an issue, add a comment, update a label) either all land or none do. Partial state on a remote service is often worse than no change.
  • Reviewability. You can inspect the full changeset before anything goes upstream. omnifs draft diff gives you the same confidence that git diff --cached gives before a commit.

The no-ambient-authority rule that governs reads will apply equally to writes. A provider WASM component will not open its own socket to apply a change. The host runtime will hold the credentials and gate every outbound mutation through an explicit capability. A provider that receives no write capability cannot stage or apply anything, even if it contains mutation logic.

Stable inode identity (inodes survive upstream renames) will extend to the draft namespace. If an upstream object is renamed between staging a write and applying it, the host will resolve the correct target by identity rather than path. After apply, the cache will drop entries for mutated objects and repopulate from the upstream response, so the read tree stays coherent without a full flush.

The planned design intentionally excludes:

  • Streaming writes. No incremental upload path for large files in the first iteration.
  • Conflict resolution UI. The host will report a conflict; resolution requires re-staging after you fetch the latest state.
  • Cross-provider transactions. A single draft applies to one provider. Writing to /github/... and /linear/... in one atomic commit is out of scope for the initial design.