fix(daemon): bloom-aware warm gate (warm_plan RPC) + compact-cache delta-poisoning fix - #614
Merged
Merged
Conversation
…mpty-trigram reader gap Two writer/reader mismatches produced the recurring 'bloom k_hashes out of range' quarantines (2026-08 drive-C ten-day incident; winbox M/C/D/S on 2026-08-24, caches provably written by the then-current daemon between two restarts): 1. READER: the v6+ writer always emits the full trigram CSR - an empty index still writes its [0] offsets entry plus a zero values count - but both loaders' tkc>0 fast-path consumed only the key count in the empty case, shifting every later section by 8 bytes. Both readers now walk the real shape; an empty on-disk trigram is rebuilt from records rather than adopted. 2. WRITER (the live producer): the surgical-patch path appends created records while children/trigram/ext stay the Arc-shared bases (edges in the delta overlay). serialize then wrote a children CSR sized rc_base+1 under a header saying rc_new - the reader, sizing from the header, mis-walks everything after; small shifts even LOAD silently corrupt. Fires whenever a drive had >=1 create since the last 50k-threshold fold at save time. Save-bound patches now fold the delta inside the patch task (fold_delta_for_save), and save_compact_cache_background refuses any delta-carrying index outright so no future path can reintroduce the poison. Regression tests pin the exact field error, both faces of the poison round-trip, the fold repair (created record's child edge present), the boundary refusal, and the save-vs-apply fold contract.
…nal gates must use The MCP warm gate inferred readiness from the tier marker alone: any Parked/Cold drive in a query's scope produced 'index warming - poll uffs_status, retry' plus a detached warm trigger that force-promoted the drive's body into RAM. But the daemon's own dispatch bloom-skips a Parked drive whose bloom proves it holds nothing matching the query's extension filter (Phase-4 zero-RAM-touch): such a drive answers instantly with zero rows and is ready by definition. The gate and dispatch disagreed - field 2026-08-24, winbox drive E: (docenta via uffsmcp). The daemon now exposes warm_plan: given the SAME SearchParams a search would carry, it returns the promote set dispatch would actually execute - same canonicalisation, same filter resolution (build_search_filters, factored out of run_search_over so the two can never drift), same bloom pre-check, all funneling into the shared promote_plan the dispatch itself now calls. The MCP gate consumes the plan and warms only daemon-named drives; the tier-based check remains solely as the conservative fallback for pre-v0.6.38 daemons (method-not-found detection). Parity pinned at three levels: promote_plan against the tight-bloom fixture (miss => empty plan, hit/no-filter => planned, scope respected), warm_plan from wire params through the real filter pipeline, and the MCP fallback selection on exact error shape.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two field bugs from the winbox logs (2026-08-24), both root-caused to source and test-pinned. Ships as v0.6.38.
1. MCP warm gate contradicted the daemon's bloom (drive E: report)
The gate inferred readiness from the tier marker: any Parked/Cold drive in scope →
⏳ index warming — retry+ a detached warm trigger that force-promoted the body into RAM. But dispatch bloom-skips a Parked drive whose bloom proves it irrelevant to the query's ext filter (Phase-4 zero-RAM-touch) — that drive answers instantly with zero rows and is ready by definition.Fix: new
warm_planRPC — the daemon returns the exact promote set dispatch would execute (same canonicalisation, same filter resolution via the newly factoredbuild_search_filters, same bloom pre-check, all through the sharedpromote_plandispatch itself now calls — one computation, so gate and dispatch can never disagree). The MCP gate consumes the plan and warms only daemon-named drives; the tier check survives solely as the conservative fallback for pre-v0.6.38 daemons.2. Compact-cache poisoning — the recurring
bloom k_hashes out of rangequarantinesField evidence (docenta-relayed winbox logs): M/C/D/S caches written by v0.6.37 itself between two restarts quarantined on the next start; also retro-explains the 2026-08 "drive C failed for ten days" incident. AES-GCM proves the bytes were written misaligned, not disk-corrupted.
[0]offsets entry + zero values count), but both loaders'tkc > 0fast-path consumed only the key count in the empty case — 8 unconsumed bytes shifting ext-names/bloom/trie/frs. Both readers fixed; empty on-disk trigram is rebuilt from records.serializewrote a children CSR sizedrc_base+1under a header sayingrc_new— the header-driven reader mis-walks everything after; small shifts even load silently corrupt. Fires whenever a drive had ≥1 create since the last 50k-threshold fold at save time — exactly the M/C/D/S vs E/F/G split. Fix: save-bound patches fold the delta inside the patch task (fold_delta_for_save);save_compact_cache_backgroundrefuses any delta-carrying index outright (boundary enforcement).Tests: the exact field error reproduced pre-fix (
bloom k_hashes out of rangefrom an empty-trigram save); both faces of the poison round-trip (quarantine + silent); fold repair with the created record's child edge present; boundary refusal; save-vs-apply fold contract; warm-plan parity at three levels; MCP fallback selection.Field note: until this lands on winbox, v0.6.37 keeps writing delta-poisoned caches for drives with creates — each restart quarantines + full-rebuilds them (loud, correct, minutes of warm cost). Historic silently-misaligned loads on affected generations are unknowable retroactively; noted for release notes.
Verified: full
just gogreen, xwin clippy-D warningsgreen, 913 uffs-core + full daemon/mcp/client suites green.