Files
multi-agent-mux/.agents/reports/planner-reviewer-claude-01/report-495a1373.md
T
GodopuandClaude Opus 5.5 121eab71d4 release(v4.9.3): u1e no longer writes the checkout's .mam/shim/herdr - archive the review reports and bump the lockstep version
Review loop (--review-only, --all-reviewer): round 1 (@3a30d7d) 4/4 PASS;
each reviewer reproduced W1 failing on the pre-fix tree. Seven #50/#55 and
leak modules (112 tests) from a clean worktree left no .mam in the
checkout.

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

5.6 KiB

테스트 격리 수정(u1e 의 WORKSPACE_ROOT) 리뷰 — 커밋 3a30d7d (job 495a1373)

  • 리뷰어: planner-reviewer-claude-01 (Reviewer)
  • 리뷰 identity: loop-20261013T025803Z-c69408 / base 42e2a7ea .. head 3a30d7da (커밋 1개, 테스트 2 파일) / tree bd43e464
  • 검증 경로: /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261013T025803Z-c69408/1 — HEAD·tree 일치, git status --porcelain 0 줄, .mam 없음(시작·종료 모두). 본 체크아웃 HEAD 42e2a7e(main) 변동 없음.
  • 실행 안전: 모든 실행은 env -i(PATH/HOME/LANG/TMPDIR 만)로 브리프의 -u 목록을 포함한 라우팅 변수를 비웠고, basetemp 는 scratchpad 아래(이름에 "shim" 없음). 수정 전 재현은 검증 경로를 git clone --no-hardlinks 한 임시 복사본에서만 했고 거기 생긴 .mam 은 지웠다. 검증 경로에서 돌린 것은 W1/W2 뿐이며(W1 은 체크아웃을 tmp 로 복사해 그 안에서 노드를 돌린다), 끝난 뒤 검증 경로에 .mam 이 없음을 확인했다. 실제 .mam·.mam.env·모니터·실제 서버·에이전트 홈 미접촉.

1. 원인과 수정

  • 원인(1차 README 리뷰에서 재현한 그대로): test_u1e 는 래퍼를 subprocess.run(["bash", WRAPPER, "submit", …, "--dry-run"], env=dict(os.environ, HOME=…, MAM_ENV_FILE=…), cwd=tmp_path) 로 부르는데, 래퍼가 source 하는 lib.sh 는 WORKSPACE_ROOT 가 없으면 체크아웃을 기본값으로 삼고(lib.sh:26) _init_herdr_isolation 이 $WORKSPACE_ROOT/.mam/shim/herdr 를 쓴다(lib.sh:150-154). conftest 의 pytest_configure 는 다른 체크아웃을 가리키는 WORKSPACE_ROOT 만 떨어뜨리므로 pane 밖에서는 변수가 없고, 체크아웃이 기본값이 된다.
  • 수정(tests/test_issue50_dispatch.py:167-170): env 에 WORKSPACE_ROOT=str(tmp_path) 추가 → shim 은 tmp_path/.mam/shim/herdr 에 쓰인다. tests/test_issue17_workspace_root_isolation.py:43: 이 노드를 W1 NODES 에 추가. 두 파일 py_compile 통과. 같은 파일의 다른 테스트는 decide.* 를 in-process 로 부르므로(_register/_edit/_event 헬퍼) shim 을 쓰지 않는다 — 아래 §2 의 파일 전체 실행이 이를 확인.

2. 실행 결과

실험 결과
수정 전 복사본(검증 경로 clone + test_issue50_dispatch.py 를 base 42e2a7e 로 되돌림): u1e 단독 1 passed, 복사본에 .mam/shim/herdr 생성 — 원인 재현
수정 전 복사본: W1(새 NODES 포함) FAIL: AssertionError: tests wrote into the checkout they ran in: ['.mam/shim', '.mam/shim/herdr'] — W1 이 이 노드로 회귀를 잡는다(복사본 안의 tmp 복사본에만 쓰였고 복사본 자체에는 .mam 없음)
head, 검증 경로: test_issue17_workspace_root_isolation.py (W1+W2) 2 passed, 검증 경로 .mam 없음
head 복사본(git archive): test_issue50_dispatch.py 전체 49 passed, 복사본 .mam 없음

W1 이 잡는 원리: W1 은 복사본에 WORKSPACE_ROOT=<복사본> 을 주고 노드를 돌린다. 수정 전 u1e 는 os.environ 을 그대로 물려주므로 래퍼가 그 복사본에 shim 을 쓰고, 수정 후는 tmp_path 로 덮어써 복사본에 아무것도 남지 않는다. pane 밖(변수 없음)에서도 lib.sh 의 체크아웃 기본값 때문에 같은 결과이므로 두 환경 모두를 대표한다.

3. 같은 결함이 남은 테스트가 있는가

  • 정적: 래퍼·lib.sh·run_loop.sh·create_session.sh·reconcile.sh·stop/resume_session.sh 를 subprocess 로 부르는 테스트 파일 59 개를 추려 mam_sandbox/own_workspace_root/WORKSPACE_ROOT 참조 여부를 봤다. 참조가 하나도 없는 7 파일과, 참조가 적어 테스트별 누락이 있을 수 있는 18 파일(W1 NODES 에 없는 것 위주)을 골랐다.
  • 경험적: 그 25 파일을 head 의 git archive 복사본에서 파일마다 따로 돌리고 매번 복사본의 .mam 을 봤다 — test_b7_diff_untracked, test_deploy_freshness, test_deploy_layout, test_issue42_skill_blocks, test_issue45_herdr_config, test_issue5_phase0_contracts, test_local_mqtt, test_issue14_delivery_ack, test_issue18_liveness_contract, test_issue6_turn_handshake, test_issue26_envfile, test_issue26_ints, test_issue33_budget, test_layout, test_workspace_scope, test_a4_adapter_contract, test_issue45_restore, test_sanitize_and_mock_errors, test_sanity, test_issue12_registry_secrets, test_issue21_acceptance, test_issue15_registry_isolation, test_issue20_state_isolation, test_issue36_prompt_transport, test_issue34_job_tree: 전부 통과(skip 은 tomllib/nats-docker 류), .mam 생성 0 건.
  • 이전 리뷰들에서 같은 방식으로 돌린 파일들(leak·startup_path·shim_contract·issue17/9/45, scenario4, pane_lock, issue50_dispatch_herdr 등)도 검증 경로에 .mam 을 남기지 않았고, .mam/shim 이 생긴 경우는 모두 test_issue50_dispatch.py 가 포함된 실행뿐이었다(u1e). 즉 이 결함은 u1e 하나였고, 수정으로 닫혔다.

4. 잔류물

  • clone 복사본·archive 복사본·basetemp·로그는 scratchpad 아래. 검증 경로는 깨끗(.mam 없음, git status 0 줄). #55 가드 오탐은 이번 실행에서 나오지 않았다.

결론

원인 진단이 맞고, WORKSPACE_ROOT=tmp_path 가 정확한 최소 수정이며, W1 은 수정 전 트리에서 이 노드로 실패하고 수정 후 통과한다. 다른 테스트에서 같은 누출은 25 파일의 파일별 실행으로 재현되지 않았다.

[VERDICT: PASS]