The process suite required the loser of a stale-lock contest to
be timed-out. On a slow runner the winner's unlink-guard /
create-successor gap is missing+missing, which the lock honestly
reports as completed-by-other (#904).
Exactly one owner still publishes. The loser may be timed-out,
completed-by-other, or unavailable — never parsed. Do not delay
the clean-release path by treating missing+missing as wait-out.
observe() classified a stable unparseable session-refresh.lock body as the
terminal 'unavailable'. parseAllSessions routes that to a read-only parse, so a
zero-byte or truncated lock froze warm-cache ingestion permanently across every
later run while each command still exited successfully.
A corrupt body is now a recoverable observation carrying a real mtime, and is
recovered only through the UNMODIFIED staleness gate — tryTakeover and the age
check are byte-identical to main. sameObservation gains an explicit null/non-null
boundary and a sha1 of the raw bytes, because two corrupt bodies have no tokens
to compare and mtime granularity is coarse on some filesystems.
The heartbeat deliberately does NOT rewrite a body it cannot prove is its own.
An owner that cannot prove ownership ends its ownership: mtime stops advancing,
the publication fence refuses, and a successor recovers the lock one staleMs
later. Losing that parse is the price of never having two owners.
* cache: strict cross-process gate for the warm session-cache refresh transaction (#645)
* lock: serialize the fence against the owner's own heartbeat
verifyStillOwner and the heartbeat tick both take the takeover guard;
without in-process serialization the fence could observe its own
heartbeat's guard file, read it as displacement, and abort a legitimate
publication. Fail-safe, but it discarded the parse the lock exists to
protect (~6% of verifies at a 1ms heartbeat in the repro). Owner-side
guard operations now run through one serializer; cross-process guard
semantics are unchanged. Regression test at heartbeatMs 1, mutation-
verified against the unserialized code.
---------
Co-authored-by: Aditya Vikram Singh <247195684+avs-io@users.noreply.github.com>
Co-authored-by: reviewer <review@local>