rath.persistence#

Cross-plane atomic writes, root layout compatibility, and retention/garbage collection for OpenRath’s .openrath/ data root.

Source#

Module

Purpose

rath.persistence.atomic

Atomic text/JSON replacement helpers.

rath.persistence.manifest

Root layout and plane schema versions.

rath.persistence.gc

Dry-run-first retention across persisted planes.

Atomic writes#

from rath.persistence import atomic_write_json, atomic_write_text

atomic_write_text(path, "ready\n")
atomic_write_json(path, {"ready": True}, mode=0o600)

The helpers write a temporary sibling and replace the destination with os.replace. A process-local, path-keyed lock serializes writers in the same process; Windows sharing violations receive bounded retries.

This is not a cross-process transaction and does not replace the append/FileLock protocol used by Session JSONL persistence.

Root layout manifest#

.openrath/manifest.json records layout_version plus schema versions for the config, backend, and memory planes. It does not describe Session JSONL.

API

Behavior

ensure_manifest(root)

Creates or refreshes the current manifest.

check_manifest(root)

Rejects a layout version newer than this install. Missing legacy manifests are accepted.

LAYOUT_VERSION

Current overall on-disk layout version.

ManifestVersionError

Raised for a newer unsupported layout.

ConfigStore load/save is the automatic wiring point in v1.3.0. Other users of the data root may call the public helpers explicitly.

Two different manifests

.openrath/manifest.json is an on-disk compatibility record. flow.ResourceManifest is a compile-time Workflow resource snapshot. They are unrelated despite sharing the word “manifest.”

Garbage collection#

from datetime import timedelta

from rath.persistence import gc

preview = gc(older_than=timedelta(days=30))
deleted = gc(older_than=timedelta(days=30), dry_run=False)

dry_run=True is the default. GCReport contains sessions, local_sandboxes, remote_sandboxes, memory_stores, memory_commits, and dry_run.

Deletion is confined to the resolved OpenRath data root. Pruning a remote sandbox deletes the local registry record; it does not terminate the remote container.

Autodoc#

rath.persistence.atomic_write_text(path: Path | str, text: str, *, newline: bool = False, encoding: str = 'utf-8', mode: int | None = None) None[source]#

Atomically write text to path.

Creates the parent directory if missing. Writes a uniquely-named temp file in the same directory, then os.replace it into place. Concurrent writers to the same resolved path are serialized; the Windows sharing-violation window is retried. On any failure the temp file is removed and the original target is left untouched.

newline appends a trailing "\n" when the caller has not already. mode (e.g. 0o600) restricts the final file on POSIX; ignored on Windows (matching rath.config.secrets.chmod_user_only()).

rath.persistence.atomic_write_json(path: Path | str, payload: Any, *, indent: int | None = 2, sort_keys: bool = False, ensure_ascii: bool = False, mode: int | None = None) None[source]#

Atomically write payload as JSON to path.

Serialization happens before the temp file is created, so an unserializable payload raises without touching the filesystem (no temp debris, original target intact). Otherwise defers to atomic_write_text().

rath.persistence.gc(*, older_than: timedelta, dry_run: bool = True) GCReport[source]#

Sweep prunable artifacts older than older_than across all planes.

With dry_run=True (default) nothing is deleted — the report lists what would be removed. With dry_run=False the existing per-plane prune helpers run and the memory commits archive is trimmed. Deletion is confined to the resolved data root.

class rath.persistence.GCReport(sessions: list[~uuid.UUID] = <factory>, local_sandboxes: list[~uuid.UUID] = <factory>, remote_sandboxes: list[~uuid.UUID] = <factory>, memory_stores: list[~uuid.UUID] = <factory>, memory_commits: list[~pathlib.Path] = <factory>, dry_run: bool = True)[source]#

What a gc() sweep removed (or would remove, in dry-run).

rath.persistence.ensure_manifest(root: Path) dict[str, Any][source]#

Create the manifest if missing; return the effective manifest.

Idempotent: an existing current-layout manifest is refreshed with the latest per-plane schema versions but keeps its layout version.

rath.persistence.check_manifest(root: Path) None[source]#

Raise ManifestVersionError if the layout is newer than ours.

No-op when the manifest is absent (fresh or legacy root) — this must never break an install that predates the manifest.

exception rath.persistence.ManifestVersionError[source]#

Raised when the on-disk layout version is newer than this install.

← API Reference