fix(opencode): a -wal left without its -shm is read, not ignored (Issue #60, Linux item 5, review)

_ro_connect read every database without both sidecars as immutable, which
skips a -wal's committed rows: a recovered DB+WAL with no -shm showed no
sessions (planner-reviewer-codex-01). That state - no writer runs without
a -shm - is now read from a private DB+WAL copy, where SQLite may rebuild
the index, loaded into memory; nothing beside the source is touched. The
query matrix gains the walonly state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-18 13:36:41 +00:00
1 parent 463817ee34
commit 7803d47026
2 files changed
+28 -9

No files matched your search

@@ -1,4 +1,4 @@
import os, sys, sqlite3, shutil, subprocess
import os, sys, sqlite3, shutil, subprocess, tempfile
from urllib.parse import quote
from typing import Optional, Any, List
from lib_py.agents.base import BaseAgentAdapter, DiscoveryContext, scan_names, db_rows_naming, conversation_in_use
@@ -11,12 +11,29 @@ _LEGACY_TABLES = (("message", "session_id"), ("messages", "session_id"), ("part"
("session", "id"), ("sessions", "id"))
def _ro_connect(db: str):
"""A read that neither creates nor removes anything beside db (Issue #60):
the WAL sidecars are used only when both already exist (a live writer
keeps them); otherwise the file is read as immutable."""
"""A read that neither creates nor removes anything beside db (Issue #60).
Both WAL sidecars (a live writer keeps them): read through them. No -wal:
nothing to apply, so the file is read as immutable. A -wal without its
-shm (left behind - no writer runs without one) still holds committed
rows: they are read from a private copy, where SQLite may rebuild the
index, loaded into memory."""
path = os.path.abspath(db)
both = os.path.exists(path + "-wal") and os.path.exists(path + "-shm")
return sqlite3.connect(f"file:{quote(path)}?mode=ro" + ("" if both else "&immutable=1"), uri=True)
wal, shm = os.path.exists(path + "-wal"), os.path.exists(path + "-shm")
if wal and shm:
return sqlite3.connect(f"file:{quote(path)}?mode=ro", uri=True)
if not wal:
return sqlite3.connect(f"file:{quote(path)}?mode=ro&immutable=1", uri=True)
mem = sqlite3.connect(":memory:")
with tempfile.TemporaryDirectory(prefix="mam-opencode-") as tmp:
copy = os.path.join(tmp, "opencode.db")
shutil.copyfile(path, copy)
shutil.copyfile(path + "-wal", copy + "-wal")
src = sqlite3.connect(copy)
try:
src.backup(mem)
finally:
src.close()
return mem
# (binary, HOME, XDG_DATA_HOME) -> the db `debug paths` printed for them.