Files
multi-agent-mux/.agents/reports/planner-reviewer-claude-01/report-1fb2cefa.md
T

5.8 KiB

PR #62 리뷰 2회차 — Issue #60 Linux 확인 후속 (job 1fb2cefa)

  • 리뷰어: planner-reviewer-claude-01
  • 검증 경로: /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261019T015801Z-05463c/1
  • identity: HEAD 6a37c0019baa31ee28b32a086e57b4c8239413c4, tree 87013e7ef7f5239f1bf6ea38a2cbda214257be3c 가 일치한다. 작업 트리는 clean 이고 .mam 은 없다.
  • 범위: base 1d7b7da..head 9커밋. 판정은 base..head 전체에 대한 것이다. 1회차 이후 바뀐 것은 6a37c00 하나이고, opencode.py·status.sh·reconcile.sh·test_issue60_linux_fixes.py 4개 파일만 바뀌었다.
  • 1회차(@6a4e385)의 확인은 6a37c00 이 건드리지 않은 코드라 그대로 유효하다. 1회차에 확인한 것: 임시 DB 에서 _ro_connect 세 갈래, _DB_PATHS 키, auth-ok CLI, stop 문구.
  • 환경: macOS, Python 3.9.6, sqlite 3.51.0. 실제 opencode 데이터는 ls·grep -c·ps·lsof 로만 봤다.

결론

1회차의 공통 차단(B1)과 codex·agy 지적이 모두 해결됐고, 새 회귀는 찾지 못했다. base..head 전체를 병합 가능으로 판단한다.

1회차 지적별 확인

B1 (clean 상태 5개가 macOS 에서 실패) — 해결.

  • make("clean") 이 close 뒤 남은 -wal·-shm 을 지운다(tests/test_issue60_linux_fixes.py:158-162). 1회차 사본에서 내가 검증한 수정과 같다.
  • 검증 경로에서 이 모듈이 모두 통과한다(아래 실행 결과).
  • 뮤테이션 i1(immutable 분기를 mode=ro 로)이 이제 이 Mac 에서 5 failed 로 잡힌다. 1회차에는 fixture 가 먼저 실패해서 이 뮤테이션이 가려졌었다.

안내 문구 패턴이 사용자가 친 Ask anything… 를 지움(codex) — 해결.

  • 패턴이 Ask anything(?:…|\.\.\.) "[^"]*"? 가 되어 따옴표 예시가 필수다(opencode.py:80).
  • 두 fixture 에 넣어 직접 확인한 결과:
    • Ask anything…, Ask anything... 는 친 그대로 읽힌다.
    • 홈 화면 원본, 잘린 예시, Ask anything… " 는 빈 입력으로 읽힌다.
  • 회귀 테스트 2개가 추가됐다(:84-85). 뮤테이션 p1(예시를 다시 선택 사항으로)은 4 failed 로 잡힌다.

auth_ok 가 실행 불가한 ~/.opencode/bin/opencode 도 인정(codex) — 해결.

  • 이제 isfile and access(X_OK) 로 본다(opencode.py:322-323).
  • 권한 644 파일과 디렉터리는 모두 False 로 고정됐다(test_a_home_install_that_cannot_run_is_not_enough). 뮤테이션 a1(exists 로 되돌림)은 1 failed 로 잡힌다.
  • shutil.which 가 이미 실행 가능 여부를 보므로 PATH 쪽은 그대로다.

status.sh·reconcile.sh 의 sqlite3.connect(odb)(agy) — 해결.

  • status 의 opencode 두 블록(status.sh:115-117, :316-318)과 reconcile drift C(reconcile.sh:953-955)가 _ro_connect 를 쓴다.
  • 두 스크립트는 lib_py 를 이미 import 하는 경로에서 돌기 때문에 import 가 된다(status 는 env_python/PYTHONPATH, reconcile 은 env_python).
  • status 블록에서 import sqlite3 를 지웠지만 영향이 없다. 같은 함수의 다른 블록(hermes :90, codex :132)은 각자 import sqlite3 를 한다.
  • 행동 확인: git archive 사본에 임시 e2e 를 넣었다. 순서는 이렇다.
    1. mam_sandbox+mock 에서 create → 자식 세션 추가 → journal_mode=wal → 사이드카 삭제(Linux 의 닫힌 상태)
    2. reconcile.sh --once --emit-diff → status.sh --json 과 plain status
  • 결과(head): rc 는 모두 0. 부모 id 로 고정됐고 resume_state == "yes" 이다. DB 디렉터리는 실행 전후 모두 ['opencode.db'] 였다.
  • 대조(두 스크립트를 sqlite3.connect(odb) 로 되돌린 사본): reconcile 뒤 opencode.db-shm·opencode.db-wal 이 생겨 같은 테스트가 실패했다.
  • 참고: mock opencode 가 만드는 DB 는 WAL 모드가 아니다. 그래서 WAL 로 바꾸지 않으면 이 차이가 드러나지 않는다.

테스트 실행 (검증 경로)

  • 조건: env -i, 임시 HOME, XDG_DATA_HOME=<scratchpad>, basetemp 는 scratchpad, -p no:cacheprovider, PYTHONDONTWRITEBYTECODE=1.
  • 대상 12개 모듈: issue60_linux_fixes, issue60_opencode_v2, a4, tier1, tier2, issue31, issue55, issue57, issue21_worktree_prereqs, issue50_dispatch, issue30_stall_watch, c1_tui_readiness.
  • 결과: 463 passed, 2 skipped, 실패 0, 16분.
    • skip 1: /proc 전용 테스트.
    • skip 2: PATH 에 opencode 가 없어 건너뛴 실바이너리 계약 테스트(1회차·이전 이슈에서 따로 확인함).
  • 부작용 확인:
    • scratchpad XDG 디렉터리는 실행 뒤에도 비어 있었다.
    • 실제 ~/.local/share/opencode 의 목록은 전후가 같았다.
    • 실제 log 의 debug 줄 수는 2 → 2 였다.
    • 남은 opencode 프로세스는 사용자 서비스 하나뿐이다(pid 23630, 시작 08:13, 이 잡 이전).
    • #55 가드 오탐은 없었다.
  • 린트:
    • git diff --check 1d7b7da..HEAD 는 깨끗하다.
    • 바뀐 Python 은 3.9 로 파싱된다.
    • status.sh·reconcile.sh 는 /bin/bash -n(3.2)을 통과한다.

비차단

  • N1. 새 test_status_and_reconcile_open_the_database_read_only 는 소스 문자열만 센다. sqlite3.connect(odb, timeout=…) 같은 변형은 지나간다. 위의 임시 e2e(WAL DB, 사이드카 없음 → reconcile·status → 목록 불변)를 tier2 opencode e2e 에 붙이면 행동으로 고정할 수 있다.
  • N2. 1회차 비차단은 의도된 완화로 그대로 남아 있다(브리프에도 기록됨):
    • immutable 경쟁 창(ms 수준)
    • _DB_PATHS 의 프로세스 수명 캐시
    • create 사전 검사의 완화
  • N3. 아주 좁은 화면에서 예시의 여는 따옴표까지 잘리면 Ask anything… 만 남는다. 이때는 친 초안으로 읽힌다(안전한 쪽). 실제 캡처로는 확인하지 않았다.

[VERDICT: PASS]