Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
11 KiB
11 KiB
PR #79 (Issue #68) 리뷰 — head 3b81f99
리뷰어: planner-reviewer-claude-01 (claude) · job 2ab23f4e
0. 리뷰 경로 확인
- 검증 경로:
/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261029T045625Z-74296d/1- HEAD 는
3b81f9973223d2a910369711c08adc772003639d, tree 는ff705b61bf25fe40d0ff054c372a399eacc79730로 [리뷰 identity] 와 같다. 리뷰 전과 후 두 번 확인했다. git status --porcelain --ignored결과는 비어 있고,.mam도 없다.
- HEAD 는
- 리뷰 범위: base
b9c828f와 HEAD 사이의 커밋 5개, 9개 파일, +277/−22 줄. - 기준 문서(읽기만 했다):
tea issues 68 --comments의 결정 1–4 와 완료 조건,tea pulls 79설명,INSTRUCTION.md.
1. 결정·완료 조건 대조표
| 조건 | 구현(파일:줄) | 테스트 | 판정 |
|---|---|---|---|
결정 1: create 의 --no-onboard 유지, 기본은 온보딩 |
create_session.sh:67 ONBOARD=1, :87-88 그대로 |
기존 테스트 전체가 그대로 통과 | ✅ |
| 결정 2: worktree_prepare 기본을 온보딩으로 | worktree_prepare.sh:30 ONBOARD=1 |
test_prepare_onboards_by_default_end_to_end(온보딩 잡 completed, "onboarding completed" 출력) |
✅ |
결정 2: --no-onboard 는 건너뛰고 create 에 그대로 넘김 |
:43, :232 args+=(--no-onboard) |
test_prepare_no_onboard_sends_none, test_prepare_forwards_onboarding_choice[opts2] |
✅ |
결정 2: 기존 --onboard 도 같은 동작 |
:42 |
forwards[opts1], [opts3](둘 다 주면 마지막 것이 이김) |
✅ |
| 결정 3: agy·codex·hermes·opencode 에만 경고, claude·grok 에는 없음 | create_session.sh:208-211, facts lib_py/agents/__main__.py:75 |
test_facts_expose_post_discovered[6], test_no_onboard_warning_dry_run[6], ..._keeps_exit_and_row[6] |
✅ |
| 결정 3: 경고 내용 "첫 대화 전까지 ID 미기록, 같은 폴더 같은 종류는 기다림(#63)" | :210 의 문구가 이 두 가지와 MAM_ID_ORDER_WAIT_S 를 말한다 |
경고에 Issue #63 과 에이전트 이름이 들어 있는지 확인 |
✅ |
| 결정 3: 종료 코드·행이 바뀌지 않음 | 경고 출력만 하고 분기는 없다 | keeps_exit_and_row: rc 0, 행 필드(이름, status, role, server, workspace, cmd, cmd_full, cwd, id source·verified, 상태, control_plane)를 기대값과 비교 |
✅ |
| 결정 3: 뒤에서 거부돼도 경고가 먼저 보임 | spawn·#63 검사(:287 부근)보다 앞에서 출력 |
test_no_onboard_warning_precedes_a_later_refusal |
✅ |
| 결정 4: 문서는 create SKILL.md 옵션 표와 worktree 절만 고침 | SKILL.md:173, :205, :210, :213 네 줄 |
test_issue42_skill_blocks(블록 sha 와 근거 핀) |
✅ |
| 완료: "기본은 온보딩 안 함" 을 전제로 한 worktree 테스트를 고침 | test_issue21_acceptance.py:47, :207, test_issue21_phase2_loop_a.py:422 |
모두 통과 | ✅ |
| 완료: macOS(bash 3.2, Python 3.9)에서 통과 | — | §3 | ✅ |
빠진 조건은 없다.
2. 꼼꼼히 본 것
2.1 경고 판정과 facts
- 이 Mac 에서
lib_py.agents facts <agent>를 직접 실행했다.- agy, codex, hermes, opencode 는
MAM_ID_POST_DISCOVERED=1이다. - claude, grok 은
0이다. - 값은 어댑터의
id_lifecycle(base.py:174-175의PRE_ASSIGNED/POST_DISCOVERED)에서 나온다. 셸 쪽에는 에이전트 목록을 두지 않았다.
- agy, codex, hermes, opencode 는
- facts 를 쓰는 다른 곳에는 영향이 없다.
lib.sh:2596(eval 뒤 필요한 키만 읽음),:2957(eval),:3156(sed -n 's/^KEY=//p'로 키별 추출)은 모두 키 단위로 읽는다. 그래서 줄이 하나 늘어도 문제가 없다.- facts 출력을 다루는 테스트(
test_a4_adapter_contract.py,test_issue23_24_startup_path.py)도 이 Mac 에서 103 passed 였다.
- facts 를 얻지 못하는 경우(파이썬 실패 등)
eval "$(… || true)"는 아무 값도 정하지 않는다. 그러면${MAM_ID_POST_DISCOVERED:-0}가 0 이 되어 경고 없이 지나간다. 동작이 바뀌지 않는 쪽으로 실패하므로 안전하다. MAM_DELEGATION_PY=0는 위임(delegation) 경로에만 쓰이는 스위치다.lib_py.agents facts와는 관계가 없어 경고 판정에 영향이 없다.test_issue26_ints.py:111은 이 값을 "문자열 비교" 로 분류해 정수 기본값 검사 대상에서 뺐다. 코드도 실제로 문자열로 비교하므로(= 1) 맞는 분류다.
2.2 --creator-agent 를 부르는 모든 곳 (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,test_issue50_onboard.py:192,test_issue57_logs_follow_registry.py:276,test_issue50_dispatch_herdr.py:868는 원래--onboard를 명시하므로 동작이 같다.test_issue21_phase2_loop_a.py:355(w6c)는 옵션이 없다. 하지만 서브모듈 초기화가 실패해 create 이전에 exit 1 로 끝나고, 행이 없음을 확인하는 테스트다. 그래서 온보딩까지 가지 않는다. 뒤에 다시 부르는_prepare(main, wt)에는--creator-agent가 없다.- 새 테스트 파일의 세 호출은 의도한 대로다.
- 문서와 기록
docs/design/worktree-creator-model.md:48-51의 예시에는 옵션이 없다. 그래서 이제 온보딩하는데, 예시가 보여 주려는 creator 흐름에도 그게 맞다. 이 문서에는 "기본은 온보딩 안 함" 이라는 문장이 없어 고칠 내용도 없다. 결정 4 의 "최소 변경" 과도 맞는다.VERSIONS.md:632는 과거 기록이고,README*.md:51은 create 에 대한 설명이라 맞다.- 그 밖의 스크립트에서는
worktree_prepare.sh를 부르는 곳이 없다.
- 결론적으로 온보딩 대기(최대
MAM_ONBOARD_WAIT_S) 때문에 의도치 않게 느려지거나 44/45 로 끝날 호출은 남아 있지 않다.
2.3 SKILL.md 와 코드의 줄 단위 대조 (INSTRUCTION.md)
SKILL.md:173은 "--no-onboard로 만든, ID 가 첫 턴 뒤에 생기는 에이전트(id_lifecycle)는 그때까지 ID 를 기록하지 않고, 같은 폴더의 같은 종류 create 를 막는다(#63). create 가 경고한다" 고 설명한다.- 코드(
create_session.sh:209-210)의 조건과 문구가 이와 같다. - #63 쪽은 정확히는 "막는다" 가 아니라 "기다린 뒤 거부" 다. 하지만 표 한 줄 요약으로는 맞다.
- 코드(
SKILL.md:205의 시놉시스[--no-onboard]는worktree_prepare.sh:9,:43과 같다.SKILL.md:210의 "onboards it …--no-onboardskips it,--onboardis the default and still accepted" 는:30,:42-43,:232와 같다.SKILL.md:213의 종료 코드 "44/45 are create's (…onboarding is the default…)" 는 스크립트 머리말:17-19와 같고, create 의 44/45 정의(create_session.sh:22-23)와도 같다.- 판단이 필요한 내용만 문서에 있고, 판정은 코드(adapter facts)에 있다. INSTRUCTION.md 를 따른 것이다.
2.4 tests/data/skill_code_blocks.json
- 근거 핀의 줄 번호 이동은 실제로 늘어난 줄 수와 맞는다.
create_session.sh는 경고 4줄을:208에 넣었으므로 그 뒤 근거가 모두 +4 줄 밀렸다(360→364, 518-545→522-549 등).worktree_prepare.sh는--no-onboardcase 한 줄 때문에 +1 줄 밀렸다(250→251).
- 내용이 바뀐 블록은 하나다.
SKILL.md:202-206의 worktree 시놉시스가[--onboard]에서[--no-onboard]로 바뀌었고, 그 블록의 sha 만38836d31bf38에서8bfabafb0328로 바뀌었다. test_issue42_skill_blocks.py가 sha 와 근거를 다시 계산해 통과했다(§3).
2.5 새 테스트가 결함을 잡는지
- base 대조 실행:
git archive HEAD를 TMPDIR 에 풀고, 코드 3개 파일(__main__.py,create_session.sh,worktree_prepare.sh)만b9c828f판으로 바꾼 뒤tests/test_issue68_onboard_default.py를 돌렸다.- 결과는 20 failed, 5 passed 로, 작성자의 주장과 같다.
- 통과한 5건은 base 에서도 맞아야 하는 경우다. claude·grok 의 dry-run 과 행 시험 4건, 그리고
--onboard전달 1건이다. - 사본은 확인한 뒤 지웠다.
- Python 3.9 호환성:
str.removeprefix는 3.9 부터 있다.list[str]주석은from __future__ import annotations덕분에 3.9 에서도 문제가 없다.
3. 실행한 테스트 (이 Mac: macOS, /bin/bash 3.2, /usr/bin/python3 3.9.6)
cd <검증 경로>
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 \
PYTHONDONTWRITEBYTECODE=1 /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux/.venv/bin/python \
-m pytest -p no:cacheprovider --basetemp="$TMPDIR/claude-j2ab-bt" -q -rfs \
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_issue57_logs_follow_registry.py tests/test_issue63_same_cwd_ids.py
- 결과: 265 passed, 1 skipped, 0 failed (724 s).
- skip 1건은
test_issue42_skill_blocks.py:266이다. untracked.claude/skills가 worktree 에 없어서 생기는 환경 문제다.
- skip 1건은
- facts 를 쓰는 다른 테스트
tests/test_a4_adapter_contract.py,tests/test_issue23_24_startup_path.py는 103 passed (152 s). - base 대조 실행(§2.5)은
test_issue68_onboard_default.py기준 20 failed, 5 passed. test_issue50_dispatch_herdr.py는 실제 herdr 서버를 띄우므로 브리프 제약에 따라 실행하지 않았다. 이 파일이 worktree_prepare 를 부르는 곳(:868)은--onboard를 명시하므로 이번 변경으로 동작이 바뀌지 않는다.- 테스트가 끝난 뒤 남은 프로세스: 테스트가 띄운
reconcile.sh, mock herdr, 구독자는 없다. 남아 있는 것은 원래 있던 셋뿐이다.- 본 체크아웃 모니터 3714
- 이번 루프 88445
- 이번 잡의 job_subscriber 88788 (13:56:28 시작)
4. 발견 사항
차단
- 없음.
비차단
- N1.
tests/test_issue68_onboard_default.py:17의import yaml은 쓰이지 않는다. PR 설명에서도 남긴 것으로 밝혔다. - N2.
--no-onboard --submit-job "<프롬프트>"를 함께 주면, 제출한 잡이 첫 턴이 되는데도 경고가 나온다.- 이 조합에서는 원래 온보딩 프롬프트를 만들지 않는다(
create_session.sh:440). 그래서--no-onboard가 사실상 아무 일도 하지 않는다. - 결정 3 의 조건("
--no-onboard를 주고 ID 후발견 에이전트이면")을 그대로 구현한 결과다. 그래서 결함은 아니고, 문구가 조금 지나치게 경고할 뿐이다.
- 이 조합에서는 원래 온보딩 프롬프트를 만들지 않는다(
- N3. facts 를 얻지 못했는데 호출자 환경에
MAM_ID_POST_DISCOVERED=1이 export 돼 있으면, claude 에도 경고가 나올 수 있다. 현실적인 경로가 없어 참고로만 적는다.
5. 사용자 확인 필요
- N2:
--submit-job과 함께 준--no-onboard에도 경고를 낼지. 지금은 결정 3 의 문언대로 경고를 낸다.
6. 결론
- 결정 1–4 와 완료 조건이 모두 구현됐고 테스트로 덮였다.
- 새 테스트는 base 에서 20건이 실패하므로 결함을 실제로 잡는다.
- 바뀐 테스트 파일과 create/worktree 관련 테스트가 이 Mac 에서 모두 통과한다.
- SKILL.md 의 설명은 코드와 줄 단위로 맞는다.
[VERDICT: PASS]