# 테스트 실제 herdr 서버 누수 수정 2차 리뷰 — 커밋 db7f4ca (job 834fa032) - 리뷰어: planner-reviewer-claude-01 (Reviewer) - 리뷰 identity: loop-20261013T010208Z-f90dd4 / base 325b0560 .. head db7f4cab (커밋 1개, 2 파일) / tree f32cabd3 - 검증 경로: `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261013T010208Z-f90dd4/1` — HEAD·tree 일치, `git status --porcelain` 0 줄(시작·종료), `.mam` 생성 없음. 본 체크아웃 HEAD 8b0b4a0(main) 변동 없음. - 실행 안전: 1차와 같이 모든 테스트·탐침은 `env -i`(PATH/HOME/LANG/TMPDIR 만, 필요한 변수는 명시 추가)로 돌려 브리프의 `-u` 목록 전부가 비워진다. basetemp 는 scratchpad 아래(이름에 "shim" 없음). 실제 바이너리는 일회용 HOME 에서 `status server` 읽기만(서버 미기동). Python 은 본 체크아웃 `.venv`(3.9.6). 전체 스위트는 돌리지 않았다. 범위는 이 커밋만. ## 1. 변경 - `tests/conftest.py:299`: `mam_sandbox` 가 `HERDR_SESSION` 도 지운다(주석 `:296-297`). 현재 제거 목록: `HERDR_CONFIG_PATH`, `HERDR_PANE_ID`, `HERDR_SERVER_NAME`, `HERDR_SESSION_NAME`, `HERDR_SESSION`, `HERDR_SOCKET_PATH`, `HERDR_TAB_ID`, `HERDR_WORKSPACE_ID`, `XDG_CONFIG_HOME`. - `tests/test_herdr_real_server_leak.py:76`: L2 의 `PANE_VARS` 에 `HERDR_SESSION` 추가. 수정 전 conftest(325b056)에 새 테스트를 얹은 scratch 복사본에서 L2 는 `AssertionError: ['HERDR_SESSION']` 로 실패 → 테스트가 이 변경을 정확히 겨눈다. - Python 3.9 컴파일 통과. 제품 코드 변경 없음. ## 2. HERDR_SESSION 을 지워서 깨지는 테스트가 있는가 (검토 관점 1) - 소비자: `lib.sh:1425 _herdr_caller_server`, `lib_py/pane_lock.py:49 caller_server`, `lib_py/loop/watcher.py:64` — 셋 다 "있으면 호출자 서버, 없으면 `HERDR_SOCKET_PATH` 모양" 이고 `HERDR_SOCKET_PATH` 는 이미 지워지므로 샌드박스에서는 일관되게 "pane 밖" 으로 판정된다. - 테스트 쪽 bare `HERDR_SESSION` 참조는 전부 테스트가 **스스로** 넣는 값이다(픽스처 뒤라 영향 없음): `test_issue23_24_startup_path.py:264,369,395`(S1g·watcher 케이스는 `env={...}` 로 명시), `test_issue34_job_tree.py:580`, `test_issue30_stall_watch.py:486`, `test_issue45_restore.py:42`(`SCOPE_ENV` 로 이미 `HERDR_SESSION`·`HERDR_ENV` 까지 자체 제거). 반대로 "`HERDR_SESSION` 이 없어야" 하는 테스트(`test_s2b…:188`, S2 계열 "pane 밖 호출자") 는 이제 pane 안에서 돌려도 전제가 보장된다 — 이것이 이 변경의 목적이다. - 실측: 같은 6 파일(`test_herdr_real_server_leak`, `test_issue50_pane_lock`, `test_issue23_24_startup_path`, `test_herdr_shim_contract`, `test_issue45_herdr_config`, `test_issue9_server_env`)을 (a) 깨끗한 환경, (b) 바깥 환경에 `HERDR_SESSION=pane-real-srv` 를 넣은 환경에서 각각 돌렸다: **둘 다 139 passed, 34 skipped** (skip 은 모두 Python 3.9 의 tomllib skip). pane 안/밖 결과가 같다. ## 3. 다른 라우팅 변수가 남았는가 (검토 관점 2) - 내 pane 이 내보내는 `HERDR_*` 는 `HERDR_BIN_PATH`, `HERDR_CONFIG_PATH`, `HERDR_ENV`, `HERDR_PANE_ID`, `HERDR_SESSION`, `HERDR_SESSION_NAME`, `HERDR_SOCKET_PATH`, `HERDR_TAB_ID`, `HERDR_WORKSPACE_ID` 아홉 개. 샌드박스가 지우지 않는 것은 `HERDR_BIN_PATH`·`HERDR_ENV` 둘뿐이다. - 실제 바이너리(0.9.3) 에 각각을 단독으로 주고 `status server` 를 읽었다: `HERDR_ENV`, `HERDR_BIN_PATH`, `HERDR_CONFIG_PATH`, `HERDR_WORKSPACE_ID`, `HERDR_PANE_ID` 모두 소켓은 `$HOME/.config/herdr/herdr.sock`(가짜 HOME) — 서버 선택에 영향 없음. 1차에서 확인한 대로 소켓을 바꾸는 것은 `HERDR_SOCKET_PATH`(최우선)와 `HERDR_SESSION`(HOME 상대) 둘뿐이며 이제 둘 다 제거된다. - `.agents`·`tests` 에서 `HERDR_BIN_PATH`·`HERDR_ENV` 를 읽는 코드는 없다(`test_issue45_restore.py:42` 가 자체 정리 목록에 넣어 둔 것뿐). 남은 라우팅 변수 없음. ## 4. 잔류물 - scratch 복사본·basetemp·로그는 scratchpad 아래. 일회용 HOME `/tmp/j834-h` 제거(서버 미기동). 실제 `.mam`·`.mam.env`·모니터·실제 서버·`~/.config/herdr`·에이전트 홈은 건드리지 않았다. ## 결론 `HERDR_SESSION` 제거는 호출자 서버 판정을 pane 안/밖에서 동일하게 만들고, 그 값을 쓰는 테스트는 모두 자체 설정이라 깨지지 않는다(두 환경에서 동일하게 139 passed). 실제 바이너리의 서버 선택에 관여하는 변수는 이제 모두 샌드박스에서 제거된다. [VERDICT: PASS]