Expand description
G114 — Write-Ahead Log (WAL) sidecar for crash recovery (v0.1.12). G114 — Write-Ahead Log (WAL) sidecar for crash-safe atomic writes.
§Problem
The atomic_write pipeline has 13 steps. If the process is killed
(SIGKILL, OOM, power loss) between any two steps, the target file may
be left in a partially-written, truncated, or otherwise inconsistent
state. The variant AtomwriteError::CopyBackBlake3Failed (exit 92)
indicates a partial WriteStrategy::CopyBack failure, but offers no
recovery mechanism.
§Solution
Before performing any write, append a JSON journal entry to a sidecar
file .atomwrite.journal.<target>.json that records:
- The operation type (
write/replace/edit) - The target path (relative to workspace)
- The BLAKE3 checksum of the previous content (if any)
- The BLAKE3 checksum of the new content (precomputed)
- The PID and start timestamp
- A 16-byte random
op_idfor idempotency
After the atomic rename succeeds, append a committed entry with the
same op_id. On startup, the recover_orphan_journals function scans
for .atomwrite.journal.*.json files whose last entry is not
committed, and emits a structured NDJSON event wal_recovery per
orphan, listing the original target, the pre-computed
expected_new_checksum, and the recorded op_id for the caller to
decide whether to replay or abort.
§Causa x Efeito
- Causa:
atomic_writeé uma sequência de 13 passos; crash entre qualquer par pode deixar o arquivo em estado inconsistente. - Efeito: Sem WAL, recovery exige intervenção manual via
git checkout,cpdo backup mais recente, ou heurística ad-hoc. - Solução: Sidecar journal append-only + recovery idempotente via
op_id; recovery é puramente consultivo (não toca o filesystem). - Benefício: Operador recebe
wal_recoveryNDJSON estruturado comtarget,expected_new_checksum,op_idpara replay manual ou script de recovery.
Modules§
- heuristics
- Heuristics for deciding whether a
Committedsidecar should be kept past the immediate Drop-guard removal (G119 L4).
Structs§
- Auto
Heal Report - Result of an auto-heal pass on startup (G119 L3).
- Journal
Guard - RAII guard that removes the sidecar journal on normal drop (G119 L2).
- Orphan
Journal Report - Per-sidecar recovery report emitted by
recover_orphan_journals. Populated for every sidecar whose last entry isStarted(a real orphan that needs operator attention) and for sidecars whose last entry isCommittedorAborted(informational; safe to clean). - WalDir
Entry - Count of journals in a single directory.
- WalState
Breakdown - Breakdown of journals by terminal state.
- WalStats
- Snapshot of journal state for
wal-stats(G119 L5 telemetry).
Enums§
- Journal
Entry - A single entry in the append-only WAL journal.
- Journal
Op - Operation type recorded in the journal.
- WalPolicy
- Policy governing WHEN a WAL sidecar is created (G119 L1 prevention).
Constants§
- L1_
LARGE_ FILE_ BYTES - Threshold above which a target file is considered “large” for the L1
prevention heuristic. Files smaller than this on a routine write do
not generate a WAL sidecar in
WalPolicy::Automode.
Functions§
- auto_
heal_ on_ startup - Auto-heal stale terminal journals on startup (G119 L3).
- compute_
wal_ stats - Compute a snapshot of the current journal state. Read-only and safe
to call from any context. Used by the
wal-statssubcommand (G119 L5). - generate_
op_ id - Generate a 16-hex-char op ID from random bytes.
- heuristics_
should_ preserve - Compose all 5 L4 heuristics into a single decision. Returns
truewhen AT LEAST ONE heuristic votes to PRESERVE the sidecar. - journal_
aborted - Append an
Abortedentry to the journal fortarget. - journal_
committed - Append a
Committedentry to the journal fortarget. - journal_
path - Compute the sidecar path used as the WAL journal for
target. - journal_
started - Append a
Startedentry to the journal fortarget. - journal_
started_ with_ guard - Wrap a
Startedjournal write in a Drop guard. On normal scope exit (the caller did not callkeep()), the sidecar is removed — theCommittedentry is the last useful record and the file is deleted to keep the working tree clean (G119 R1 fix). - recover_
orphan_ journals - Scan
dir(non-recursive) for.atomwrite.journal.*.jsonsidecars and emit a recovery report for each orphan. - should_
create_ sidecar - Decide whether a sidecar should be created for
targetgiven the operation kind and the active policy (G119 L1). - walk_
journal_ paths - Recursively walk a directory and yield all
*.atomwrite.journal.jsonsidecar paths. Returns an empty Vec if the workspace does not exist.