From 328526a8346f6a5c7a93fa8fd36be0d499d6e113 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 01:36:10 +0000 Subject: [PATCH 1/3] Initial plan From d763b8df9591cfab89df6b25b28f2353813fc28c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 01:38:07 +0000 Subject: [PATCH 2/3] Fix EventStore read verbs to avoid WAL sidecar creation --- loop/runtime.py | 9 +++++++-- scripts/test_doctor_eventstore.py | 12 ++++++++++++ scripts/test_loop_cli_status_replay.py | 13 ++++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/loop/runtime.py b/loop/runtime.py index 7ebd367..cb47865 100644 --- a/loop/runtime.py +++ b/loop/runtime.py @@ -26,10 +26,15 @@ def _store_path(target: str | Path) -> Path: return resolve_loop_paths(target).loop_dir / "events.db" +def _readonly_query(path: Path) -> str: + """Avoid creating sidecars on clean stores while preserving crash-left WAL reads.""" + return "mode=ro" if path.with_name(path.name + "-wal").exists() else "mode=ro&immutable=1" + + def _read_events_readonly(path: Path, run_id: str) -> list[dict[str, Any]]: """Read the EventStore row shape without invoking its write-capable connector.""" try: - conn = sqlite3.connect(f"{path.absolute().as_uri()}?mode=ro", uri=True) + conn = sqlite3.connect(f"{path.absolute().as_uri()}?{_readonly_query(path)}", uri=True) try: rows = conn.execute( "SELECT run_id, sequence, event_id, type, actor, causation_id, " @@ -59,7 +64,7 @@ def _discover_run_id(path: Path) -> str: if not path.exists(): raise RuntimeStoreError("missing_store", f"event store does not exist: {path}") try: - conn = sqlite3.connect(f"{path.absolute().as_uri()}?mode=ro", uri=True) + conn = sqlite3.connect(f"{path.absolute().as_uri()}?{_readonly_query(path)}", uri=True) try: rows = conn.execute("SELECT DISTINCT run_id FROM events ORDER BY run_id ASC").fetchall() finally: diff --git a/scripts/test_doctor_eventstore.py b/scripts/test_doctor_eventstore.py index b816693..5a45570 100644 --- a/scripts/test_doctor_eventstore.py +++ b/scripts/test_doctor_eventstore.py @@ -164,3 +164,15 @@ def test_ambiguous_run_id_fails_doctor(tmp_path): assert report["ok"] is False assert report["event_store"]["error_code"] == "ambiguous_run_id" assert "ambiguous_run_id" in _codes(report) + + +def test_doctor_event_store_reads_do_not_leave_wal_or_shm_sidecars(tmp_path): + target = _fresh_contract(tmp_path) + _sync_active_task(target) + _open(_store(target)) + wal = target / ".loop" / "events.db-wal" + shm = target / ".loop" / "events.db-shm" + assert not wal.exists() and not shm.exists() + report = doctor_report(target) + assert report["event_store"]["present"] is True + assert not wal.exists() and not shm.exists() diff --git a/scripts/test_loop_cli_status_replay.py b/scripts/test_loop_cli_status_replay.py index 4734644..bf61517 100644 --- a/scripts/test_loop_cli_status_replay.py +++ b/scripts/test_loop_cli_status_replay.py @@ -148,11 +148,18 @@ def test_events_db_is_opened_strictly_read_only_no_write_side_effects(tmp_path): workspace, store = _workspace(tmp_path) _terminal(store) (workspace / ".loop" / "terminal_state.json").write_text('{"state":"Succeeded"}', encoding="utf-8") - files = sorted((workspace / ".loop").iterdir()) - before = {p.name: (p.stat().st_mtime_ns, hashlib.sha256(p.read_bytes()).hexdigest()) for p in files if p.is_file()} + before = { + p.name: (p.stat().st_mtime_ns, hashlib.sha256(p.read_bytes()).hexdigest()) + for p in sorted((workspace / ".loop").iterdir()) + if p.is_file() + } status_report(workspace) replay_report(workspace) - after = {p.name: (p.stat().st_mtime_ns, hashlib.sha256(p.read_bytes()).hexdigest()) for p in files if p.is_file()} + after = { + p.name: (p.stat().st_mtime_ns, hashlib.sha256(p.read_bytes()).hexdigest()) + for p in sorted((workspace / ".loop").iterdir()) + if p.is_file() + } assert after == before From 160b331e7198a1405f61a4d5656bb0160ad50c45 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 01:39:07 +0000 Subject: [PATCH 3/3] Address review follow-ups for runtime sidecar fix --- loop/runtime.py | 2 +- scripts/test_doctor_eventstore.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/loop/runtime.py b/loop/runtime.py index cb47865..37ca33f 100644 --- a/loop/runtime.py +++ b/loop/runtime.py @@ -28,7 +28,7 @@ def _store_path(target: str | Path) -> Path: def _readonly_query(path: Path) -> str: """Avoid creating sidecars on clean stores while preserving crash-left WAL reads.""" - return "mode=ro" if path.with_name(path.name + "-wal").exists() else "mode=ro&immutable=1" + return "mode=ro" if (path.parent / (path.name + "-wal")).exists() else "mode=ro&immutable=1" def _read_events_readonly(path: Path, run_id: str) -> list[dict[str, Any]]: diff --git a/scripts/test_doctor_eventstore.py b/scripts/test_doctor_eventstore.py index 5a45570..4d77f65 100644 --- a/scripts/test_doctor_eventstore.py +++ b/scripts/test_doctor_eventstore.py @@ -170,9 +170,8 @@ def test_doctor_event_store_reads_do_not_leave_wal_or_shm_sidecars(tmp_path): target = _fresh_contract(tmp_path) _sync_active_task(target) _open(_store(target)) - wal = target / ".loop" / "events.db-wal" - shm = target / ".loop" / "events.db-shm" - assert not wal.exists() and not shm.exists() + sidecars = (target / ".loop" / "events.db-wal", target / ".loop" / "events.db-shm") + assert all(not path.exists() for path in sidecars) report = doctor_report(target) assert report["event_store"]["present"] is True - assert not wal.exists() and not shm.exists() + assert all(not path.exists() for path in sidecars)