Files
multi-agent-mux/.agents/reports/reviewer-grok-01/report-d384cdc0.md
T

6.2 KiB
Raw Blame History

Review d384cdc0 — Issue #60, third pass

Reviewed only the snapshot /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261018T073639Z-b5cb7f/1 (loop-20261018T073639Z-b5cb7f). Head 0e05b1b6777ceb837066454ac688e04a0f5d14a0, tree c5cb1b16af283b3fdb447bafb865ba1abbfbb5a8, base 74333f87d0c02888c2b5b281e912d97e74348c01 is an ancestor. Five commits, 15 files, +705/−330. git diff --check is clean. Snapshot porcelain is empty and the snapshot has no .mam. Control-plane main is 74333f87d0c02888c2b5b281e912d97e74348c01, porcelain empty. No product file was edited.

The new commit on top of cb5f439 is 0e05b1b. It changes three files: tests/_agent_home_guard.py, .agents/skills/multi-agent-mux-status/scripts/status.sh (both copies of resume_on_disk), and the --version probe in tests/test_issue60_opencode_v2.py.

Host tools: the control-plane venv is Python 3.9.6, /bin/bash is 3.2.57. bash -n accepts status.sh and create_session.sh. opencode --version in a temporary home, with an environment of only PATH, HOME, and TMPDIR, printed opencode v2.0.32.

The user's background service stayed up. Its pid is 86524, the command is opencode serve --service, and both service-file mtimes stayed 1792246838. The real database mtime stayed 1792247140, with 4 session rows and 4 session_v2 rows. The real opencode.log mtime stayed 1792308195 and its size stayed the same. The herdr config mtime stayed 1784456394.

What 0e05b1b fixes

_agent_home_guard.DROPPED_VARS now includes XDG_DATA_HOME (_agent_home_guard.py:21). conftest._isolate_agent_homes drops that tuple for every test, and pytest_configure records the value first so the session guard can watch it. watch_dirs uses <XDG_DATA_HOME>/opencode when the recorded environment has the variable, and <home>/.local/share/opencode otherwise (_agent_home_guard.py:48-49).

That matches the second-pass failure. The adapter follows the caller's XDG_DATA_HOME when ctx.home_dir is the caller's own home. A sandbox that only changed HOME still inherited the runner's XDG_DATA_HOME, so discovery and purge resolved the runner's data directory. Dropping the variable makes HOME govern, which is what _data_home does when the variable is unset.

test_l1_every_path_variable_the_code_reads_is_accounted_for scans adapters for *_HOME reads. XDG_DATA_HOME is one of them (opencode.py os.environ.get("XDG_DATA_HOME")). A clone whose DROPPED_VARS omitted it failed that test in 0.04 s with ['XDG_DATA_HOME']. The suite below was started with XDG_DATA_HOME pointed at an empty directory /tmp/mamd384-d384cdc0-xdg. After 65 passed tests that directory was still empty.

status.sh resume_on_disk, in the --json block and in the text block, asks get_adapter('opencode')._resolve_db(DiscoveryContext(..., home_dir=home)) (status.sh:108-111 and :305-308 in the second copy). home is HOME_DIR. env_python passes the parent environment through, so a set XDG_DATA_HOME reaches _data_home when HOME_DIR is the caller's home. A copy of the tree, with the fake opencode on PATH and the only database under a separate XDG_DATA_HOME, returned exit 0. --json resume_state was yes for ses_probe and MISSING for an id the database does not hold. Text mode exited 0 and the session's line contained yes. ~/.local/share/opencode/opencode.db under that sandbox home was not created. The existing status checks in the same suite (test_status_json_schema_fields, test_status_text_headers_presence, and the claude and agy resume_on_disk helpers) also exited 0.

_real_opencode runs --version inside tempfile.TemporaryDirectory with HOME and TMPDIR set to that directory and no XDG_* variables (test_issue60_opencode_v2.py:298-300). The same shape, run on its own, wrote a log only under that temporary home. The real log was unchanged. The opt-in contract ran as part of the 65 (no skip).

Suite

Pytest used the control-plane venv, PYTHONDONTWRITEBYTECODE=1, -p no:cacheprovider, and --basetemp /tmp/mamd384-d384cdc0-pybase. Inherited HERDR_*, MAM_*, MQTT_*, SKS_*, WORKSPACE_ROOT, DELEGATE_JOB_LOGS_DIR, HOME_DIR, CLAUDE_*, CODEX_HOME, and PYTHONPATH were dropped. XDG_DATA_HOME was the empty sentinel above. XDG_STATE_HOME, XDG_CONFIG_HOME, and XDG_CACHE_HOME were unset.

65 passed in 68.75 s: tests/test_issue55_agent_homes.py, tests/test_issue60_opencode_v2.py (including the real-binary contract), tests/test_a4_adapter_contract.py, tests/test_issue31_purge_residual.py::test_opencode_purge_leaves_no_rows, tests/test_tier2_component.py::test_comp_opencode_create_and_reconcile_and_stop, and the four status cases named above. No skip and no error. Snapshot porcelain stayed empty.

opencode debug paths in a temporary home prints the db line under that home's .local/share/opencode and creates log/opencode.log there. It does not create opencode.db. So an opencode row in status.sh now runs that command, and a real status check appends the log under the data directory _resolve_db is about to open. The RESUME value and the exit code measured above stay 0 / yes / MISSING. The database file is untouched by the path lookup.

The earlier commits are unchanged in this pass: purge still collects descendants before session delete and deletes the 1.x rows of parent and children, conversation_in_use still ignores only a serve --service holder, drift C still requires parent_id IS NULL, and spawn/resume stay --auto --standalone. The tier-2 test in this suite pins the parent when a newer child shares the directory, against the mock herdr. This review did not drive a live herdr pane through create, a first TUI message, stop, and resume.

The new code uses the environment, sqlite, and subprocess. Nothing added in 0e05b1b is macOS-only. This host is macOS, so Linux was not executed here.

After the report, snapshot porcelain is still empty, the snapshot still has no .mam, and control-plane porcelain is still empty at 74333f87. The herdr config mtime is still 1784456394. The opencode database mtime is still 1792247140, the opencode log mtime is still 1792308195, and service pid 86524 is still opencode serve --service.

[VERDICT: PASS]