Skip to content

V4.1 Engram file-backed: release verify page cache (fail-closed on residue); batched fetch_rows gather - #12304

Merged
gunbai-bot[bot] merged 4 commits into
mainfrom
session/quick-lynx-421
Sep 26, 2026
Merged

gunbai-bot[bot] merged 4 commits into
mainfrom
session/quick-lynx-421

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Brief: node adhoc-213164f5-0bd (DS4.1, operator-approved 2026-09-25). Two fixes to FileBackedEngramStorage (dag/gunbc/spark/patches/d2d649e6/engram_file_backed.py.patch). The facts behind them are declared in the new gunbc.spark.v41_engram_file_backed.

Fix 1: release the page cache the checksum read leaves behind

  • Whole-file SHA-256 verification is kept, and it still fails closed. The magic check now reads the bytes from the same hash pass, so nothing touches the mmap before the release.
  • After verifying, open calls posix_fadvise(POSIX_FADV_DONTNEED) over the verified range. It then reads residency back with mincore over a transient mapping that is never touched, and returns EngramStoreOpenReceipt(verified_bytes, resident_bytes_after_verify, resident_bytes_after_release).
  • If any bytes are still resident, open refuses with EngramPageCacheResident. There is no toggle; a switch that keeps the cache would be a §5 escape hatch.
  • Model: V41StoreOpenReceipt / v41_open_residency_verdict. The verdict refuses a partial verification and any residue, down to one page.

Fix 2: batched fetch_rows

  • The mmap is exposed once as a zero-copy uint8 tensor. fetch_rows builds one flat index of offset + span and runs a single torch.index_select(out=) into the staging rows, in request order.
  • Every offset must be magic + k·record with the whole record inside the file, and nbytes must equal expected.record_bytes. That value is newly supplied, from v41_row_bytes, not minted in the patch. Anything else refuses the whole batch with EngramRowOffsetMisaligned.
  • The old per-row loop stays only as _fetch_rows_per_row, the differential oracle for the instrument. It is never a fallback.
  • Model: v41_gather_rows refuses non-record offsets; each row is the store's bytes at a v41_row_address offset.

Claims (test.claim.spark.v41_engram_file_backed_witness)

  • RED (a) verification_that_leaves_the_cache_resident_refuses, with positive control a_verified_store_whose_cache_was_released_opens.
  • RED (b) the_batched_gather_is_the_per_row_records_in_request_order_over_boundary_rows: the batch equals v41_place_row records at a rank's first and last local rows, out of order and with a repeat. Also a_shifted_offset_batch_refuses: an offset shifted +1, one inside the magic, and one past the end.

Execution status of these claims: a remote gunbc run was OOM-killed (rc=137) on closure load, including for the trivial receipt claim. Their first execution is this PR's floor run; I'll report it here.

Python realization, executed locally (torch 2.14 cpu, synthetic store of magic + 200k × 264-byte records)

  • Receipt after open shows full residency after verify and 0 after release.
  • Holding a touched mmap of the store open makes open refuse with EngramPageCacheResident, which is RED (a) on the real path.
  • Batched and per-row bytes are identical, and equal to the file bytes, at rows 0, 1, n-2, n-1 in mixed order. A wide non-contiguous staging tensor also works. Offset +1, offset inside the magic, offset past the end, and nbytes ≠ record all refuse.

Instrument (§6: named, not transcribed)

measure_fetch_rows(storage, rows, repeats), also python3 engram_file_backed.py --store … --rank-digest-hex … --magic-hex … --record-bytes … --rows N. It reports seconds per call for batched and per-row, bytes_agree, and the open receipt. My first batched version (advanced indexing) was slower than per-row at N=12, the per-token size. index_select(out=) fixed that. Re-run the instrument on a Spark rank for the real figures.

Out of scope / frontier

  • A live receipt needs the _allocate_weights wiring patch, which is already the named trigger in v41_engram_row_store.
  • clever-gull-48's per-rank distinct-page counter and metrics surface is not in this PR. I replied to them, and proud-deer-538 decides whether it gets a follow-up.

🤖 Generated with Claude Code

gunbc-ci-auto-heal and others added 2 commits September 25, 2026 16:29
…sidue); batched fetch_rows gather

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…el; receipt carries store_bytes; name the verdict's consumer frontier

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

Addressing review 71352 (REQUEST_CHANGES) in the new commit.

  • Drift, fixed. The realization now refuses exactly where v41_open_residency_verdict does. _verify_and_release reads fstat size and raises when the hashed bytes differ from the store size. EngramStoreOpenReceipt now carries store_bytes, so its fields are V41StoreOpenReceipt's. Re-ran locally: the receipt shows store_bytes = verified_bytes, and residue 0 after release. The module annotation now maps each Python raise to its model branch, including _record_index ↔ v41_is_record_offset.
  • Consumer (§3c). I took option 1, not option 2, because the brief places the behaviour's facts in the model and treats the patch as realization. The consumer is now named as a declared frontier with its trigger: the wiring patch in _allocate_weights, already the named trigger in v41_engram_row_store, reads each rank's receipt into v41_runtime_candidate, next to v41_published_store_readback_readings, and folds it through the verdict, so a rank that stayed resident refuses the candidate. §3c admits this state only with its trigger stated; it is not a consumer in this closure yet.
  • What remains true: no enrolled check executes the Python against the fold. Torch isn't available on CI, and I ran the Python locally. I won't claim more than that.

— sent from quick-lynx-421

gunbc-ci-auto-heal and others added 2 commits September 25, 2026 18:39
… (UnimportedBareProvider)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tructor type built outside its module)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 25, 2026
Merged via the queue into main with commit 1f5150e Sep 26, 2026
5 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/quick-lynx-421 branch September 26, 2026 01:05
@briansrls
briansrls restored the session/quick-lynx-421 branch September 26, 2026 01:10
gunbai-bot Bot pushed a commit that referenced this pull request Sep 26, 2026
…es.dag keeps main's any, moved fns stay on std.algebra

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Sep 26, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants