Storage Operations
Meerkat resolves durable realm state through oneStorageLayout and one
realm-level storage provider. The rkat storage commands operate below normal
runtime scope so they can inspect or repair states that ordinary realm
resolution correctly refuses.
The three commands have deliberately different safety contracts:
These commands never read, move, or report credential stores. A persistent
rkat-rpc host also keeps approval records in approvals.json under its
resolved persistence store path. That RPC-owned sidecar is not an eighth
StorageProvider domain, and the current storage doctor, migration, and prune
commands do not inventory, migrate, or delete it.
Select Roots And Realms
Without explicit roots, storage commands inspect two sweep candidates:- invocation-context-local
<context-root>/.rkat/realms - the user-global Meerkat data root
.rkat, so run storage commands from that project root (or pass --root) when
you want their local sweep to match the runtime’s project-local candidate.
Use global --state-root or repeatable command --root to provide an explicit
set. Once either is present, only those roots are read; ambient candidates are
not added. Global --realm restricts work to one validated realm ID while
still detecting twins across every swept root.
--default-model are rejected.
Read-Only Diagnosis
rkat storage doctor is safe against a live realm. It takes no realm lease or
maintenance fence, never changes logical database content, and never creates a
database or directory. A read-only SQLite connection may create or update the
-wal/-shm sidecars required for a coherent read of a live WAL database.
On truly read-only media, a WAL database without the required sidecars fails
typed instead of falling back to an unsafe immutable read.
- realm inventory by root and manifest/backend state
- per-database
meerkat_schemaledger domains and versions - the same realm ID materialized under more than one swept root
- persisted-session structural decode failures and transcript footprint
- dangling session-to-blob references
- orphaned lock, lease, index, and registered backup artifacts
0 when there are no error-severity findings and 1 when
errors are present. Warnings and informational findings alone do not make the
command fail.
The CLI reaches the built-in disk migrator because it intentionally runs
before an external-provider realm can be composed. External providers expose
the same
StorageMigrator::diagnose contract through their provider-native
operator surface; an unknown external backend is report-only to this CLI.Dry-Run And Apply Migrations
storage migrate is a dry run by default:
mobs/
remain report-only in migration v1.
Apply only with the realm offline or after verifying all writers honor the
shared maintenance fence:
--fence-wait-secs.
Migration refuses when the fence cannot be acquired, a schema is from the
future, the manifest is unreadable, durable identity is ambiguous, or input
does not match a recognized predecessor. It never guesses a merge.
Exit status is 0 for a clean report and 1 for an error or fail-closed
refusal.
Resolve A Split-Brain Realm
If one realm ID exists under multiple swept roots, ordinary runtime resolution and migration both fail closed. First inspect the divergence report:*.pre-<version>-<timestamp> naming scheme.
Meerkat does not synthesize or merge divergent WorkGraph event streams,
schedule aggregates, or session histories.
--adopt-root requires --apply and must name one of the swept roots that
actually contains the realm.
Recover Storage From Before 0.8.10
Ordinary opens enforce the v0.8.10 compatibility floor. Current releases also provide an explicit, fenced bridge for authenticated historical SQLite schemas:sqlite backend. It verifies an exact known physical schema and durable
evidence before importing, then normal strict migration continues under the
same fence. Unknown, malformed, ambiguous, JSONL, memory, and external-provider
state is refused without stamping a ledger version.
Take an external backup or immutable generation snapshot before this recovery
path. The bridge is not an authorization to repair by hand or invent missing
authority.
Prune Registered Maintenance Artifacts
storage prune is unrelated to live realm deletion. Its dry run lists only
recognized migration backups and index quarantines:
*.pre-<version>-<timestamp> backups and
*.corrupt-<timestamp> quarantines under the swept roots are candidates.
The command never deletes a live realm or an unregistered filename. Use
rkat realm delete or rkat realm prune for realm lifecycle.
Exit status is 1 only when deletion/reporting errors occur.
Recover From A Durable Projection Halt
If appending a canonical session event fails, the persistent session path records a durable projection-halt marker and refuses replay or resume past the hole. There is currently no self-service command to clear or repair that marker, andstorage doctor does not report it. Do not delete or edit it by
hand. Stop writers, preserve the complete store for diagnostics, and restore
an independently verified complete generation or escalate the store for
provider-specific recovery.
Operational Runbook
For an unreadable or refused realm:- Stop writers if any mutation may be needed.
- Run
storage doctor --jsonagainst an explicit root set and save the report with the deployment evidence. - If the issue is split-brain, identify the authoritative generation from
external provenance, then use
--apply --adopt-root. Do not choose by newest timestamp alone. - If the report identifies pre-v0.8.10 SQLite state, take a backup and use the explicit compatibility bridge.
- Run
storage migrateas a dry run, then--applyonly after the report is clean and the maintenance fence can be acquired. - Run
storage doctoragain and boot the candidate normally. - Prune registered backups only after the rollback window expires.
