Rust: a cache must pull its stores before it writes (cache-must-pull-before-write) #133

Merged
libby merged 2 commits from libby/cache-must-pull-before-write-rs into main 2026-11-12 08:01:33 +00:00
Member

Closes follow-up cultlib-gaps:follow_up:cache-must-pull-before-write.

A cache attached to a populated store that never pulled held an empty image, so put_prepared_batch replaced the store with only its new keys (data loss, predates bytes-after). require_loaded now also refuses while the cache is unpulled: never pulled, or a store attached after the last pull. A cache with no stores needs no pull. Refusal is CultCacheLoadRefused, as for a refused load.

Tests: wipe reproduced first (single-file and redb), then gate across batch, put, put_raw_envelope and delete; pull lifts it; late attach closes it. 36 existing tests pulled after attach as the rule now requires.

Parity: C# and Python write staged records onto the store (read from source). TS does NOT: pushAll replaces the file, so CultMesh.createNode(pullOnStart:false) then flush() wipes it (follow-up ts-flush-replaces-store). A cache that pulled but is stale still wipes in Rust (follow-up rs-batch-merges-onto-store). Soul: three integration tests, is_writable and the changelog were fixed in d1a028f6.

🤖 Generated with Claude Code

Closes follow-up `cultlib-gaps:follow_up:cache-must-pull-before-write`. A cache attached to a populated store that never pulled held an empty image, so `put_prepared_batch` replaced the store with only its new keys (data loss, predates bytes-after). `require_loaded` now also refuses while the cache is unpulled: never pulled, or a store attached after the last pull. A cache with no stores needs no pull. Refusal is `CultCacheLoadRefused`, as for a refused load. Tests: wipe reproduced first (single-file and redb), then gate across batch, put, put_raw_envelope and delete; pull lifts it; late attach closes it. 36 existing tests pulled after attach as the rule now requires. Parity: C# and Python write staged records onto the store (read from source). TS does NOT: pushAll replaces the file, so CultMesh.createNode(pullOnStart:false) then flush() wipes it (follow-up ts-flush-replaces-store). A cache that pulled but is stale still wipes in Rust (follow-up rs-batch-merges-onto-store). Soul: three integration tests, is_writable and the changelog were fixed in d1a028f6. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Rust: a cache must pull its stores before it writes (cache-must-pull-before-write)
Some checks failed
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 10m23s
dbbd25f74d
A cache attached to a populated store that never pulled held an empty image, so put_prepared_batch replaced the store with only its new keys. The require_loaded gate now covers a never-pulled state (and a store attached after a pull) as well as a refused load. A cache without stores needs no pull. Pinned in single-file and redb.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Rust: pull gate covers is_writable and the integration tests, with a changelog entry
All checks were successful
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Successful in 20m18s
d1a028f6c4
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
libby merged commit 12f3801893 into main 2026-11-12 08:01:33 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/CultLib!133
No description provided.