Staged filesystem (hostlib)

harn-hostlib includes a session-scoped filesystem staging layer for hosts that want agents to accumulate a diff before applying it to the working tree.

The capability is registered by harn_hostlib::install_default as the fs module:

MethodResult
hostlib_fs_set_modeSwitches a session between immediate and staged, returning the previous mode.
hostlib_fs_staged_statusLists pending writes/deletes with byte counts and oldest pending age.
hostlib_fs_commit_stagedApplies all pending changes, or only selected paths, to disk.
hostlib_fs_discard_stagedDrops all pending changes, or only selected paths.
hostlib_fs_read_textOverlay-aware UTF-8 read returning { content, sha256, size, exists }. Un-gated companion to the tools/read_file primitive — Harn scripts call it to snapshot pre-image hashes without enabling the deterministic-tools feature.
hostlib_fs_safe_text_patchAtomic compare-and-swap text write. Reads the overlay pre-image, rejects with result: "stale_base" if expected_hash diverges, writes through the overlay otherwise. Backs std/edit's edit_safe_text_patch multi-hunk wrapper.

Staged data is stored below:

<workspace>/.harn/state/staged/<session_id>/

The manifest records the active mode, root, and pending entries. File bodies are stored by SHA-256 content hash under bodies/, and journal.jsonl records each staging operation for audit/debugging.

When a session is in staged mode, hostlib mutating tools write into the overlay:

  • hostlib_tools_write_file records a staged write.
  • hostlib_tools_delete_file records a staged delete.

Read helpers use the same overlay before falling back to disk:

  • hostlib_tools_read_file
  • hostlib_tools_list_directory
  • hostlib_tools_get_file_outline
  • hostlib_ast_parse_file
  • code-index file read/hash helpers

The ACP adapter exposes host controls for the same state:

  • session/fs_mode with { sessionId, mode }
  • session/fs_commit_staged with { sessionId, paths? }
  • session/fs_discard_staged with { sessionId, paths? }

Every staging mutation emits a session/update progress extension with _meta.harn.kind = "staged_writes_pending", _meta.harn.pendingCount, and _meta.harn.totalBytes.