The full self-contained markdown (root-cause analysis, on-disk protocol, byte-exact code, tests, and verified output) is at ~/SOLUTION.md (copy at ~/cac/SOLUTION.md), with the runnable implementation in ~/cac/{cache.js,test.js,crash-child.js}.
The full self-contained markdown (root-cause analysis, on-disk protocol, byte-exact code, tests, and verified output) is at ~/SOLUTION.md (copy at ~/cac/SOLUTION.md), with the runnable implementation in ~/cac/{cache.js,test.js,crash-child.js}.
The failures are five missing guarantees, not one bug:
fsync → atomic link(2), which fails EEXIST, so identical concurrent uploads converge on one inode.unlink TOCTOU. A manifest can acquire a reference between the refs==0 check and the unlink.reserves every newly referenced blob before the atomic rename that publishes it. Eviction succeeds only when refs == 0 && reserved == 0, under the same per-shard lock → the published manifest's reference set is undeletable from the instant it is visible.refs from manifests; the per-shard WAL only records reservations (multi-process correctness) and evict intents (so an interrupted unlink is completed).<crc32>\t<json>\n; replay stops at the first bad/short record and truncates the torn tail.shard = parseInt(hash[0:8],16) % S, one mutex + journal per shard, plus a per-manifest-name mutex. Reservations hold exactly one shard lock at a time and release before the next → no deadlock, no global serialization.Linearization points: commit = rename; eviction = unlink (WAL evict written before it).
The document is self-contained: extracting its three js blocks reproduces the source files byte-identically, and running from the extracted directory passes:
ok basic put/get and manifest commit/delete (8ms)
ok concurrent identical uploads converge to one blob (25ms)
ok commit-vs-evict race never yields a manifest with a dead blob (93ms) # 300 raced trials
ok sweep storm preserves committed blobs (13ms) # 600 concurrent ops
ok crash recovery: torn tail, orphan reserve, interrupted evict (3ms)
ok SIGKILL during commit/sweep loop is recoverable (370ms) # 5 real SIGKILLs
6 test group(s) passed
Run it yourself:
cd ~/cac && node test.js
The suite was run five consecutive times with identical results (no flakiness). The key invariant — if a manifest is committed, all of its blobs are present — is asserted both under in-process races and after real SIGKILL recovery.
Limitations are stated honestly in §5: the reference implementation is single-process with full intra-process concurrency; the same protocol extends to multi-process by adding a per-shard OS advisory lock around the reservation-append critical section, with no new invariants.
# Evidence - Problem class: js-20261008-content-addressed-cache-linearizable-eviction-races - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-10-08T17:10:34.506Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Implement a sharded content-addressed cache that supports concurrent reads, writes, conditional eviction, and crash recovery while preserving linearizable metadata and never deleting a blob still referenced by a committed manifest. Specify the on-disk journal protocol and resolve races between deduplicated uploads, eviction, and recovery without globally serializing operations.", "environment": "node20", "language": "js", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "js-20261008-content-addressed-cache-linearizable-eviction-races", "provider": "openrouter", "solved_at": "2026-10-08T17:10:34.506Z", "version": "20"}