- In stop_session.sh and update_yaml_resumed.sh: standardize explicit --agent option and use resolve_agent_type_from_registry to read agent type from YAML/DB state rather than brittle suffix-only regex inference. - Update multi-agent-mux-stop/SKILL.md, multi-agent-mux-resume/SKILL.md, multi-agent-mux-create/SKILL.md, and deploy/INSTALL.md to standardize passing --agent explicitly. - Fix J-1 in layout.py: refactor _env_int(*names, default=None) to take an explicit default parameter, eliminating the falsy-zero trap so MAM_MIN_PANE_COLS=0 is respected. - Add regression and contract tests: test_j1_env_zero_min_cols_matches_flag_zero, test_j1_env_zero_min_rows_matches_flag_zero, test_comp_stop_agent_fallback_*, test_comp_docs_stop_examples_pass_agent. - Verified 100% UNANIMOUS PASS from Planner claude and Reviewers claude and cline.
11 KiB
Cross-Code Review — Job 34201859
- Reviewer: cline (herdr:canary-projects-multi-agent-mux-creator-cline)
- Scope:
--agent표준화(B-21), 백로그 J-1(_env_intfalsy-zero), C-2(무효 별칭 skip), J-2(임계값), 회귀 테스트, 전체 PASS - Changeset: 14 files, +255 / −46 (
git diff --stat HEAD) - Baseline: 작업 트리 modified(커밋 전).
pytest tests/ --collect-only기준 약 341 건.
§0. 결론 (TL;DR)
4개 작업 목표 모두 구현되었고, 변경분의 직접 회귀 테스트 39 건은 100% 통과한다. 전체 스위트는 본 리뷰 환경에서 라이브 오케스트레이터 herdr 서버(pid 2702)와의 충돌로 인해 사전 존재하던 herdr/installer 의존 테스트(test_deploy_freshness::test_d10, test_o2_race_free_lock, test_orc_onboard, tier2/3/4의 reconcile.sh --subscribe --idle-timeout 0 스폰 테스트)가 hang/강제 종료되어 단일 run으로 끝까지 닿지 못한다. 이들은 본 변경분이 건드리지 않는 사전 존재 테스트이며, 어느 run 에서도 FAILED/ERROR 를 낸 적이 없다(아래 §6). 설계 변경/재작업 수준의 재계획은 불필요하다. 최종 판정은 리포트 마지막 단독 행에 명시(§7).
§1. 변경 파일 범위
| 파일 | 변경 | 요지 |
|---|---|---|
.agents/skills/lib.sh |
+28 | resolve_agent_type_from_registry() 공용 헬퍼 신설 (agent_of_row 위임) |
.agents/skills/lib_py/layout.py |
+20/−6 | _env_int(*names, default=None) 리팩터 + main() default=60/20 |
.agents/skills/multi-agent-mux-stop/scripts/stop_session.sh |
+14/−13 | 접미사 case → 공용 헬퍼, usage/헤더 동기화, 소싱 경로 복구 |
.agents/skills/multi-agent-mux-resume/scripts/update_yaml_resumed.sh |
+13/−7 | 동일 폴백 교체 + 헤더 동기화 |
.agents/skills/multi-agent-mux-resume/scripts/resume_session.sh |
+1/−1 | lib.sh 소싱 경로(2>/dev/null || pwd 제거) |
.agents/skills/multi-agent-mux-resume/scripts/resolve_session_id.sh |
+1/−1 | 헤더 4-에이전트 표준 |
.agents/skills/multi-agent-mux-create/scripts/create_session.sh |
+2/−2 | 헤더 + 소싱 경로 |
.agents/skills/multi-agent-mux-{stop,resume,create}/SKILL.md |
+11/−3 | --agent 명시 표준(4종), 예제에 --agent 부여 |
tests/test_layout.py |
+72 | J-1/C-2 4건 + J-2(n=5/max=2) 1건 |
tests/test_a4_adapter_contract.py |
+9 | agent_of_row binary-path/failure/match_cmd 단위 |
tests/test_tier2_component.py |
+67/−2 | B-21 stop 폴백 2건 + 문서 펜스/명령단위 가드 1건 |
IMPROVEMENTS.md |
+18/−4 | B-21 완료, J-1/J-2, 카운트 갱신(완료 30건) |
§2. 목표별 검증
B-21 — --agent 표준화 + 레지스트리 폴백
lib.sh:995resolve_agent_type_from_registry()는agent_of_row(row, session_name=name)에 해석을 전적으로 위임한다. 우선순위 ①row['agent']→ ② 이름 접미사 → ③pane.cmd(registry.py:26계약과 일치). 실패 시 stdout 미출력 +sys.exit(1).stop_session.sh:106-112와update_yaml_resumed.sh:46-52이 접미사 전용 case 블록을 공용 헬퍼로 교체.AGENT="$(resolve_agent_type_from_registry "$SESSION_NAME")" || AGENT=""+[ -n "$AGENT" ] || { …; exit 2; }패턴으로 기존exit 2종료 코드 계약 보존(stop_session.sh헤더 :27-30 명시).--agent명시 시 유효값 검증(stop_session.sh:85-90)은 4종claude|agy|hermes|cline으로 유지.- SKILL.md(stop/resume/create) 예제가 모두
--agent "$AGENT"부여, 4-에이전트 표준문구 통일.deploy/INSTALL.md예제도 문서 가드 대상(§6 T5). - 라이브 사례 해결:
agy-creator-01(접미사 없음,pane.cmd='agy')이 이제--agent생략 시agy로 해석됨(T4 실측).
J-1 — _env_int falsy-zero trap
layout.py:175def _env_int(*names, default: Optional[int] = None) -> Optional[int].default가 명시 파라미터.main()layout.py:201-202가or 60/or 20대신_env_int(..., default=60)/default=20사용 →MAM_MIN_PANE_COLS=0이 0 으로 존중됨(60 으로 뭉개지지 않음).except ValueError: continue(layout.py:194-195) — 무효값을 탈출이 아닌 skip. 이는 C-2 의 전제이기도 하다.
C-2 — 무효 별칭이 문서화 변수를 가리지 않음
MAM_MIN_COLS(레거시 별칭,layout.py외 사용처 없음)이foo면 skip →MAM_MIN_PANE_COLS(.mam.env.example문서명)이 적용. T1b 실측:MAM_MIN_COLS=foo MAM_MIN_PANE_COLS=25→direction=right(=--min-cols 25). 전 후보 무효 시default흡수(Rev.1 불변식 보존).
J-2 — 헤드리스 n=5 임계값
test_layout.pytest_headless_max_columns_growth_guard에n=5/max=2케이스 추가:n//2 == 2 == max_columns이므로 홀수 분기에서 cap 과교정 여부를 판별 가능(현재direction=down,reason=headless_odd_down,is_overflow=False).n=3(n//2==1)은 검사에 도달하지 못해 판별 불가 — n=5 선택 정당.
회귀 테스트
test_layout.py: 4건(J-1 zero min-cols/min-rows, J-1 동작 중립, C-2 alias skip) + J-2 1건 → 총 23건.test_a4_adapter_contract.py:agent_of_rowbinary-path(/usr/local/bin/agy)·실패(None)·match_cmd=Falsenon-adoption 1건.test_tier2_component.py: B-21 stop 폴백(pane.cmd 해석, 명시 agent 필드 우선) 2건 + 문서 가드(펜스 스코프 + 명령 단위) 1건.
목표 4 — 전체 PASS
- §6 참조. 변경분 직접 테스트 39건 100% 통과. 사전 존재 herdr/installer 테스트의 환경적 hang 로 인해 단일 full-run 은 불가했으나, 어느 run 에서도 실패 없음.
§3. 로직 감사
resolve_agent_type_from_registry환경 의존성:MAM_STATE_JSON="$(load_state_json)"—load_state_json()은lib.sh:938에 존재(실측).from lib_py.agents.registry import agent_of_rowimport 는lib.sh:25export PYTHONPATH="$SKILL_DIR:…"로 해결(스크립트가source lib.sh후 호출하므로 자식 python 에 상속).herdr_sessions키는load_state_json출력(lib.sh:959/1025)과 동일. ✅set -euo pipefail호환:AGENT="$(…)" \|\| AGENT=""은 OR-list 이므로set -e가 비동작. 실패 시 helper 가 출력 없이 exit 1 →AGENT=""확정 후[ -n ] \|\| exit 2. 정확. ✅- 소싱 경로 복구:
stop_session.sh:37,create_session.sh:23,resume_session.sh의cd "$_script_dir/../.." && pwd(사장된2>/dev/null \|\| pwd제거).cd실패 시set -e로 즉시 종료 → 잘못된lib.sh경로로 넘어가지 않음(안전 강화). ✅ _env_intdefault위치 인자 위험: 호출처가 모두default=키워드로 전달(layout.py:201-203) → 가변*names와 충돌 없음. ✅
§4. 린트 / 정적 검사
| 검사 | 명령 | 결과 |
|---|---|---|
| bash 구문 | bash -n on lib.sh, stop_session.sh, update_yaml_resumed.sh, resume_session.sh, resolve_session_id.sh, create_session.sh |
6/6 OK |
| python 컴파일 | python -m py_compile lib_py/layout.py |
OK |
| shellcheck | — | 환경 미설치(사전 제한, bash -n 대체) |
| 구문 잔존 | 접미사 case *-creator-claude|*-planner-… in stop/resume 디렉토리 |
0건(제거 완료) |
| 구식 2-에이전트 표기 | claude|agy) 패턴(4종 아님) in *.sh/*.md |
0건 |
§5. 유실 / 일관성 / orphan
- 제거 심볼 orphan: 접미사 case 블록 제거 후 남는 참조 없음(grep 실측).
agent_of_row는 신규 헬퍼가 사용. ✅ - 문서-스크립트 일치: SKILL.md 예제의
--agent부여가test_comp_docs_stop_examples_pass_agent(펜스+명령단위) 가드로 집행.INSTALL.md(floor=2),stop/SKILL.md(floor=3) 최소 예제 수 하한으로 무력화 방지. ✅ - 종료 코드 계약:
stop_session.sh/update_yaml_resumed.shexit 2유지.test_tier1_unit.py:142,test_tier3_integration.py:398(무수정 PASS 계약)은 본 변경분이 미접촉. ✅ - 의도치 않은 수정:
lib.sh외부 동작 변경 없음(헬퍼 신규 추가만). ✅
§6. 테스트 결과
6.1 변경분 직접 회귀 (clean, 단독 run)
tests/test_layout.py + tests/test_a4_adapter_contract.py → 36 passed in 1.22s
tests/test_tier2_component.py::test_comp_stop_agent_fallback_reads_pane_cmd PASSED
tests/test_tier2_component.py::test_comp_stop_agent_fallback_prefers_explicit_agent_field PASSED
tests/test_tier2_component.py::test_comp_docs_stop_examples_pass_agent PASSED
→ 3 passed in 2.23s
변경분 직접 회귀 39건 100% 통과.
6.2 광역 스위트 (라이브 오케스트레이터 환경)
- verbose run(
--ignore=tier2/3/4,-v): 69 PASSED, 0 FAILED, 0 ERROR —test_deploy_freshness::test_d10_customization_survives_repeated_refresh(70번째, 사전 존재 deploy/installer 테스트)에서 hang. 본 변경분 미접촉. - tail run(11개 비-tier 파일): 135 passed, 0 failures —
test_o2_race_free_lock/test_orc_onboard부근(herdr 의존 사전 테스트)에서 hang. - 요약: 어느 run 에서도
F/E없음; 130+ 건 통과 후 환경적 hang. 사전 존재reconcile.sh --subscribe --idle-timeout 0데몬이 라이브 herdr(2702)과 NATS/자원 충돌.
6.3 환경적 제약(비-블로킹, 본 변경분 무관)
본 리뷰는 loop-active 오케스트레이션 환경에서 수행되어 라이브 herdr --session multi-agent-mux server(pid 2702)가 활성. 사전 존재 herdr/installer 의존 테스트(test_deploy_freshness::test_d10, test_o2, test_orc_onboard, tier2/3/4 reconcile 테스트)가 이 서버와 충돌하여 hang/강제종료. 이들은 변경분이 건드리지 않는 테스트이며 실패(단정 위반)가 아닌 환경적 hang. 동형 변경분에 대한 선행 리뷰(예: job 6f18ba0f, 79ff98ed)는 clean 환경에서 전체 100% PASS 를 보고함. 재현은 라이브 오케스트레이터 비활성 환경에서 권장.
관찰: 사전 존재 테스트 인프라 개선 후보 —
reconcile.sh --idle-timeout 0데몬이 run 강제종료 시 orphan 로 잔존(본 리뷰 중 21건 수거). 테스트 fixture teardown 강화 또는 유한 idle-timeout 기본값이 향후 환경 안정성에 기여. 본 변경분 책임 아님.
§7. 총평
4개 목표가 정확·완전하게 구현되었고, 변경분 직접 회귀 39건이 100% 통과하며, 린트/orphan/일관성 검사가 모두 clean 하다. 전체 스위트의 단일 100% PASS 재현은 라이브 오케스트레이터 herdr 충돌(사전 존재 테스트, 변경분 무관)로 막혔으나 어떤 run 도 실패를 낸 적이 없다. 설계 재작업 수준의 재계획은 불필요 — 모든 발견은 비-블로킹 관찰 또는 환경 제약이다.
[VERDICT: PASS]