From 562dd5bf98f8b3c066399392bb8e0c4c1e9c3691 Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 10:44:53 +0200 Subject: [PATCH 01/11] test(sources): prove excluded cursor revival outcomes Problem: parser-fingerprint revival needed an executable proof of indexed, unchanged-excluded, and typed-terminal outcomes without confusing fixture coverage for a live census. What changed: add a production-route candidate harness with a self-hashed receipt contract, red-mutation cursor assertions, and catch-up round-robin anti-starvation coverage. Compatibility/migration: no runtime behavior changes; the terminal candidate records its readiness-frontier injection as an explicit residual. Co-Authored-By: Claude --- tests/infra/excluded_cursor_live_proof.py | 373 ++++++++++++++++++ .../test_excluded_cursor_live_proof.py | 135 +++++++ .../test_live_watcher_catchup_order.py | 13 + 3 files changed, 521 insertions(+) create mode 100644 tests/infra/excluded_cursor_live_proof.py create mode 100644 tests/unit/sources/test_excluded_cursor_live_proof.py diff --git a/tests/infra/excluded_cursor_live_proof.py b/tests/infra/excluded_cursor_live_proof.py new file mode 100644 index 0000000000..776f4a8a6f --- /dev/null +++ b/tests/infra/excluded_cursor_live_proof.py @@ -0,0 +1,373 @@ +"""Proof harness for parser-fingerprint revival of excluded live cursors. + +The harness uses the production watcher and live batch processor against a +candidate archive fixture. It deliberately reports candidate-fixture +coverage separately from a live census. +""" + +from __future__ import annotations + +import asyncio +import json +import os +import sqlite3 +from contextlib import nullcontext +from hashlib import sha256 +from pathlib import Path +from types import SimpleNamespace +from typing import Any, cast +from unittest.mock import patch + +from polylogue.core.enums import Provider +from polylogue.sources.live.batch import LiveBatchProcessor +from polylogue.sources.live.cursor import CursorStore +from polylogue.sources.live.watcher import LiveWatcher, WatchSource +from polylogue.storage.sqlite.archive_tiers.bootstrap import initialize_active_archive_root +from tests.infra.reindex_campaign import _codex_records, _write_jsonl + +RECEIPT_SCHEMA = "polylogue.excluded-cursor-live-proof.v1" +FIXTURE_VERSION = "candidate-codex-live-compatible-2026-08-06" +OLD_PARSER_FINGERPRINT = "live-batched-v1" + + +def _canonical_json(payload: object) -> bytes: + return (json.dumps(payload, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + + +def _sha256_file(path: Path) -> str: + digest = sha256() + with path.open("rb") as handle: + for chunk in iter(lambda: handle.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def _seed_excluded(cursor: CursorStore, path: Path, *, parser_fingerprint: str) -> None: + stat = path.stat() + cursor.set( + path, + stat.st_size, + byte_offset=stat.st_size, + last_complete_newline=stat.st_size, + parser_fingerprint=parser_fingerprint, + content_fingerprint=_sha256_file(path), + source_name="codex", + st_dev=stat.st_dev, + st_ino=stat.st_ino, + mtime_ns=stat.st_mtime_ns, + failure_count=5, + excluded=True, + ) + + +def _attempts_for_path(root: Path, path: Path) -> list[dict[str, object]]: + with sqlite3.connect(root / "ops.db") as conn: + rows = conn.execute( + """ + SELECT outcome_code, retryable, evidence_ref, status, source_paths_json + FROM ingest_attempts + ORDER BY started_at_ms DESC + """ + ).fetchall() + attempts: list[dict[str, object]] = [] + for outcome_code, retryable, evidence_ref, status, source_paths_json in rows: + try: + source_paths = json.loads(str(source_paths_json or "[]")) + except json.JSONDecodeError: + source_paths = [] + if str(path) not in source_paths: + continue + attempts.append( + { + "outcome_code": outcome_code, + "retryable": None if retryable is None else bool(retryable), + "evidence_ref": evidence_ref, + "status": status, + } + ) + return attempts + + +def _retry_state(cursor: CursorStore, path: Path) -> dict[str, object]: + record = cursor.get_record(path) + if record is None: + raise AssertionError(f"proof cursor disappeared for {path}") + retry_paths = {record.source_path for record in cursor.list_retry_records()} + failed_paths = set(cursor.list_failed_with_retry()) + return { + "excluded": bool(record.excluded), + "failure_count": record.failure_count, + "retry_due": record.source_path in retry_paths, + "failed_with_retry": record.source_path in failed_paths, + "parser_fingerprint": record.parser_fingerprint, + } + + +def _indexed_counts(root: Path, path: Path) -> dict[str, int]: + with sqlite3.connect(root / "source.db") as source_conn: + raw_rows = source_conn.execute( + "SELECT raw_id FROM raw_sessions WHERE source_path = ? AND parse_error IS NULL", + (str(path),), + ).fetchall() + raw_ids = tuple(str(row[0]) for row in raw_rows) + if not raw_ids: + return {"parsed_raw": 0, "indexed_sessions": 0} + placeholders = ",".join("?" for _ in raw_ids) + with sqlite3.connect(root / "index.db") as index_conn: + indexed = index_conn.execute( + f"SELECT COUNT(*) FROM sessions WHERE raw_id IN ({placeholders})", + raw_ids, + ).fetchone() + return {"parsed_raw": len(raw_ids), "indexed_sessions": int(indexed[0]) if indexed else 0} + + +def _terminal_evidence(root: Path, path: Path) -> dict[str, object] | None: + with sqlite3.connect(root / "source.db") as conn: + row = conn.execute( + """ + SELECT a.artifact_kind, a.support_status, r.parse_error + FROM raw_artifacts AS a + JOIN raw_sessions AS r USING (raw_id) + WHERE r.source_path = ? AND a.artifact_kind LIKE 'terminal_%' + ORDER BY r.acquired_at_ms DESC, r.raw_id DESC + LIMIT 1 + """, + (str(path),), + ).fetchone() + if row is None: + return None + return { + "artifact_kind": str(row[0]), + "support_status": str(row[1]), + "parse_error_present": row[2] is not None, + } + + +def _case_summary( + *, + case_id: str, + path: Path, + cursor: CursorStore, + needs_work: bool, + metrics: object | None, + root: Path, + attempts_before: int, +) -> dict[str, object]: + retry_state = _retry_state(cursor, path) + attempts = _attempts_for_path(root, path) + proof_attempts = attempts[: max(0, len(attempts) - attempts_before)] + attempt = proof_attempts[0] if proof_attempts else None + return { + "case_id": case_id, + "source_content_sha256": _sha256_file(path), + "needs_work_after_fingerprint_change": needs_work, + "metrics": { + "succeeded_file_count": int(getattr(metrics, "succeeded_file_count", 0)) if metrics else 0, + "failed_file_count": int(getattr(metrics, "failed_file_count", 0)) if metrics else 0, + "full_file_count": int(getattr(metrics, "full_file_count", 0)) if metrics else 0, + }, + "indexed": _indexed_counts(root, path), + "terminal_evidence": _terminal_evidence(root, path), + "attempt": attempt, + "proof_attempt_count": len(proof_attempts), + "retry_state": retry_state, + "attempt_present": attempt is not None, + } + + +def _run_case( + *, + root: Path, + source_root: Path, + cursor: CursorStore, + case_id: str, + path: Path, + parser_fingerprint: str, + ingest: bool, + attempts_before: int, + bypass_frontier_gate: bool = False, + force_codex_detection: bool = False, +) -> dict[str, Any]: + polylogue = SimpleNamespace(archive_root=root, backend=SimpleNamespace(db_path=root / "index.db")) + watcher = LiveWatcher(cast(Any, polylogue), (WatchSource(name="codex", root=source_root),), cursor=cursor) + try: + with patch("polylogue.sources.live.watcher._PARSER_FINGERPRINT", parser_fingerprint): + needs_work = watcher._needs_work(path) + frontier_patch = ( + patch("polylogue.readiness.capability.raw_frontier_source_selection_block_reason", lambda _root: None) + if bypass_frontier_gate + else nullcontext() + ) + detection_patch = ( + patch( + "polylogue.sources.live.batch._jsonl_provider_and_session_artifact", + lambda _path, _fallback: (Provider.CODEX, True), + ) + if force_codex_detection + else nullcontext() + ) + with frontier_patch, detection_patch: + metrics = asyncio.run(watcher._ingest_files([path])) if ingest and needs_work else None + finally: + watcher.stop() + return _case_summary( + case_id=case_id, + path=path, + cursor=cursor, + needs_work=needs_work, + metrics=metrics, + root=root, + attempts_before=attempts_before, + ) + + +def run_excluded_cursor_live_proof(root: Path, receipt_path: Path) -> dict[str, Any]: + """Run the real cursor/fingerprint route and write a self-hashed receipt.""" + case_roots = {case_id: root / case_id for case_id in ("indexed", "still-excluded", "typed-terminal")} + + def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[Path, Path, CursorStore, int]: + case_root = case_roots[case_id] + source_root = case_root / "wire" / "excluded-cursor-proof" + path = _write_jsonl(source_root / f"{case_id}.jsonl", _codex_records(native_id, texts)) + initialize_active_archive_root(case_root) + cursor = CursorStore(case_root / "ops.db") + polylogue = SimpleNamespace(archive_root=case_root, backend=SimpleNamespace(db_path=case_root / "index.db")) + processor = LiveBatchProcessor( + cast(Any, polylogue), + (WatchSource(name="codex", root=source_root),), + cursor=cursor, + parser_fingerprint="live-batched-v2", + ) + baseline = asyncio.run(processor.ingest_files([path])) + if baseline.succeeded_file_count != 1 or baseline.failed_file_count != 0: + raise AssertionError(f"candidate baseline ingest failed for {case_id}: {baseline}") + return case_root, source_root, cursor, len(_attempts_for_path(case_root, path)) + + indexed_root, indexed_source_root, indexed_cursor, indexed_attempts_before = prepare_case( + "indexed", "excluded-proof-indexed", ("revived", "indexed") + ) + indexed_path = indexed_source_root / "indexed.jsonl" + _seed_excluded(indexed_cursor, indexed_path, parser_fingerprint=OLD_PARSER_FINGERPRINT) + indexed = _run_case( + root=indexed_root, + source_root=indexed_source_root, + cursor=indexed_cursor, + case_id="indexed", + path=indexed_path, + parser_fingerprint="live-batched-v2", + ingest=True, + attempts_before=indexed_attempts_before, + ) + + unchanged_root, unchanged_source_root, unchanged_cursor, unchanged_attempts_before = prepare_case( + "still-excluded", "excluded-proof-still-excluded", ("unchanged", "poison") + ) + unchanged_path = unchanged_source_root / "still-excluded.jsonl" + _seed_excluded(unchanged_cursor, unchanged_path, parser_fingerprint="live-batched-v2") + still_excluded = _run_case( + root=unchanged_root, + source_root=unchanged_source_root, + cursor=unchanged_cursor, + case_id="still-excluded", + path=unchanged_path, + parser_fingerprint="live-batched-v2", + ingest=True, + attempts_before=unchanged_attempts_before, + ) + + terminal_root = case_roots["typed-terminal"] + terminal_source_root = terminal_root / "wire" / "excluded-cursor-proof" + terminal_path = terminal_source_root / "typed-terminal.jsonl" + terminal_path.parent.mkdir(parents=True, exist_ok=True) + terminal_path.write_text( + '{"type":"session_meta","payload":{"id":"excluded-proof-terminal"}}\n' + '{"type":"response_item","payload":{"type":"message","id":"m0","role":"user","content":[', + encoding="utf-8", + ) + initialize_active_archive_root(terminal_root) + terminal_cursor = CursorStore(terminal_root / "ops.db") + terminal_attempts_before = len(_attempts_for_path(terminal_root, terminal_path)) + _seed_excluded(terminal_cursor, terminal_path, parser_fingerprint=OLD_PARSER_FINGERPRINT) + typed_terminal = _run_case( + root=terminal_root, + source_root=terminal_source_root, + cursor=terminal_cursor, + case_id="typed-terminal", + path=terminal_path, + parser_fingerprint="live-batched-v2", + ingest=True, + attempts_before=terminal_attempts_before, + bypass_frontier_gate=True, + force_codex_detection=True, + ) + + cases = [indexed, still_excluded, typed_terminal] + outcomes = { + "indexed": indexed["indexed"]["indexed_sessions"] == 1 + and indexed["retry_state"]["excluded"] is False + and indexed["attempt"]["outcome_code"] == "success", + "still_excluded": still_excluded["retry_state"]["excluded"] is True + and still_excluded["attempt_present"] is False + and still_excluded["retry_state"]["retry_due"] is False, + "typed_terminal": typed_terminal["terminal_evidence"]["artifact_kind"] == "terminal_corrupt_input" + and typed_terminal["terminal_evidence"]["support_status"] == "decode_failed" + and typed_terminal["retry_state"]["excluded"] is False + and typed_terminal["retry_state"]["retry_due"] is False, + } + if not all(outcomes.values()): + raise AssertionError(f"excluded-cursor proof outcomes failed: {outcomes}") + + body: dict[str, object] = { + "schema": RECEIPT_SCHEMA, + "fixture_version": FIXTURE_VERSION, + "execution": { + "mode": "candidate_fixture", + "live_census": "not_run", + "live_residual": "Historical excluded population and current live file states were not accessed.", + "terminal_frontier_residual": "The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only.", + "residual_successor": "polylogue-excluded-cursor-live-proof", + }, + "production_route": { + "cursor_gate": "LiveWatcher._needs_work", + "transition": "CursorStore.revive_replaced_exclusion", + "ingest": "LiveWatcher._ingest_files -> LiveBatchProcessor.ingest_files", + "terminal_evidence": "source.raw_artifacts", + "retry_state": "ops.ingest_cursor and ops.ingest_attempts", + }, + "outcomes": outcomes, + "cases": cases, + "fairness": { + "planner": "_interleave_by_source", + "property": "one candidate from each present source family reaches the first round", + }, + "anti_vacuity": { + "indexed_session_count": indexed["indexed"]["indexed_sessions"], + "typed_terminal_artifact": typed_terminal["terminal_evidence"]["artifact_kind"], + "unchanged_excluded_attempt_present": still_excluded["attempt_present"], + }, + } + digest = sha256(_canonical_json(body)).hexdigest() + receipt = {**body, "receipt_sha256": digest} + receipt_path.parent.mkdir(parents=True, exist_ok=True) + temporary_path = receipt_path.with_suffix(receipt_path.suffix + ".tmp") + temporary_path.write_bytes(_canonical_json(receipt)) + os.replace(temporary_path, receipt_path) + return receipt + + +def verify_receipt(receipt_path: Path) -> dict[str, Any]: + """Load and verify the immutable self-hash carried by a proof receipt.""" + receipt = json.loads(receipt_path.read_text(encoding="utf-8")) + if not isinstance(receipt, dict): + raise AssertionError("proof receipt must be a JSON object") + recorded = receipt.pop("receipt_sha256", None) + if not isinstance(recorded, str): + raise AssertionError("proof receipt has no receipt_sha256") + actual = sha256(_canonical_json(receipt)).hexdigest() + if recorded != actual: + raise AssertionError(f"proof receipt hash mismatch: recorded={recorded}, actual={actual}") + receipt["receipt_sha256"] = recorded + return receipt + + +__all__ = ["RECEIPT_SCHEMA", "run_excluded_cursor_live_proof", "verify_receipt"] diff --git a/tests/unit/sources/test_excluded_cursor_live_proof.py b/tests/unit/sources/test_excluded_cursor_live_proof.py new file mode 100644 index 0000000000..4f2db55365 --- /dev/null +++ b/tests/unit/sources/test_excluded_cursor_live_proof.py @@ -0,0 +1,135 @@ +"""Executable proof for excluded-cursor revival and retry-state honesty.""" + +from __future__ import annotations + +import json +from pathlib import Path +from types import SimpleNamespace +from typing import Any, cast +from unittest.mock import Mock + +import pytest + +import polylogue.sources.live.watcher as live_watcher +from polylogue.sources.live.cursor import CursorStore +from polylogue.sources.live.watcher import LiveWatcher, WatchSource +from tests.infra.excluded_cursor_live_proof import run_excluded_cursor_live_proof, verify_receipt + + +def test_candidate_fixture_proves_all_cursor_outcomes_and_is_immutable(tmp_path: Path) -> None: + archive_root = tmp_path / "candidate-archive" + receipt_path = tmp_path / "proof.json" + + receipt = run_excluded_cursor_live_proof(archive_root, receipt_path) + checked = verify_receipt(receipt_path) + + assert checked == receipt + assert set(cast(dict[str, Any], receipt["outcomes"])) == {"indexed", "still_excluded", "typed_terminal"} + assert receipt["outcomes"] == { + "indexed": True, + "still_excluded": True, + "typed_terminal": True, + } + assert receipt["execution"] == { + "mode": "candidate_fixture", + "live_census": "not_run", + "live_residual": "Historical excluded population and current live file states were not accessed.", + "terminal_frontier_residual": "The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only.", + "residual_successor": "polylogue-excluded-cursor-live-proof", + } + assert receipt["anti_vacuity"] == { + "indexed_session_count": 1, + "typed_terminal_artifact": "terminal_corrupt_input", + "unchanged_excluded_attempt_present": False, + } + + +def test_parser_fingerprint_revival_calls_real_actuator_and_excludes_unchanged_retry( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + source_root = tmp_path / "codex" + source_root.mkdir() + path = source_root / "excluded.jsonl" + path.write_text("payload\n", encoding="utf-8") + cursor = CursorStore(tmp_path / "ops.db") + stat = path.stat() + cursor.set( + path, + stat.st_size, + byte_offset=stat.st_size, + last_complete_newline=stat.st_size, + parser_fingerprint="old-parser", + content_fingerprint="payload-hash", + source_name="codex", + st_dev=stat.st_dev, + st_ino=stat.st_ino, + mtime_ns=stat.st_mtime_ns, + failure_count=5, + excluded=True, + ) + watcher = LiveWatcher( + cast(Any, SimpleNamespace(archive_root=tmp_path, backend=SimpleNamespace(db_path=tmp_path / "index.db"))), + (WatchSource(name="codex", root=source_root),), + cursor=cursor, + ) + try: + actuator = Mock(wraps=cursor.revive_replaced_exclusion) + monkeypatch.setattr(cursor, "revive_replaced_exclusion", actuator) + monkeypatch.setattr(live_watcher, "_PARSER_FINGERPRINT", "new-parser") + + assert watcher._needs_work(path) + actuator.assert_called_once() + revived = cursor.get_record(path) + assert revived is not None + assert not revived.excluded + assert revived.failure_count == 0 + assert cursor.list_retry_records() == [] + finally: + watcher.stop() + + unchanged_cursor = CursorStore(tmp_path / "unchanged-ops.db") + unchanged_cursor.set( + path, + stat.st_size, + byte_offset=stat.st_size, + last_complete_newline=stat.st_size, + parser_fingerprint="new-parser", + content_fingerprint="payload-hash", + source_name="codex", + st_dev=stat.st_dev, + st_ino=stat.st_ino, + mtime_ns=stat.st_mtime_ns, + failure_count=5, + excluded=True, + ) + unchanged_watcher = LiveWatcher( + cast(Any, SimpleNamespace(archive_root=tmp_path, backend=SimpleNamespace(db_path=tmp_path / "index.db"))), + (WatchSource(name="codex", root=source_root),), + cursor=unchanged_cursor, + ) + try: + assert not unchanged_watcher._needs_work(path) + assert unchanged_cursor.list_excluded() == [str(path)] + assert unchanged_cursor.list_retry_records() == [] + finally: + unchanged_watcher.stop() + + +def test_receipt_round_trip_preserves_machine_readable_fields(tmp_path: Path) -> None: + receipt_path = tmp_path / "receipt.json" + body = {"schema": "test", "receipt_sha256": "placeholder"} + receipt_path.write_text(json.dumps(body), encoding="utf-8") + with pytest.raises(AssertionError, match="hash mismatch"): + verify_receipt(receipt_path) + + +def test_committed_candidate_receipt_is_self_hashed() -> None: + receipt = verify_receipt(Path("docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json")) + + assert receipt["schema"] == "polylogue.excluded-cursor-live-proof.v1" + assert receipt["execution"]["live_census"] == "not_run" + assert receipt["outcomes"] == { + "indexed": True, + "still_excluded": True, + "typed_terminal": True, + } diff --git a/tests/unit/sources/test_live_watcher_catchup_order.py b/tests/unit/sources/test_live_watcher_catchup_order.py index 63ab8c7515..447ed6bf17 100644 --- a/tests/unit/sources/test_live_watcher_catchup_order.py +++ b/tests/unit/sources/test_live_watcher_catchup_order.py @@ -41,6 +41,19 @@ def test_interleave_by_source_round_robins_families() -> None: assert claude_paths == sorted(claude_paths) +def test_interleave_by_source_prevents_large_family_starvation() -> None: + """A long Codex backlog cannot hide a smaller family from round one.""" + candidates = [_candidate("codex", f"/home/u/.codex/sessions/x/{index:02d}.jsonl") for index in range(20)] + [ + _candidate("codex", "/home/u/.codex/sessions/x/excluded-after-fingerprint-change.jsonl"), + _candidate("hermes", "/home/u/.hermes/sessions/retry.jsonl"), + ] + + ordered = live_watcher._interleave_by_source(candidates) + + assert {candidate.source_name for candidate in ordered[:2]} == {"codex", "hermes"} + assert ordered[0].path.name != "retry.jsonl" or ordered[1].path.name == "retry.jsonl" + + def test_interleave_by_source_empty_input_returns_empty() -> None: assert live_watcher._interleave_by_source([]) == [] From 5f19ccf934ad533b006e7714a2fd057665867d8c Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 10:45:28 +0200 Subject: [PATCH 02/11] docs(coverage): bind excluded cursor proof receipt Problem: the parent cursor implementation was closed without an immutable effect receipt, leaving the live-proof successor unbound. What changed: record the self-hashed candidate receipt, register its fixture and receipt in the incident coverage ledger, and bind the parent red mutation to the new fixture. Compatibility/migration: the receipt states that the historical live census was not run and names polylogue-excluded-cursor-live-proof as the residual successor. Co-Authored-By: Claude --- .../polylogue-excluded-cursor-live-proof-2026-08-06.json | 1 + docs/plans/reindex-incident-coverage.json | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json diff --git a/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json b/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json new file mode 100644 index 0000000000..a71d850836 --- /dev/null +++ b/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json @@ -0,0 +1 @@ +{"anti_vacuity":{"indexed_session_count":1,"typed_terminal_artifact":"terminal_corrupt_input","unchanged_excluded_attempt_present":false},"cases":[{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"indexed","indexed":{"indexed_sessions":1,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"needs_work_after_fingerprint_change":true,"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"fbe00b1bf4fe9b647b143e5f002a8edfd9d3685944fa44125586a679c4cc6534","terminal_evidence":null},{"attempt":null,"attempt_present":false,"case_id":"still-excluded","indexed":{"indexed_sessions":1,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":0,"succeeded_file_count":0},"needs_work_after_fingerprint_change":false,"proof_attempt_count":0,"retry_state":{"excluded":true,"failed_with_retry":false,"failure_count":5,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"cb7b4873a5dc05a7cac589c60a8069dc9f91f234af3076f8ea558bfafe69612a","terminal_evidence":null},{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"typed-terminal","indexed":{"indexed_sessions":0,"parsed_raw":0},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"needs_work_after_fingerprint_change":true,"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"a45ef05f5b9d3348c373f5d62309896bb9ecb077fc65540fb213eb4661c7150f","terminal_evidence":{"artifact_kind":"terminal_corrupt_input","parse_error_present":true,"support_status":"decode_failed"}}],"execution":{"live_census":"not_run","live_residual":"Historical excluded population and current live file states were not accessed.","mode":"candidate_fixture","residual_successor":"polylogue-excluded-cursor-live-proof","terminal_frontier_residual":"The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only."},"fairness":{"planner":"_interleave_by_source","property":"one candidate from each present source family reaches the first round"},"fixture_version":"candidate-codex-live-compatible-2026-08-06","outcomes":{"indexed":true,"still_excluded":true,"typed_terminal":true},"production_route":{"cursor_gate":"LiveWatcher._needs_work","ingest":"LiveWatcher._ingest_files -> LiveBatchProcessor.ingest_files","retry_state":"ops.ingest_cursor and ops.ingest_attempts","terminal_evidence":"source.raw_artifacts","transition":"CursorStore.revive_replaced_exclusion"},"receipt_sha256":"daf9ea6f158aa4e05ae8a99682032fa089f10a7a1c029e7f447a3139e65269ac","schema":"polylogue.excluded-cursor-live-proof.v1"} diff --git a/docs/plans/reindex-incident-coverage.json b/docs/plans/reindex-incident-coverage.json index eedaee9813..c675861092 100644 --- a/docs/plans/reindex-incident-coverage.json +++ b/docs/plans/reindex-incident-coverage.json @@ -16,7 +16,8 @@ "lineage-corpus": {"kind": "lineage-corpus", "source": "tests/infra/reindex_campaign.py"}, "derived-model": {"kind": "derived-model", "source": "tests/infra/reindex_differential.py"}, "title-census": {"kind": "title-census", "source": "tests/unit/maintenance/test_reindex_campaign.py"}, - "parser-replay": {"kind": "parser-replay", "source": "tests/unit/maintenance/test_reindex_campaign.py"} + "parser-replay": {"kind": "parser-replay", "source": "tests/unit/maintenance/test_reindex_campaign.py"}, + "excluded-cursor-proof": {"kind": "candidate-live-compatible", "source": "tests/infra/excluded_cursor_live_proof.py"} }, "checks": { "campaign-coverage": {"kind": "registry", "source": "polylogue-incident-coverage-ledger"}, @@ -57,7 +58,8 @@ "live-proof-7zp4": {"kind": "live-proof", "status": "recorded", "source": "content-hash-census"}, "live-proof-gzgyl": {"kind": "live-proof", "status": "recorded", "source": "material-origin-census"}, "live-proof-mvcbi": {"kind": "live-proof", "status": "recorded", "source": "origin-dispatch-census"}, - "live-proof-qsagp": {"kind": "live-proof", "status": "recorded", "source": "derived-refresh-census"} + "live-proof-qsagp": {"kind": "live-proof", "status": "recorded", "source": "derived-refresh-census"}, + "excluded-cursor-proof-receipt": {"kind": "proof-receipt", "status": "recorded", "source": "docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json"} }, "successors": { "polylogue-claude-vintage-live-proof": {"kind": "named-child-bead"}, @@ -92,7 +94,7 @@ {"bead_id": "polylogue-fsgdd", "bead_status": "open", "incident": {"incident_id": "incident-fsgdd", "bead_id": "polylogue-fsgdd", "forcing_class": "coverage"}, "route": {"kind": "registry", "entrypoint": "polylogue-incident-coverage-ledger"}, "schedule": {"phase": "preflight", "order": 20}, "expected_snapshot": {"snapshot_id": "post-reindex-acceptance", "state": "blocking"}, "registry_checks": ["campaign-coverage"], "red_mutation": {"fixture_id": "campaign-graph", "mutation_id": "mutation-fsgdd"}, "receipts": [], "residual_successor": null}, {"bead_id": "polylogue-gzgyl", "bead_status": "closed", "incident": {"incident_id": "incident-gzgyl", "bead_id": "polylogue-gzgyl", "forcing_class": "material-origin"}, "route": {"kind": "registry", "entrypoint": "origin-capability"}, "schedule": {"phase": "preflight", "order": 21}, "expected_snapshot": {"snapshot_id": "post-reindex-acceptance", "state": "blocking"}, "registry_checks": ["material-origin"], "red_mutation": {"fixture_id": "origin-matrix", "mutation_id": "mutation-gzgyl"}, "receipts": ["live-proof-gzgyl"], "residual_successor": null}, {"bead_id": "polylogue-ih67", "bead_status": "in_progress", "incident": {"incident_id": "incident-ih67", "bead_id": "polylogue-ih67", "forcing_class": "title"}, "route": {"kind": "registry", "entrypoint": "reindex-campaign"}, "schedule": {"phase": "preflight", "order": 22}, "expected_snapshot": {"snapshot_id": "derived-model-candidate", "state": "blocking"}, "registry_checks": ["title-resolution"], "red_mutation": {"fixture_id": "title-census", "mutation_id": "mutation-ih67"}, "receipts": [], "residual_successor": null}, - {"bead_id": "polylogue-ix5r", "bead_status": "closed", "incident": {"incident_id": "incident-ix5r", "bead_id": "polylogue-ix5r", "forcing_class": "cursor"}, "route": {"kind": "registry", "entrypoint": "reindex-campaign"}, "schedule": {"phase": "preflight", "order": 23}, "expected_snapshot": {"snapshot_id": "live-preflight-2026-08-04", "state": "blocking"}, "registry_checks": ["cursor-freshness"], "red_mutation": {"fixture_id": "campaign-corpus", "mutation_id": "mutation-ix5r"}, "receipts": [], "residual_successor": {"bead_id": "polylogue-excluded-cursor-live-proof", "kind": "live-proof"}}, + {"bead_id": "polylogue-ix5r", "bead_status": "closed", "incident": {"incident_id": "incident-ix5r", "bead_id": "polylogue-ix5r", "forcing_class": "cursor"}, "route": {"kind": "registry", "entrypoint": "reindex-campaign"}, "schedule": {"phase": "preflight", "order": 23}, "expected_snapshot": {"snapshot_id": "live-preflight-2026-08-04", "state": "blocking"}, "registry_checks": ["cursor-freshness"], "red_mutation": {"fixture_id": "excluded-cursor-proof", "mutation_id": "mutation-ix5r"}, "receipts": ["excluded-cursor-proof-receipt"], "residual_successor": {"bead_id": "polylogue-excluded-cursor-live-proof", "kind": "live-proof"}}, {"bead_id": "polylogue-mvcbi", "bead_status": "closed", "incident": {"incident_id": "incident-mvcbi", "bead_id": "polylogue-mvcbi", "forcing_class": "origin"}, "route": {"kind": "registry", "entrypoint": "origin-capability"}, "schedule": {"phase": "preflight", "order": 24}, "expected_snapshot": {"snapshot_id": "post-reindex-acceptance", "state": "blocking"}, "registry_checks": ["origin-matrix"], "red_mutation": {"fixture_id": "origin-matrix", "mutation_id": "mutation-mvcbi"}, "receipts": ["live-proof-mvcbi"], "residual_successor": null}, {"bead_id": "polylogue-nas1", "bead_status": "open", "incident": {"incident_id": "incident-nas1", "bead_id": "polylogue-nas1", "forcing_class": "lineage"}, "route": {"kind": "registry", "entrypoint": "reindex-differential"}, "schedule": {"phase": "preflight", "order": 25}, "expected_snapshot": {"snapshot_id": "derived-model-candidate", "state": "blocking"}, "registry_checks": ["lineage-differential"], "red_mutation": {"fixture_id": "lineage-corpus", "mutation_id": "mutation-nas1"}, "receipts": [], "residual_successor": null}, {"bead_id": "polylogue-omsw", "bead_status": "open", "incident": {"incident_id": "incident-omsw", "bead_id": "polylogue-omsw", "forcing_class": "sidecar"}, "route": {"kind": "registry", "entrypoint": "reindex-campaign"}, "schedule": {"phase": "preflight", "order": 26}, "expected_snapshot": {"snapshot_id": "live-preflight-2026-08-04", "state": "blocking"}, "registry_checks": ["sidecar-admission"], "red_mutation": {"fixture_id": "sidecar-admission", "mutation_id": "mutation-omsw"}, "receipts": [], "residual_successor": null}, From c32bca97ee71acbb597d091e4eb63ca087102ebf Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 11:49:02 +0200 Subject: [PATCH 03/11] test(sources): qualify cursor fairness proof Problem: the cursor proof forced terminal admission for a truncated stream and stated a universal fairness property despite browser-capture priority.\n\nWhat changed: exercise detector admission with a valid Codex prefix plus terminal corruption, remove the detector override, and cover the browser-priority exception while narrowing the receipt property to non-browser families.\n\nCompatibility/migration: test and evidence-only change.\n\nRef #3852 --- tests/infra/excluded_cursor_live_proof.py | 28 +++++++------------ .../test_live_watcher_catchup_order.py | 14 ++++++++++ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/tests/infra/excluded_cursor_live_proof.py b/tests/infra/excluded_cursor_live_proof.py index 776f4a8a6f..c1973157d9 100644 --- a/tests/infra/excluded_cursor_live_proof.py +++ b/tests/infra/excluded_cursor_live_proof.py @@ -18,7 +18,6 @@ from typing import Any, cast from unittest.mock import patch -from polylogue.core.enums import Provider from polylogue.sources.live.batch import LiveBatchProcessor from polylogue.sources.live.cursor import CursorStore from polylogue.sources.live.watcher import LiveWatcher, WatchSource @@ -186,7 +185,6 @@ def _run_case( ingest: bool, attempts_before: int, bypass_frontier_gate: bool = False, - force_codex_detection: bool = False, ) -> dict[str, Any]: polylogue = SimpleNamespace(archive_root=root, backend=SimpleNamespace(db_path=root / "index.db")) watcher = LiveWatcher(cast(Any, polylogue), (WatchSource(name="codex", root=source_root),), cursor=cursor) @@ -198,15 +196,7 @@ def _run_case( if bypass_frontier_gate else nullcontext() ) - detection_patch = ( - patch( - "polylogue.sources.live.batch._jsonl_provider_and_session_artifact", - lambda _path, _fallback: (Provider.CODEX, True), - ) - if force_codex_detection - else nullcontext() - ) - with frontier_patch, detection_patch: + with frontier_patch: metrics = asyncio.run(watcher._ingest_files([path])) if ingest and needs_work else None finally: watcher.stop() @@ -278,12 +268,12 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ terminal_root = case_roots["typed-terminal"] terminal_source_root = terminal_root / "wire" / "excluded-cursor-proof" terminal_path = terminal_source_root / "typed-terminal.jsonl" - terminal_path.parent.mkdir(parents=True, exist_ok=True) - terminal_path.write_text( - '{"type":"session_meta","payload":{"id":"excluded-proof-terminal"}}\n' - '{"type":"response_item","payload":{"type":"message","id":"m0","role":"user","content":[', - encoding="utf-8", + _write_jsonl( + terminal_path, + _codex_records("excluded-proof-terminal", ("valid prefix", "terminal corruption")), ) + with terminal_path.open("ab") as handle: + handle.write(b'{"type":"response_item","payload":{"type":"message","content":[') initialize_active_archive_root(terminal_root) terminal_cursor = CursorStore(terminal_root / "ops.db") terminal_attempts_before = len(_attempts_for_path(terminal_root, terminal_path)) @@ -298,7 +288,6 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ ingest=True, attempts_before=terminal_attempts_before, bypass_frontier_gate=True, - force_codex_detection=True, ) cases = [indexed, still_excluded, typed_terminal] @@ -338,7 +327,10 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ "cases": cases, "fairness": { "planner": "_interleave_by_source", - "property": "one candidate from each present source family reaches the first round", + "property": ( + "browser-capture drains first; among non-browser-capture families, one candidate from each " + "present family reaches the first round" + ), }, "anti_vacuity": { "indexed_session_count": indexed["indexed"]["indexed_sessions"], diff --git a/tests/unit/sources/test_live_watcher_catchup_order.py b/tests/unit/sources/test_live_watcher_catchup_order.py index 447ed6bf17..1c7538f67c 100644 --- a/tests/unit/sources/test_live_watcher_catchup_order.py +++ b/tests/unit/sources/test_live_watcher_catchup_order.py @@ -54,6 +54,20 @@ def test_interleave_by_source_prevents_large_family_starvation() -> None: assert ordered[0].path.name != "retry.jsonl" or ordered[1].path.name == "retry.jsonl" +def test_interleave_by_source_prioritizes_browser_capture_before_round_robin() -> None: + candidates = [ + _candidate("codex", "/home/u/.codex/sessions/x/codex.jsonl"), + _candidate("hermes", "/home/u/.hermes/sessions/retry.json"), + _candidate("browser-capture", "/home/u/.browser/capture-b.json"), + _candidate("browser-capture", "/home/u/.browser/capture-a.json"), + ] + + ordered = live_watcher._interleave_by_source(candidates) + + assert [candidate.source_name for candidate in ordered[:2]] == ["browser-capture", "browser-capture"] + assert {candidate.source_name for candidate in ordered[2:4]} == {"codex", "hermes"} + + def test_interleave_by_source_empty_input_returns_empty() -> None: assert live_watcher._interleave_by_source([]) == [] From 5e26e748e1fe056c613bc2edc7e107ba31c2ce3c Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 11:50:37 +0200 Subject: [PATCH 04/11] docs(coverage): refresh cursor proof receipt Problem: the committed cursor receipt described the superseded detector override and universal fairness claim.\n\nWhat changed: record the detector-admitted valid-prefix terminal fixture and the browser-capture priority exception with a new immutable receipt hash.\n\nCompatibility/migration: evidence-only change.\n\nRef #3852 --- .../polylogue-excluded-cursor-live-proof-2026-08-06.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json b/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json index a71d850836..607f46d695 100644 --- a/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json +++ b/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json @@ -1 +1 @@ -{"anti_vacuity":{"indexed_session_count":1,"typed_terminal_artifact":"terminal_corrupt_input","unchanged_excluded_attempt_present":false},"cases":[{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"indexed","indexed":{"indexed_sessions":1,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"needs_work_after_fingerprint_change":true,"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"fbe00b1bf4fe9b647b143e5f002a8edfd9d3685944fa44125586a679c4cc6534","terminal_evidence":null},{"attempt":null,"attempt_present":false,"case_id":"still-excluded","indexed":{"indexed_sessions":1,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":0,"succeeded_file_count":0},"needs_work_after_fingerprint_change":false,"proof_attempt_count":0,"retry_state":{"excluded":true,"failed_with_retry":false,"failure_count":5,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"cb7b4873a5dc05a7cac589c60a8069dc9f91f234af3076f8ea558bfafe69612a","terminal_evidence":null},{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"typed-terminal","indexed":{"indexed_sessions":0,"parsed_raw":0},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"needs_work_after_fingerprint_change":true,"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"a45ef05f5b9d3348c373f5d62309896bb9ecb077fc65540fb213eb4661c7150f","terminal_evidence":{"artifact_kind":"terminal_corrupt_input","parse_error_present":true,"support_status":"decode_failed"}}],"execution":{"live_census":"not_run","live_residual":"Historical excluded population and current live file states were not accessed.","mode":"candidate_fixture","residual_successor":"polylogue-excluded-cursor-live-proof","terminal_frontier_residual":"The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only."},"fairness":{"planner":"_interleave_by_source","property":"one candidate from each present source family reaches the first round"},"fixture_version":"candidate-codex-live-compatible-2026-08-06","outcomes":{"indexed":true,"still_excluded":true,"typed_terminal":true},"production_route":{"cursor_gate":"LiveWatcher._needs_work","ingest":"LiveWatcher._ingest_files -> LiveBatchProcessor.ingest_files","retry_state":"ops.ingest_cursor and ops.ingest_attempts","terminal_evidence":"source.raw_artifacts","transition":"CursorStore.revive_replaced_exclusion"},"receipt_sha256":"daf9ea6f158aa4e05ae8a99682032fa089f10a7a1c029e7f447a3139e65269ac","schema":"polylogue.excluded-cursor-live-proof.v1"} +{"anti_vacuity":{"indexed_session_count":1,"typed_terminal_artifact":"terminal_corrupt_input","unchanged_excluded_attempt_present":false},"cases":[{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"indexed","indexed":{"indexed_sessions":1,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"needs_work_after_fingerprint_change":true,"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"fbe00b1bf4fe9b647b143e5f002a8edfd9d3685944fa44125586a679c4cc6534","terminal_evidence":null},{"attempt":null,"attempt_present":false,"case_id":"still-excluded","indexed":{"indexed_sessions":1,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":0,"succeeded_file_count":0},"needs_work_after_fingerprint_change":false,"proof_attempt_count":0,"retry_state":{"excluded":true,"failed_with_retry":false,"failure_count":5,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"cb7b4873a5dc05a7cac589c60a8069dc9f91f234af3076f8ea558bfafe69612a","terminal_evidence":null},{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"typed-terminal","indexed":{"indexed_sessions":0,"parsed_raw":0},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"needs_work_after_fingerprint_change":true,"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"2e5c27f8ae0c2f4176892776a5a0ac5e1d598178676396f86fa4f6d608778d75","terminal_evidence":{"artifact_kind":"terminal_corrupt_input","parse_error_present":true,"support_status":"decode_failed"}}],"execution":{"live_census":"not_run","live_residual":"Historical excluded population and current live file states were not accessed.","mode":"candidate_fixture","residual_successor":"polylogue-excluded-cursor-live-proof","terminal_frontier_residual":"The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only."},"fairness":{"planner":"_interleave_by_source","property":"browser-capture drains first; among non-browser-capture families, one candidate from each present family reaches the first round"},"fixture_version":"candidate-codex-live-compatible-2026-08-06","outcomes":{"indexed":true,"still_excluded":true,"typed_terminal":true},"production_route":{"cursor_gate":"LiveWatcher._needs_work","ingest":"LiveWatcher._ingest_files -> LiveBatchProcessor.ingest_files","retry_state":"ops.ingest_cursor and ops.ingest_attempts","terminal_evidence":"source.raw_artifacts","transition":"CursorStore.revive_replaced_exclusion"},"receipt_sha256":"66d959091a0b8d2126fd42a7b502c2619688f43c789f53527792ceeb4c9e7678","schema":"polylogue.excluded-cursor-live-proof.v1"} From e2c40029c6f6e24a6bdcd469e4162c7e52207b08 Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 12:56:11 +0200 Subject: [PATCH 05/11] test(sources): repair cursor authority revival proof Problem: the indexed proof pre-seeded an indexed session and the direct ingest path bypassed the watcher catch-up planner. After switching to the real route, the fixture lacked a comparable cursor/head authority row.\n\nWhat changed: seed only byte-proven source evidence and a matching revision head, derive its session identity and content hash from the parser, then assert zero indexed sessions before automatic catch-up and one after revival. The harness now records the full catch-up route, uses the parser fingerprint constant, closes attempt reads, and tightens ordering and null assertions.\n\nCompatibility/migration: test harness and proof fixtures only; production code is unchanged.\n\nCo-Authored-By: Claude --- tests/infra/excluded_cursor_live_proof.py | 140 +++++++++++++----- .../test_excluded_cursor_live_proof.py | 18 ++- .../test_live_watcher_catchup_order.py | 3 +- 3 files changed, 124 insertions(+), 37 deletions(-) diff --git a/tests/infra/excluded_cursor_live_proof.py b/tests/infra/excluded_cursor_live_proof.py index c1973157d9..9ea6fc3216 100644 --- a/tests/infra/excluded_cursor_live_proof.py +++ b/tests/infra/excluded_cursor_live_proof.py @@ -18,15 +18,20 @@ from typing import Any, cast from unittest.mock import patch -from polylogue.sources.live.batch import LiveBatchProcessor +from polylogue.archive.revision_authority import RawRevisionAuthority, RawRevisionEnvelope, RawRevisionKind +from polylogue.core.enums import Provider +from polylogue.pipeline.ids import session_content_hash, session_id +from polylogue.sources.dispatch import parse_payload from polylogue.sources.live.cursor import CursorStore from polylogue.sources.live.watcher import LiveWatcher, WatchSource +from polylogue.storage.sqlite.archive_tiers.archive import ArchiveStore from polylogue.storage.sqlite.archive_tiers.bootstrap import initialize_active_archive_root from tests.infra.reindex_campaign import _codex_records, _write_jsonl RECEIPT_SCHEMA = "polylogue.excluded-cursor-live-proof.v1" FIXTURE_VERSION = "candidate-codex-live-compatible-2026-08-06" OLD_PARSER_FINGERPRINT = "live-batched-v1" +NEW_PARSER_FINGERPRINT = "live-batched-v2" def _canonical_json(payload: object) -> bytes: @@ -59,15 +64,69 @@ def _seed_excluded(cursor: CursorStore, path: Path, *, parser_fingerprint: str) ) +def _seed_byte_authority(root: Path, path: Path, *, native_id: str) -> None: + """Seed source evidence plus a byte head without materializing a session.""" + payload = path.read_bytes() + logical_source_key = f"codex:{native_id}" + [parsed] = parse_payload( + Provider.CODEX, + [json.loads(line) for line in payload.splitlines()], + native_id, + source_path=str(path), + ) + source_revision = "excluded-cursor-proof-authority-0" + accepted_content_hash = bytes.fromhex(session_content_hash(parsed)) + accepted_session_id = str(session_id(parsed.source_name, parsed.provider_session_id)) + revision = RawRevisionEnvelope( + logical_source_key, + RawRevisionKind.FULL, + source_revision, + 0, + authority=RawRevisionAuthority.BYTE_PROVEN, + ) + with ArchiveStore.open_existing(root, read_only=False) as archive: + raw_id = archive.write_raw_payload( + provider=Provider.CODEX, + payload=payload, + source_path=str(path), + acquired_at_ms=1, + native_id=native_id, + revision=revision, + ) + with sqlite3.connect(root / "index.db") as conn: + conn.execute( + """ + INSERT INTO raw_revision_heads ( + logical_source_key, session_id, accepted_raw_id, + accepted_source_revision, accepted_content_hash, + accepted_frontier_kind, accepted_frontier, + acquisition_generation, append_end_offset, decided_at_ms + ) VALUES (?, ?, ?, ?, ?, 'byte', ?, 0, NULL, 1) + """, + ( + logical_source_key, + accepted_session_id, + raw_id, + source_revision, + accepted_content_hash, + len(payload), + ), + ) + conn.commit() + + def _attempts_for_path(root: Path, path: Path) -> list[dict[str, object]]: - with sqlite3.connect(root / "ops.db") as conn: + conn = sqlite3.connect(root / "ops.db") + try: rows = conn.execute( """ SELECT outcome_code, retryable, evidence_ref, status, source_paths_json FROM ingest_attempts - ORDER BY started_at_ms DESC + ORDER BY started_at_ms DESC, attempt_id DESC """ ).fetchall() + finally: + conn.close() attempts: list[dict[str, object]] = [] for outcome_code, retryable, evidence_ref, status, source_paths_json in rows: try: @@ -147,7 +206,7 @@ def _case_summary( case_id: str, path: Path, cursor: CursorStore, - needs_work: bool, + fingerprint_changed_before_catch_up: bool, metrics: object | None, root: Path, attempts_before: int, @@ -159,7 +218,7 @@ def _case_summary( return { "case_id": case_id, "source_content_sha256": _sha256_file(path), - "needs_work_after_fingerprint_change": needs_work, + "fingerprint_changed_before_catch_up": fingerprint_changed_before_catch_up, "metrics": { "succeeded_file_count": int(getattr(metrics, "succeeded_file_count", 0)) if metrics else 0, "failed_file_count": int(getattr(metrics, "failed_file_count", 0)) if metrics else 0, @@ -182,30 +241,42 @@ def _run_case( case_id: str, path: Path, parser_fingerprint: str, - ingest: bool, attempts_before: int, bypass_frontier_gate: bool = False, ) -> dict[str, Any]: polylogue = SimpleNamespace(archive_root=root, backend=SimpleNamespace(db_path=root / "index.db")) watcher = LiveWatcher(cast(Any, polylogue), (WatchSource(name="codex", root=source_root),), cursor=cursor) try: + record = cursor.get_record(path) + fingerprint_changed_before_catch_up = ( + record is not None + and record.excluded + and record.parser_fingerprint != parser_fingerprint + ) + metrics_holder: list[object] = [] + original_ingest = watcher._ingest_files + + async def capture_ingest(*args: Any, **kwargs: Any) -> object: + metrics = await original_ingest(*args, **kwargs) + metrics_holder.append(metrics) + return metrics + with patch("polylogue.sources.live.watcher._PARSER_FINGERPRINT", parser_fingerprint): - needs_work = watcher._needs_work(path) frontier_patch = ( patch("polylogue.readiness.capability.raw_frontier_source_selection_block_reason", lambda _root: None) if bypass_frontier_gate else nullcontext() ) - with frontier_patch: - metrics = asyncio.run(watcher._ingest_files([path])) if ingest and needs_work else None + with frontier_patch, patch.object(watcher, "_ingest_files", capture_ingest): + asyncio.run(watcher._catch_up([source_root])) finally: watcher.stop() return _case_summary( case_id=case_id, path=path, cursor=cursor, - needs_work=needs_work, - metrics=metrics, + fingerprint_changed_before_catch_up=fingerprint_changed_before_catch_up, + metrics=metrics_holder[-1] if metrics_holder else None, root=root, attempts_before=attempts_before, ) @@ -221,22 +292,16 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ path = _write_jsonl(source_root / f"{case_id}.jsonl", _codex_records(native_id, texts)) initialize_active_archive_root(case_root) cursor = CursorStore(case_root / "ops.db") - polylogue = SimpleNamespace(archive_root=case_root, backend=SimpleNamespace(db_path=case_root / "index.db")) - processor = LiveBatchProcessor( - cast(Any, polylogue), - (WatchSource(name="codex", root=source_root),), - cursor=cursor, - parser_fingerprint="live-batched-v2", - ) - baseline = asyncio.run(processor.ingest_files([path])) - if baseline.succeeded_file_count != 1 or baseline.failed_file_count != 0: - raise AssertionError(f"candidate baseline ingest failed for {case_id}: {baseline}") return case_root, source_root, cursor, len(_attempts_for_path(case_root, path)) indexed_root, indexed_source_root, indexed_cursor, indexed_attempts_before = prepare_case( "indexed", "excluded-proof-indexed", ("revived", "indexed") ) indexed_path = indexed_source_root / "indexed.jsonl" + _seed_byte_authority(indexed_root, indexed_path, native_id="excluded-proof-indexed") + indexed_before = _indexed_counts(indexed_root, indexed_path) + if indexed_before["indexed_sessions"] != 0: + raise AssertionError(f"indexed case was not empty before catch-up: {indexed_before}") _seed_excluded(indexed_cursor, indexed_path, parser_fingerprint=OLD_PARSER_FINGERPRINT) indexed = _run_case( root=indexed_root, @@ -244,24 +309,23 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ cursor=indexed_cursor, case_id="indexed", path=indexed_path, - parser_fingerprint="live-batched-v2", - ingest=True, + parser_fingerprint=NEW_PARSER_FINGERPRINT, attempts_before=indexed_attempts_before, ) + indexed["indexed_before"] = indexed_before unchanged_root, unchanged_source_root, unchanged_cursor, unchanged_attempts_before = prepare_case( "still-excluded", "excluded-proof-still-excluded", ("unchanged", "poison") ) unchanged_path = unchanged_source_root / "still-excluded.jsonl" - _seed_excluded(unchanged_cursor, unchanged_path, parser_fingerprint="live-batched-v2") + _seed_excluded(unchanged_cursor, unchanged_path, parser_fingerprint=NEW_PARSER_FINGERPRINT) still_excluded = _run_case( root=unchanged_root, source_root=unchanged_source_root, cursor=unchanged_cursor, case_id="still-excluded", path=unchanged_path, - parser_fingerprint="live-batched-v2", - ingest=True, + parser_fingerprint=NEW_PARSER_FINGERPRINT, attempts_before=unchanged_attempts_before, ) @@ -284,22 +348,26 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ cursor=terminal_cursor, case_id="typed-terminal", path=terminal_path, - parser_fingerprint="live-batched-v2", - ingest=True, + parser_fingerprint=NEW_PARSER_FINGERPRINT, attempts_before=terminal_attempts_before, bypass_frontier_gate=True, ) cases = [indexed, still_excluded, typed_terminal] + indexed_attempt = indexed["attempt"] + terminal_evidence = typed_terminal["terminal_evidence"] outcomes = { - "indexed": indexed["indexed"]["indexed_sessions"] == 1 + "indexed": indexed["indexed_before"]["indexed_sessions"] == 0 + and indexed["indexed"]["indexed_sessions"] == 1 and indexed["retry_state"]["excluded"] is False - and indexed["attempt"]["outcome_code"] == "success", + and indexed_attempt is not None + and indexed_attempt["outcome_code"] == "success", "still_excluded": still_excluded["retry_state"]["excluded"] is True and still_excluded["attempt_present"] is False and still_excluded["retry_state"]["retry_due"] is False, - "typed_terminal": typed_terminal["terminal_evidence"]["artifact_kind"] == "terminal_corrupt_input" - and typed_terminal["terminal_evidence"]["support_status"] == "decode_failed" + "typed_terminal": terminal_evidence is not None + and terminal_evidence["artifact_kind"] == "terminal_corrupt_input" + and terminal_evidence["support_status"] == "decode_failed" and typed_terminal["retry_state"]["excluded"] is False and typed_terminal["retry_state"]["retry_due"] is False, } @@ -319,6 +387,10 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ "production_route": { "cursor_gate": "LiveWatcher._needs_work", "transition": "CursorStore.revive_replaced_exclusion", + "catch_up": ( + "LiveWatcher._catch_up -> _scan_catch_up_candidates -> _catch_up_candidates -> " + "_plan_catch_up -> coordinated chunk ingest" + ), "ingest": "LiveWatcher._ingest_files -> LiveBatchProcessor.ingest_files", "terminal_evidence": "source.raw_artifacts", "retry_state": "ops.ingest_cursor and ops.ingest_attempts", @@ -333,8 +405,10 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ ), }, "anti_vacuity": { + "indexed_authority": "byte_proven_source_raw_and_revision_head", + "indexed_session_count_before": indexed["indexed_before"]["indexed_sessions"], "indexed_session_count": indexed["indexed"]["indexed_sessions"], - "typed_terminal_artifact": typed_terminal["terminal_evidence"]["artifact_kind"], + "typed_terminal_artifact": terminal_evidence["artifact_kind"] if terminal_evidence else None, "unchanged_excluded_attempt_present": still_excluded["attempt_present"], }, } diff --git a/tests/unit/sources/test_excluded_cursor_live_proof.py b/tests/unit/sources/test_excluded_cursor_live_proof.py index 4f2db55365..a86ef30db0 100644 --- a/tests/unit/sources/test_excluded_cursor_live_proof.py +++ b/tests/unit/sources/test_excluded_cursor_live_proof.py @@ -15,6 +15,8 @@ from polylogue.sources.live.watcher import LiveWatcher, WatchSource from tests.infra.excluded_cursor_live_proof import run_excluded_cursor_live_proof, verify_receipt +REPO_ROOT = Path(__file__).resolve().parents[3] + def test_candidate_fixture_proves_all_cursor_outcomes_and_is_immutable(tmp_path: Path) -> None: archive_root = tmp_path / "candidate-archive" @@ -37,7 +39,13 @@ def test_candidate_fixture_proves_all_cursor_outcomes_and_is_immutable(tmp_path: "terminal_frontier_residual": "The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only.", "residual_successor": "polylogue-excluded-cursor-live-proof", } + assert receipt["production_route"]["catch_up"] == ( + "LiveWatcher._catch_up -> _scan_catch_up_candidates -> _catch_up_candidates -> " + "_plan_catch_up -> coordinated chunk ingest" + ) assert receipt["anti_vacuity"] == { + "indexed_authority": "byte_proven_source_raw_and_revision_head", + "indexed_session_count_before": 0, "indexed_session_count": 1, "typed_terminal_artifact": "terminal_corrupt_input", "unchanged_excluded_attempt_present": False, @@ -87,7 +95,11 @@ def test_parser_fingerprint_revival_calls_real_actuator_and_excludes_unchanged_r finally: watcher.stop() - unchanged_cursor = CursorStore(tmp_path / "unchanged-ops.db") + unchanged_root = tmp_path / "unchanged" + unchanged_root.mkdir() + unchanged_cursor = CursorStore(unchanged_root / "ops.db") + assert unchanged_cursor._db_path != cursor._db_path + assert unchanged_cursor._ops_db_path != cursor._ops_db_path unchanged_cursor.set( path, stat.st_size, @@ -115,7 +127,7 @@ def test_parser_fingerprint_revival_calls_real_actuator_and_excludes_unchanged_r unchanged_watcher.stop() -def test_receipt_round_trip_preserves_machine_readable_fields(tmp_path: Path) -> None: +def test_receipt_with_wrong_self_hash_is_rejected(tmp_path: Path) -> None: receipt_path = tmp_path / "receipt.json" body = {"schema": "test", "receipt_sha256": "placeholder"} receipt_path.write_text(json.dumps(body), encoding="utf-8") @@ -124,7 +136,7 @@ def test_receipt_round_trip_preserves_machine_readable_fields(tmp_path: Path) -> def test_committed_candidate_receipt_is_self_hashed() -> None: - receipt = verify_receipt(Path("docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json")) + receipt = verify_receipt(REPO_ROOT / "docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json") assert receipt["schema"] == "polylogue.excluded-cursor-live-proof.v1" assert receipt["execution"]["live_census"] == "not_run" diff --git a/tests/unit/sources/test_live_watcher_catchup_order.py b/tests/unit/sources/test_live_watcher_catchup_order.py index 1c7538f67c..5d79ad339c 100644 --- a/tests/unit/sources/test_live_watcher_catchup_order.py +++ b/tests/unit/sources/test_live_watcher_catchup_order.py @@ -51,7 +51,7 @@ def test_interleave_by_source_prevents_large_family_starvation() -> None: ordered = live_watcher._interleave_by_source(candidates) assert {candidate.source_name for candidate in ordered[:2]} == {"codex", "hermes"} - assert ordered[0].path.name != "retry.jsonl" or ordered[1].path.name == "retry.jsonl" + assert [candidate.source_name for candidate in ordered[:2]] == ["codex", "hermes"] def test_interleave_by_source_prioritizes_browser_capture_before_round_robin() -> None: @@ -65,6 +65,7 @@ def test_interleave_by_source_prioritizes_browser_capture_before_round_robin() - ordered = live_watcher._interleave_by_source(candidates) assert [candidate.source_name for candidate in ordered[:2]] == ["browser-capture", "browser-capture"] + assert [candidate.path.name for candidate in ordered[:2]] == ["capture-a.json", "capture-b.json"] assert {candidate.source_name for candidate in ordered[2:4]} == {"codex", "hermes"} From af3b2a69099afa5c066d7abb286b46f001ed10f5 Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 12:56:29 +0200 Subject: [PATCH 06/11] style: format cursor proof predicate Apply the repository formatter's required wrapping to the cursor proof predicate.\n\nCo-Authored-By: Claude --- tests/infra/excluded_cursor_live_proof.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/infra/excluded_cursor_live_proof.py b/tests/infra/excluded_cursor_live_proof.py index 9ea6fc3216..d529e1060d 100644 --- a/tests/infra/excluded_cursor_live_proof.py +++ b/tests/infra/excluded_cursor_live_proof.py @@ -249,9 +249,7 @@ def _run_case( try: record = cursor.get_record(path) fingerprint_changed_before_catch_up = ( - record is not None - and record.excluded - and record.parser_fingerprint != parser_fingerprint + record is not None and record.excluded and record.parser_fingerprint != parser_fingerprint ) metrics_holder: list[object] = [] original_ingest = watcher._ingest_files From 92af9b809fd0d633ed1fdeb37f7b3b13af09de51 Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 12:58:35 +0200 Subject: [PATCH 07/11] docs(evidence): refresh cursor revival receipt Problem: the committed candidate receipt described the pre-repair indexed fixture and direct-ingest path.\n\nWhat changed: record the automatic catch-up route, the zero-to-one indexed transition, and the byte-proven source/head authority setup from the repaired proof harness.\n\nCompatibility/migration: this is an immutable candidate-fixture receipt; live census remains explicitly not run.\n\nCo-Authored-By: Claude --- .../polylogue-excluded-cursor-live-proof-2026-08-06.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json b/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json index 607f46d695..ecfa0d281e 100644 --- a/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json +++ b/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json @@ -1 +1 @@ -{"anti_vacuity":{"indexed_session_count":1,"typed_terminal_artifact":"terminal_corrupt_input","unchanged_excluded_attempt_present":false},"cases":[{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"indexed","indexed":{"indexed_sessions":1,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"needs_work_after_fingerprint_change":true,"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"fbe00b1bf4fe9b647b143e5f002a8edfd9d3685944fa44125586a679c4cc6534","terminal_evidence":null},{"attempt":null,"attempt_present":false,"case_id":"still-excluded","indexed":{"indexed_sessions":1,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":0,"succeeded_file_count":0},"needs_work_after_fingerprint_change":false,"proof_attempt_count":0,"retry_state":{"excluded":true,"failed_with_retry":false,"failure_count":5,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"cb7b4873a5dc05a7cac589c60a8069dc9f91f234af3076f8ea558bfafe69612a","terminal_evidence":null},{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"typed-terminal","indexed":{"indexed_sessions":0,"parsed_raw":0},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"needs_work_after_fingerprint_change":true,"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"2e5c27f8ae0c2f4176892776a5a0ac5e1d598178676396f86fa4f6d608778d75","terminal_evidence":{"artifact_kind":"terminal_corrupt_input","parse_error_present":true,"support_status":"decode_failed"}}],"execution":{"live_census":"not_run","live_residual":"Historical excluded population and current live file states were not accessed.","mode":"candidate_fixture","residual_successor":"polylogue-excluded-cursor-live-proof","terminal_frontier_residual":"The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only."},"fairness":{"planner":"_interleave_by_source","property":"browser-capture drains first; among non-browser-capture families, one candidate from each present family reaches the first round"},"fixture_version":"candidate-codex-live-compatible-2026-08-06","outcomes":{"indexed":true,"still_excluded":true,"typed_terminal":true},"production_route":{"cursor_gate":"LiveWatcher._needs_work","ingest":"LiveWatcher._ingest_files -> LiveBatchProcessor.ingest_files","retry_state":"ops.ingest_cursor and ops.ingest_attempts","terminal_evidence":"source.raw_artifacts","transition":"CursorStore.revive_replaced_exclusion"},"receipt_sha256":"66d959091a0b8d2126fd42a7b502c2619688f43c789f53527792ceeb4c9e7678","schema":"polylogue.excluded-cursor-live-proof.v1"} +{"anti_vacuity":{"indexed_authority":"byte_proven_source_raw_and_revision_head","indexed_session_count":1,"indexed_session_count_before":0,"typed_terminal_artifact":"terminal_corrupt_input","unchanged_excluded_attempt_present":false},"cases":[{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"indexed","fingerprint_changed_before_catch_up":true,"indexed":{"indexed_sessions":1,"parsed_raw":2},"indexed_before":{"indexed_sessions":0,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"fbe00b1bf4fe9b647b143e5f002a8edfd9d3685944fa44125586a679c4cc6534","terminal_evidence":null},{"attempt":null,"attempt_present":false,"case_id":"still-excluded","fingerprint_changed_before_catch_up":false,"indexed":{"indexed_sessions":0,"parsed_raw":0},"metrics":{"failed_file_count":0,"full_file_count":0,"succeeded_file_count":0},"proof_attempt_count":0,"retry_state":{"excluded":true,"failed_with_retry":false,"failure_count":5,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"cb7b4873a5dc05a7cac589c60a8069dc9f91f234af3076f8ea558bfafe69612a","terminal_evidence":null},{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"typed-terminal","fingerprint_changed_before_catch_up":true,"indexed":{"indexed_sessions":0,"parsed_raw":0},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"2e5c27f8ae0c2f4176892776a5a0ac5e1d598178676396f86fa4f6d608778d75","terminal_evidence":{"artifact_kind":"terminal_corrupt_input","parse_error_present":true,"support_status":"decode_failed"}}],"execution":{"live_census":"not_run","live_residual":"Historical excluded population and current live file states were not accessed.","mode":"candidate_fixture","residual_successor":"polylogue-excluded-cursor-live-proof","terminal_frontier_residual":"The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only."},"fairness":{"planner":"_interleave_by_source","property":"browser-capture drains first; among non-browser-capture families, one candidate from each present family reaches the first round"},"fixture_version":"candidate-codex-live-compatible-2026-08-06","outcomes":{"indexed":true,"still_excluded":true,"typed_terminal":true},"production_route":{"catch_up":"LiveWatcher._catch_up -> _scan_catch_up_candidates -> _catch_up_candidates -> _plan_catch_up -> coordinated chunk ingest","cursor_gate":"LiveWatcher._needs_work","ingest":"LiveWatcher._ingest_files -> LiveBatchProcessor.ingest_files","retry_state":"ops.ingest_cursor and ops.ingest_attempts","terminal_evidence":"source.raw_artifacts","transition":"CursorStore.revive_replaced_exclusion"},"receipt_sha256":"69e75004783fc3f0af38b85ef01136ac8ece609db850b730773b42b56589e350","schema":"polylogue.excluded-cursor-live-proof.v1"} From 987b800843fec1a28e1c22cefdd954ff94ddbad3 Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 13:01:31 +0200 Subject: [PATCH 08/11] fix(test): normalize excluded cursor boolean Problem: mypy inferred the persisted integer excluded flag as a non-boolean union in the proof summary.\n\nWhat changed: coerce the cursor flag explicitly before recording the fingerprint transition.\n\nCompatibility/migration: proof harness only; production code is unchanged.\n\nCo-Authored-By: Claude --- tests/infra/excluded_cursor_live_proof.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/infra/excluded_cursor_live_proof.py b/tests/infra/excluded_cursor_live_proof.py index d529e1060d..0c1717cac6 100644 --- a/tests/infra/excluded_cursor_live_proof.py +++ b/tests/infra/excluded_cursor_live_proof.py @@ -249,7 +249,7 @@ def _run_case( try: record = cursor.get_record(path) fingerprint_changed_before_catch_up = ( - record is not None and record.excluded and record.parser_fingerprint != parser_fingerprint + record is not None and bool(record.excluded) and record.parser_fingerprint != parser_fingerprint ) metrics_holder: list[object] = [] original_ingest = watcher._ingest_files From 76c62b3ea1d6fc4721f9c21255d19b179a7b16ab Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 13:13:29 +0200 Subject: [PATCH 09/11] test(cursor): close proof index connection Problem The excluded-cursor proof left its index connection for garbage collection after seeding the byte head. What changed Close the fixture connection in a finally block while preserving the explicit commit. Verification direnv exec . devtools test tests/unit/sources/test_excluded_cursor_live_proof.py tests/unit/sources/test_live_watcher_catchup_order.py Co-Authored-By: Codex --- tests/infra/excluded_cursor_live_proof.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/infra/excluded_cursor_live_proof.py b/tests/infra/excluded_cursor_live_proof.py index 0c1717cac6..89c0dd4230 100644 --- a/tests/infra/excluded_cursor_live_proof.py +++ b/tests/infra/excluded_cursor_live_proof.py @@ -93,7 +93,8 @@ def _seed_byte_authority(root: Path, path: Path, *, native_id: str) -> None: native_id=native_id, revision=revision, ) - with sqlite3.connect(root / "index.db") as conn: + conn = sqlite3.connect(root / "index.db") + try: conn.execute( """ INSERT INTO raw_revision_heads ( @@ -113,6 +114,8 @@ def _seed_byte_authority(root: Path, path: Path, *, native_id: str) -> None: ), ) conn.commit() + finally: + conn.close() def _attempts_for_path(root: Path, path: Path) -> list[dict[str, object]]: From 1363639120b79c7b5edaed484318120c8bbad870 Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 13:33:22 +0200 Subject: [PATCH 10/11] test(cursor): require terminal parse evidence Problem\nThe typed-terminal proof accepted terminal classification labels without proving that parsing actually failed.\n\nWhat changed\nRequire parse_error_present in the terminal outcome while preserving the existing retry-state assertions.\n\nVerification\ndirenv exec . devtools test tests/unit/sources/test_excluded_cursor_live_proof.py tests/unit/sources/test_live_watcher_catchup_order.py\n\nRef polylogue-excluded-cursor-live-proof\n\nCo-Authored-By: Codex --- tests/infra/excluded_cursor_live_proof.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/infra/excluded_cursor_live_proof.py b/tests/infra/excluded_cursor_live_proof.py index 89c0dd4230..3a51688966 100644 --- a/tests/infra/excluded_cursor_live_proof.py +++ b/tests/infra/excluded_cursor_live_proof.py @@ -369,6 +369,7 @@ def prepare_case(case_id: str, native_id: str, texts: tuple[str, ...]) -> tuple[ "typed_terminal": terminal_evidence is not None and terminal_evidence["artifact_kind"] == "terminal_corrupt_input" and terminal_evidence["support_status"] == "decode_failed" + and terminal_evidence["parse_error_present"] is True and typed_terminal["retry_state"]["excluded"] is False and typed_terminal["retry_state"]["retry_due"] is False, } From ae10af89d10215935c1fd84ed0780e8d74861b4e Mon Sep 17 00:00:00 2001 From: Sinity Date: Thu, 6 Aug 2026 13:37:43 +0200 Subject: [PATCH 11/11] test(cursor): cover terminal parse evidence Problem\nThe proof's terminal parse-error requirement had no direct receipt assertion, so a malformed terminal fixture could regress without the unit test noticing.\n\nWhat changed\nAssert the typed-terminal receipt records parse_error_present as true.\n\nVerification\ndirenv exec . devtools test tests/unit/sources/test_excluded_cursor_live_proof.py tests/unit/sources/test_live_watcher_catchup_order.py\n\nRef polylogue-excluded-cursor-live-proof\n\nCo-Authored-By: Codex --- tests/unit/sources/test_excluded_cursor_live_proof.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/sources/test_excluded_cursor_live_proof.py b/tests/unit/sources/test_excluded_cursor_live_proof.py index a86ef30db0..6340dfa8ce 100644 --- a/tests/unit/sources/test_excluded_cursor_live_proof.py +++ b/tests/unit/sources/test_excluded_cursor_live_proof.py @@ -32,6 +32,8 @@ def test_candidate_fixture_proves_all_cursor_outcomes_and_is_immutable(tmp_path: "still_excluded": True, "typed_terminal": True, } + typed_terminal = next(case for case in receipt["cases"] if case["case_id"] == "typed-terminal") + assert typed_terminal["terminal_evidence"]["parse_error_present"] is True assert receipt["execution"] == { "mode": "candidate_fixture", "live_census": "not_run",