Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
8.5 KiB
PR #62 Code Review Report — Issue #60 Linux Follow-up (1d7b7da..6a4e385)
- Job ID:
ba63f0b5 - Reviewer:
agy(herdr:reviewer-agy-01) - Branch:
fix/issue-60-linux - Base .. Head:
1d7b7dab58a10fe86fd747b7290d47674ca93230..6a4e385a78c8a561d5cf3644336de6a352ea9271(8 commits) - Verification Worktree:
/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261019T000805Z-975c4c/1
1. Executive Summary
All production code changes in PR #62 (_ro_connect, _DB_PATHS cache, input_placeholder_pattern, auth_ok / auth-ok, stop_session.sh log text, and test_u1e) are well-designed and behave as intended on macOS (Python 3.9.6, Apple SQLite 3.51.0, opencode 2.0.32).
However, 5 test cases in tests/test_issue60_linux_fixes.py fail on macOS (test_a_query_reads_right_and_leaves_the_sidecars_alone[clean-listing0-*]) due to a macOS vs. Linux SQLite difference in wal_home's make("clean") fixture helper:
- On Linux (upstream SQLite default
SQLITE_FCNTL_PERSIST_WAL = 0), closing the last connection to a WAL database (_wal_writer(db, ws).close()) checkpoints the WAL intoopencode.dband unlinksopencode.db-walandopencode.db-shm. - On macOS (
/usr/bin/python3linked against Apple's/usr/lib/libsqlite3.dylib, which setsSQLITE_FCNTL_PERSIST_WAL = 1by default),_wal_writer(db, ws).close()checkpoints the WAL intoopencode.dband truncatesopencode.db-walto 0 bytes, but leavesopencode.db-walandopencode.db-shmon disk. - Consequently,
assert make(state) == listingattests/test_issue60_linux_fixes.py:181fails withAssertionError: assert ['opencode.db', 'opencode.db-shm', 'opencode.db-wal'] == ['opencode.db']before_ro_connectis even called.
Unlinking opencode.db-wal and opencode.db-shm after _wal_writer(db, ws).close() in make("clean") makes all 20 (query × state) cases pass on macOS as well.
2. Findings
[P1] Blocking — wal_home fixture make("clean") fails on macOS due to Apple SQLite SQLITE_FCNTL_PERSIST_WAL=1
- Location:
tests/test_issue60_linux_fixes.py:157-159, 181 - Symptom:
Running
pytest tests/test_issue60_linux_fixes.pyon macOS (/usr/bin/python33.9.6,sqlite3.sqlite_version == '3.51.0') fails 5 tests:FAILED tests/test_issue60_linux_fixes.py::test_a_query_reads_right_and_leaves_the_sidecars_alone[clean-listing0-_descendants]FAILED tests/test_issue60_linux_fixes.py::test_a_query_reads_right_and_leaves_the_sidecars_alone[clean-listing0-_has_session]FAILED tests/test_issue60_linux_fixes.py::test_a_query_reads_right_and_leaves_the_sidecars_alone[clean-listing0-discover]FAILED tests/test_issue60_linux_fixes.py::test_a_query_reads_right_and_leaves_the_sidecars_alone[clean-listing0-residual_artifacts]FAILED tests/test_issue60_linux_fixes.py::test_a_query_reads_right_and_leaves_the_sidecars_alone[clean-listing0-verify_artifact]
- Root Cause:
Apple's system
libsqlite3.dylibenablesSQLITE_FCNTL_PERSIST_WALby default. When_wal_writer(db, ws).close()runs on macOS, SQLite checkpoints the committed WAL frames intoopencode.db(8192bytes) and truncatesopencode.db-walto0bytes, but keepsopencode.db-walandopencode.db-shmon disk instead of unlinking them. - Verification & Fix:
In
make(state)(tests/test_issue60_linux_fixes.py:157-159), removing any remaining sidecars after_wal_writer(db, ws).close()checkpoints the DB:leavesdef make(state): if state == "clean": _wal_writer(db, ws).close() for suffix in ("-wal", "-shm"): if os.path.exists(str(db) + suffix): os.unlink(str(db) + suffix)opencode.dbwith its WAL header and checkpointed rows and no sidecar files (["opencode.db"]). Verified on macOS that all 20(query × state)combinations pass with this change, and that_ro_connect(db)'smode=ro&immutable=1branch is crucial on macOS (where a plainmode=roopen on a sidecar-free WAL-mode DB raisessqlite3.OperationalError: unable to open database file, and a plain read-writesqlite3.connect(db)creates and leaves-waland-shm).
[P2] Non-blocking — status.sh and reconcile.sh still open opencode.db with read-write sqlite3.connect(odb)
- Locations:
.agents/skills/multi-agent-mux-status/scripts/status.sh:116, 316.agents/skills/multi-agent-mux-monitor/scripts/reconcile.sh:953
- Observation:
While
OpenCodeAgentAdaptermethods (verify_artifact,discover,_has_session,_descendants,residual_artifacts) now use_ro_connect(db),status.sh(both--jsonand text mode) andreconcile.sh(drift C, whichstatus.shalso runs via--dry-run) still callsqlite3.connect(odb)directly:- On macOS, calling
sqlite3.connect(odb)on a sidecar-free WAL-modeopencode.dbcreatesopencode.db-walandopencode.db-shmand leaves them on disk after.close(). - On Linux, calling
sqlite3.connect(odb)on aleftoverWAL database checkpoints the WAL and deletesopencode.db-walandopencode.db-shmon.close().
- On macOS, calling
- Suggestion:
In
status.sh:108-120, 308-320, replace the rawsqlite3.connect(odb)block withget_adapter('opencode')._has_session(odb, u)(which already uses_ro_connect), and inreconcile.sh:953, use_ro_connect(odb)fromlib_py.agents.adapters.opencode.
3. Detailed Review by Checklist Item
_ro_connecton macOS (.agents/skills/lib_py/agents/adapters/opencode.py:13-36):- Both
-waland-shmpresent (leftover/writer):sqlite3.connect(f"file:{quote(path)}?mode=ro", uri=True)reads uncommitted-to-main-file (WAL-committed) rows through the existing WAL index without creating or removing sidecars. - No
-wal(clean):sqlite3.connect(f"file:{quote(path)}?mode=ro&immutable=1", uri=True)readsopencode.dbdirectly without creating-wal/-shm(and avoidssqlite3.OperationalError: unable to open database filethat plainmode=roraises on macOS when opening a WAL-header DB without sidecars). Because every query opens, fetches, and immediately closesconn, any race with a writer starting right afteros.path.exists(path + "-wal")only sees the pre-WAL snapshot for that single short read and never holds an immutable handle across writes. -walwithout-shm(walonly): Copiesopencode.dbandopencode.db-walinto atempfile.TemporaryDirectory(prefix="mam-opencode-"), opens the private copy so SQLite can rebuild-shmand recover the committed WAL frames, backs it up to:memory:, and cleans up the temp dir. Verified on macOS that committed rows in-walare returned and the source directory remains['opencode.db', 'opencode.db-wal'].
- Both
_DB_PATHSprocess-local cache (opencode.py:40, 144-160):- Keyed by
(bin_path, ctx.home_dir, self._data_home(ctx))(or(bin_path, HOME, XDG_DATA_HOME)whenctx.home_diris unset). - Different
HOME,XDG_DATA_HOME, or binary paths produce distinct cache keys; faileddebug pathsruns (returncode != 0or nodbline) are not cached.
- Keyed by
auth_ok&create_session.sh(opencode.py:317-321,__main__.py:120-127,create_session.sh:146-151):- Checks binary existence on
PATHor<home>/.opencode/bin/opencodewithout spawningopencode --version(preventing log writes to the real opencode data dir). Other agents' branches increate_session.share untouched.
- Checks binary existence on
input_placeholder_pattern(opencode.py:75-79,base.py:212-217,input_region.py:80-81):re.fullmatch(r'Ask anything(?:…|\.\.\.)(?: "[^"]*"?)?', head.strip())strips both full and narrow-truncated 2.x home screen placeholders while preserving user input starting withAsk anything…(such as'Ask anything… "x" and fix it'). Other adapters returnNone.
- Python 3.9 & macOS compatibility:
- All syntax, type annotations, and shell scripts are compatible with Python 3.9.6 and macOS bash 3.2 (
set -euo pipefail).git diff --checkis clean.
- All syntax, type annotations, and shell scripts are compatible with Python 3.9.6 and macOS bash 3.2 (
4. Test Execution Summary
Executed in /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261019T000805Z-975c4c/1 with isolated HOME, external --basetemp, PYTHONDONTWRITEBYTECODE=1, and -p no:cacheprovider:
tests/test_issue60_opencode_v2.py: 15 passedtests/test_a4_adapter_contract.py: 33 passedtests/test_issue50_dispatch.py: 49 passedtests/test_issue55_agent_homes.py: 11 passedtests/test_issue60_linux_fixes.py: 40 passed, 5 failed (test_a_query_reads_right_and_leaves_the_sidecars_alone[clean-listing0-*])
[VERDICT: NOT PASS]