herdr 0.9.3 의 별도 시험 서버에서 보면 agent attach 도 agent get 과 같은 방식으로 대상을 찾습니다. 없는 이름이면 둘 다 agent_not_found 이고, attach 쪽 오류 위치는 cli:agent:attach:resolve 입니다. #66 에서 agent get 은 원래 이름(32자 초과·대문자)으로 에이전트를 찾지 못했습니다.
따라서 이름이 32자를 넘거나 대문자가 들어간 세션은, 기록된 attach 명령을 그대로 실행하면 실패할 것으로 봅니다. 실제 에이전트를 긴 이름으로 띄워 확인하지는 않았습니다.
2. stall_watch 가 이름 변환을 두 곳에서 한다 (정리)
lib_py/stall_watch.py 의 HerdrSource.__init__(:162)와 StallWatch.__init__(:229)가 같은 --target 을 각자 변환합니다.
지금은 결과가 같습니다. 하지만 한쪽만 바뀌면 agent wait 만 다른 이름으로 herdr 를 부르게 됩니다.
3. lib.sh 에 _sanitize_herdr_agent_name 정의가 두 벌 있다 (정리)
lib.sh:36 과 lib.sh:293 에 있고, 뒤의 정의가 적용됩니다.
해시 도구(shasum·sha1sum·openssl)가 없을 때만 다릅니다. 앞의 정의는 32자로 자르고, 뒤의 정의는 python3 로 해시를 구하며 그것도 안 되면 00000000 을 붙입니다.
제안
1: 실행할 명령을 만드는 곳에서 이름을 변환합니다.
attach_command(·resume 의 start_command)에 sanitize_herdr_agent_name(name) 을 씁니다.
lib.sh 래퍼의 agent attach 도 get/read/prompt 와 같이 변환합니다.
문서의 <name> 은 "herdr 에 등록된 이름" 으로 고칩니다. 바꾸는 줄은 최소로 합니다.
2: 변환을 한 곳에서 하고(예: StallWatch 가 HerdrSource 의 이름을 받아 씀), 테스트로 묶습니다.
3: 한 벌만 남깁니다. 결과가 Python sanitize_herdr_agent_name 과 같은지 테스트로 확인합니다(해시 도구가 없는 경우 포함).
완료 조건 (회귀 테스트로)
32자를 넘는 이름과 대문자가 든 이름의 세션에서, create·resume·reconcile 이 기록하는 attach_command 가 변환된 이름을 쓴다.
lib.sh 래퍼로 부른 herdr agent attach <원래 이름> 이 변환된 이름으로 herdr 를 부른다(mock herdr 의 strict_agent_names 로 확인).
변환이 필요 없는 이름은 동작이 그대로다.
stall_watch 의 herdr 호출 이름이 한 곳에서 정해진다. tests/test_issue66_stall_watch_sanitized_name.py 는 그대로 통과한다.
lib.sh 의 정의가 하나이고, 해시 도구가 없는 경우를 포함해 Python 함수와 결과가 같다.
실제 에이전트를 32자를 넘는 이름으로 띄우고, 기록된 attach 명령으로 붙을 수 있다(수동 확인).
## 문제
#66(v4.10.1)에서 stall_watch 는 고쳤지만, herdr 에이전트 이름 변환(`sanitize_herdr_agent_name`)을 둘러싼 문제 세 가지가 남아 있습니다. 모두 v4.10.1(`29cc4fd`)에서 확인했습니다.
### 1. `attach_command` 가 원래 세션 이름을 쓴다 (버그로 보임)
- 레지스트리 행의 `attach_command` 는 `HERDR_SESSION_NAME=<server> herdr agent attach <원래 이름>` 입니다. 이 명령을 쓰는 곳은 다음과 같습니다.
- create: `multi-agent-mux-create/scripts/create_session.sh:571`
- resume: `multi-agent-mux-resume/scripts/update_yaml_resumed.sh:150-151`, `:162-163` (`start_command` 도 같은 명령)
- reconcile: `multi-agent-mux-monitor/scripts/reconcile.sh:678`
- status 는 이 값을 그대로 보여 줍니다(`status.sh:222`).
- lib.sh 의 herdr 래퍼는 `agent get/read/prompt` 만 `_resolve_herdr_target` 으로 변환하고, `attach` 는 그대로 넘깁니다(`lib.sh:608`).
- 스킬 문서도 `herdr --session <server> agent attach <name>` 을 안내합니다(`multi-agent-mux-resume/SKILL.md:30`, `:63`, `:139`, `multi-agent-mux-create/SKILL.md:150`, `:261`).
- herdr 0.9.3 의 별도 시험 서버에서 보면 `agent attach` 도 `agent get` 과 같은 방식으로 대상을 찾습니다. 없는 이름이면 둘 다 `agent_not_found` 이고, attach 쪽 오류 위치는 `cli:agent:attach:resolve` 입니다. #66 에서 `agent get` 은 원래 이름(32자 초과·대문자)으로 에이전트를 찾지 못했습니다.
- 따라서 이름이 32자를 넘거나 대문자가 들어간 세션은, 기록된 attach 명령을 그대로 실행하면 실패할 것으로 봅니다. 실제 에이전트를 긴 이름으로 띄워 확인하지는 않았습니다.
### 2. stall_watch 가 이름 변환을 두 곳에서 한다 (정리)
- `lib_py/stall_watch.py` 의 `HerdrSource.__init__`(`:162`)와 `StallWatch.__init__`(`:229`)가 같은 `--target` 을 각자 변환합니다.
- 지금은 결과가 같습니다. 하지만 한쪽만 바뀌면 `agent wait` 만 다른 이름으로 herdr 를 부르게 됩니다.
### 3. lib.sh 에 `_sanitize_herdr_agent_name` 정의가 두 벌 있다 (정리)
- `lib.sh:36` 과 `lib.sh:293` 에 있고, 뒤의 정의가 적용됩니다.
- 해시 도구(`shasum`·`sha1sum`·`openssl`)가 없을 때만 다릅니다. 앞의 정의는 32자로 자르고, 뒤의 정의는 python3 로 해시를 구하며 그것도 안 되면 `00000000` 을 붙입니다.
## 제안
- **1**: 실행할 명령을 만드는 곳에서 이름을 변환합니다.
- `attach_command`(·resume 의 `start_command`)에 `sanitize_herdr_agent_name(name)` 을 씁니다.
- lib.sh 래퍼의 `agent attach` 도 `get/read/prompt` 와 같이 변환합니다.
- 문서의 `<name>` 은 "herdr 에 등록된 이름" 으로 고칩니다. 바꾸는 줄은 최소로 합니다.
- **2**: 변환을 한 곳에서 하고(예: `StallWatch` 가 `HerdrSource` 의 이름을 받아 씀), 테스트로 묶습니다.
- **3**: 한 벌만 남깁니다. 결과가 Python `sanitize_herdr_agent_name` 과 같은지 테스트로 확인합니다(해시 도구가 없는 경우 포함).
## 완료 조건 (회귀 테스트로)
1. 32자를 넘는 이름과 대문자가 든 이름의 세션에서, create·resume·reconcile 이 기록하는 `attach_command` 가 변환된 이름을 쓴다.
2. lib.sh 래퍼로 부른 `herdr agent attach <원래 이름>` 이 변환된 이름으로 herdr 를 부른다(mock herdr 의 `strict_agent_names` 로 확인).
3. 변환이 필요 없는 이름은 동작이 그대로다.
4. stall_watch 의 herdr 호출 이름이 한 곳에서 정해진다. `tests/test_issue66_stall_watch_sanitized_name.py` 는 그대로 통과한다.
5. lib.sh 의 정의가 하나이고, 해시 도구가 없는 경우를 포함해 Python 함수와 결과가 같다.
6. 실제 에이전트를 32자를 넘는 이름으로 띄우고, 기록된 attach 명령으로 붙을 수 있다(수동 확인).
본문 5 를 바꿉니다. 해시 도구가 없으면 python3 로 Python 함수와 같은 결과를 내고, python3 도 없으면 오류로 끝난다.
PATH 에서 shasum·sha1sum·openssl 을 빼고 시험합니다.
macOS 의 bash 3.2 에서도 통과해야 합니다.
추가: 옛 형식의 행(세 필드가 있는 행, stopped 행 포함)이 마이그레이션 뒤 새 형태가 되고, 두 번째 실행은 아무것도 바꾸지 않는다. YAML 과 DB 가 같다.
추가: stop 이 행이 없는 세션의 herdr 세션을 닫고, 레지스트리는 바꾸지 않는다.
추가: create_session.sh·id_order.py 의 정리 안내가 stop 스킬 명령이다.
테스트 주의: reconcile 경로의 테스트에는 mock herdr 에 해당 pane 이 있어야 합니다. pane 이 없으면 reconcile 이 행을 등록하는 경로까지 가지 않고, 테스트가 실제로는 아무것도 확인하지 않은 채 통과합니다.
릴리스: 레지스트리 필드 두 개를 지우고 형식 버전을 추가하므로, VERSIONS 에 "세션 시작·종료는 스킬로" 를 적습니다.
## 범위 정리 (v4.10.1 `29cc4fd` 기준 확인)
본문의 줄 번호와 설명은 코드와 맞습니다. 아래는 논의해서 정한 범위입니다. 본문의 제안과 다른 점은 이 댓글을 따릅니다.
### 정한 것
1. **attach 명령의 형태**
- `herdr --session <서버> agent attach <변환된 이름>` 으로 기록합니다.
- 지금의 `HERDR_SESSION_NAME=<서버> herdr agent attach ...` 는 lib.sh 래퍼만 그 환경 변수를 읽습니다. 그래서 일반 셸에서 실행하면 `default` 서버로 갑니다.
- 명령은 `lib_py` 의 함수 하나가 만들고, create(`create_session.sh:571`), resume(`update_yaml_resumed.sh:151`, `:163`), reconcile(`reconcile.sh:678`)이 모두 그 함수를 씁니다.
2. **`default` 서버 표기**: `--session default` 를 항상 적습니다. 실제 herdr 에서 `herdr --session default agent list` 와 `herdr agent list` 의 결과가 같은 것을 확인했습니다.
3. **lib.sh 래퍼**
- `agent attach` 도 `get/read/prompt` 처럼 `_resolve_herdr_target` 으로 이름을 변환합니다(`lib.sh:608`).
- 기록된 명령은 래퍼를 거치지 않으므로, 이것은 보조 경로입니다.
4. **`kill_command`·`start_command` 삭제**
- 값을 적는 곳: create `:570`·`:572`, resume `:150`·`:152`·`:162`·`:164`, reconcile `:677`·`:679`
- 출력·문서: status 출력(`status.sh:228`), create SKILL.md:149·151·154, status SKILL.md:101, stop SKILL.md:28
- 테스트 단언: `tests/test_tier2_component.py`, `test_issue50_pane_lock.py:173`, `test_issue21_worktree_prereqs.py:584`
- 두 필드 모두 코드에서 읽는 곳이 없는 기록용 문자열입니다.
- `new-session`·`kill-session` 은 lib.sh 래퍼의 가짜 명령이라 실제 herdr 에는 없습니다.
- 손으로 실행하면 레지스트리 등록·정리를 건너뜁니다.
5. **원칙: 상태를 바꾸는 인터페이스는 반드시 스킬을 거칩니다.**
- 시작은 create·resume, 종료는 stop 으로 합니다.
- `kill-session` 을 직접 안내하는 두 곳을 stop 스킬 명령으로 바꿉니다: `create_session.sh:364`(정리 실패, exit 43), `id_order.py:344`(등록 전에 죽은 세션).
- 두 번째 경우는 레지스트리 행이 없습니다. 지금의 stop 은 이런 세션을 "not in YAML" 로 거부합니다(exit 1, `stop_session.sh:139`).
- 그래서 **stop 이 행이 없는 세션도 닫게** 합니다. herdr 세션만 닫고 레지스트리는 건드리지 않습니다.
6. **attach 는 원칙의 예외**: 화면에 붙어서 보기만 하고 상태를 바꾸지 않으므로, 실제 herdr 명령을 그대로 씁니다.
7. **이름 변환 규칙은 Python 함수 하나와 lib.sh 정의 하나만 남깁니다.** (본문 항목 3 확장)
- lib.sh 의 두 벌(`:36`, `:293`)을 하나로 합칩니다.
- `lib.sh:636`(`has-session`)의 대체 코드 `lambda s: s.lower()[:32]` 를 지웁니다. 이 코드는 해시도 문자 치환도 하지 않습니다.
- 그 위의 import 경로가 현재 폴더 기준(`os.path.abspath(".agents/skills")`)이라, 체크아웃 밖에서는 이 대체 코드가 쓰입니다. 경로를 lib.sh 파일 위치 기준으로 바꾸거나, lib.sh 가 계산한 이름을 넘깁니다.
8. **해시를 만들 수 없으면 오류로 끝냅니다.**
- `shasum`·`sha1sum`·`openssl`·python3 가 모두 없을 때 `00000000` 을 붙이지 않습니다.
- 틀린 이름으로 조용히 계속하면 herdr 에 등록된 이름과 찾는 이름이 달라집니다.
9. **이미 기록된 행 (마이그레이션)**
- `lib_py` 에 마이그레이션 함수를 둡니다. `kill_command`·`start_command` 를 지우고 `attach_command` 를 새 형태로 만듭니다.
- 레지스트리에 형식 버전을 적고, 옛 형식이면 레지스트리를 읽을 때 한 번 실행합니다.
- YAML 과 DB 사본(`agent-sessions.db`)을 함께 고칩니다. 여러 번 실행해도 결과가 같습니다.
- 개발 체크아웃(`git pull`)과 설치된 작업 공간 모두에서 사람이 따로 할 일이 없습니다.
10. **stall_watch**: 이름 변환을 `StallWatch` 에서 한 번만 하고 `HerdrSource` 에 넘깁니다(`stall_watch.py:162`, `:229`).
### 범위 밖
- **update 스킬**: `multi-agent-mux-update` 스킬은 별도 이슈로 진행합니다. 업데이트 뒤 9 의 마이그레이션 함수를 직접 부르는 것도 그 이슈에서 합니다.
### 완료 조건 보강
- 본문 1 에 추가합니다.
- `attach_command` 가 `herdr --session <서버> agent attach <변환된 이름>` 형태다(`default` 포함).
- 새 행에 `kill_command`·`start_command` 가 없다.
- 본문 5 를 바꿉니다. 해시 도구가 없으면 python3 로 Python 함수와 같은 결과를 내고, python3 도 없으면 오류로 끝난다.
- PATH 에서 `shasum`·`sha1sum`·`openssl` 을 빼고 시험합니다.
- macOS 의 bash 3.2 에서도 통과해야 합니다.
- 추가: 옛 형식의 행(세 필드가 있는 행, `stopped` 행 포함)이 마이그레이션 뒤 새 형태가 되고, 두 번째 실행은 아무것도 바꾸지 않는다. YAML 과 DB 가 같다.
- 추가: stop 이 행이 없는 세션의 herdr 세션을 닫고, 레지스트리는 바꾸지 않는다.
- 추가: `create_session.sh`·`id_order.py` 의 정리 안내가 stop 스킬 명령이다.
- **테스트 주의**: reconcile 경로의 테스트에는 mock herdr 에 해당 pane 이 있어야 합니다. pane 이 없으면 reconcile 이 행을 등록하는 경로까지 가지 않고, 테스트가 실제로는 아무것도 확인하지 않은 채 통과합니다.
- **릴리스**: 레지스트리 필드 두 개를 지우고 형식 버전을 추가하므로, VERSIONS 에 "세션 시작·종료는 스킬로" 를 적습니다.
PR #73 을 merge commit 으로 병합했다(v4.11.0). squash 하지 않아 S11 의 기준 커밋 0fc162e 가 main 에 남는다.
검증
리뷰(--all-reviewer, 리뷰 전용 루프): 2회차에서 4/4 PASS. 1회차의 지적 하나(행 없는 stop 의 HERDR_SESSION_NAME=default 처리)는 create 와 같은 서버 선택 규칙이라는 반론으로 철회됐다. 리뷰어들이 macOS bash 3.2 에서 이름 변환이 Python 함수와 같은 것을 LC_ALL=C·UTF-8 양쪽에서 확인했다.
회귀: tests/test_issue71_herdr_names.py 70개. base 에서 68개 실패, head 에서 모두 통과.
전체 스위트(macOS, Python 3.9.6): 2173 passed, 56 skipped, 2 failed. 실패 둘은 부하에 민감한 타이밍 테스트(test_issue14_delivery_ack.py 의 idle grace, test_issue30_stall_watch.py 의 S13)이고, 단독 3회와 두 파일 전체 실행에서 모두 통과했다. 실제 에이전트 홈·herdr 서버·opencode 데이터에 남은 것은 없었다.
완료 조건
1–5: 회귀 테스트로 확인했다.
6(실제 에이전트를 32자를 넘는 이름으로 띄우고 기록된 attach 명령으로 붙기): 수동 확인이 남아 이슈는 열어 둔다. 확인 방법:
create 로 32자를 넘는 이름의 세션을 띄운다(예: --session 에 긴 이름).
레지스트리 행의 attach_command(herdr --session <server> agent attach <변환된 이름>)를 그대로 실행해 붙는지 본다.
stop 스킬로 닫는다.
알려진 비차단 / 후속 후보
name 이 없는 행은 형식 변환에서 건너뛰므로 두 필드가 남을 수 있다(실제로 그런 행은 없다).
delegate-job 래퍼가 위임 뒤 출력하는 안내(작업이 세션 ...에 전송되었습니다)는 아직 옛 attach 형태(HERDR_SESSION_NAME=... herdr agent attach <원래 이름>)다. 레지스트리 값이 아니라 출력 문구라 이번 범위 밖이었다.
PR #73 을 merge commit 으로 병합했다(v4.11.0). squash 하지 않아 S11 의 기준 커밋 `0fc162e` 가 main 에 남는다.
**검증**
- 리뷰(`--all-reviewer`, 리뷰 전용 루프): 2회차에서 4/4 PASS. 1회차의 지적 하나(행 없는 stop 의 `HERDR_SESSION_NAME=default` 처리)는 create 와 같은 서버 선택 규칙이라는 반론으로 철회됐다. 리뷰어들이 macOS bash 3.2 에서 이름 변환이 Python 함수와 같은 것을 `LC_ALL=C`·UTF-8 양쪽에서 확인했다.
- 회귀: `tests/test_issue71_herdr_names.py` 70개. base 에서 68개 실패, head 에서 모두 통과.
- 전체 스위트(macOS, Python 3.9.6): 2173 passed, 56 skipped, 2 failed. 실패 둘은 부하에 민감한 타이밍 테스트(`test_issue14_delivery_ack.py` 의 idle grace, `test_issue30_stall_watch.py` 의 S13)이고, 단독 3회와 두 파일 전체 실행에서 모두 통과했다. 실제 에이전트 홈·herdr 서버·opencode 데이터에 남은 것은 없었다.
**완료 조건**
- 1–5: 회귀 테스트로 확인했다.
- 6(실제 에이전트를 32자를 넘는 이름으로 띄우고 기록된 attach 명령으로 붙기): 수동 확인이 남아 이슈는 열어 둔다. 확인 방법:
1. create 로 32자를 넘는 이름의 세션을 띄운다(예: `--session` 에 긴 이름).
2. 레지스트리 행의 `attach_command`(`herdr --session <server> agent attach <변환된 이름>`)를 그대로 실행해 붙는지 본다.
3. stop 스킬로 닫는다.
**알려진 비차단 / 후속 후보**
- `name` 이 없는 행은 형식 변환에서 건너뛰므로 두 필드가 남을 수 있다(실제로 그런 행은 없다).
- delegate-job 래퍼가 위임 뒤 출력하는 안내(`작업이 세션 ...에 전송되었습니다`)는 아직 옛 attach 형태(`HERDR_SESSION_NAME=... herdr agent attach <원래 이름>`)다. 레지스트리 값이 아니라 출력 문구라 이번 범위 밖이었다.
- 업데이트 직후 형식 변환 진입점을 부르는 일은 #72 에서 한다.
실제 claude 에이전트를 37자 이름으로 띄웠습니다(create 스킬, 격리 herdr 서버).
herdr 에는 32자로 변환된 이름으로 등록됐고, 레지스트리 행의 attach_command 도 그 변환된 이름을 썼습니다.
herdr --session <server> agent attach <변환된 이름>
그 명령을 별도 터미널에서 그대로 실행하니 에이전트 화면에 붙었습니다.
시험 세션은 stop 스킬로 정리했습니다.
조건 1–5 는 앞 댓글대로 테스트로 확인했으므로 이 이슈를 닫습니다.
후속: 잡을 보낸 뒤 delegate-job 이 출력하는 attach 안내와, create 가 끝에 출력하는 attach 안내가 아직 원래 이름을 씁니다. 둘 다 #72 에서 함께 고칩니다.
## 완료 조건 6 확인 (수동, v4.11.0)
- 실제 claude 에이전트를 37자 이름으로 띄웠습니다(create 스킬, 격리 herdr 서버).
- herdr 에는 32자로 변환된 이름으로 등록됐고, 레지스트리 행의 `attach_command` 도 그 변환된 이름을 썼습니다.
- `herdr --session <server> agent attach <변환된 이름>`
- 그 명령을 별도 터미널에서 그대로 실행하니 에이전트 화면에 붙었습니다.
- 시험 세션은 stop 스킬로 정리했습니다.
조건 1–5 는 앞 댓글대로 테스트로 확인했으므로 이 이슈를 닫습니다.
후속: 잡을 보낸 뒤 delegate-job 이 출력하는 attach 안내와, create 가 끝에 출력하는 attach 안내가 아직 원래 이름을 씁니다. 둘 다 #72 에서 함께 고칩니다.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
문제
#66(v4.10.1)에서 stall_watch 는 고쳤지만, herdr 에이전트 이름 변환(
sanitize_herdr_agent_name)을 둘러싼 문제 세 가지가 남아 있습니다. 모두 v4.10.1(29cc4fd)에서 확인했습니다.1.
attach_command가 원래 세션 이름을 쓴다 (버그로 보임)attach_command는HERDR_SESSION_NAME=<server> herdr agent attach <원래 이름>입니다. 이 명령을 쓰는 곳은 다음과 같습니다.multi-agent-mux-create/scripts/create_session.sh:571multi-agent-mux-resume/scripts/update_yaml_resumed.sh:150-151,:162-163(start_command도 같은 명령)multi-agent-mux-monitor/scripts/reconcile.sh:678status.sh:222).agent get/read/prompt만_resolve_herdr_target으로 변환하고,attach는 그대로 넘깁니다(lib.sh:608).herdr --session <server> agent attach <name>을 안내합니다(multi-agent-mux-resume/SKILL.md:30,:63,:139,multi-agent-mux-create/SKILL.md:150,:261).agent attach도agent get과 같은 방식으로 대상을 찾습니다. 없는 이름이면 둘 다agent_not_found이고, attach 쪽 오류 위치는cli:agent:attach:resolve입니다. #66 에서agent get은 원래 이름(32자 초과·대문자)으로 에이전트를 찾지 못했습니다.2. stall_watch 가 이름 변환을 두 곳에서 한다 (정리)
lib_py/stall_watch.py의HerdrSource.__init__(:162)와StallWatch.__init__(:229)가 같은--target을 각자 변환합니다.agent wait만 다른 이름으로 herdr 를 부르게 됩니다.3. lib.sh 에
_sanitize_herdr_agent_name정의가 두 벌 있다 (정리)lib.sh:36과lib.sh:293에 있고, 뒤의 정의가 적용됩니다.shasum·sha1sum·openssl)가 없을 때만 다릅니다. 앞의 정의는 32자로 자르고, 뒤의 정의는 python3 로 해시를 구하며 그것도 안 되면00000000을 붙입니다.제안
attach_command(·resume 의start_command)에sanitize_herdr_agent_name(name)을 씁니다.agent attach도get/read/prompt와 같이 변환합니다.<name>은 "herdr 에 등록된 이름" 으로 고칩니다. 바꾸는 줄은 최소로 합니다.StallWatch가HerdrSource의 이름을 받아 씀), 테스트로 묶습니다.sanitize_herdr_agent_name과 같은지 테스트로 확인합니다(해시 도구가 없는 경우 포함).완료 조건 (회귀 테스트로)
attach_command가 변환된 이름을 쓴다.herdr agent attach <원래 이름>이 변환된 이름으로 herdr 를 부른다(mock herdr 의strict_agent_names로 확인).tests/test_issue66_stall_watch_sanitized_name.py는 그대로 통과한다.범위 정리 (v4.10.1
29cc4fd기준 확인)본문의 줄 번호와 설명은 코드와 맞습니다. 아래는 논의해서 정한 범위입니다. 본문의 제안과 다른 점은 이 댓글을 따릅니다.
정한 것
herdr --session <서버> agent attach <변환된 이름>으로 기록합니다.HERDR_SESSION_NAME=<서버> herdr agent attach ...는 lib.sh 래퍼만 그 환경 변수를 읽습니다. 그래서 일반 셸에서 실행하면default서버로 갑니다.lib_py의 함수 하나가 만들고, create(create_session.sh:571), resume(update_yaml_resumed.sh:151,:163), reconcile(reconcile.sh:678)이 모두 그 함수를 씁니다.default서버 표기:--session default를 항상 적습니다. 실제 herdr 에서herdr --session default agent list와herdr agent list의 결과가 같은 것을 확인했습니다.agent attach도get/read/prompt처럼_resolve_herdr_target으로 이름을 변환합니다(lib.sh:608).kill_command·start_command삭제:570·:572, resume:150·:152·:162·:164, reconcile:677·:679status.sh:228), create SKILL.md:149·151·154, status SKILL.md:101, stop SKILL.md:28tests/test_tier2_component.py,test_issue50_pane_lock.py:173,test_issue21_worktree_prereqs.py:584new-session·kill-session은 lib.sh 래퍼의 가짜 명령이라 실제 herdr 에는 없습니다.kill-session을 직접 안내하는 두 곳을 stop 스킬 명령으로 바꿉니다:create_session.sh:364(정리 실패, exit 43),id_order.py:344(등록 전에 죽은 세션).stop_session.sh:139).:36,:293)을 하나로 합칩니다.lib.sh:636(has-session)의 대체 코드lambda s: s.lower()[:32]를 지웁니다. 이 코드는 해시도 문자 치환도 하지 않습니다.os.path.abspath(".agents/skills"))이라, 체크아웃 밖에서는 이 대체 코드가 쓰입니다. 경로를 lib.sh 파일 위치 기준으로 바꾸거나, lib.sh 가 계산한 이름을 넘깁니다.shasum·sha1sum·openssl·python3 가 모두 없을 때00000000을 붙이지 않습니다.lib_py에 마이그레이션 함수를 둡니다.kill_command·start_command를 지우고attach_command를 새 형태로 만듭니다.agent-sessions.db)을 함께 고칩니다. 여러 번 실행해도 결과가 같습니다.git pull)과 설치된 작업 공간 모두에서 사람이 따로 할 일이 없습니다.StallWatch에서 한 번만 하고HerdrSource에 넘깁니다(stall_watch.py:162,:229).범위 밖
multi-agent-mux-update스킬은 별도 이슈로 진행합니다. 업데이트 뒤 9 의 마이그레이션 함수를 직접 부르는 것도 그 이슈에서 합니다.완료 조건 보강
attach_command가herdr --session <서버> agent attach <변환된 이름>형태다(default포함).kill_command·start_command가 없다.shasum·sha1sum·openssl을 빼고 시험합니다.stopped행 포함)이 마이그레이션 뒤 새 형태가 되고, 두 번째 실행은 아무것도 바꾸지 않는다. YAML 과 DB 가 같다.create_session.sh·id_order.py의 정리 안내가 stop 스킬 명령이다.범위 밖으로 둔
multi-agent-mux-update스킬은 #72 로 등록했습니다. 업데이트 뒤 마이그레이션 함수를 명시적으로 부르는 일은 그 이슈에서 합니다.PR #73 을 merge commit 으로 병합했다(v4.11.0). squash 하지 않아 S11 의 기준 커밋
0fc162e가 main 에 남는다.검증
--all-reviewer, 리뷰 전용 루프): 2회차에서 4/4 PASS. 1회차의 지적 하나(행 없는 stop 의HERDR_SESSION_NAME=default처리)는 create 와 같은 서버 선택 규칙이라는 반론으로 철회됐다. 리뷰어들이 macOS bash 3.2 에서 이름 변환이 Python 함수와 같은 것을LC_ALL=C·UTF-8 양쪽에서 확인했다.tests/test_issue71_herdr_names.py70개. base 에서 68개 실패, head 에서 모두 통과.test_issue14_delivery_ack.py의 idle grace,test_issue30_stall_watch.py의 S13)이고, 단독 3회와 두 파일 전체 실행에서 모두 통과했다. 실제 에이전트 홈·herdr 서버·opencode 데이터에 남은 것은 없었다.완료 조건
--session에 긴 이름).attach_command(herdr --session <server> agent attach <변환된 이름>)를 그대로 실행해 붙는지 본다.알려진 비차단 / 후속 후보
name이 없는 행은 형식 변환에서 건너뛰므로 두 필드가 남을 수 있다(실제로 그런 행은 없다).작업이 세션 ...에 전송되었습니다)는 아직 옛 attach 형태(HERDR_SESSION_NAME=... herdr agent attach <원래 이름>)다. 레지스트리 값이 아니라 출력 문구라 이번 범위 밖이었다.완료 조건 6 확인 (수동, v4.11.0)
attach_command도 그 변환된 이름을 썼습니다.herdr --session <server> agent attach <변환된 이름>조건 1–5 는 앞 댓글대로 테스트로 확인했으므로 이 이슈를 닫습니다.
후속: 잡을 보낸 뒤 delegate-job 이 출력하는 attach 안내와, create 가 끝에 출력하는 attach 안내가 아직 원래 이름을 씁니다. 둘 다 #72 에서 함께 고칩니다.