- Standardize --herdr-session as primary flag with --herdr-server alias across create_session.sh, resume_session.sh, update_yaml_resumed.sh, and stop_session.sh - Guard HERDR_SESSION_NAME in create_session.sh from being overwritten by workspace slug defaults when explicitly provided - Forward explicit --herdr-session from resume_session.sh to update_yaml_resumed.sh and force-update row metadata - Add 5 new Tier 2 component tests covering CLI dry-run parsing, usage matching, default preservation, YAML serialization, and resume propagation - Update multi-agent-mux-create/SKILL.md documentation - Verified by autonomous multi-agent loop with unanimous PASS verdicts from Claude and Cline
8.0 KiB
🔍 교차 코드 리뷰 (2차) — Job 1b18eb9a
- 역할: Reviewer
- 대상:
--herdr-session/--herdr-server표준화 구현분 — 워킹 트리 6파일 (+245 / −56) - 기준 커밋:
f7e1513/ 미추적 파일 0건 - 직전 판정:
2d3fef82NOT PASS (차단 2건 B-1·B-2, 권고 2건)
1. 결론
직전 리뷰의 차단 2건과 권고 2건이 전부 해소됐고, 각각에 뮤테이션으로 감도가 확인되는 회귀 가드가 붙었습니다. 전체 스위트 346 passed / 실패 0.
P3 관찰 2건만 남습니다. 어느 쪽도 결함을 가리지 않아 통과 처리합니다(최종 태그는 보고서 마지막 줄).
2. 직전 지적 대비 이행
| 직전 항목 | 이행 | 가드 |
|---|---|---|
B-1 resume 주 경로가 --herdr-session 미전달 |
✅ resume_session.sh:136-138 이 조기 종료 분기(:72-74)와 동일하게 전달 |
H1 검출 |
B-2 setdefault 로 기존 행에 무효 |
✅ HERDR_SERVER_OPT_EXPLICIT 로 명시/백필 구분, start/attach/kill_command 까지 갱신 |
H2 검출 |
| §4.1 dry-run 이 플래그 무시를 구분 못 함 | ✅ 출력에 herdr_session=${HERDR_SESSION_NAME:-default} 추가 + 두 플래그 각각 단언 |
H4 검출 |
| §4.2 감사 지시된 세 가드에 커버리지 0 | ✅ test_comp_create_herdr_session_default_preserved 신설 |
H3 검출 |
| N-2 create usage 테스트가 파서 미실행 | ✅ 수용 경로(--herdr-session + dry-run rc=0)와 거부 경로(--invalid-flag-xyz rc=2) 양방향 추가 |
— |
N-3 HERDR_SERVER_NAME 지원 여부 모호 |
✅ SKILL.md 에 "legacy env alias: HERDR_SERVER_NAME" 명기 |
— |
B-2 의 처방은 제가 제안한 것보다 낫습니다. if is_explicit or not target.get('herdr_session') 는 herdr_session: null 인 행까지 백필합니다 — setdefault 는 키가 존재하기만 하면 None 도 보존해 버리던 구멍이었는데, 이 형태가 그것도 함께 닫습니다. 또 start_command/attach_command/kill_command 3종을 함께 갱신해, 행의 라우팅 정보가 부분적으로만 갱신되는 상태를 만들지 않습니다.
3. 검증 결과
| 검증 | 결과 |
|---|---|
| 전체 스위트 | 346 passed / 462.39s / 실패 0 |
| 수집 수 | 341 → 346 (신설 5건) |
bash -n 4개 변경 스크립트 |
4/4 OK |
| 신설 5건 대조군 | 5 passed |
| 뮤테이션 | H1~H5 전부 지정 테스트 검출 |
1차 리뷰에서 관찰됐던 test_o2_18_orphan_steal_lock_recovered 플레이크는 이번 실행에서 재현되지 않았습니다(선재 부하 민감 이슈, §5 N-1).
4. 뮤테이션 매트릭스
격리 rsync 사본. 대조군 5/5 통과.
| # | 뮤테이션 | 결과 |
|---|---|---|
| H1 | resume_session.sh:136-138 에서 --herdr-session 제거 (B-1 되돌림) |
resume_herdr_session_propagation FAILED |
| H2 | is_explicit or not target.get(...) → setdefault (B-2 되돌림) |
resume_herdr_session_propagation FAILED |
| H3 | create_session.sh 의 HERDR_SERVER_OPT 가드 되돌림 |
default_preserved FAILED / 나머지 2건 PASSED |
| H4 | dry-run 출력에서 herdr_session= 제거 |
cli_parsing_dry_run FAILED |
| H5 | create 파서가 값을 버림 (shift 2 만) |
cli_parsing_dry_run · default_preserved · yaml_propagation 3건 FAILED |
H3 이 정확히 하나만 깨는 것이 중요합니다. 직전 리뷰에서 실측했듯 그 가드들의 행동 변화는 리터럴 값 default 하나뿐이므로, default_preserved 만 실패하고 cli_parsing_dry_run·yaml_propagation 이 통과하는 것이 정확한 감도입니다. 과잉 결합 없이 딱 그 성질만 잡습니다.
H1 은 제가 차단했던 바로 그 회귀입니다. 이제 잡힙니다.
5. 플래그 없는 resume 경로 확인 (신규 검토)
resume_session.sh 는 이제 --herdr-session "$HERDR_SESSION_NAME" 을 무조건 전달합니다. 사용자가 플래그를 주지 않아도 값이 resolve_herdr_session(...) 결과로 채워져 넘어가므로, 자식에서 HERDR_SERVER_OPT_EXPLICIT 이 항상 1 이 됩니다. 명시/백필 구분이 이 호출자에서는 무의미해지는 셈이라, 잘못된 기록을 만드는지 실측했습니다.
행의 herdr_session |
플래그 없이 resume 후 | 판정 |
|---|---|---|
RECORDED-X |
RECORDED-X (attach_command 도 일치) |
멱등 ✅ |
default |
mam-<ws-slug> |
정정 ✅ |
| (키 없음) | mam-<ws-slug> |
백필 ✅ |
2행이 유일한 행동 변화입니다. 행이 default 를 기록하고 있으면 resolve_herdr_session 은 (val != 'default' 조건 때문에) 그 값을 건너뛰고 폴백으로 내려가므로, 실제 스폰은 이미 mam-<ws-slug> 로 이뤄집니다. 즉 기록을 mam-<ws-slug> 로 바꾸는 것은 행을 현실과 일치시키는 정정이지 오작동이 아닙니다. 세 경우 모두 문제없습니다.
6. 관찰 사항 (P3 — 비차단)
🟡 O-1: update_yaml_resumed.sh 신규 행 분기의 herdr_server 추가에 가드가 없다
target is None 분기에 'herdr_server': server_name 이 추가됐는데, 이 줄을 제거해도 검출되지 않습니다.
H6 (신규 행 dict 에서 'herdr_server' 제거)
tier2 33 passed
tier1 + tier3 + tier4 + uuid_target + ws_scope 69 passed
→ 102건 전부 통과, 미검출
신설 resume 테스트가 기존 행을 심어 놓고 시작하므로 신규 행 경로를 타지 않습니다. 레지스트리에 없는 세션을 resume 할 때만 도달하는 좁은 경로이고, 추가된 필드는 기존 필드 옆에 별칭을 하나 더 두는 순수 가산 변경이라 회귀 위험이 낮습니다. 차단하지 않습니다.
처방이 필요하면 기존 resume 테스트에서 herdr_sessions: [] 로 시작하는 케이스 1건이면 충분합니다.
🟡 O-2: create_session.sh:216 가드는 여전히 무동작
if [ -z "$HERDR_SERVER_OPT" ]; then
RESOLVED_SERVER="$(resolve_herdr_workspace "$SESSION_NAME" "$WORKSPACE")"
export HERDR_SESSION_NAME="${HERDR_SESSION_NAME:-$RESOLVED_SERVER}"
fi
--herdr-session 이 주어지면 :78-79 에서 이미 HERDR_SESSION_NAME 이 비어 있지 않으므로 ${VAR:-...} 가 발동하지 않습니다. 즉 이 가드의 유일한 실효는 resolve_herdr_workspace 서브프로세스 호출 1회를 건너뛰는 것입니다. 브리프가 감사를 지시한 세 지점 중 하나이므로 "감사했고 무동작임을 확인했다" 는 사실 자체가 기록될 가치가 있습니다 — 다만 방어적으로 남겨 두는 것이 해롭지 않고, 미래에 :78-79 가 바뀌면 실효가 생길 수 있으므로 제거를 권하지는 않습니다.
이월 (범위 밖, 선재)
| ID | 내용 |
|---|---|
| N-1 | test_o2_18_orphan_steal_lock_recovered 부하 민감 플레이크 — acquire_bg() 의 고정 time.sleep(0.3) 을 마커 폴링으로 교체하면 해소. 이번 변경과 무관 |
| N-4 | README.md:98,100 / README.ko.md:80,82 가 구 herdr -L <server> 메커니즘을 서술 — IMPROVEMENTS.md:304 기준 이미 완료된 전환이므로 선재 드리프트. SKILL.md 만 정리되어 문서 표면 간 불일치가 남아 있음 |
7. 총평
차단 2건이 모두 닫혔고, 더 중요하게는 각각에 감도가 실증된 가드가 붙었습니다. 직전 리뷰에서 "신설 3건 중 실효는 1건" 이었던 상태가 이번에는 신설 5건 중 4건이 뮤테이션을 잡습니다(usage 테스트는 성격상 문서 단언이라 제외).
B-2 의 처방은 제가 제안한 형태보다 낫습니다 — herdr_session: null 구멍과 라우팅 명령 3종의 부분 갱신 문제를 함께 닫았습니다.
남은 2건은 P3 입니다. O-1 은 좁은 경로의 가산 변경이라 회귀 위험이 낮고, O-2 는 방어적 무동작 코드입니다. 다음 커밋에 정리하거나 그대로 둬도 무방합니다.
[VERDICT: PASS]