5 Commits
9 changed files with 609 additions and 9 deletions
+59
View File
@@ -0,0 +1,59 @@
# 📘 herdr_docs.md: Herdr 공식 문서 사이드맵 및 문서 구조 레퍼런스
이 문서는 AI 에이전트 인지형 멀티플렉서인 **herdr**의 공식 문서 구조 및 핵심 경로 링크들을 정리한 참고서입니다. 개발 과정 및 스킬 설계 시 참조용 사양으로 활용합니다.
---
## 🔗 Herdr 공식 문서 사이트 구조
공식 홈페이지 및 메인 설명: **[herdr.dev](https://herdr.dev)**
### 1. 🚀 시작하기 (Start here)
* **Overview (개요)**: [herdr.dev/docs/](https://herdr.dev/docs/)
* Herdr의 도입 목적 및 핵심 철학
* **Install (설치 방법)**: [herdr.dev/docs/install/](https://herdr.dev/docs/install/)
* 시스템 요구사항 및 바이너리 설치 스크립트 제공
* **Quick start (빠른 시작)**: [herdr.dev/docs/quick-start/](https://herdr.dev/docs/quick-start/)
* 기본 워크스페이스 생성 및 에이전트 실행 예시
* **Concepts (핵심 개념)**: [herdr.dev/docs/concepts/](https://herdr.dev/docs/concepts/)
* 에이전트 인지식 터미널 구조, Pane, Tab, Workspace 관계
* **Keyboard (키보드 단축키)**: [herdr.dev/docs/keyboard/](https://herdr.dev/docs/keyboard/)
* 멀티플렉서 제어를 위한 주요 기본 단축키 목록
### 2. 🤖 Herdr 실무 활용 (Using Herdr)
* **How to work with Herdr (작업 워크플로우)**: [herdr.dev/docs/how-to-work/](https://herdr.dev/docs/how-to-work/)
* 개발자와 에이전트 간의 화면 분할 및 협업 모범 사례
* **Agents (에이전트 제어)**: [herdr.dev/docs/agents/](https://herdr.dev/docs/agents/)
* Claude Code, Cline, Agy 등 주요 코딩 에이전트 실행 및 연동 규칙
* **Session state and restore (세션 상태 및 복원)**: [herdr.dev/docs/session-state/](https://herdr.dev/docs/session-state/)
* 호스트 리부팅 및 연결 유실 시 대화 상태 원자적 백업 및 복원
* **Persistence and remote access (영속성 및 원격 접속)**: [herdr.dev/docs/persistence-remote/](https://herdr.dev/docs/persistence-remote/)
* 백그라운드 영속 구동 및 원격 터미널에서의 Attach 방법
### 3. ⚙️ 설정 가이드 (Configure)
* **Configuration (설정 기초)**: [herdr.dev/docs/configuration/](https://herdr.dev/docs/configuration/)
* 사용자 프로필 설정 및 환경 변수 연동
* **Config reference (설정 참조)**: [herdr.dev/docs/config-reference/](https://herdr.dev/docs/config-reference/)
* `config.toml` 구조 및 전역 키 맵 변경 스펙
* **Plugins (플러그인)**: [herdr.dev/docs/plugins/](https://herdr.dev/docs/plugins/)
* Herdr 확장용 플러그인 사양 및 연동
* **Marketplace (마켓플레이스)**: [herdr.dev/docs/marketplace/](https://herdr.dev/docs/marketplace/)
* 커뮤니티 플러그인 공유 및 다운로드
### 4. 📚 레퍼런스 및 사양 (Reference)
* **CLI reference (명령어 참조)**: [herdr.dev/docs/cli-reference/](https://herdr.dev/docs/cli-reference/)
* `herdr run`, `herdr capture`, `herdr kill` 등 CLI 인자 설명
* **Socket API (소켓 API)**: [herdr.dev/docs/socket-api/](https://herdr.dev/docs/socket-api/)
* 프로그래밍 방식으로 창 분할, 입력 전송, 상태 조회를 수행하기 위한 로컬 Unix 소켓 규격
* **Integrations (외부 연동)**: [herdr.dev/docs/integrations/](https://herdr.dev/docs/integrations/)
* CI/CD 환경 및 외부 IDE 어댑터 연동 방안
* **Agent skill file (에이전트 스킬 파일)**: [herdr.dev/docs/agent-skill/](https://herdr.dev/docs/agent-skill/)
* 에이전트가 자체적으로 Herdr 환경을 진단할 때 읽는 규칙 정의
* **Windows beta (윈도우 베타)**: [herdr.dev/docs/windows-beta/](https://herdr.dev/docs/windows-beta/)
* Windows 환경 구동 현황 및 제약 사항
### 5. 🚑 문제 해결 및 기타 (Help)
* **Troubleshooting (문제 해결)**: [herdr.dev/docs/troubleshooting/](https://herdr.dev/docs/troubleshooting/)
* 인증 실패, PTY 블로킹, 세션 크래시 자가 진단 및 대처법
* **Preview docs (프리뷰 문서)**: [herdr.dev/docs/preview/](https://herdr.dev/docs/preview/)
* 차기 업데이트 예정 기능 문서
@@ -0,0 +1,46 @@
# 리뷰 리포트 — Job 20a83d73
- **리뷰 대상**: 커밋 `f79fd99``create_session.sh` / `resume_session.sh`에 에이전트 바이너리 절대 경로 해석(`command -v`) 및 macOS 격리 속성 해제(`xattr -d com.apple.quarantine`) 추가로 macOS 타임아웃 오류 수정
- **리뷰어**: claude (planner-reviewer)
- **리뷰 방식**: 정적 분석(bash -n, shellcheck 기준선 대비) + 격리 tmux 서버에서의 실제 실행 재현 검증
## 1. 설계 타당성 — 실행으로 검증함
macOS에서의 실제 고장 메커니즘은 "tmux 서버가 축소된 PATH로 기동 → pane에서 `claude`/`agy` 미발견 → pane 즉사 → `wait_for_tui_ready` 타임아웃"이다. 이 메커니즘과 수정 효과를 Linux에서 격리 tmux 서버(`-L mam_rev_20a83d73`, `env -i PATH=/usr/bin:/bin`)로 직접 재현했다:
- **Case A (수정 전 시나리오)**: PATH 밖의 가짜 에이전트를 bare name으로 `new-session`**pane 즉사 확인** (타임아웃 전조 재현 성공).
- **Case B (수정 후 시나리오)**: 동일 조건에서 절대 경로로 `new-session`**세션 생존 + 에이전트 실제 실행 확인** (마커 파일 기록됨).
호출 스크립트(전체 PATH 보유) 시점에 `command -v`로 해석해 절대 경로를 명령 문자열에 굽는 설계는 이 문제의 정확한 해법이다. Gatekeeper quarantine 해제도 macOS 최초 실행 지연/행에 대한 합리적 보완책이다(Darwin 전용 가드로 Linux 무영향).
## 2. 정적 분석
- `bash -n` 양 파일 통과.
- `shellcheck -S warning`: 변경 전 기준선(31ca11c 시점 파일을 추출해 비교) 대비 **신규 경고 0건**. `resume_session.sh:40`의 SC2155 1건은 이번 diff와 무관한 기존 경고로 변화 없음.
## 3. 동작성 검증 (실행 기반)
- **해석 스니펫 단독 실행**: PATH에 있는 `claude``/home/godopu16/.local/bin/claude`로 정상 해석. PATH에 없는 이름 → bare name으로 안전한 폴백, `set -euo pipefail` 하에서 exit 0 (조건문 내 `command -v` 실패가 set -e를 트립하지 않음을 실측).
- **실제 스크립트 스모크**: `create_session.sh --dry-run`(실제 claude 에이전트, 격리 서버명 지정)으로 신규 블록 포함 전체 경로가 exit 0으로 통과 — 부수효과 없이 CMD_FULL 확정 지점까지 실행됨.
- **xattr 안전성**: Darwin 가드로 Linux에서 완전 스킵. macOS에서 `xattr` 부재/실패 시에도 `2>/dev/null || true` 패턴이 `set -e`를 트립하지 않음을 동형 재현으로 확인. `[ -f "$RESOLVED_BIN" ]` 가드 덕에 미해석(bare name) 상태에서는 실행 자체가 스킵됨.
## 4. 유실 검사
- 4개 에이전트(claude/agy/hermes/cline)의 플래그(`--dangerously-skip-permissions`, `-i`, `-r/--conversation/--resume/--id $UUID`) 및 `ISO_ENV_PREFIX`/`ISO_CMD_ARGS` 배치가 변경 전과 전부 동일하게 보존됨. cline이 env prefix를 받지 않는 기존 비대칭도 그대로 유지(회귀 없음).
- claude wrapper 경로(비격리 시 `~/.local/bin/<session>` 우선)는 양 스크립트 모두 변경되지 않음.
- 다운스트림 영향: drift 클래스 AD(reconcile.sh)와 status.sh는 `cmd_full`/`start_command`를 비교 로직에 사용하지 않고 표시용으로만 전달함을 확인 — 절대 경로가 들어가도 오탐 없음.
## 5. 비차단(Non-blocking) 지적 사항
1. **경로 내 공백 취약**`RESOLVED_BIN`이 공백 포함 경로로 해석되면 CMD_FULL이 깨짐을 격리 tmux에서 실측으로 확인(pane 즉사). 다만 대상 CLI들의 표준 설치 경로(`/opt/homebrew/bin`, `~/.local/bin`, npm global 등)에는 공백이 없고 macOS 홈 디렉터리 short name에도 공백이 없어 실사용 확률은 낮음. 후속 개선 시 `printf %q` 또는 인용 부호 처리를 권장(단, resume 쪽 `eval` 이중 해석 계층 고려 필요).
2. **중복 분기**`cline` 분기와 else 분기가 기능적으로 완전 동일(`command -v cline` == `command -v "$AGENT"` when AGENT=cline). 동작 문제는 없으나 단순화 여지 있음(양 파일 공통).
3. **resume 후 메타데이터 불일치(외관상)**`update_yaml_resumed.sh`가 resume 후 `cmd_full`을 bare name 형태로 되써서, 실제 pane은 절대 경로로 실행됐는데 YAML 기록은 bare name이 됨. 비교 로직에 쓰이지 않는 표시 전용 필드라 실해는 없음.
4. **macOS 실기기 미검증** — 본 리뷰 환경은 Linux이므로 `xattr` 실효(quarantine 속성 실제 제거) 자체는 실측 불가. 가드/에러 억제 로직의 안전성은 동형 재현으로 확인했고, 명령·플래그는 표준 macOS 관행과 일치함.
참고: 리뷰 중 발견된 저장소 내 `multi-agent-mux-delegate-job.27194_12342.tmp` 파일은 고아 파일이 아니라 **본 job(20a83d73)을 디스패치 중인 살아있는 delegate_job_safe 임시 사본**(PID 확인됨)으로, 직전 라운드에서 검증한 trap 정리 대상이다. 결함 아님.
## 6. 결론
수정의 핵심 메커니즘(절대 경로 baking)이 재현 실험으로 실효성이 입증되었고, 기존 동작 유실·신규 경고·다운스트림 회귀가 전무하다. 비차단 지적 4건은 모두 후속 개선 수준이며 설계 재작업이 필요한 사항은 없다.
[VERDICT: PASS]
@@ -0,0 +1,41 @@
# 리뷰 리포트 — Job dbab0e07
- **리뷰 대상**: 커밋 `36b3910` — (1) `create_session.sh` agy 인증 사전검증을 파일 기반으로 우회해 macOS 키체인 접근 Hang 방지, (2) `lib.sh provision_isolation()`에 Darwin 전용 `~/Library/Keychains` 심링크 시딩 추가로 격리 모드 인증 토큰 소실 해결
- **리뷰어**: claude (planner-reviewer)
- **리뷰 방식**: 정적 분석(bash -n, shellcheck 기준선 대비) + 계측 스텁/가짜 HOME/uname 오버라이드 기반 실행 검증
## 1. 설계 타당성
- **Hang 우회**: agy 격리 lever가 `HOME=<root>`이고(lib.sh 주석의 Phase 0 실측 매트릭스), macOS에서 `agy models`가 키체인 접근 프롬프트로 비대화식 환경에서 블로킹되는 문제를, 디스크상 토큰 파일(`~/.gemini/oauth_creds.json` 또는 `~/.gemini/antigravity-cli/antigravity-oauth-token`) 존재 시 CLI 호출 자체를 생략하는 방식으로 회피 — 검사 파일 경로 2개가 `provision_isolation()`이 agy 자격증명으로 시딩하는 파일 목록과 정확히 일치함(저장소 내부 지식과 정합).
- **토큰 소실 해결**: 격리 시 `HOME=<root>`로 바뀌면 macOS 키체인 경로(`$HOME/Library/Keychains`)가 빈 격리 홈을 가리켜 자격증명 조회가 실패하는 구조 — 실제 Keychains 디렉터리를 심링크로 시딩하는 것은 이 파일의 기존 철학("auth/config files are SYMLINKED ... never copied — token refresh must converge on the real files")과 일치하는 올바른 해법.
## 2. 실행 검증 (전부 실측)
- **사전검증 우회(Case A)**: 가짜 HOME에 토큰 파일 배치 + 호출 기록 스텁 `agy`를 PATH 선두에 두고 `create_session.sh --dry-run --agent agy` 실행 → **`agy` 바이너리가 단 한 번도 실행되지 않음**(Hang 원인 원천 제거 확인), exit 0.
- **폴백 보존(Case B)**: 토큰 파일 없는 빈 HOME → `agy models`가 정확히 1회 호출되고 스텁 실패 시 기존 오류 메시지("agy is not authenticated")와 exit 1이 그대로 동작 — 미인증 조기 차단 시맨틱 유실 없음.
- **Keychains 시딩**: lib.sh를 소싱한 격리 하네스에서 `uname`을 Darwin으로 오버라이드하고 가짜 HOME(`Library/Keychains/login.keychain-db` 포함)으로 `provision_isolation agy` 실행 →
- 심링크 정상 생성, 격리 홈 경유 read-through로 실제 키체인 데이터 접근 확인.
- `seeded` 출력에 `Library/Keychains`가 기존 포맷대로 병합됨.
- **재프로비저닝 멱등성**: 2회 실행에도 `ln -sfn``-n` 덕에 중첩 링크(`Keychains/Keychains`) 없이 동일 결과.
- **🔑 삭제 안전성(최중요)**: create rollback의 `rm -rf "$ISOLATION_ROOT"` 시뮬레이션 → **심링크만 제거되고 실제 키체인 파일은 온전히 생존**함을 실측 확인(rm -rf는 심링크를 따라 들어가지 않음). `seeded` 목록을 순회하며 삭제하는 소비자는 코드베이스에 존재하지 않음(생성·기록 전용)도 grep으로 확인.
## 3. 정적 분석
- `bash -n` 양 파일 통과. `shellcheck -S warning`: 변경 전 기준선(fc24af4) 대비 양 파일 모두 **경고 0건 → 0건, 신규 경고 없음**.
## 4. 유실 검사
- agy 외 에이전트(claude/cline/hermes)의 provision 분기·사전검증 분기는 바이트 단위로 무변경. Darwin 가드로 Linux에서 Keychains 시딩 완전 스킵(Linux 회귀 없음).
## 5. 비차단(Non-blocking) 지적 사항
1. **사전검증 약화** — 파일 존재가 토큰 유효성을 보증하지 않으므로, 만료/폐기된 토큰은 이제 preflight를 통과하고 TUI 기동 단계에서야 실패가 드러남. Hang 대비 합리적 트레이드오프이나 오류 표면화 시점이 늦어짐.
2. **Darwin 미게이팅** — 우회 분기가 OS 무관하게 적용되어, Hang이 없던 Linux에서도 엄격 검사가 생략됨(부수적으로 네트워크 호출 생략이라 빨라지는 이점은 있음). 엄격성이 중요해지면 `uname` 게이트 추가 고려.
3. **자격증명 격리 부재(의도된 설계)** — 격리 세션이 실제 키체인을 공유하게 되나, 시딩의 목적 자체가 인증 공유이므로 기존 심링크 시딩 철학과 일치. 기록 차원의 언급.
4. **macOS 실기기 미검증** — Security.framework가 심링크된 `$HOME/Library/Keychains`를 실제로 수용하는지는 Linux 환경에서 실측 불가. 메커니즘 수준(경로 해석·링크·멱등성·삭제 안전성)은 전부 검증 완료.
## 6. 결론
두 수정 모두 고장 메커니즘을 정확히 겨냥했고, 우회·폴백·시딩·멱등성·삭제 안전성이 전부 실행으로 입증되었으며 정적 분석 신규 경고와 기존 동작 유실이 없다. 비차단 4건은 후속 개선/기록 수준이다.
[VERDICT: PASS]
@@ -0,0 +1,162 @@
# ✅ Peer Review Report: macOS 키체인 Hang 우회 및 격리 모드 인증 토큰 소실 수정 (Job 14943484)
**Job**: `14943484` · **Reviewer**: Reviewer B (Cline, `canary-projects-multi-agent-mux-reviewer-cline`)
**Review Target**: 커밋 `36b3910` "fix(mac-compat): bypass keyring auth check hang and link macOS Library/Keychains to isolated home"
**Files Changed**: `lib.sh` (+8/-0), `create_session.sh` (+4/-1) — 2 files, 12 insertions, 1 deletion
**Review Scope**: 작업 목표 "create_session.sh 및 lib.sh에서 macOS 키체인(keyring) 접근 차단으로 인한 비대화식 Hang 현상과 격리 모드(--isolate) 시 인증 토큰 소실 문제를 각각 파일 기반 사전 검증 우회 및 Library/Keychains 폴더 링크 추가를 통해 해결" — 린트, 동작성, 유실 관점 교차 리뷰
**Method**: 커밋 diff 분석 + `bash -n`/`shellcheck` 정적 분석 + 인증 바이패스 로직 4케이스 검증 + Darwin 가드 검증 + 경로 일치성 확인 + seeded 패턴 일관성 확인 + 타 agent keychain 필요성 분석
---
## 1. 변경 사항 개요
### 1.1 파일 기반 사전 검증 우회 (create_session.sh 라인 92-98)
```diff
elif [ "$AGENT" = "agy" ]; then
- if ! agy models >/dev/null 2>&1; then
+ # Fast, non-blocking check: if token or credentials exist on disk, assume authenticated to prevent keyring hang
+ if [ -f "$HOME/.gemini/oauth_creds.json" ] || [ -f "$HOME/.gemini/antigravity-cli/antigravity-oauth-token" ]; then
+ true
+ elif ! agy models >/dev/null 2>&1; then
echo "ERROR: agy is not authenticated. Please log in first." >&2
exit 1
fi
```
**목적**: `agy models` 명령이 macOS에서 키체인 접근 시 비대화식 Hang 유발. 토큰/자격증명 파일 존재 시 파일 기반으로 인증 가정하여 Hang 우회.
### 1.2 Library/Keychains 폴더 링크 추가 (lib.sh 라인 841-848)
```diff
+ # On macOS, seed ~/Library/Keychains to allow isolated agy to query Keychain Access credentials
+ if [ "$(uname)" = "Darwin" ]; then
+ mkdir -p "$root/Library"
+ if [ -d "$HOME/Library/Keychains" ]; then
+ ln -sfn "$HOME/Library/Keychains" "$root/Library/Keychains"
+ seeded="${seeded:+$seeded,}Library/Keychains"
+ fi
+ fi
```
**목적**: `--isolate` 모드 시 격리된 홈 디렉토리에 `~/Library/Keychains` 심볼릭 링크 추가 → 격리 agy가 Keychain Access 자격증명 조회 가능.
---
## 2. 작업 목표 달성도
| 목표 | 상태 | 확인 |
|------|------|------|
| macOS 키체인 Hang 우회 (파일 기반 사전 검증) | ✅ | 토큰 파일 존재 시 `agy models` 스킵 |
| 격리 모드 인증 토큰 소실 해결 (Keychains 링크) | ✅ | Darwin 가드 + Library/Keychains 심볼릭 링크 |
| create_session.sh 적용 | ✅ | 라인 92-98 |
| lib.sh 적용 | ✅ | 라인 841-848 (agy case) |
---
## 3. 정적 분석
| 파일 | bash -n | shellcheck | 비고 |
|------|---------|------------|------|
| lib.sh | ✅ SYNTAX OK | ✅ 경고 없음 (clean) | 본 diff 새 경고 0건 |
| create_session.sh | ✅ SYNTAX OK | SC1091 (info, 기존 source) — **본 diff 새 경고 없음** | EXIT 1 (기존) |
---
## 4. 동작성 검증
### 4.1 ✅ 인증 바이패스 로직 4케이스 검증
| 케이스 | 조건 | 결과 | 판정 |
|--------|------|------|------|
| 1 | `antigravity-oauth-token` 파일 존재 | BYPASS (token found) | ✅ Hang 우회 |
| 2 | `oauth_creds.json` 파일 존재 | BYPASS (oauth_creds found) | ✅ Hang 우회 |
| 3 | 파일 없음 + agy models 실패 | ERROR (not authenticated) | ✅ 정상 에러 |
| 4 | 파일 없음 + agy models 성공 | PASS (agy models succeeded) | ✅ 정상 통과 |
**검증**: 파일 존재 시 `agy models` 호출 스킵 → macOS 키체인 Hang 방지. 파일 부재 시 기존 `agy models` 체크 유지 → 미인증 감지.
### 4.2 ✅ Darwin 가드 검증 (Keychains 링크)
| 조건 | 결과 | 판정 |
|------|------|------|
| `uname` = Linux | Darwin 체크 실패 → 블록 스킵 | ✅ Linux에서 Keychains 링크 미생성 |
| `uname` = Darwin + `~/Library/Keychains` 존재 | `mkdir -p $root/Library` + `ln -sfn` 실행 | ✅ macOS에서 심볼릭 링크 생성 |
| `uname` = Darwin + `~/Library/Keychains` 부재 | `[ -d ]` 실패 → 링크 미생성 | ✅ graceful (seeded 미추가) |
### 4.3 ✅ 경로 일치성 (auth check vs provisioning)
| 파일 | create_session.sh 체크 경로 | lib.sh provisioning 경로 | 일치 |
|------|---------------------------|-------------------------|------|
| oauth_creds.json | `$HOME/.gemini/oauth_creds.json` | `$HOME/.gemini/oauth_creds.json` (라인 835) | ✅ |
| antigravity-oauth-token | `$HOME/.gemini/antigravity-cli/antigravity-oauth-token` | `$HOME/.gemini/antigravity-cli/antigravity-oauth-token` (라인 838) | ✅ |
인증 체크 파일과 격리 provisioning 파일 경로가 완전 일치 → 일관성 확보.
### 4.4 ✅ seeded 패턴 일관성
`seeded="${seeded:+$seeded,}Library/Keychains"` (라인 846) — 기존 패턴(라인 836, 839, 853)과 동일한 `${seeded:+$seeded,}` 누적 패턴. 일관성 확보 ✅
### 4.5 ✅ 타 agent keychain 필요성 분석
| Agent | 인증 방식 | Keychain 필요 | Keychains 링크 적용 |
|-------|----------|---------------|---------------------|
| claude | `.credentials.json` 파일 기반 | 아니오 | 불필요 (맞음) |
| cline | 파일 기반 settings + DB | 아니오 | 불필요 (맞음) |
| agy | macOS Keychain Access | **예** | **적용됨** ✅ |
| hermes | `auth.json` 파일 기반 | 아니오 | 불필요 (맞음) |
Keychains 링크가 agy case에만 추가된 것은 **정확한 타겟팅** — agy만 macOS Keychain 사용, 타 agent는 파일 기반 인증.
### 4.6 ✅ true 문 유효성
`if` 블록 본문으로 `true` 사용 — bash에서 유효 (no-op). `if true; then true; fi` 검증 통과. 의도: 파일 존재 시 아무 동작 없이 통과(바이패스).
---
## 5. 잔여 결함 (LOW — INFORMATIONAL)
### 5.1 ⚠️ 만료된 토큰 시 false positive 가능성 (LOW, 설계 트레이드오프)
**위치**: create_session.sh 라인 93
**분석**: 토큰 파일이 존재하지만 **만료/무효**한 경우, 바이패스가 `agy models` 체크를 스킵하여 세션 시작 → agy 실행 시 인증 실패 가능.
**평가**: 의도적 트레이드오프 — 원 문제는 **Hang**(무한 대기)이며, 만료 토큰으로 인한 후속 실패는 Hang보다 나음(진단 가능). 주석(라인 92)이 의도 명시.
**심각도**: LOW — BLOCKING 아님. 설계 결정으로 수용 가능.
### 5.2 ️ 작업 트리 잔여 .tmp 파일 (INFO, unrelated)
**위치**: `.agents/skills/multi-agent-mux-delegate-job/multi-agent-mux-delegate-job.14657_36745.tmp` (untracked)
**분석**: 이전 delegate_job_safe 실행 잔여물. 본 diff와 무관. 무해하지만 정리 권장.
**심각도**: INFO — 본 리뷰 범위 외.
---
## 6. 종합 평가
### 작업 목표 달성도
"create_session.sh 및 lib.sh에서 macOS 키체인(keyring) 접근 차단으로 인한 비대화식 Hang 현상과 격리 모드(--isolate) 시 인증 토큰 소실 문제를 각각 파일 기반 사전 검증 우회 및 Library/Keychains 폴더 링크 추가를 통해 해결" — **달성**.
### 변경 품질
1.**파일 기반 Hang 우회**: 토큰/자격증명 파일 존재 시 `agy models` 스킵 — 4케이스 검증 모두 PASS
2.**Keychains 심볼릭 링크**: Darwin 가드 + `[ -d ]` 존재 확인 + `ln -sfn` — 안전한 조건부 생성
3.**경로 일치성**: auth check 파일과 provisioning 파일 경로 완전 일치
4.**타겟팅 정확**: agy case에만 Keychains 링크 추가 — 타 agent는 파일 기반 인증으로 불필요
5.**seeded 패턴 일관**: 기존 누적 패턴과 동일
6.**Darwin 가드**: Linux에서 미실행, macOS에서만 동작
### 검증 결과
- 정적 분석: `bash -n` 2/2 OK, `shellcheck` 본 diff 새 경고 없음 (lib.sh clean, create SC1091 기존만) ✅
- 인증 바이패스: 4케이스(토큰 존재/ oauth_creds 존재/ 파일 없음+실패/ 파일 없음+성공) 모두 PASS ✅
- Darwin 가드: Linux 스킵 확인 ✅
- 경로 일치성: auth check ↔ provisioning 완전 일치 ✅
- seeded 일관성: 기존 패턴과 동일 ✅
- 타 agent 분석: agy만 Keychain 사용, 타겟팅 정확 ✅
### 잔여 LOW 1건 + INFO 1건
- LOW 5.1: 만료 토큰 false positive — 의도적 트레이드오프 (Hang > 후속 실패), 주석 명시
- INFO 5.2: 잔여 .tmp 파일 (본 diff 무관)
### 판정 근거
작업 목표(키체인 Hang 우회 + 격리 토큰 소실 해결) 완전 달성. 파일 기반 바이패스 4케이스 검증 PASS, Darwin 가드 동작 확인, 경로 일치성 확보, agy 타겟팅 정확. 정적 분석 통과. 잔여 LOW 1건은 의도적 설계 트레이드오프(Hang 방지가 만료 토큰 후속 실패보다 우선). 주 개발자가 macOS 키체인 문제를 정확히 진단하고 파일 기반 우회 + Keychains 링크로 해결했으므로 PASS 판정이 타당.
[VERDICT: PASS]
@@ -0,0 +1,172 @@
# ✅ Peer Review Report: macOS 타임아웃 오류 수정 — 절대 경로 분석 및 quarantine 해제 (Job e81e70d6)
**Job**: `e81e70d6` · **Reviewer**: Reviewer B (Cline, `canary-projects-multi-agent-mux-reviewer-cline`)
**Review Target**: 커밋 `f79fd99` "fix(mac-compat): resolve absolute path of agent binary and strip macos quarantine attribute to prevent gatekeeper and path-resolution timeouts"
**Files Changed**: `create_session.sh` (+18/-4), `resume_session.sh` (+17/-4) — 2 files, 43 insertions, 8 deletions
**Review Scope**: 작업 목표 "create_session.sh 및 resume_session.sh에서 에이전트 실행 시 절대 경로 분석(command -v)과 macOS 격리 해제(xattr) 처리로 macOS 타임아웃 오류를 수정" — 린트, 동작성, 유실 관점 교차 리뷰
**Method**: 커밋 diff 분석 + `bash -n`/`shellcheck` 정적 분석 + `command -v` 해상도 검증 + Darwin/xattr 가드 검증 + 양 파일 블록 일치성 비교 + 사전 패턴 회귀 확인 + cline 특수 케이스 중복성 검증
---
## 1. 변경 사항 개요
### 1.1 절대 경로 분석 (command -v)
두 파일 모두 동일한 블록 추가:
```bash
RESOLVED_BIN="$AGENT"
if [ "$AGENT" = "cline" ]; then
if command -v cline >/dev/null 2>&1; then
RESOLVED_BIN="$(command -v cline)"
fi
else
if command -v "$AGENT" >/dev/null 2>&1; then
RESOLVED_BIN="$(command -v "$AGENT")"
fi
fi
```
**목적**: tmux 세션 spawn 시 PATH 상속 문제 방지. `command -v`로 절대 경로 해상 → tmux가 올바른 바이너리 실행.
### 1.2 macOS quarantine 속성 제거 (xattr)
```bash
if [ "$(uname)" = "Darwin" ] && [ -f "$RESOLVED_BIN" ]; then
xattr -d com.apple.quarantine "$RESOLVED_BIN" 2>/dev/null || true
fi
```
**목적**: macOS Gatekeeper가 quarantine 속성으로 인해 바이너리 실행 시 확인 대화상자 표시 → 타임아웃 발생. `xattr -d`로 속성 제거.
### 1.3 case 문 RESOLVED_BIN 적용
모든 agent 케이스(claude/agy/hermes/cline)의 `CMD_FULL`에서 bare 이름 → `${RESOLVED_BIN}` 교체.
---
## 2. 작업 목표 달성도
| 목표 | 상태 | 확인 |
|------|------|------|
| 절대 경로 분석 (command -v) | ✅ | 두 파일 모두 RESOLVED_BIN 블록 추가 |
| macOS 격리 해제 (xattr) | ✅ | Darwin 가드 + xattr -d com.apple.quarantine |
| macOS 타임아웃 오류 수정 | ✅ | PATH 해상 + Gatekeeper 방지로 근원 해결 |
| create_session.sh 적용 | ✅ | 라인 152-174 |
| resume_session.sh 적용 | ✅ | 라인 90-113 |
---
## 3. 정적 분석
| 파일 | bash -n | shellcheck | 비고 |
|------|---------|------------|------|
| create_session.sh | ✅ SYNTAX OK | SC1091 (info, 기존 source) — **본 diff 새 경고 없음** | EXIT 1 (기존) |
| resume_session.sh | ✅ SYNTAX OK | SC1091 (info, 기존), SC2155 (warning, 라인 40, 기존) — **본 diff 새 경고 없음** | EXIT 1 (기존) |
`shellcheck -x`(source follow)에서도 본 diff 관련 새 경고 없음 ✅
---
## 4. 동작성 검증
### 4.1 ✅ command -v 해상도 검증
| 조건 | 결과 | 판정 |
|------|------|------|
| agent 바이너리 PATH에 있음 | `command -v` → 절대 경로 | ✅ 정상 (예: `/home/godopu16/.npm-global/bin/cline`) |
| agent 바이너리 PATH에 없음 | `command -v` 실패 → `RESOLVED_BIN` stays as `$AGENT` | ✅ graceful fallback |
| Linux 환경 | 모든 agent NOT FOUND → fallback | ✅ 정상 동작 |
### 4.2 ✅ Darwin/xattr 가드 검증
| 조건 | 결과 | 판정 |
|------|------|------|
| `uname` = Linux | Darwin 체크 실패 → xattr 블록 스킵 | ✅ Linux에서 xattr 미호출 |
| `uname` = Darwin + 파일 존재 | `xattr -d com.apple.quarantine` 실행 | ✅ macOS에서 quarantine 제거 |
| `uname` = Darwin + quarantine 없음 | `xattr -d` 실패 → `\|\| true`로 무시 | ✅ graceful |
| `RESOLVED_BIN` = bare 이름(해상 실패) | `[ -f "$RESOLVED_BIN" ]` 실패 → xattr 스킵 | ✅ 파일이 아닌 경우 안전 |
### 4.3 ✅ 양 파일 블록 일치성
`RESOLVED_BIN` 해상 블록 + `xattr` 블록이 create_session.sh(라인 152-167)와 resume_session.sh(라인 90-105)에서 **byte-identical** ✅. `diff`로 확인 — IDENTICAL.
### 4.4 ✅ 사전 패턴 회귀 확인
- `cline` case의 `ISO_ENV_PREFIX` 누락: **사전 패턴** (원본 `cline -i...``ISO_ENV_PREFIX` 없음). 본 diff는 `cline``${RESOLVED_BIN}`만 교체, 패턴 유지. 회귀 아님 ✅
- `case` 문의 `CMD_FULL` 구조: bare 이름 → `${RESOLVED_BIN}` 교체만, 나머지 인자/플래그 동일 ✅
- auth check(라인 86-102)는 bare 이름 사용: `RESOLVED_BIN` 블록 **이전** pre-flight 검사이므로 PATH 기반 조회가 적절. 본 diff 범위 외 ✅
### 4.5 ✅ spawn 경로 모두 CMD_FULL 사용
- create_session.sh spawn(): claude(라인 184), agy|hermes|cline(라인 188) 모두 `"$CMD_FULL"` 사용 → `RESOLVED_BIN` 반영 ✅
- resume_session.sh: claude wrapper 경로(라인 127)는 사전 패턴(하드코딩 wrapper), else(라인 129) + agy|hermes|cline(라인 136)은 `$CMD_FULL``RESOLVED_BIN` 반영 ✅
---
## 5. 잔여 결함 (LOW — INFORMATIONAL)
### 5.1 ⚠️ cline 특수 케이스 중복 (LOW, code smell)
**위치**: 양 파일 라인 154-162
```bash
if [ "$AGENT" = "cline" ]; then
if command -v cline >/dev/null 2>&1; then
RESOLVED_BIN="$(command -v cline)" # hardcode "cline"
fi
else
if command -v "$AGENT" >/dev/null 2>&1; then
RESOLVED_BIN="$(command -v "$AGENT")" # variable "$AGENT"
fi
fi
```
**분석**: `AGENT=cline`일 때 else 브랜치 `command -v "$AGENT"`(= `command -v cline`)와 동일 결과.实证: 두 방법 모두 `/home/godopu16/.npm-global/bin/cline` 반환 → **IDENTICAL**.
**평가**: 특수 케이스가 기능적으로 중복. else 브랜치만으로 충분. 단, 버그 아님 — 올바르게 동작함. 단순 code smell.
**심각도**: LOW — BLOCKING 아님.
**권고**: 향후 `if command -v "$AGENT"` 단일 브랜치로 단순화 고려.
### 5.2 ⚠️ RESOLVED_BIN 경로 내 공백 시 eval 분할 (LOW, theoretical)
**위치**: resume_session.sh 라인 136 `eval "tmux ... \"$CMD_FULL\""`
**분석**: `RESOLVED_BIN`이 공백 포함 경로(예: `/path with spaces/claude`)인 경우, `CMD_FULL` 내 공백이 eval에 의해 단어 분할 → 잘못된 실행.
**현재 영향**: macOS/Linux 표준 설치 경로(`/usr/local/bin`, `/opt/homebrew/bin`, `~/.npm-global/bin`)는 공백 없음. 이론적 가능성만 존재.
**참고**: 사전 패턴 — 원본도 `CMD_FULL="claude --dangerously..."`를 eval로 실행. 본 diff가 도입한 문제 아님.
**심각도**: LOW — 이론적, BLOCKING 아님.
### 5.3 ️ 작업 트리 잔여 .tmp 파일 (INFO, unrelated)
**위치**: `.agents/skills/multi-agent-mux-delegate-job/multi-agent-mux-delegate-job.16035_12342.tmp` (untracked)
**분석**: 이전 delegate_job_safe 실행 잔여물. 본 diff와 무관. 무해하지만 정리 권장.
**심각도**: INFO — 본 리뷰 범위 외.
---
## 6. 종합 평가
### 작업 목표 달성도
"create_session.sh 및 resume_session.sh에서 에이전트 실행 시 절대 경로 분석(command -v)과 macOS 격리 해제(xattr) 처리로 macOS 타임아웃 오류를 수정" — **달성**.
### 변경 품질
1.**절대 경로 해상**: `command -v`로 PATH 상속 문제 해결, graceful fallback(해상 실패 시 bare 이름 유지)
2.**quarantine 제거**: Darwin 가드 + `xattr -d ... || true`로 안전 처리, Linux에서 미실행
3.**양 파일 일치**: RESOLVED_BIN + xattr 블록이 byte-identical — 일관성 확보
4.**사전 패턴 존중**: cline ISO_ENV_PREFIX 누락 등 기존 설계 유지, 회귀 없음
5.**모든 spawn 경로 반영**: create/resume 모든 case에서 `${RESOLVED_BIN}` 적용
### 검증 결과
- 정적 분석: `bash -n` 2/2 OK, `shellcheck` 본 diff 새 경고 없음 ✅
- command -v 해상: 정상(절대 경로) + fallback(bare 이름) 모두 확인 ✅
- Darwin/xattr 가드: Linux 스킵, macOS 실행, quarantine 없음 시 graceful ✅
- 양 파일 일치성: IDENTICAL ✅
- 사전 패턴 회귀: 없음 ✅
### 잔여 LOW 2건 + INFO 1건
- LOW 5.1: cline 특수 케이스 중복 (code smell, 버그 아님)
- LOW 5.2: RESOLVED_BIN 공백 시 eval 분할 (이론적, 사전 패턴)
- INFO 5.3: 잔여 .tmp 파일 (본 diff 무관)
### 판정 근거
작업 목표(절대 경로 분석 + quarantine 해제) 완전 달성. 양 파일에 동일 블록 추가로 일관성 확보. 정적 분석 통과, 동작성 검증(command -v fallback, Darwin 가드, 일치성) 모두 PASS. 사전 패턴 회귀 없음. 잔여 LOW 2건은 모두 BLOCKING 아닌 code smell/이론적 가능성. 주 개발자가 macOS 타임아웃 근원(PATH 해상 + Gatekeeper)을 정확히 진단하고 수정했으므로 PASS 판정이 타당.
[VERDICT: PASS]
+8
View File
@@ -838,6 +838,14 @@ provision_isolation() {
for f in antigravity-oauth-token installation_id settings.json; do for f in antigravity-oauth-token installation_id settings.json; do
if [ -e "$HOME/.gemini/antigravity-cli/$f" ]; then ln -sfn "$HOME/.gemini/antigravity-cli/$f" "$root/.gemini/antigravity-cli/$f"; seeded="${seeded:+$seeded,}.gemini/antigravity-cli/$f"; fi if [ -e "$HOME/.gemini/antigravity-cli/$f" ]; then ln -sfn "$HOME/.gemini/antigravity-cli/$f" "$root/.gemini/antigravity-cli/$f"; seeded="${seeded:+$seeded,}.gemini/antigravity-cli/$f"; fi
done done
# On macOS, seed ~/Library/Keychains to allow isolated agy to query Keychain Access credentials
if [ "$(uname)" = "Darwin" ]; then
mkdir -p "$root/Library"
if [ -d "$HOME/Library/Keychains" ]; then
ln -sfn "$HOME/Library/Keychains" "$root/Library/Keychains"
seeded="${seeded:+$seeded,}Library/Keychains"
fi
fi
;; ;;
hermes) hermes)
mkdir -p "$root/.hermes" mkdir -p "$root/.hermes"
@@ -89,7 +89,10 @@ if [ "$AGENT" = "claude" ]; then
exit 1 exit 1
fi fi
elif [ "$AGENT" = "agy" ]; then elif [ "$AGENT" = "agy" ]; then
if ! agy models >/dev/null 2>&1; then # Fast, non-blocking check: if token or credentials exist on disk, assume authenticated to prevent keyring hang
if [ -f "$HOME/.gemini/oauth_creds.json" ] || [ -f "$HOME/.gemini/antigravity-cli/antigravity-oauth-token" ]; then
true
elif ! agy models >/dev/null 2>&1; then
echo "ERROR: agy is not authenticated. Please log in first." >&2 echo "ERROR: agy is not authenticated. Please log in first." >&2
exit 1 exit 1
fi fi
@@ -148,11 +151,29 @@ if [ -n "$ISOLATION_ROOT" ]; then
ISO_ENV_PREFIX="$(isolation_env_prefix "$AGENT" "$ISOLATION_ROOT")" ISO_ENV_PREFIX="$(isolation_env_prefix "$AGENT" "$ISOLATION_ROOT")"
ISO_CMD_ARGS="$(isolation_cmd_args "$AGENT" "$ISOLATION_ROOT")" ISO_CMD_ARGS="$(isolation_cmd_args "$AGENT" "$ISOLATION_ROOT")"
fi fi
# Resolve absolute path of the agent command to prevent tmux PATH inheritance issues (especially on macOS)
RESOLVED_BIN="$AGENT"
if [ "$AGENT" = "cline" ]; then
if command -v cline >/dev/null 2>&1; then
RESOLVED_BIN="$(command -v cline)"
fi
else
if command -v "$AGENT" >/dev/null 2>&1; then
RESOLVED_BIN="$(command -v "$AGENT")"
fi
fi
# On macOS, clear quarantine attribute for the agent binary to prevent Gatekeeper hangs
if [ "$(uname)" = "Darwin" ] && [ -f "$RESOLVED_BIN" ]; then
xattr -d com.apple.quarantine "$RESOLVED_BIN" 2>/dev/null || true
fi
case "$AGENT" in case "$AGENT" in
claude) CMD_FULL="${ISO_ENV_PREFIX}claude --dangerously-skip-permissions" ;; claude) CMD_FULL="${ISO_ENV_PREFIX}${RESOLVED_BIN} --dangerously-skip-permissions" ;;
agy) CMD_FULL="${ISO_ENV_PREFIX}agy --dangerously-skip-permissions" ;; agy) CMD_FULL="${ISO_ENV_PREFIX}${RESOLVED_BIN} --dangerously-skip-permissions" ;;
hermes) CMD_FULL="${ISO_ENV_PREFIX}hermes" ;; hermes) CMD_FULL="${ISO_ENV_PREFIX}${RESOLVED_BIN}" ;;
cline) CMD_FULL="cline -i${ISO_CMD_ARGS:+ $ISO_CMD_ARGS}" ;; cline) CMD_FULL="${RESOLVED_BIN} -i${ISO_CMD_ARGS:+ $ISO_CMD_ARGS}" ;;
esac esac
spawn() { spawn() {
@@ -87,12 +87,29 @@ if [ -n "$ISO_ROOT" ]; then
echo "Re-applying isolation: root=$ISO_ROOT env=$ISO_ENV args=$ISO_ARGS" echo "Re-applying isolation: root=$ISO_ROOT env=$ISO_ENV args=$ISO_ARGS"
fi fi
# Resolve absolute path of the agent command to prevent tmux PATH inheritance issues (especially on macOS)
RESOLVED_BIN="$AGENT"
if [ "$AGENT" = "cline" ]; then
if command -v cline >/dev/null 2>&1; then
RESOLVED_BIN="$(command -v cline)"
fi
else
if command -v "$AGENT" >/dev/null 2>&1; then
RESOLVED_BIN="$(command -v "$AGENT")"
fi
fi
# On macOS, clear quarantine attribute for the agent binary to prevent Gatekeeper hangs
if [ "$(uname)" = "Darwin" ] && [ -f "$RESOLVED_BIN" ]; then
xattr -d com.apple.quarantine "$RESOLVED_BIN" 2>/dev/null || true
fi
# Determine CMD_FULL with isolation applied # Determine CMD_FULL with isolation applied
case "$AGENT" in case "$AGENT" in
claude) CMD_FULL="claude --dangerously-skip-permissions -r $UUID" ;; claude) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions -r $UUID" ;;
agy) CMD_FULL="agy --dangerously-skip-permissions --conversation $UUID" ;; agy) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions --conversation $UUID" ;;
hermes) CMD_FULL="hermes --resume $UUID" ;; hermes) CMD_FULL="${RESOLVED_BIN} --resume $UUID" ;;
cline) CMD_FULL="cline -i --id $UUID" ;; cline) CMD_FULL="${RESOLVED_BIN} -i --id $UUID" ;;
esac esac
# Prepend env prefix and append command args (T4) # Prepend env prefix and append command args (T4)
+74
View File
@@ -0,0 +1,74 @@
# 📋 PLAN_HERDR.md: herdr 기반 멀티플렉서 백엔드 전환 작업 계획서
이 문서는 기존 `tmux` 기반의 에이전트 라이프사이클 관리를 Rust 기반의 에이전트 인지형 멀티플렉서인 **herdr**로 전면 전환하기 위한 도입 배경, 아키텍처 전략 및 상세 작업 단계들을 정의합니다.
---
## 1. 🔍 도입 배경 및 필요성
현재 운영 중인 `tmux` 기반 백엔드는 훌륭한 호환성을 제공하지만, 다음과 같은 구조적 한계와 간헐적인 프롬프트 유실 오류(Prompt-lock)를 동반합니다.
### 🔴 기존 tmux 환경의 한계
* **대략적인 정적 상태 감지 (Coarse Quiescence)**: 입력을 주입하기 전에 터미널이 키를 수락할 수 있는 휴지 상태인지 확인하기 위해, 셸 스크립트 상에서 `capture-pane`을 0.1~0.5초 주기로 돌려 화면 변경 여부를 체크합니다. 이로 인해 CPU 자원이 급증하는 멀티 에이전트 구동 상황에서 입력을 유실하거나 `Enter` 키가 씹히는 현상이 발생합니다.
* **TUI 모달 상태 기계 파싱의 비효율**: 에이전트가 띄운 다이얼로그(예: 인증, 신뢰 확인)를 인식하기 위해 터미널 하단 20줄의 문자열을 정규식으로 직접 파싱하므로, 에이전트 버전업에 따른 TUI 레이아웃 변경에 매우 취약합니다.
### 🟢 herdr 도입 시 기대 효과
* **PTY 레벨의 밀리초(ms) 단위 이벤트 제어**: `herdr`은 Rust 네이티브로 작성되어 PTY(가상 터미널) 입출력 스트림의 유휴 상태를 서브-밀리초 레벨로 감지합니다. 이로 인해 프롬프트 주입 실패 및 명령 유실 오류가 **근본적으로 제로(0)에 가깝게 줄어듭니다.**
* **에이전트 상태 인지 API**: 에이전트 프로세스의 상태(Working, Idle, Blocked, Done)를 멀티플렉서 레벨에서 해석해 소켓 API로 제공하므로, 지저분한 화면 파싱 코드 없이 정교한 자율 관제가 가능합니다.
---
## 2. 🔀 형상 관리 및 배포 전략
두 백엔드(tmux/herdr)를 단일 코드베이스에서 듀얼 스위칭(`if/else`) 방식으로 지원하면 코드가 과도하게 무거워지고 버그 가능성이 높아집니다. 따라서 **독립된 브랜치 구조**로 깨끗하게 이원화하여 제공합니다.
* **`main` 브랜치 (tmux 기반)**:
* **목표**: 어디서나 즉시 실행 가능한 고호환성 프로덕션 버전.
* **의존성**: 추가 설치가 필요 없는 표준 `tmux` 환경.
* **`herdr` 브랜치 (herdr 기반)**:
* **목표**: 대화식 락 오류가 완벽히 통제되는 워크스테이션(macOS/Linux) 최적화 고안전성 버전.
* **의존성**: `herdr` CLI 및 Unix 소켓 API 환경.
---
## 3. 🎯 상세 구현 마일스톤 및 작업 계획
### 📍 Milestone 1: 개발 환경 구성 및 의존성 진단
* [ ] **브랜치 격리**: `git checkout -b herdr` 브랜치 생성 및 격리 개발 공간 확보.
* [ ] **인스톨러 개정 (`deploy/install_mam.sh`)**:
* 호스트 의존성 체크 대상에 `herdr` 추가 (`tmux` 진단 제거).
* `herdr`이 미설치된 경우, 공식 설치 가이드라인(`https://herdr.dev/install.sh`) 안내 출력 및 조기 종료 처리.
* `.mam/` 격리 폴더 및 환경설정 배포 규칙을 `herdr` 스펙에 맞게 조정.
### 📍 Milestone 2: 로우레벨 어댑터 전면 리팩토링 (`lib.sh`)
* [ ] **명령어 매핑**: `lib.sh` 내의 모든 `tmux` API 호출을 `herdr` 명령으로 전면 개정.
* `_tmux new-session` ➡️ `herdr run -d --name "$SESSION_NAME" -- "$CMD_FULL"`
* `_tmux capture-pane` ➡️ `herdr capture --name "$SESSION_NAME"`
* `_tmux send-keys` ➡️ `herdr send-keys --name "$SESSION_NAME" "$KEYS"`
* `_tmux kill-session` ➡️ `herdr kill --name "$SESSION_NAME"`
* [ ] **정적 상태 감지 함수 재작성 (`_pane_quiescent`)**:
* `herdr`이 기본 제공하는 세션 상태 조회 API를 파싱하여 PTY 정적 상태 여부를 판별하도록 대폭 경량화 및 고도화.
* [ ] **인풋 주입 엔진 고도화 (`send_keys_safe`)**:
* 복잡한 버퍼 제어(`set-buffer`/`paste-buffer`) 대신, `herdr` API를 경유한 다이렉트 프롬프트 주입 방식으로 단순화.
### 📍 Milestone 3: 에이전트 라이프사이클 관리 도구 이관
* [ ] **`create_session.sh` 수정**:
* `herdr` 기동 방식 및 pane PID 수집 로직 교체.
* `.mam/agent-sessions.yaml` 메타데이터 규격을 `herdr` 사양(예: `tmux_server` ➡️ `herdr_workspace`)에 맞게 정렬.
* [ ] **`resume_session.sh` 수정**:
* 죽은 `herdr` 프로세스를 감지하고 저장된 대화 ID와 함께 `herdr run`으로 복원하는 흐름 이식.
* [ ] **`stop_session.sh` 수정**:
* 에이전트 세션의 깔끔한 graceful 종료 및 최종 TUI 캡처 흐름을 `herdr` 규격으로 전환.
### 📍 Milestone 4: 검증 및 루프 완주
* [ ] **정적 분석**: `bash -n``shellcheck` 신규 경고 0건 검증.
* [ ] **오케스트레이션 루프 검증 (`run_loop.sh`)**:
* `run_loop.sh` 내부의 `delegate_job_safe` 실행을 `herdr` 세션 기반으로 연동하여 100% 자율 루프 구동 확인.
* 피어 리뷰어(`cline`, `claude`)들로부터 최종 `[VERDICT: PASS]` 서명 획득.
---
## 4. 📈 사후 관리 및 형상 병합 정책
* `herdr` 브랜치의 개발 및 검증이 완주되어 `PASS` 서명이 누적되면, `deploy/INSTALL.md``README.md` 문서를 개정하여 각 브랜치별 설치 절차를 문서화합니다.
* `main` 브랜치의 공통 규칙 버그 수정 사항(예: `AGENTS.md` 수정 등)은 주기적으로 `herdr` 브랜치로 `git merge`하여 정책적 일치성을 유지합니다.