Files
multi-agent-mux/.agents/reports/planner-reviewer-codex-01/report-c20f3d1f.md
T
GodopuandClaude Opus 5.5 e0181ea9be release(v4.8.8): Issue #17 follow-up - archive the review reports and bump the lockstep version
Merge-workspace review loop (--all-reviewer): round 1 (@d198dd5) claude
agy PASS, grok codex NOT PASS (the same inherited WORKSPACE_ROOT in eleven
more modules; test_orc_onboard's import-time env); fixed in 8b47cc7.
Round 2 claude grok NOT PASS (test_o2_race_free_lock, test_o1_rebuttal
missed), agy codex PASS; fixed in ac48cb7. Round 3 (@ac48cb7) 4/4 PASS.
Full suite at ac48cb7 on macOS / Python 3.9 / herdr 0.9.3 with
WORKSPACE_ROOT set to an empty sentinel: 1751 passed / 0 failed / 38
skipped; the sentinel stayed empty and the main checkout's shim was not
touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-09 05:01:05 +09:00

11 KiB

Review — c20f3d1f

Verdict

PASS. 이번 누적 변경에서 차단할 결함을 찾지 못했다. 이전 리뷰 9bc1f200의 R1(상속 환경으로 lib.sh를 source하는 다른 테스트 누락), R2(onboard의 import 시점 WORKSPACE_ROOT 캐시)는 수정되었다. 이 판정은 아래 정적 검토와 제한 환경 실행에 근거하며 전체 통합 스위트 통과를 뜻하지 않는다. 브리프가 허용한 대로 소켓/프로세스 조회 제한 자체를 NOT PASS 사유로 삼지 않았다.

Review identity / scope

  • loop: loop-20261008T133858Z-9e7f5b
  • base: 6b00b6e06f55299cb60f156ccef09ede4bae5bdd
  • head: 8b47cc76eed4582b1848b2eec529523a61497320
  • tree: bfe5fcbbefbde9562334515b4a9803bee96f84fd
  • 검증 cwd: /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261008T133858Z-9e7f5b/2
  • 실행 Python: /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux-wt/issue17-wsroot/.venv/bin/python (Python 3.9).
  • creator 작업 트리에서 실행하거나 소스를 수정하지 않았다. 검증 전후 identity가 일치하고 최종 git status --porcelain은 비어 있다. git diff --check 6b00b6e HEAD 통과. 변경 15개 Python 파일 AST 파싱 통과. 제품 코드 .agents/skills의 base..head diff는 없다.

요구사항 및 이전 지적 확인

  1. tests/test_issue17_item4_decisions.py:224의 _env가 WORKSPACE_ROOT를 제외하고 테스트 tmp_path로 지정한다. 단순 unset이면 lib.sh가 checkout을 기본값으로 삼으므로 명시적 임시 경로가 맞다. 마지막 extra 적용은 테스트가 의도한 override를 유지한다.
  2. tests/conftest.py:180의 opt-in own_workspace_root와 10개 모듈의 usefixtures 표시는 기존 mam_sandbox를 쓰지 않던 셸 테스트를 격리한다. 전역 autouse가 아니므로 WORKSPACE_ROOT 기본값을 검사하는 다른 Python 테스트를 일괄 변경하지 않는다.
  3. 실제 conftest fixture를 등록한 별도 탐침에서 module fixture가 tmp_path/.mam-test-state/workspace를 설정하고, 명시적인 mam_sandbox가 그 뒤 자신의 root로 덮어쓰는 것을 각각 확인했다. 테스트 본문 monkeypatch도 이후 적용된다.
  4. tests/test_orc_onboard.py:19에서 캐시의 WORKSPACE_ROOT를 제거하고 :27의 _scrubbed_env가 호출 시점의 root를 적용한다. run_onboard/run_find_uuid/run_verify_uuid/dump_state 및 inline 호출이 이 경로로 전환되었다. import 시점 sentinel을 이후 fixture root로 바꾸는 W2 탐침이 통과했다.
  5. tests/test_workspace_scope.py:31은 unittest 경로를 자신의 ws_dir로 고정한다. tests/test_issue21_worktree_prereqs.py:544의 _mutate도 자신의 tmp root를 사용한다. 후자는 실제 mam_sandbox와 별도 sentinel을 사용한 탐침으로 검증했다.
  6. 새 tests/test_issue17_workspace_root_isolation.py:54 W1은 checkout 복사본과 real conftest를 사용하는 nested pytest로 이전 fallback-to-checkout 문제를 검사한다. nested pytest의 성공/통과 수를 요구하므로 환경 실패를 격리 성공으로 오인하지 않는다. W1 자체는 로컬 브로커가 필요하여 이 샌드박스에서 완주하지 않았으며 아래 표의 실행 결과에 포함하지 않았다.
  7. 추가된 코드는 Python 3.9 AST 파싱 및 실제 실행을 통과했다. Bash 제품 로직이나 Bash 버전 의존 문법은 변경하지 않았다.

실행 결과와 한계

실험 전 HERDR_, MAM_, MQTT_, SKS_, WORKSPACE_ROOT 및 control-plane 경로 환경을 제거하고 HOME을 테스트별 임시 디렉터리로 설정했다. 모든 pytest 실행은 bytecode/cache 쓰기를 끄고 별도 임시 basetemp를 썼다. 실제 .mam.env 값을 읽어 export하거나 출력하지 않았다.

정상 conftest의 session-autouse local MQTT broker는 sandbox의 socket bind 제한 때문에 사용할 수 없다. /tmp/c20f3d1f-run.py는 검증 트리의 실제 conftest를 import하고 local_mqtt_broker fixture만 메모리에서 제외한 뒤 pytest.main(..., --noconftest, plugins=[module])를 실행한다. 나머지 fixture, 환경 처리 hook, 상태 guard는 유지했다. 이는 수정하지 않은 전체 스위트 실행과 다르다.

실행 결과 sentinel
WORKSPACE_ROOT unset, 주 검증 묶음 135 passed, 21 failed, 107.10s 0 entries
WORKSPACE_ROOT=기존 sentinel, 동일 묶음 135 passed, 21 failed, 107.53s 0 entries
추가 검증 묶음, unset 84 passed, 69.36s 0 entries
fixture 순서 및 _mutate 직접 탐침 3 passed, 0.24s 0 entries

주 검증 묶음은 다음 파일 전체와 두 회귀 node다:

  • test_b19_headless_reconcile_fixes, test_b8_send_keys_verification, test_loop_cli, test_version_consistency, test_workspace_scope, test_orc_onboard, test_o3_scoped_guard, test_issue5_phase3_loop, test_issue5_phase4_runtime, test_issue25_plan_reuse, test_issue33_budget.
  • test_issue17_workspace_root_isolation::test_w2_onboard_does_not_carry_its_import_time_root.
  • test_issue17_item4_decisions::test_c_helpers_write_nothing_to_an_inherited_workspace.

두 환경의 실패 21건은 동일하다:

  • O3 guard 12건: ps 실행 시 PermissionError / Operation not permitted.
  • onboard O18/O28/O29 3건: 프로세스 command/parent를 ps로 읽는 autodetection 불가로 exit 3. orc_onboard.sh:108,185의 조회와 해당 환경 의존 테스트 경로를 확인했다. explicit UUID 및 나머지 onboard 검증은 통과했다.
  • issue33 budget 6건: local_broker_env()가 실제 로컬 브로커를 요구하여 실패. 제외한 broker fixture에 따른 실행 제약이다. 나머지 budget 13건은 통과했다.

추가 묶음 84건에는 test_tier1_unit 전체, phase1 delegation C01/C02/C04/C05 및 event/exit mapping 두 contract node, fail_closed의 T1-25와 T3-1/T3-2, worktree_prereqs T2-8이 포함된다. 해당 phase1 node의 파라미터 케이스를 모두 포함한다.

따라서 수정 파일 전체와 phase1 delegation 전체의 두 환경 통합 실행을 모두 통과했다고 주장하지 않는다. 특히 W1 nested pytest와 실제 broker/process-inspection 경로의 전체 확인은 브리프에 따라 오케스트레이터의 제한 없는 실행으로 남긴다.

임시 로그 및 재현 드라이버:

  • /tmp/c20f3d1f-run.py
  • /tmp/c20f3d1f-unset.log
  • /tmp/c20f3d1f-sentinel.log
  • /tmp/c20f3d1f-extra.log
  • /tmp/c20f3d1f-probe-tests/test_order.py

실행 후 확인한 sentinel:

  • /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/c20f3d1f-unset-ffhmus4t/sentinel
  • /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/c20f3d1f-sentinel-bi_df5cb/sentinel

모두 비어 있으며 검증 checkout의 .mam 아래에도 파일/하위 디렉터리가 없다. 별도 탐침의 첫 시도는 /tmp 상위 수집 중 접근 제한 디렉터리 때문에 collection 오류였고, 전용 probe 디렉터리와 rootdir를 지정한 재실행에서 3건 통과했다. 소스 변경은 하지 않았다.

회귀 negative control

/tmp/c20f3d1f-negative.py로 현재 검증 트리에서 base 코드를 git show로 읽어 메모리에만 로드했다. 실제 저장소/작업 트리를 되돌리지 않았다.

탐침 수정 전 base 현재 head
W2와 같은 import-time onboard root 시나리오 sentinel 3 entries (.mam/shim/herdr), own shim 없음 sentinel 0 entries, own shim 존재
현재 decisions 회귀 테스트에 base _env만 교체 AssertionError: written into the sentinel 동일 테스트 통과

절차: 기존 빈 sentinel을 WORKSPACE_ROOT로 설정 → onboard 모듈 import → 환경을 fixture-ws로 변경 → run_find_uuid(fixture-ws, 'claude'). 두 번째 탐침은 현재 회귀 함수에 base _env 함수 AST를 넣고 실행한 다음 head 함수로 복원해 재실행했다. 기대 결과는 sentinel 불변 및 자기 root에만 shim 생성이다. 현재 코드는 두 시나리오 모두 기대와 일치한다.

산출물: /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/c20f3d1f-negative-opdzrib1.

같은 결함 후보 재조사 / 수정하지 않은 후보

rg로 환경 복사, lib.sh source, wrapper/run_loop 실행 지점을 다시 조사하고 fixture 또는 명시적 root 경로를 대조했다. 아래는 변경하지 않은 주요 후보의 제외 근거다. 단순히 환경을 복사한다는 이유만으로 안전하다고 판단하지 않았다.

후보 파일:라인 제외 근거
tests/test_issue14_delivery_ack.py:33 _env(cwd)가 WORKSPACE_ROOT=cwd를 지정한다.
tests/test_issue18_liveness_contract.py:54 _env(cwd)가 WORKSPACE_ROOT=cwd를 지정한다.
tests/test_issue33_budget.py:43 독립 _env가 테스트 root를 지정한다.
tests/test_issue34_job_tree.py:50,587 _env(home)은 root를 고정하고 _run_lib 호출은 mam_sandbox를 사용한다.
tests/test_issue36_prompt_transport.py:47,532 _env(home) 및 shell-loop 실행이 명시적인 임시 control root를 쓴다.
tests/test_issue26_ints.py:124 HOME과 WORKSPACE_ROOT를 같은 테스트 home으로 설정한다.
tests/test_c1_tui_readiness.py:12 helper 내부 mkdtemp를 WORKSPACE_ROOT로 설정한 뒤 source한다.
tests/test_layout.py:310 generated-shim 테스트가 임시 ws_dir를 source 전에 export한다.
tests/test_issue6_turn_handshake.py:24,43 cwd를 준 helper는 root/home을 그 경로로 바꾸며 mock_herdr 경로는 mam_sandbox에 의존한다.
tests/test_issue5_phase1_delegation.py:49 lib helper 호출은 mam_sandbox에서 실행되고 root는 fixture의 임시 경로다. Python-only 계약 검사는 shim bootstrap이 없다.
tests/test_tier1_unit.py:14,464 셸 helper 호출은 mam_sandbox 사용. :464의 별도 환경은 Python workspace_uuid만 실행하며 lib.sh를 source하지 않는다.
tests/test_uuid_target.py:11 mutation helper와 셸 호출이 mam_sandbox를 사용한다.
tests/test_o2_race_free_lock.py:16 상태 helper 호출은 mam_sandbox fixture를 사용한다.
tests/test_issue20_state_isolation.py:150,199 격리 회귀 목적으로 자체 임시 repo/root를 명시한다.
tests/test_b7_diff_untracked.py:11 diff_collect는 lib.sh shim bootstrap 경로가 아니다.
tests/test_issue8_update_state.py:24 설치/업데이트 대상은 별도 임시 workspace이며 lib.sh source 결함과 다르다.
tests/test_issue5_phase2a_loop.py:754 해당 source 문자열은 static guard 검사용 텍스트이며 실제 셸 실행이 아니다.

이번에 수정된 누락 후보(b19/b8/loop CLI/phase3/phase4/O3/version/issue25/fail_closed)는 own_workspace_root에 opt-in했다. unittest workspace_scope와 worktree_prereqs mutation은 직접 고정하고, import-time 캐시를 쓰던 onboard는 runtime root 적용으로 별도 해결했다. 추가 동일 결함은 확인하지 못했다.

Lifecycle

요청한 started 명령을 먼저 실행했으나 MQTT 연결이 sandbox의 Operation not permitted로 실패하여 exit 2였다. 리뷰 결과 파일을 쓴 뒤 요청된 completed 명령도 실행했다. 3회 연결 시도 후 같은 Operation not permitted로 exit 2를 반환했다. 따라서 MQTT 전달 성공은 확인하지 못했다. 보고서의 PASS와 MQTT 전달 성공 여부는 별개다.

[VERDICT: PASS]