Files
multi-agent-mux/.agents/reports/reviewer-agy-01/report-e95527ef.md
T

7.4 KiB

Issue #64 Code Review Report (3ce5d5f..b0eccc5)

  • Job ID: e95527ef
  • Reviewer: agy (herdr:reviewer-agy-01)
  • Branch: fix/issue-64-ro-connect
  • Base .. Head: 3ce5d5fdc108b0435e933a251fe1c1256b5d7973 (v4.9.7) .. b0eccc530149bc6e9211727e19921665c7b80492 (1 commit)
  • Verification Worktree: /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261019T134017Z-d90c23/1

1. Root Cause Analysis (Task 1)

Why did the Issue #55 agent home guard detect newly created .db-wal and .db-shm sidecars beside another workspace's agy conversation DB during a macOS test run?

  1. Global agy conversation directory scan in reconcile.sh drift C (.agents/skills/multi-agent-mux-monitor/scripts/reconcile.sh:797-817):
    • When an agy session is running and unpinned (agy_conversation_id_own is None), reconcile.sh globs every *.db in ${HOME_DIR}/.gemini/antigravity-cli/conversations/ (a global directory shared across all workspaces under that HOME) and invokes verify_session_uuid(cwd, 'agy', uuid, s_eval, mode="discover").
  2. AgyAgentAdapter.verify_artifact opened every candidate .db with read-write sqlite3.connect(path) (.agents/skills/lib_py/agents/adapters/agy.py:60-80):
    • In discover mode, verify_artifact reads cache/last_conversations.json. When lc_data.get(ctx.cwd) == uuid is False (for example, uuid belongs to another workspace), verify_artifact only filters out uuid if it is in ctx.row.get("_sibling_claimed_uuids") (which tracks siblings in the same workspace cwd) or if os.path.getmtime(path) < ctx.epoch.
    • For any conversation .db from another workspace whose mtime >= ctx.epoch (or when ctx.epoch is not set), verify_artifact proceeded to conn = sqlite3.connect(path) to run SELECT count(*) FROM steps.
  3. macOS persistent WAL sidecar creation:
    • On macOS, Apple's system libsqlite3.dylib sets SQLITE_FCNTL_PERSIST_WAL = 1 by default. Opening a WAL-mode .db that currently has no -wal/-shm sidecars with read-write sqlite3.connect(path) and closing it creates <uuid>.db-wal and <uuid>.db-shm and leaves them on disk.
    • Similarly, if any reconcile.sh or verify_artifact call ran against the real HOME (or if another workspace's reconcile.sh / agy process scanned conversations/*.db while the test suite was running), opening a clean WAL .db with sqlite3.connect(path) created <uuid>.db-wal and <uuid>.db-shm in ~/.gemini/antigravity-cli/conversations/, which _agent_home_guard flagged at session teardown.
    • Replacing sqlite3.connect(path) with _ro_connect(path) (mode=ro&immutable=1 when no -wal exists) prevents MAM from ever creating or removing -wal/-shm sidecars when inspecting agy conversation databases (verified by test_unpinned_agy_reconcile_leaves_other_workspace_clean_db_without_sidecars, which fails on base 3ce5d5f and passes on head b0eccc5).

2. Summary of Changes (3ce5d5f..b0eccc5)

Changed Files & Lines (Read-Only Agent DB Queries)

  1. .agents/skills/lib_py/agents/base.py:111-145:
    • Moved _ro_connect(db: str) to lib_py.agents.base as a shared helper (with tempfile.TemporaryDirectory(prefix="mam-ro-") and os.path.basename(path) or "state.db" for the walonly branch).
    • Updated db_rows_naming default connect to _ro_connect (conn = (connect or _ro_connect)(db)), so codex.residual_artifacts (state_*.sqlite, thread_history_*.sqlite) and any other db_rows_naming callers also use _ro_connect instead of plain mode=ro.
  2. .agents/skills/lib_py/agents/adapters/opencode.py:3, 161-185:
    • Imports and reuses _ro_connect from lib_py.agents.base.
  3. .agents/skills/lib_py/agents/adapters/agy.py:3, 74:
    • verify_artifact (and discover, which delegates to verify_artifact) opens conversations/<uuid>.db via _ro_connect(path).
  4. .agents/skills/lib_py/agents/adapters/codex.py:3, 80, 195:
    • _find_rollout_via_db (used by _find_rollout, artifact_path, verify_artifact) and discover open state_*.sqlite via _ro_connect(db).
  5. .agents/skills/lib_py/agents/adapters/hermes.py:3, 51, 100:
    • verify_artifact and discover open ~/.hermes/state.db via _ro_connect(hdb).
  6. .agents/skills/multi-agent-mux-status/scripts/status.sh:90-91, 103, 120-121, 290-291, 303, 320-321:
    • Both --json and text modes use _ro_connect from lib_py.agents.base for hermes (hdb), opencode (odb), and codex (db). Zero raw sqlite3.connect calls remain in status.sh.
  7. .agents/skills/multi-agent-mux-monitor/scripts/reconcile.sh:423, 865, 954, 1047:
    • Imports _ro_connect from lib_py.agents.base at top level and uses it for hermes drift C (_ro_connect(hdb)), opencode drift C (_ro_connect(odb)), and codex drift C (_ro_connect(state_db)). Zero raw sqlite3.connect calls remain in reconcile.sh.
  8. tests/test_issue64_ro_connect.py (lines 1-408):
    • 43 new regression tests covering shared helper identity, all 4 WAL states (clean, leftover, walonly, writer) across agy, codex, hermes, and db_rows_naming, static and runtime checks of status.sh and reconcile.sh, and cross-workspace unpinned agy drift-C discovery.

Intentionally Excluded sqlite3.connect Call Sites

  • Agent DB write paths (purge_artifacts):
    • lib_py/agents/adapters/codex.py:152 (DELETE FROM threads WHERE id=?)
    • lib_py/agents/adapters/hermes.py:74 (DELETE FROM sessions / DELETE FROM messages)
    • lib_py/agents/adapters/opencode.py:193 (DELETE from 1.x legacy tables)
  • MAM's own state database (agent-sessions.db):
    • lib_py/atomic_yaml.py:61, lib_py/state.py:17, lib_py/verify_session.py:41, lib_py/loop/runner.py:416, lib.sh:1599, 2068.

3. Test Results (Base vs. Head) & Remaining Risks

  1. Negative verification on base (3ce5d5f):
    • Running tests/test_issue64_ro_connect.py against an archive copy of base (3ce5d5f) on macOS: 23 failed, 20 passed in 10.97s (every clean and walonly state across agy, codex, hermes, db_rows_naming, status.sh, reconcile.sh, plus test_ro_connect_lives_in_base_and_opencode_reuses_it, test_status_and_reconcile_static_ro_connect_usage, and test_unpinned_agy_reconcile_leaves_other_workspace_clean_db_without_sidecars failed as expected).
  2. Verification on head (b0eccc5):
    • tests/test_issue64_ro_connect.py: 43 passed
    • tests/test_issue60_linux_fixes.py: 52 passed
    • tests/test_issue60_opencode_v2.py: 15 passed
    • tests/test_a4_adapter_contract.py: 33 passed
    • tests/test_issue55_agent_homes.py: 11 passed
    • tests/test_issue31_purge_residual.py: 67 passed
    • Total: 221 passed in 119.66s
    • git status -s and git diff --check in the verification worktree are completely clean.
  3. Remaining risks:
    • External processes outside MAM (such as an active agy IDE/CLI session running in another workspace on the same host) can still create or remove their own conversation .db-wal/.db-shm sidecars in ~/.gemini/antigravity-cli/conversations/ while a pytest session is running, which _agent_home_guard (which only exempts live non-temp workspace directories for claude) can observe as a new directory entry. Within MAM itself, all read-only queries against agy, codex, hermes, and opencode databases are now sidecar-safe.

[VERDICT: PASS]