From f2ad571290346d93e8d97d0a22ac1324d07dee15 Mon Sep 17 00:00:00 2001 From: Sinity Date: Sun, 2 Aug 2026 15:08:05 +0200 Subject: [PATCH] fix(test): add real message content to raw-materialization fixtures Problem `devtools test tests/unit/storage/test_repair.py -k raw_materialization` failed 11 of 48 tests on master, reproducible on a clean checkout (polylogue-3jv24). Every failure traced back to the same cause: PR #3497 wired `require_positive_conversational_evidence` into `sources/revision_backfill.py` (the offline replay path raw materialization repair uses), refusing any parsed session with zero messages carrying real text/blocks. That PR never touched test_repair.py, and eleven of its raw materialization fixtures built raw payloads that were structurally valid (Codex `session_meta` only, or ChatGPT `{"mapping": {...}}` with empty node bodies) but carried no actual message content -- exactly what the new filter is designed to refuse. Once the filter went live, those sessions were silently dropped during replay, so `repaired_count`/`executed_count` assertions that previously reflected "this row got materialized" started coming back short or zero. This is not a data-loss regression in raw-authority replay: the filter is working as designed (it's already measured against the live archive and closes a real correctness gap, per its docstring). It's test-infra staleness -- fixtures that never exercised genuine conversational content because the repair-plumbing tests only cared about selection/batching/ retry semantics, not parse-content semantics, until the content gate started enforcing that distinction. Solution Added a minimal real message to each of the eleven affected fixtures: - Codex payloads: one `response_item` line with a `role":"user"` message and `input_text` content, appended after the existing `session_meta` line. - ChatGPT-shaped payloads (`test_raw_materialization_split_root_routes_ authority_replay`, `test_raw_materialization_uses_authority_replay_ not_legacy_batch_parser`): a `mapping` node carrying a real `message` object instead of an empty `{}`. Every touched fixture already overrides `blob_size` via a direct SQL UPDATE where size math matters, so appending message bytes does not perturb any size-based assertion. No production code changed. Verification - `devtools test tests/unit/storage/test_repair.py -k raw_materialization` -> 48 passed (was 11 failed / 37 passed) - `devtools test tests/unit/storage/test_repair.py` -> 66 passed - `devtools verify --quick` -> exit 0 (ruff format/check, mypy --strict, render all --check, layering, schema-versioning, and friends all green) Ref polylogue-3jv24 Co-Authored-By: Claude --- tests/unit/storage/test_repair.py | 64 ++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/tests/unit/storage/test_repair.py b/tests/unit/storage/test_repair.py index 0b4ba44101..598244ba80 100644 --- a/tests/unit/storage/test_repair.py +++ b/tests/unit/storage/test_repair.py @@ -336,7 +336,11 @@ def test_raw_materialization_split_root_routes_authority_replay(tmp_path: Path) routed_root.mkdir() initialize_archive_database(routed_root / "source.db", ArchiveTier.SOURCE) initialize_archive_database(routed_root / "index.db", ArchiveTier.INDEX) - raw_id, raw_size = BlobStore(routed_root / "blob").write_from_bytes(b'{"mapping":{"routed":{}}}') + raw_id, raw_size = BlobStore(routed_root / "blob").write_from_bytes( + b'{"mapping":{"routed":{"id":"routed","message":{"id":"m1","author":{"role":"user"},' + b'"content":{"content_type":"text","parts":["hi"]}},"parent":null,"children":[]}},' + b'"current_node":"routed"}' + ) with sqlite3.connect(routed_root / "source.db") as source_conn: source_conn.execute( """ @@ -1208,8 +1212,16 @@ def test_raw_materialization_uses_authority_replay_not_legacy_batch_parser( initialize_archive_database(tmp_path / "source.db", ArchiveTier.SOURCE) initialize_archive_database(tmp_path / "index.db", ArchiveTier.INDEX) blob_store = BlobStore(tmp_path / "blob") - first_raw_id, first_size = blob_store.write_from_bytes(b'{"mapping":{"first":{}}}') - second_raw_id, second_size = blob_store.write_from_bytes(b'{"mapping":{"second":{}}}') + first_raw_id, first_size = blob_store.write_from_bytes( + b'{"mapping":{"first":{"id":"first","message":{"id":"m1","author":{"role":"user"},' + b'"content":{"content_type":"text","parts":["hi"]}},"parent":null,"children":[]}},' + b'"current_node":"first"}' + ) + second_raw_id, second_size = blob_store.write_from_bytes( + b'{"mapping":{"second":{"id":"second","message":{"id":"m1","author":{"role":"user"},' + b'"content":{"content_type":"text","parts":["hi"]}},"parent":null,"children":[]}},' + b'"current_node":"second"}' + ) with sqlite3.connect(tmp_path / "source.db") as source_conn: source_conn.executemany( @@ -1453,7 +1465,11 @@ def test_raw_materialization_execute_limits_authority_selection( raw_ids = [ archive.write_raw_payload( provider=Provider.CODEX, - payload=f'{{"type":"session_meta","payload":{{"id":"execute-{index}"}}}}\n'.encode(), + payload=( + f'{{"type":"session_meta","payload":{{"id":"execute-{index}"}}}}\n' + '{"type":"response_item","payload":{"type":"message","role":"user",' + '"content":[{"type":"input_text","text":"hi"}]}}\n' + ).encode(), source_path=f"execute-{index}.jsonl", acquired_at_ms=index + 1, ) @@ -1740,7 +1756,11 @@ def test_raw_materialization_uses_authority_substrate_not_legacy_ingest_stage( with ArchiveStore.open_existing(tmp_path, read_only=False) as archive: archive.write_raw_payload( provider=Provider.CODEX, - payload=b'{"type":"session_meta","payload":{"id":"authority-substrate"}}\n', + payload=( + b'{"type":"session_meta","payload":{"id":"authority-substrate"}}\n' + b'{"type":"response_item","payload":{"type":"message","role":"user",' + b'"content":[{"type":"input_text","text":"hi"}]}}\n' + ), source_path="authority-substrate.jsonl", acquired_at_ms=1, ) @@ -1770,7 +1790,11 @@ def test_raw_materialization_reports_authority_progress_and_payload_size( with ArchiveStore.open_existing(tmp_path, read_only=False) as archive: raw_id = archive.write_raw_payload( provider=Provider.CODEX, - payload=b'{"type":"session_meta","payload":{"id":"progress"}}\n', + payload=( + b'{"type":"session_meta","payload":{"id":"progress"}}\n' + b'{"type":"response_item","payload":{"type":"message","role":"user",' + b'"content":[{"type":"input_text","text":"hi"}]}}\n' + ), source_path="progress.jsonl", acquired_at_ms=1, ) @@ -2113,7 +2137,11 @@ def test_raw_materialization_processes_independent_components_across_bounded_pas raw_ids = [ archive.write_raw_payload( provider=Provider.CODEX, - payload=f'{{"type":"session_meta","payload":{{"id":"independent-{index}"}}}}\n'.encode(), + payload=( + f'{{"type":"session_meta","payload":{{"id":"independent-{index}"}}}}\n' + '{"type":"response_item","payload":{"type":"message","role":"user",' + '"content":[{"type":"input_text","text":"hi"}]}}\n' + ).encode(), source_path=f"independent-{index}.jsonl", acquired_at_ms=index, ) @@ -2227,6 +2255,8 @@ def test_raw_materialization_durable_ledger_survives_ops_reset_for_fairness( payload=( f'{{"type":"session_meta","payload":{{"id":"session-{index}",' '"timestamp":"2026-07-15T00:00:00Z"}}}}\n' + '{"type":"response_item","payload":{"type":"message","role":"user",' + '"content":[{"type":"input_text","text":"hi"}]}}\n' ).encode(), source_path=f"session-{index}.jsonl", acquired_at_ms=index + 1, @@ -2400,7 +2430,11 @@ def test_raw_materialization_isolates_failed_component_and_continues_batch( raw_ids = [ archive.write_raw_payload( provider=Provider.CODEX, - payload=f'{{"type":"session_meta","payload":{{"id":"session-{index}"}}}}\n'.encode(), + payload=( + f'{{"type":"session_meta","payload":{{"id":"session-{index}"}}}}\n' + '{"type":"response_item","payload":{"type":"message","role":"user",' + '"content":[{"type":"input_text","text":"hi"}]}}\n' + ).encode(), source_path=f"session-{index}.jsonl", acquired_at_ms=index + 1, ) @@ -2438,7 +2472,11 @@ def test_raw_materialization_transient_failure_retries_with_same_plan_id_then_su with ArchiveStore.open_existing(tmp_path, read_only=False) as archive: raw_id = archive.write_raw_payload( provider=Provider.CODEX, - payload=b'{"type":"session_meta","payload":{"id":"transient-target"}}\n', + payload=( + b'{"type":"session_meta","payload":{"id":"transient-target"}}\n' + b'{"type":"response_item","payload":{"type":"message","role":"user",' + b'"content":[{"type":"input_text","text":"hi"}]}}\n' + ), source_path="transient-target.jsonl", acquired_at_ms=1, ) @@ -2558,7 +2596,11 @@ def test_raw_materialization_fails_closed_on_plan_conservation_mismatch( with ArchiveStore.open_existing(tmp_path, read_only=False) as archive: archive.write_raw_payload( provider=Provider.CODEX, - payload=b'{"type":"session_meta","payload":{"id":"conservation"}}\n', + payload=( + b'{"type":"session_meta","payload":{"id":"conservation"}}\n' + b'{"type":"response_item","payload":{"type":"message","role":"user",' + b'"content":[{"type":"input_text","text":"hi"}]}}\n' + ), source_path="conservation.jsonl", acquired_at_ms=1, ) @@ -2615,6 +2657,8 @@ def test_raw_materialization_batch_limit_counts_authority_components(tmp_path: P payload=( f'{{"type":"session_meta","payload":{{"id":"independent-{index}",' '"timestamp":"2026-07-15T00:00:00Z"}}}}\n' + '{"type":"response_item","payload":{"type":"message","role":"user",' + '"content":[{"type":"input_text","text":"hi"}]}}\n' ).encode(), source_path=f"independent-{index}.jsonl", acquired_at_ms=100 + index,