Compute <project_root>/.agent-doc/crdt-replica-events/<hash>.json for a
document. The controller writes this as an editor-facing event signal after
CRDT fan-out or replace rebootstrap work is queued, and editor plugins watch
the directory to drain pending replica deliveries without polling.
Compute <project_root>/.agent-doc/disk-change-requests/<hash>.json for a
document. The controller watch daemon drops this marker when the file changed
on disk out of band; the CPC/controller consumer reads it, reconciles the
change into the canonical replica, and clears it (the marker + idle-poll
cross-process signal, mirroring recycle-request).
Preserve a buffer the merge is about to drop to a durable recovery sidecar at
<project_root>/.agent-doc/recovery/<hash>.<pid>-<seq>.md, so concurrent
operator text is recoverable instead of silently lost (#qftlossdelta).
Written atomically; returns the sidecar path. Best-effort by the caller —
this is a safety net alongside, not a replacement for, the merge decision.
Rename a corrupt state file aside to a sibling <name>.corrupt-<pid>-<seq>
so it stops wedging reads while remaining available for forensics. A file
that raced away (already removed) is treated as success.
Read path and parse it with parse. Missing → Ok(None). If the file
exists but is empty / whitespace-only / fails to parse (a corrupt state
file — e.g. a 0-byte controller-state.json left by a pre-write_atomic
interrupted write or an external truncation), quarantine the bad file by
renaming it aside and return Ok(None) so the caller reboots from a clean
slate instead of wedging on every future read.
Atomically write contents to path by writing a sibling temp file and
renaming it into place. rename(2) on the same filesystem is atomic, so a
crash or execve mid-write leaves either the previous file or the
fully-written new one — never a truncated/0-byte file. Creates the parent
directory if missing.