Files

144 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ✅ Peer Review Report: delegate-job run_agent() herdr 버그 3건 수정 검토
**Reviewer**: Reviewer B (Cline, `canary-projects-multi-agent-mux-reviewer-cline`)
**Job ID**: 7f25e72e
**Review Target**: `.agents/skills/multi-agent-mux-delegate-job/multi-agent-mux-delegate-job``run_agent()` 함수 herdr 관련 버그 3건 수정 (커밋 `6df4b03`에 반영됨, working tree의 해당 파일은 clean)
**Review Scope**: (a) 수정이 실제 herdr CLI 문법과 맞는지, (b) source 순서 변경이 스크립트 다른 부분과 충돌하지 않는지, (c) HERDR_SERVER_NAME 자동 해석이 비격리(default) 세션에 회귀 없이 동작하는지
**Method**: 실제 herdr v0.7.4 도움말 직접 열람 + shim has-session/agent attach 실행 + resolve_herdr_workspace python3 시뮬레이션 + 형제 스킬(resume/stop) 일관성 비교 + 55개 테스트 실행
---
## 1. 발견된 버그 3건과 수정 내용 (커밋 6df4b03)
### 버그 1: lib.sh source 순서 — has-session이 실제 바이너리 호출 (항상 실패)
- **문제**: lib.sh를 `run_agent()` 내부, has-session 체크(라인 437)보다 늦게(라인 444) source → has-session 호출 시점엔 `herdr`이 shim이 아닌 실제 바이너리 → 존재하지 않는 `has-session` 서브커맨드 → 항상 실패
- **수정**: `source "$SCRIPT_DIR/../lib.sh"`를 라인 31(스크립트 상단, `run_agent()` 정의 라인 408보다 377줄 앞)로 이동 + 주석 "Source EARLY (before any herdr usage in run_agent)"
- **결과**: `herdr has-session -t`가 shim 경유로 `_real_herdr agent get "$sess"`로 번역되어 정상 동작
### 버그 2: HERDR_SERVER_NAME 자동 해석 누락 — 격리 세션 위임 실패
- **문제**: 호출자가 `HERDR_SERVER_NAME`를 수동 export하길 기대 → 격리된 세션 위임 시 default 세션에서 찾아 실패
- **수정**: `export HERDR_SERVER_NAME="$(resolve_herdr_workspace "$sess")"` 자동 해석 추가 (라인 443) + 주석 "Auto-resolve isolation the same way resume/stop/create do"
- **이전 코드**: `local _herdr="herdr"; if [ -n "${HERDR_SERVER_NAME:-}" ]; then _herdr="herdr -L $HERDR_SERVER_NAME"; fi` — 수동 env 의존 + `herdr -L` 직접 사용(shim 경유 아님)
- **신규 코드**: 자동 해석 + `herdr has-session -t` (shim이 `-L`를 내부 처리)
### 버그 3: 안내 메시지 'session attach' → 'agent attach'
- **문제**: 마지막 안내가 `herdr session attach $sess``session attach`는 서버 전체 단위 명령이라 개별 에이전트 이름으로 못 찾음
- **수정**: `HERDR_SERVER_NAME=$HERDR_SERVER_NAME herdr agent attach $sess` (라인 513) + 주석 "`session attach` operates on whole herdr *sessions*, not an individual agent"
- **추가**: `HERDR_SERVER_NAME` 인라인 포함 — source 안 된 fresh shell에서도 copy-paste 가능
---
## 2. 검증 관점 (a): 실제 herdr CLI 문법 일치 여부
### 2.1 ✅ has-session — shim 번역 정확
- 실제 herdr v0.7.4에 `has-session` 서브커맨드 **없음** (도움말에 없음)
- shim(lib.sh 147-163): `has-session -t <sess>``_real_herdr agent get "$sess" >/dev/null 2>&1` — agent 존재 여부로 세션 존재 판정
- **실행 검증**: 존재 세션 → exit 0, 비존재 세션 → exit 1 ✅
### 2.2 ✅ agent attach — 실제 서브커맨드 확인
- `herdr agent --help` 출력: `herdr agent attach <target> [--takeover]`**실제 존재**
- `herdr agent attach <target>`는 **개별 에이전트 target**을 받음 — `$sess`(MAM 에이전트 이름)와 일치 ✅
### 2.3 ✅ session attach vs agent attach 구분 정확
- `herdr session --help` 출력: `herdr session attach <name>`**서버 전체 session** name을 받음
- `herdr agent attach <target>`**개별 에이전트** target을 받음
- delegate-job의 `$sess`는 MAM 에이전트 이름(예: `canary-projects-multi-agent-mux-reviewer-cline`) → `agent attach`가 정답 ✅
- 수정 전 `session attach $sess`는 에이전트 이름을 session 이름으로 잘못 전달 → 실패 확정 ✅ (버그 재현 논리 타당)
### 2.4 ✅ HERDR_SERVER_NAME 인라인 메시지
---
## 3. 검증 관점 (b): source 순서 변경 충돌 여부
### 3.1 ✅ source 위치 — run_agent보다 377줄 앞
- `source "$SCRIPT_DIR/../lib.sh"` (라인 31) vs `run_agent()` 정의 (라인 408) — 377줄 선행 ✅
- has-session 호출(라인 445) 시점엔 shim 활성화 보장 ✅
### 3.2 ✅ 다른 함수/변수와 충돌 없음
- lib.sh source 시 정의되는 함수: `herdr`(shim), `resolve_herdr_workspace`, `send_keys_safe`, `load_state_json`, `derive_session_name`, `env_python`
- delegate-job이 이미 사용 중인 함수(`send_keys_safe`, `load_state_json`) — source 순서 변경 후에도 동일 동작 ✅
- `pick_python()` (라인 34)는 source 이후 정의 — lib.sh가 `pick_python`에 의존하지 않으므로 순서 충돌 없음 ✅
- 라인 26-30 주석이 "Source EARLY" 의도 명시 — 유지보수자에게 경고 ✅
### 3.3 ✅ 기존 `source` 라인(라인 444) 제거 확인
- 6df4b03 diff: `source "$SCRIPT_DIR/../lib.sh"`가 run_agent 내부(구 라인 444)에서 제거되고 상단(라인 31)로 이동 — 중복 source 아님 ✅
---
## 4. 검증 관점 (c): HERDR_SERVER_NAME 자동 해석 — 비격리(default) 회귀 여부
### 4.1 ✅ resolve_herdr_workspace 구현 (lib.sh 550-562)
- state JSON에서 session name 매칭 → `herdr_workspace`/`herdr_server` 반환
- 매칭 실패 시 `os.environ.get('HERDR_SERVER_NAME', 'default')` fallback
- **비격리(default) 경로**: session이 JSON에 없거나 `herdr_workspace` 미설정 → `default`
### 4.2 ✅ python3 시뮬레이션 검증
- **비격리**: `MAM_STATE_JSON='{}' SESSION_NAME='nonexistent'` (HERDR_SERVER_NAME unset) → `default`
- **격리**: `MAM_STATE_JSON='{"herdr_sessions":[{"name":"isolated-agent","herdr_workspace":"iso-server"}]}' SESSION_NAME='isolated-agent'``iso-server`
- **env fallback**: `HERDR_SERVER_NAME=custom_server``custom_server` (test_resume_resolve_herdr_workspace_env 검증) ✅
### 4.3 ✅ 형제 스킬 일관성
| 스크립트 | 패턴 |
|---------|------|
| resume_session.sh:40 | `HERDR_SERVER_NAME="$(resolve_herdr_workspace "$SESSION_NAME")"` |
| update_yaml_resumed.sh:36 | `HERDR_SERVER_NAME="$(resolve_herdr_workspace "$SESSION_NAME")"` |
| stop_session.sh:85 | `HERDR_SERVER_NAME="$(resolve_herdr_workspace "$SESSION_NAME")"` |
| **delegate-job:443 (신규)** | `export HERDR_SERVER_NAME="$(resolve_herdr_workspace "$sess")"` |
- delegate-job이 형제 스킬과 **동일 패턴** 채택 — 일관성 확보 ✅
- 유일한 차이: `export` 추가 — delegate-job은 subprocess(send_keys_safe 등)에 전달 필요 → export 정당 ✅
### 4.4 ✅ 비격리 회귀 없음
- default 세션의 에이전트: `resolve_herdr_workspace``default` 반환 → `HERDR_SERVER_NAME=default` → shim이 `_MAM_SESSION=""`(빈) → `_real_herdr``--session` 없이 호출 → default 서버 사용 ✅
- 55개 테스트(깨끗한 환경) 통과 — 비격리 경로 회귀 없음 ✅
---
## 5. 추가 검증: 정적 분석 & 테스트
### 5.1 ✅ bash -n
| 파일 | 결과 |
|------|------|
| `multi-agent-mux-delegate-job` | SYNTAX OK (exit 0) ✅ |
| `.agents/skills/lib.sh` | SYNTAX OK (exit 0) ✅ |
### 5.2 ✅ 테스트 (깨끗한 환경)
- `env -u HERDR_SERVER_NAME pytest tests/test_tier1_unit.py tests/test_tier2_component.py`: **55 passed**
- **주의**: 리뷰어 세션 환경(`HERDR_SERVER_NAME=multi-agent-mux`)에서 실행 시 `test_resume_resolve_herdr_workspace_default` 실패 — 이는 **테스트 하네스 env 격리 한계**(test가 `env=` 미전달하여 부모 환경 상속), 코드 결함 아님. `env -u HERDR_SERVER_NAME`로 실행 시 통과 ✅
---
## 6. 잔여 결함
### 6.1 ⚠️ test_resume_resolve_herdr_workspace_default env 격리 부족 (LOW, 본 수정 외)
- 테스트가 `run_lib_func` 호출 시 `env=` 미전달 → 부모 shell의 `HERDR_SERVER_NAME` 상속
- 격리 herdr 세션 내에서 pytest 실행 시 실패(환경 artifact)
- **영향**: 본 delegate-job 수정과 무관, 기존 테스트 하네스 한계. CI(깨끗한 env)에서는 통과
- **심각도**: LOW — 테스트 격로 보강 권장(`env={}` 명시 또는 `monkeypatch.delenv`)
### 6.2 ️ 주석 "tmux-compat shim" (INFO)
- 라인 27 주석 "turns plain `herdr` into the tmux-compat shim" — tmux 호환성 레퍼런스는 의도된 설명(실제 shim이 tmux 문법을 herdr로 번역)
- **심각도**: INFO — 유지
---
## 7. 종합 평가
### 버그 3건 수정 품질
1.**버그 1 (source 순서)**: lib.sh를 라인 31로 조기 이동 — has-session이 shim 경유 `agent get`으로 정상 동작. run_agent보다 377줄 선행, 다른 함수와 충돌 없음
2.**버그 2 (HERDR_SERVER_NAME 자동 해석)**: `resolve_herdr_workspace` 자동 호출 — 형제 스킬(resume/stop)과 동일 패턴, 비격리(default) 회귀 없음, 격리 세션 정상 해석
3.**버그 3 (session attach → agent attach)**: 실제 herdr v0.7.4 도움말로 `agent attach <target>` 존재 확인 — 에이전트 이름 전달 정확, `session attach`는 서버 단위로 부적절
### 검증 관점 충족
- **(a) herdr CLI 문법**: has-session(shim `agent get` 번역), agent attach(실제 서브커맨드), session attach(서버 단위 구분) — 모두 실제 도움말로 확인 ✅
- **(b) source 순서 충돌**: 라인 31 조기 source, run_agent(408) 선행, 중복 source 없음, 다른 함수 충돌 없음 ✅
- **(c) 비격리 회귀**: resolve_herdr_workspace가 default fallback, 55개 테스트(깨끗한 env) 통과, 형제 스킬 일관성 ✅
### 잔여 결함 (본 수정 외, LOW/INFO)
- LOW 6.1: test env 격리 부족 (본 수정 무관, CI 통과)
- INFO 6.2: "tmux-compat shim" 주석 (의도된 설명)
### 판정 근거
3건 버그 수정 모두 실제 herdr v0.7.4 CLI 문법과 정확히 일치(has-session/agent attach/session attach 도움말 직접 확인). source 순서 변경은 run_agent 선행 보장 + 다른 함수 충돌 없음. HERDR_SERVER_NAME 자동 해석은 형제 스킬과 동일 패턴으로 일관성 확보 + 비격리 회귀 없음. 정적 분석 통과, 55개 테스트(깨끗한 환경) 통과. 잔여 결함은 본 수정 외 LOW/INFO로 BLOCKING 아님. 설계 변경/재작업 불필요. PASS.
[VERDICT: PASS]