host-persist: content-addressed blob adapter — Blocker CLOSED
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 40s

blob/put|get|has? backed by <root>/blobs/<cid>, CIDv1 (raw codec,
sha2-256 via Sx_cid/Sx_sha2). put idempotent; persist stores only the
{:cid :size :mime} ref. persist_durable_test.sh extended (8/8): blob
round-trip + content-address idempotency + bytes/ref surviving real
restart. Mock blob suite 14/0 on worktree binary. Durable-storage
Blocker now CLOSED.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-06 22:56:27 +00:00
parent c6c2cebf98
commit 95e981eb03
3 changed files with 84 additions and 9 deletions

View File

@@ -197,6 +197,16 @@ durable backend. Other subsystem loops copy this pattern; it does not touch the
real `lib/acl`.
## Progress log
- **Host durable-storage adapter — blob adapter LIVE, Blocker CLOSED (8/8).**
Added content-addressed `blob/put|get|has?` to `sx_persist_store.ml`: bytes
land in `<root>/blobs/<cid>` keyed by a CIDv1 (raw codec, sha2-256 via
`Sx_cid`/`Sx_sha2`); `put` is idempotent (identical bytes → same cid → same
file); persist stores only the `{:cid :size :mime}` ref, never the bytes. The
`(eval ...)`/bridge/resolver fall-through already routes any unowned op to the
store, so no new wiring was needed. `persist_durable_test.sh` extended:
blob round-trip, content-address idempotency, and bytes+ref-in-kv surviving a
real process restart — all green. Existing mock blob suite 14/0 against the
worktree binary. The host durable-storage Blocker is now CLOSED.
- **Host durable-storage adapter — durable+recovery LIVE (5/5 acceptance).**
`hosts/ocaml/lib/sx_persist_store.ml` services every `persist/*` IO op against
real on-disk storage (append-only log + separate monotonic `.seq` high-water
@@ -323,20 +333,26 @@ real `lib/acl`.
## Blockers
### IN PROGRESS — host durable-storage adapter (the only gap to real durability)
### CLOSED — host durable-storage adapter (real durability is live)
**Owner:** the `loops/host-persist` loop (`hosts/**` scope; `lib/persist/**` is
its contract, not its code).
**Status (2026-06-06):** durable `persist/*` ops DONE — implemented in
`hosts/ocaml/lib/sx_persist_store.ml`, wired into all three IO sites of
`hosts/ocaml/bin/sx_server.ml`, acceptance + real-restart recovery green
(`hosts/ocaml/test/persist_durable_test.sh`, 5/5). The silent-data-loss repro
below now returns the correct values. **Remaining before CLOSED:** the blob
adapter (`blob/put|get|has?`, see "Blobs" below). Original spec retained for
reference.
**Resolution (2026-06-06):** `hosts/ocaml/lib/sx_persist_store.ml` services every
`persist/*` AND `blob/*` IO op against real on-disk storage, wired into all three
IO sites of `hosts/ocaml/bin/sx_server.ml` (the `(eval ...)` suspension loop, the
`cek_run_with_io` bridge, and the in-process `_cek_io_resolver`). The
silent-data-loss repro below now returns the correct values instead of
`(1 0 nil)`. Acceptance + real-process-restart recovery green
(`hosts/ocaml/test/persist_durable_test.sh`, 8/8): durable round-trip,
monotonic-seq-across-truncate, streams-survive-compaction, kv, blob
content-addressing/idempotency, and bytes+refs surviving an actual process
restart. Existing mock suites unaffected (blob 14/0, durable 10/0, recovery,
against the worktree binary). A subsystem migrated per
`lib/persist/examples/acl.sx` is now genuinely durable. Original spec retained
below for reference.
**Without it, durable persistence silently drops all writes.**
**Was:** without it, durable persistence silently dropped all writes.
**Symptom / minimal repro.** `persist/durable-backend` performs
`{:op "persist/..." :args (...)}` for every storage op. Under `sx_server.exe`