Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
6.1 KiB
Issue #60 리뷰 3차 — opencode 2.x 전용 지원 (job f1132474)
- 리뷰어: planner-reviewer-claude-01
- 검증 경로:
/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261018T073639Z-b5cb7f/1 - identity: HEAD
0e05b1b6777ceb837066454ac688e04a0f5d14a0, treec5cb1b16af283b3fdb447bafb865ba1abbfbb5a8— 일치, 작업 트리 clean,.mam없음. base..head 5커밋(a311c23,f0d1c00,6b4b96f,cb5f439,0e05b1b). 판정은 base..head 전체에 대해 내린다. - 1차(
6b4b96f)·2차(cb5f439)에서 실바이너리로 확인한 사항은0e05b1b가 건드리지 않은 제품 코드라 그대로 유효하다.0e05b1b는 status.sh, tests/_agent_home_guard.py, tests/test_issue60_opencode_v2.py 만 바꿨다. 확인한 사항:- 측정 사실과 구현의 일치
session delete의 자식 삭제, cwd 무관, 공유 행 보존- 3단 자손 정리
- 서비스 보유자 제외
--standalone수명- resident children
- 실제 opencode 데이터는 읽기(
grep -c,stat)로만 봤다.
결론
2차 차단 지적(B1)과 비차단 N1·N2 가 모두 해결됐고 새 회귀는 찾지 못했다. base..head 전체를 병합 가능으로 판단한다. 남은 것은 테스트 보강 권고뿐이다.
2차 지적별 확인
B1 (XDG_DATA_HOME 테스트 격리) — 해결.
_agent_home_guard.DROPPED_VARS에XDG_DATA_HOME이 추가됐다(tests/_agent_home_guard.py:21). 그래서conftest._isolate_agent_homes(conftest.py:210)가 테스트마다 이를 지운다. mam_sandbox·issue31home처럼 HOME 만 바꾸는 fixture 도 이제<HOME>/.local/share를 본다.- 2차에서 실패한 두 테스트(tier2 opencode e2e,
test_opencode_purge_leaves_no_rows)가XDG_DATA_HOME=<scratchpad>에서 통과한다(아래 실행 결과). - 뮤테이션:
DROPPED_VARS에서 다시 빼면 그 두 테스트와test_issue55::test_l1_every_path_variable_the_code_reads_is_accounted_for가 실패한다(3 failed). L1 은 환경과 무관하게 실패하므로, 이후 누가 지워도 잡힌다. - 세션 가드는
XDG_DATA_HOME이 설정돼 있으면<XDG_DATA_HOME>/opencode를 감시한다(:48-49).ambient는 conftest 가 drop 전에 기록한 pane 값(_AGENT_HOME_VARS = ("HOME",) + DROPPED_VARS)이라 올바른 위치다.
N1 (status.sh 고정 경로) — 해결.
- 두 Python 블록(
status.sh:105-113,:305-313) 모두get_adapter('opencode')._resolve_db(DiscoveryContext(workspace=cwd, agent_name='opencode', home_dir=home))를 쓴다. cwd(:59/:259)와home(HOME_DIR,:41/:241)은 각 블록에 정의돼 있다.env_python이PYTHONPATH=$SKILL_DIR를 넣고 환경을 상속하므로(lib.sh:1852-1871)lib_pyimport 와 PATH·XDG 가 그대로 전달된다. 같은 파일이 이미lib_py.delegation.logroot등을 import 한다.- 행동 확인: git archive 사본에 임시 테스트를 넣고 실행했다(mam_sandbox+mock_herdr+mock_agents → create → reconcile 로 id 고정 → status). 1 passed.
--json의resume_state == "yes"와 plain 출력 행의yes, 둘 다 rc 0.- PATH 에서 opencode 를 빼도 폴백 경로로
yes. - DB 를
XDG_DATA_HOME쪽으로 옮기면, XDG 없이MISSING, XDG 를 주면yes. - 행을 지우면
MISSING. 모두 rc 0.
- status 는 이제 opencode 행마다
opencode debug paths를 실행한다. 이 명령은 opencode 자신의 log 디렉터리에 기록한다. 하지만 status 가 이미 돌리는reconcile.sh --dry-run의 drift C 도 같은_resolve_db를 부르므로 새로운 종류의 부작용은 아니다.
N2 (--version 탐침이 실제 로그에 기록) — 해결.
_real_opencode()(test_issue60_opencode_v2.py:290-303)가TemporaryDirectory를 HOME·TMPDIR 로 하고 PATH 만 넘긴다. XDG_* 는 넘기지 않는다.- 실제
~/.local/share/opencode/log/opencode.log의args="[\"--version\"]"줄 수를 읽기로 세었다. 아래 두 스위트 실행 전 50, 후 50(증가 없음) 이다.
테스트 실행 (검증 경로, env -i, basetemp 는 scratchpad)
관련 10개 모듈: a4, issue31, issue10_13, issue60, tier2, issue55, issue57(status), issue21_worktree_prereqs(status), issue30_stall_watch, tier1.
XDG_DATA_HOME=<scratchpad>/jf1/xdg, PATH 에 opencode 없음: 363 passed, 1 skipped, rc 0. 실행 뒤 그 XDG 디렉터리는 비어 있었다(아무 파일·디렉터리도 생기지 않음).XDG_DATA_HOME미설정, PATH 에~/.opencode/bin포함(실바이너리 계약 테스트 실행): 363 passed, 1 skipped, rc 0.- skip 은 두 번 모두
/proc전용 테스트(macOS)다. #55 가드 오탐은 없었고, 실행 뒤 남은 opencode 프로세스도 없었다.
비차단 (테스트 보강 권고)
-
T1. 이번에 바뀐 두 동작은 회귀 테스트가 없다. 뮤테이션(
XDG_DATA_HOME설정 상태, issue55·issue60·issue31·tier2):- 가드의 XDG 감시를 원래대로 되돌림 → 28 passed, 실패 0
- status.sh 를 고정 경로로 되돌림 → 28 passed, 실패 0
test_issue55::test_g1에watch_dirs({"HOME": h, "XDG_DATA_HOME": x})["opencode"] == x/opencode한 줄을 넣고, 위 임시 테스트와 같은 status 행동 테스트(XDG 쪽 DB →yes)를 넣기를 권한다. -
T2 (기존 설계). 가드는 opencode 데이터 디렉터리의 항목 이름을 비교한다.
XDG_DATA_HOME이 설정된 Linux 러너에서 사용자 opencode(서비스 포함)가 그 디렉터리에 새 항목을 만들면 #55 와 같은 종류의 오탐이 날 수 있다. 판정 근거로 쓰지 말고 보고만 할 종류다. -
1·2차 비차단 N3(다른 MAM opencode 세션이 떠 있으면 무관한 purge 도 exit 4, lsof 없는 Linux 에서는 DB 보유자 검사 생략)는 의도된 동작으로 보고 그대로 둔다.
병합 가능성
- base..head 전체에서
git diff --check는 깨끗하다. - 변경 Python 파일은 Python 3.9(
/usr/bin/python33.9.6)로 컴파일된다. 셸 스크립트는/bin/bash -n(3.2)을 통과한다. - 1·2차의 실바이너리 검증과 뮤테이션 결과에 이번 검증이 더해져, 차단 사항이 없다.
[VERDICT: PASS]