fix(agents): codex, grok and opencode report their residual (Issue #31)

Their purge is unchanged; what it leaves is now reported: codex names and
thread rows (state_*, thread_history_*; logs_* is not scanned), grok
memory-v2 observations, opencode event/todo rows. db_rows_naming opens the
DB read-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-15 15:16:06 +00:00
1 parent ae98cf18c4
commit b3461377ae
4 files changed
+61 -3

No files matched your search

+35
View File
@@ -2,6 +2,7 @@
import os, json, sqlite3, shutil, subprocess
from typing import Optional, Dict, Any, List
from urllib.parse import quote
from lib_py.paths import resolve_home
from lib_py.verify_session import verify_session_uuid, workspace_key
@@ -107,6 +108,40 @@ def scan_names(root: str, uuid: str, skip=()) -> list:
return sorted(found)
def db_rows_naming(db: str, uuid: str, columns=(), id_tables=()) -> list:
""""<db> (<table>.<col>: <n> rows)" for every table holding rows of this
conversation in one of `columns`, or in the id column of an `id_tables`
(table, column) pair (Issue #31). Read-only; unreadable tables are skipped."""
if not _plausible_id(uuid) or not db or not os.path.isfile(db):
return []
try:
conn = sqlite3.connect(f"file:{quote(os.path.abspath(db))}?mode=ro", uri=True)
except Exception:
return []
found = []
try:
tables = [r[0] for r in conn.execute("SELECT name FROM sqlite_master WHERE type='table'")]
for table in tables:
qt = table.replace('"', '""')
try:
cols = {r[1] for r in conn.execute(f'PRAGMA table_info("{qt}")')}
except Exception:
continue
wanted = [c for c in columns if c in cols]
wanted += [c for t, c in id_tables if t == table and c in cols and c not in wanted]
for col in wanted:
try:
n = conn.execute(f'SELECT count(*) FROM "{qt}" WHERE "{col}"=?', (uuid,)).fetchone()[0]
except Exception:
continue
if n:
found.append(f"{db} ({table}.{col}: {n} rows)")
except Exception:
pass
finally:
conn.close()
return found
class SpawnSpec:
def __init__(self, agent_name: str, session_name: str, command: str, env: Optional[Dict[str, str]] = None):
self.agent_name = agent_name