Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
7.4 KiB
7.4 KiB
Review Report: Issue #60 (fix/issue-60-opencode-v2)
- Job ID:
1abe0a90 - Reviewer:
herdr:reviewer-agy-01(agy) - Commit Range:
74333f87d0c02888c2b5b281e912d97e74348c01..6b4b96fa1875862ef3bed830fe7b04166b1fad58(3 commits across 13 files) - Verification Worktree:
/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261018T055915Z-abe16e/1 - Host / Runtime: macOS
arm64-apple-darwin25(Darwin 25.3.0),/usr/bin/python33.9.6 &.venv/bin/python3.9.6,/bin/bash3.2.57,opencodev2.0.32 (/Users/godopu16/.opencode/bin/opencode)
1. Review Findings by Focus Area
1.1 OpenCode 2.x Schema, CLI Contract, and Purge Safety
_resolve_db(opencode debug paths):.agents/skills/lib_py/agents/adapters/opencode.py:88-107invokesself._run(ctx, ["debug", "paths"], timeout=5)withHOME,HOME_DIR, andXDG_DATA_HOME=<ctx.home_dir>/.local/share, parses thedbline, and falls back tof"{ctx.home_dir}/.local/share/opencode/opencode.db".- Verified against real
opencode v2.0.32in an isolated temporaryHOME:debug pathsreturns<home>/.local/share/opencode/opencode.dbwithout creating the database file.
verify_artifactanddiscover(session_v2&parent_id IS NULL):verify_artifact(.agents/skills/lib_py/agents/adapters/opencode.py:113-147) queriesSELECT directory, time_created FROM session_v2 WHERE id=?, converts millisecondtime_created(float(started_at) / 1000.0) againstctx.epoch, and checksworkspace_key(found_cwd) == workspace_key(ctx.cwd).discover(.agents/skills/lib_py/agents/adapters/opencode.py:198-235) queriesSELECT id FROM session_v2 WHERE parent_id IS NULL, filtering out subagent child sessions (which sharedirectoryand have newertime_createdthan the top-level TUI session).- Verified against read-only inspection (
mode=ro) of the host's migratedopencode.dband a fresh2.0.32DB in a temporaryHOME: fresh 2.x databases containsession_v2(withid,parent_id,directory,time_created) and nosession/message/part/todo/session_sharetables.
purge_artifactsandresidual_artifacts:purge_artifacts(.agents/skills/lib_py/agents/adapters/opencode.py:149-181) checksself._has_session(db, uuid)(SELECT 1 FROM session_v2 WHERE id=?) before callingself._run(ctx, ["session", "delete", "--standalone", "--", uuid], timeout=60).- Using
--beforeuuidprevents option-flag injection if an ID ever starts with-, and--standaloneavoids starting or attaching to a per-user background service. - In a fresh 2.0.32 DB,
session_inbox,session_message,session_pending,instruction_entry, andinstruction_stateall haveON DELETE CASCADEforeign keys tosession_v2(id), andopencode session deletealso removeseventandevent_sequencerows (aggregate_id) for the session and its child sessions while leaving other sessions untouched. - For databases migrated from 1.x,
purge_artifactssubsequently deletes matchinguuidrows frompart/parts/message/messages/session/sessions(if those tables exist) andresidual_artifactsreports any survivingtodo.session_idorsession_v2.id(e.g., ifsession deletefailed or the binary was missing, in which casepurge_artifactsemits aWARN:onstderr).
1.2 End-to-End Lifecycle (create → reconcile drift C → status → stop → resume)
create_session.sh,resume_session.sh,update_yaml_resumed.sh:- All three scripts and
OpenCodeAgentAdapter.spawn_spec/resume_specconsistently useopencode --auto --standalone(andopencode --session <uuid> --auto --standaloneon materialized resume), removing the defunct--agent buildflag rejected by OpenCode 2.x TUI.
- All three scripts and
reconcile.sh(drift C) andstatus.sh:.agents/skills/multi-agent-mux-monitor/scripts/reconcile.sh:955-990inspectsPRAGMA table_info(session_v2), filters byparent_id IS NULL,directory = ?, andtime_created >= ?(ms), and validates candidates viaverify_session_uuid(cwd, 'opencode', uuid, s_eval, mode="discover")..agents/skills/multi-agent-mux-status/scripts/status.sh:127,337checksSELECT 1 FROM session_v2 WHERE id=?in both human and JSON status paths.
--standaloneprocess lifecycle &stop_session.sh:- Verified in an isolated PTY with real
opencode v2.0.32:opencode --auto --standalonespawnsopencode serve --stdio --port 0as a direct child of the TUI process; closing the PTY master terminates both the TUI and itsopencode serve --stdio --port 0child cleanly within ~0.1s with zero lingering background processes. stop_session.sh's graceful/exit(send_keys_safewith echo wait beforeEnter) ->herdr kill-session(closes PTY) ->SIGKILLfallback andin-usegate (psargv check for--session <uuid>) work cleanly with--standalone.
- Verified in an isolated PTY with real
1.3 Linux Portability, Shell/Python Compatibility, and Completeness
- Linux & XDG portability:
OpenCodeAgentAdapter._runexplicitly setsHOME,HOME_DIR, andXDG_DATA_HOME = os.path.join(ctx.home_dir, ".local/share"), ensuring that even on Linux hosts whereXDG_DATA_HOMEis set in the ambient desktop environment, adapter CLI invocations remain isolated toctx.home_dir.test_real_opencode_2x_contractexplicitly unsetsXDG_DATA_HOME,XDG_STATE_HOME,XDG_CONFIG_HOME,XDG_CACHE_HOME, andHOME_DIRviamonkeypatch.delenv.
- Python 3.9 & Bash 3.2 compatibility:
- Verified on macOS
/usr/bin/python3/.venv/bin/python(3.9.6) and/bin/bash(3.2.57 withset -u).
- Verified on macOS
- Repository-wide search for stale 1.x assumptions:
- Grepping
.agents/skills/,tests/, anddocs/fordb path,--agent build,FROM session\b,INTO session\b, andtable_info(session)confirms no remaining 1.x code or documentation assumptions exist outside explanatory comments.
- Grepping
- Test coverage & negative regression verification:
tests/test_issue60_opencode_v2.py(10/10 passed, includingtest_real_opencode_2x_contractagainst realopencode v2.0.32),tests/test_a4_adapter_contract.py,tests/test_issue31_purge_residual.py,tests/test_issue42_skill_blocks.py,tests/test_issue55_agent_homes.py, andtests/test_tier1_unit.pyall pass.- Reverting
SELECT id FROM session_v2 WHERE parent_id IS NULLtoSELECT id FROM sessionin an isolated/tmpcopy immediately failstest_discover_and_verify_read_session_v2_and_skip_child_sessionsandtest_a_fresh_2x_database_has_no_session_table_and_still_works.
2. Non-Blocking Observation (Out of Scope for Issue #60)
- [Note —
stall_watch.pybackground_childrenwith--standalone]:- Because
opencode --auto --standalonekeepsopencode serve --stdio --port 0alive as a child process of the TUI while idle, andOpenCodeAgentAdapter.resident_childrenis(),lib_py.stall_watch.background_children(agent_pid, adapter.resident_children)sees theopencode serve --stdio --port 0child process and conservatively withholds the optional idle nudge (NOTIFY_IDLE_AND_NUDGE). If idle nudging is desired for--standaloneOpenCode in the future,stall_watch.background_childrencan exempt children whoseargvmatchesopencode serve --stdio(while still walking any tool subprocesses spawned beneath that server). This does not affect any session lifecycle, discovery, or purge behavior in Issue #60.
- Because
[VERDICT: PASS]