# PR #79 / Issue #68 리뷰 — PASS - Job: ee26d64c / Reviewer: planner-reviewer-codex-01 - 기준: `tea issues 68 --comments`의 “구현 전에 정한 것”(결정 1–4), `tea pulls 79`, `INSTRUCTION.md:5`. - Loop: `loop-20261029T045625Z-74296d` - Base: `b9c828f09214b4bed6651a223cbb941e7b432647` - Head: `3b81f9973223d2a910369711c08adc772003639d` - Tree: `ff705b61bf25fe40d0ff054c372a399eacc79730` - 검증 루트: `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261029T045625Z-74296d/1` - 아래 파일:줄은 이 검증 루트 기준이다. 시작·종료 HEAD/tree 일치, `git status --short` 빈 출력, `git diff --check b9c828f..HEAD` 통과. creator 작업 트리에서 실행하거나 수정하지 않았다. ## 결정·완료 조건 대조 | 요구사항 | 코드·문서 근거 | 검증 | 빠진 조건 | |---|---|---|---| | 결정 1: create의 기본 온보딩 및 --no-onboard 유지 | `create_session.sh:67`, `:87`, `:88`, `:440` | 새 파일의 기본 dry-run 대조군·6종 실제 skip 행 검증, 기존 Issue #50 완료/44/45 테스트 | 없음 | | 결정 2: worktree creator 기본 온보딩, skip 전달, 기존 --onboard 수용 | `worktree_prepare.sh:30`, `:42`, `:43`, `:230`, `:232` | 새 테스트 `:195`, `:215`, `:233`: 옵션 전달 4조합 및 실제 mock 온보딩 완료/잡 미생성; 외부 탐침에서 반대 순서 옵션도 확인 | 없음 | | 결정 3: agy/codex/hermes/opencode에만 경고 1줄 | `lib_py/agents/__main__.py:75`, `create_session.sh:207`–`:211` | 새 테스트 `:50`, `:67`, `:95`: 6종 facts, dry-run/실제 create 및 기본 옵션 대조군 | 없음 | | 경고가 종료 코드·행을 바꾸지 않음 | 변경은 facts 출력과 stderr 조건문뿐; 행 기록 분기는 그대로 | 새 테스트 `:95`에서 rc=0, 이름·역할·status·cmd·cwd·ID 출처·검증 상태·control_plane·delegate_job_id 검증. base 대조에서도 이 검증 후 경고 단언에서만 실패 | 없음 | | 경고 이후의 거부도 기존 동작 유지 | `create_session.sh:209` 및 기존 #63 순서 게이트 | 새 테스트 `:157`: 미발견 agy 선행 세션, wait=0, rc=1 및 경고가 거부 설명보다 먼저 출력 | 없음 | | 결정 4: 문서 변경 최소화 | create `SKILL.md:173`, `:205`, `:210`, `:213` | 옵션 표 1줄·worktree 절 3줄만 변경. 각 설명을 위 코드와 대조 | 없음 | | 기존 implicit skip 호출 수정 및 Mac 통과 | `test_issue21_acceptance.py:47`, `:207`; `test_issue21_phase2_loop_a.py:422` | 변경 파일 5개와 관련 파일 3개 직접 실행. 아래 경로 이름 충돌 1건은 경로 보정 재실행으로 해소 | 없음 | `create_session.sh`와 `worktree_prepare.sh`의 경로는 `.agents/skills/multi-agent-mux-create/scripts/` 아래다. 새 테스트 줄은 `tests/test_issue68_onboard_default.py` 기준이다. ## 추가 코드·호출부 확인 - 어댑터: `lib_py/agents/base.py:379`–`:382`의 기본값은 POST_DISCOVERED. claude의 `adapters/claude.py:188`–`:190`, grok의 `adapters/grok.py:18`–`:20`만 PRE_ASSIGNED로 재정의한다. 나머지 4종은 기본값을 사용한다. facts는 이 값을 0/1로 출력하므로 셸에 별도 에이전트 목록을 복제하지 않는다. - facts 소비자는 `lib.sh:2596`(readiness eval), `:2957`(send_keys_safe eval), `:3156`(dialog facts의 이름별 sed 선택), `create_session.sh:207`이다. 새 항목은 숫자 할당문이므로 기존 eval 계약을 유지하고, 이름별 파싱에도 섞이지 않는다. 기존 facts 계약·CLI 인용 테스트 통과. - `MAM_DELEGATION_PY=0`도 agents facts 호출을 건너뛰지 않는다. 외부 탐침에서 6종 경고 판정 및 worktree 기본 온보딩을 확인했다. facts 출력이 비거나 조회가 실패하면, 값이 미설정인 경우 `${MAM_ID_POST_DISCOVERED:-0}`에 의해 경고만 생략된다. rc=0/1의 빈 facts 탐침 모두 dry-run rc=0, nounset 오류 없음. Python 조회 불가 상황에 새 hard failure를 추가하지 않는 기존 best-effort 동작이다. - `git grep -n worktree_prepare.sh` 및 `git grep -n -- --creator-agent`로 추적 파일을 전수 확인했다. 실행 호출은 아래 표와 같다. 숨은 자동 호출 스크립트는 없다. | 호출 위치 | 바뀐 기본값의 영향 | |---|---| | `test_issue21_acceptance.py:47,207`, `test_issue21_phase2_loop_a.py:422` | 온보딩과 무관한 기존 검증이므로 명시적 --no-onboard 추가가 맞음 | | `test_issue21_phase2_loop_a.py:339` | 이미 --onboard이며 실제 mock 완료를 검증 | | `test_issue21_phase2_loop_a.py:355` | submodule 초기화 거부가 creator 단계보다 앞서 발생; 온보딩 대기 없음 | | `test_issue50_onboard.py:192` | 기존 --onboard + stub의 44/45 전달 검증 유지 | | `test_issue50_dispatch_herdr.py:868` | 이미 --onboard를 명시한 실제 herdr 통합 테스트. 이번 제약에 따라 실행하지 않음 | | `test_issue57_logs_follow_registry.py:276` | 기존 --onboard 및 mock 완료. 이번 Mac 실행 통과 | | 새 테스트 `:202,219,237` | 전달·기본 온보딩·skip를 의도적으로 각각 검증 | | create `SKILL.md:205`, `docs/design/worktree-creator-model.md:48`–`:52` | 사용자 실행 예시는 이제 기본 온보딩을 수행. SKILL의 `:213`이 44/45 및 세션·worktree 보존을 명시 | | README/README.ko의 `:51`, VERSIONS의 역사 기록, `lib_py/worktree.py:3` | 설명/주석이며 추가 실행 호출 없음 | - `tests/data/skill_code_blocks.json`: 변경된 evidence/passthrough 9곳을 base와 HEAD의 실제 줄 내용으로 비교해 모두 동일함을 확인했다. 변경된 비핀 필드는 worktree 사용 예시의 sha 1개(`38836d31bf38 → 8bfabafb0328`)뿐이며 --onboard → --no-onboard에 해당한다. inventory 테스트 통과. - 새 테스트는 단순 문자열 존재 검사에 그치지 않고 옵션 전달, 실제 mock 잡의 completed 상태, skip 시 잡 미생성, 행의 안정 필드, 후속 거부를 확인한다. 아래 base 대조 결과도 예상과 일치했다. ## Mac 실행 및 결과 환경: Darwin arm64, `bash`는 `/bin/bash` 3.2.57, `/usr/bin/python3` 및 사용한 제어 루트 venv Python은 3.9.6. 검증 트리에는 venv가 없어 브리프 상단에 지정된 제어 루트 인터프리터를 사용했다. 모든 pytest 실행 cwd는 검증 루트이며 공통 접두부는 다음과 같다. ```bash env -u HERDR_SOCKET_PATH -u HERDR_PANE_ID -u HERDR_TAB_ID \ -u HERDR_WORKSPACE_ID -u HERDR_SESSION_NAME -u HERDR_SESSION \ -u WORKSPACE_ROOT -u MAM_ENV_FILE -u MAM_JOBS_DIR \ -u DELEGATE_JOB_LOGS_DIR -u AGENT_SESSIONS_YAML \ PYTHONDONTWRITEBYTECODE=1 \ /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux/.venv/bin/python \ -m pytest -p no:cacheprovider --basetemp=<아래의 TMPDIR 경로> -q <선택 항목> ``` TMPDIR 접두부는 `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/`이다. | 실행 | 선택 항목·추가 옵션 | 결과·증거 | |---|---|---| | 주 실행, basetemp `mam-review-ee26d64c-main` | `tests/test_issue68_onboard_default.py tests/test_issue21_acceptance.py tests/test_issue21_phase2_loop_a.py tests/test_issue26_ints.py tests/test_issue42_skill_blocks.py tests/test_issue50_onboard.py tests/test_uuid_target.py tests/test_issue21_worktree_prereqs.py` | 265 passed, 1 failed, 1 skipped / 819.55s. [main.log](evidence/main.log) | | 위 실패 사례 재실행, basetemp `mam-eval-ee26d64c-a4` | `tests/test_issue21_acceptance.py::test_a4_main_checkout_is_unchanged_by_the_whole_cycle` | 1 passed / 2.04s. [a4.log](evidence/a4.log) | | 계약/create 회귀, basetemp `mam-review-ee26d64c-contract` | `tests/test_a4_adapter_contract.py::test_agent_adapter_registry ::test_facts_bridge_eval_contract ::test_cli_bridge_subcommands_and_quote_safety`(각각 전체 node 경로 사용), `tests/test_tier2_component.py`, `tests/test_issue57_logs_follow_registry.py::test_worktree_prepare_keeps_the_logs_next_to_the_control_root_registry`; `-k 'create or facts_bridge or agent_adapter_registry or cli_bridge'` | 16 passed, 30 deselected / 184.63s. 마지막 logs 노드는 이 필터에서 제외되어 아래 별도 실행. [contract.log](evidence/contract.log) | | logs 별도 실행, basetemp `mam-eval-ee26d64c-logs` | `tests/test_issue57_logs_follow_registry.py::test_worktree_prepare_keeps_the_logs_next_to_the_control_root_registry` | 1 passed / 18.13s. [logs.log](evidence/logs.log) | | 외부 탐침, basetemp `mam-review-ee26d64c-probes` | `tests/test_issue68_onboard_default.py -s -p probe_issue68`; 추가 env `PYTHONPATH=/tmp/mam-review-ee26d64c-harness` | 12 passed / 41.84s. legacy 6종 경고+기본 온보딩 1건, 빈 facts 2건, 마지막 skip 옵션 1건, 기본 44/45 전달 2건. [probes.log](evidence/probes.log), [probe_issue68.py](evidence/probe_issue68.py) | | base 대조, basetemp `mam-eval-ee26d64c-base` | 같은 새 테스트 파일에 `-p base_issue68`; 같은 추가 PYTHONPATH | 의도한 20 failed, 5 passed / 77.25s. [base.log](evidence/base.log), [base_issue68.py](evidence/base_issue68.py) | 주 실행 실패는 `tests/test_issue21_acceptance.py:142`의 “worktree list 어디에도 mam-review 문자열이 없어야 한다”는 기존 단언 때문이다. 이 검토의 basetemp 이름 자체에 그 문자열이 들어갔다. 바로 앞의 HEAD·branch·status·branch tip·worktree list 원상복구 단언은 통과했다. 소스나 단언을 바꾸지 않고 basetemp 이름만 `mam-eval-ee26d64c-a4`로 바꾼 재실행이 통과했으므로 제품 회귀로 판정하지 않는다. 새 테스트 25건은 주 실행에서 모두 통과했다. skip 1건은 `test_issue42_skill_blocks.py:266`: 검증 worktree에 추적되지 않는 `.claude/skills` 링크가 없는 경우다. 해당 링크의 합성 layout 테스트들은 실행됐다. 주 실행의 경로 보정까지 반영하면 제품 검증은 266건 통과·1건 skip이며, 추가 회귀/탐침 29건도 통과했다. 중복 확인한 A3 단독 실행은 별도 총계에 넣지 않았다. base 대조는 다른 checkout에서 실행한 것이 아니다. HEAD의 새 테스트와 fixtures를 그대로 두고, `git show b9c828f:`로 얻은 제품 파일 3개(create, worktree_prepare, agents CLI)만 임시 샌드박스에 넣었다. 직접 facts를 조회하는 6건은 base CLI를 임시 스크립트로 실행했고, 어댑터는 변경 없는 검증 트리 것을 사용했다. 실패 구성은 facts 6 + dry-run 경고 4 + 실제 행 검증 후 경고 4 + 후속 거부 경고 1 + 전달 3 + 기본 완료 1 + skip 1이다. 통과 5건은 claude/grok 경고 없음 각 2건과 기존 --onboard 전달 1건이다. 추가 정적 검사: 변경 셸 2개 `/bin/bash -n` 통과, 변경 Python 5개 `ast.parse(..., feature_version=(3,9))` 통과, diff 공백 검사 통과. ShellCheck는 설치되어 있지 않아 실행하지 않았다. 전체 스위트는 실행하지 않았다. ## 발견 사항 - **차단: 없음.** - **비차단(P3):** `tests/test_issue68_onboard_default.py:17`의 `import yaml`은 사용되지 않는다. 해당 1줄을 제거하면 된다. 동작성·데이터 유실 문제는 아니며 판정을 막지 않는다. - 위 A4 경로 문자열 단언의 민감성은 이번 diff에 도입되지 않았다. 이 리뷰에서는 경로 보정으로 검증을 완료했으며 PR 범위 확대를 요구하지 않는다. ## 격리·잔존 확인 및 사용자 확인 필요 모든 create/worktree 동작은 테스트의 mock herdr와 임시 작업 공간에서만 실행했다. 실제 에이전트 홈 DB를 열거나 실제 opencode 서비스·herdr 서버를 사용하지 않았다. 실제 .mam.env를 읽어 출력하거나 export하지 않았다. 테스트 종료 후 이번 실행의 임시 경로를 가진 프로세스는 0개이고, 실제 제어 루트 모니터는 시작·종료 모두 PID 3714다([process-audit.json](evidence/process-audit.json)). 패턴 kill, pkill, killall 및 실제 모니터에 대한 신호는 사용하지 않았다. 제품 소스·브랜치·이슈/PR 상태를 수정하거나 push/merge하지 않았다. 제어 평면 쓰기는 승인된 잡 이벤트와 이 리포트·증거뿐이다. 사용자 확인 필요: 없음. 결정 변경이나 재설계가 필요하지 않다. [VERDICT: PASS]