From a6aab6d2ccbba0b136d7d0f0eac23407ef896447 Mon Sep 17 00:00:00 2001 From: Sinity Date: Mon, 27 Jul 2026 14:03:36 +0200 Subject: [PATCH] fix(storage): declare index schema v40 query-unit-frame delta Problem devtools lab policy schema-versioning was failing on master: "undeclared index schema deltas found: 1, missing: [40]". PR #3068 (polylogue-z9gh.9) bumped INDEX_SCHEMA_VERSION from 39 to 40, adding the query_unit_frame_state table plus its insert/update/delete triggers on session_links, sessions, messages, blocks, session_tags, session_profiles, and delegation_facts -- but never added the matching IndexDeltaDeclaration the policy lint requires for every version bump. INDEX_DELTA_DECLARATIONS jumped straight from version=39 to version=41 (added later by polylogue-2i2w), silently skipping 40. What changed Add IndexDeltaDeclaration(version=40, ...) to polylogue/storage/sqlite/lifecycle.py describing the real v40 delta: classes=(DerivedDeltaClass.INDEX_ONLY,) with one FastForwardOperation (kind=REPLACE_TABLE) whose objects list the query_unit_frame_state table and all 21 query_unit_frame_* triggers, matching the exact set added in df8683767 (#3068). No canonical DDL, executor, or runtime behavior changes -- this is purely a documentation-shaped fix that lets the schema-versioning lint recognize a clone-safe delta that already exists and is deployed. Verification - `devtools lab policy schema-versioning` before: "undeclared index schema deltas found: 1, missing: [40]"; after: "undeclared index schema deltas found: 0" / "Schema evolution policy intact." - `devtools test tests/unit/storage/test_index_fast_forward_lifecycle.py tests/unit/storage/test_index_fast_forward_executor.py`: the two tests this fix targets (test_current_index_schema_has_a_complete_delta_declaration, test_schema_policy_rejects_an_index_bump_without_a_delta_declaration) now pass. Two unrelated pre-existing failures remain (test_nonsemantic_delta_without_operations_is_rejected, test_delta_without_a_declared_class_is_rejected) -- confirmed via `git stash` to already fail identically on master, caused by a separate latent bug where invalid_versions flags every declaration with version > current_version regardless of the version-40 gap. Not in scope for this fix. - `mypy --strict polylogue/storage/sqlite/lifecycle.py`: no issues - `ruff check` / `ruff format --check` on the touched file: clean - `devtools render all --check`: no drift Ref polylogue-5h5y Co-Authored-By: Claude --- polylogue/storage/sqlite/lifecycle.py | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/polylogue/storage/sqlite/lifecycle.py b/polylogue/storage/sqlite/lifecycle.py index 5a4f49ceee..26b3e5a5eb 100644 --- a/polylogue/storage/sqlite/lifecycle.py +++ b/polylogue/storage/sqlite/lifecycle.py @@ -232,6 +232,51 @@ class IndexDeltaDeclarationReport(TypedDict): # source evidence its nodes and edges cite. classes=(DerivedDeltaClass.SEMANTIC_REPARSE,), ), + IndexDeltaDeclaration( + version=40, + # Adds query_unit_frame_state (polylogue-z9gh.9, PR #3068): a + # singleton, trigger-maintained epoch counter that composes with the + # user-tier assertion epoch to bind query-unit continuation resumes + # to the exact archive snapshot they were issued against. Insert, + # update, and delete triggers on session_links, sessions, messages, + # blocks, session_tags, session_profiles, and delegation_facts each + # bump the counter -- every table already exists at v39 and gains + # only a maintenance trigger, so no row is reparsed or reshaped. The + # table itself starts at epoch=0 via INSERT OR IGNORE. A clone can + # therefore create the table and its 21 triggers verbatim from + # canonical INDEX_DDL with no semantic reparse of raw evidence. + classes=(DerivedDeltaClass.INDEX_ONLY,), + operations=( + FastForwardOperation( + name="v40-query-unit-frame-state", + kind=FastForwardOperationKind.REPLACE_TABLE, + objects=( + ("table", "query_unit_frame_state"), + ("trigger", "query_unit_frame_session_links_insert"), + ("trigger", "query_unit_frame_session_links_update"), + ("trigger", "query_unit_frame_session_links_delete"), + ("trigger", "query_unit_frame_sessions_insert"), + ("trigger", "query_unit_frame_sessions_update"), + ("trigger", "query_unit_frame_sessions_delete"), + ("trigger", "query_unit_frame_messages_insert"), + ("trigger", "query_unit_frame_messages_update"), + ("trigger", "query_unit_frame_messages_delete"), + ("trigger", "query_unit_frame_blocks_insert"), + ("trigger", "query_unit_frame_blocks_update"), + ("trigger", "query_unit_frame_blocks_delete"), + ("trigger", "query_unit_frame_session_tags_insert"), + ("trigger", "query_unit_frame_session_tags_update"), + ("trigger", "query_unit_frame_session_tags_delete"), + ("trigger", "query_unit_frame_session_profiles_insert"), + ("trigger", "query_unit_frame_session_profiles_update"), + ("trigger", "query_unit_frame_session_profiles_delete"), + ("trigger", "query_unit_frame_delegation_facts_insert"), + ("trigger", "query_unit_frame_delegation_facts_update"), + ("trigger", "query_unit_frame_delegation_facts_delete"), + ), + ), + ), + ), IndexDeltaDeclaration( version=41, # action_pairs stops materializing tool_input/output_text text