refactor: rename resolve_herdr_workspace to resolve_herdr_session and use herdr_session database field consistently
This commit is contained in:
@@ -0,0 +1,144 @@
|
|||||||
|
# ✅ 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]
|
||||||
+4
-10
@@ -495,9 +495,9 @@ herdr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# resolve_herdr_server <session_name>
|
# resolve_herdr_session <session_name>
|
||||||
#
|
#
|
||||||
# Query agent-sessions.yaml to find the herdr_server associated with a session.
|
# Query agent-sessions.yaml to find the herdr_session associated with a session.
|
||||||
# Fallback to HERDR_SERVER_NAME or 'default' if not registered or field is missing.
|
# Fallback to HERDR_SERVER_NAME or 'default' if not registered or field is missing.
|
||||||
# Prints the resolved server name on stdout.
|
# Prints the resolved server name on stdout.
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -541,13 +541,7 @@ print(json.dumps(d, ensure_ascii=False))
|
|||||||
PYEOF
|
PYEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
# Despite the name (kept for caller compatibility — resume/stop/update_yaml_resumed
|
resolve_herdr_session() {
|
||||||
# all do `HERDR_SERVER_NAME="$(resolve_herdr_workspace "$SESSION_NAME")"`), this
|
|
||||||
# returns the isolated herdr *session* name to use for this MAM session row, not
|
|
||||||
# a workspace id. Real isolation is `--session <name>` (see `_MAM_SESSION` in the
|
|
||||||
# generated wrapper) — a workspace label match provides no actual isolation
|
|
||||||
# since agent/pane commands are server-global regardless of workspace.
|
|
||||||
resolve_herdr_workspace() {
|
|
||||||
local session_name="$1"
|
local session_name="$1"
|
||||||
MAM_STATE_JSON="$(load_state_json)" SESSION_NAME="$session_name" python3 -c "
|
MAM_STATE_JSON="$(load_state_json)" SESSION_NAME="$session_name" python3 -c "
|
||||||
import sys, os, json
|
import sys, os, json
|
||||||
@@ -555,7 +549,7 @@ name = os.environ['SESSION_NAME']
|
|||||||
d = json.loads(os.environ.get('MAM_STATE_JSON', '{}'))
|
d = json.loads(os.environ.get('MAM_STATE_JSON', '{}'))
|
||||||
for s in d.get('herdr_sessions', []):
|
for s in d.get('herdr_sessions', []):
|
||||||
if s.get('name') == name:
|
if s.get('name') == name:
|
||||||
print(s.get('herdr_workspace') or s.get('herdr_server') or 'default')
|
print(s.get('herdr_session') or s.get('herdr_workspace') or s.get('herdr_server') or 'default')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
print(os.environ.get('HERDR_SERVER_NAME', 'default'))
|
print(os.environ.get('HERDR_SERVER_NAME', 'default'))
|
||||||
"
|
"
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ entry = {
|
|||||||
'role': role,
|
'role': role,
|
||||||
'herdr_session_created_at': os.environ['NOW_ISO'],
|
'herdr_session_created_at': os.environ['NOW_ISO'],
|
||||||
'herdr_session_epoch': int(epoch) if epoch.isdigit() else 0,
|
'herdr_session_epoch': int(epoch) if epoch.isdigit() else 0,
|
||||||
'herdr_server': server_name,
|
'herdr_session': server_name,
|
||||||
'delegate_job_id': os.environ.get('DELEGATE_JOB_ID', '') or None,
|
'delegate_job_id': os.environ.get('DELEGATE_JOB_ID', '') or None,
|
||||||
'pane': {
|
'pane': {
|
||||||
'index': 0,
|
'index': 0,
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ run_agent() {
|
|||||||
# the caller having exported HERDR_SERVER_NAME by hand. This is what lets
|
# the caller having exported HERDR_SERVER_NAME by hand. This is what lets
|
||||||
# delegation reach an agent living in an isolated herdr session (e.g. one
|
# delegation reach an agent living in an isolated herdr session (e.g. one
|
||||||
# created with --herdr-server) instead of silently looking in "default".
|
# created with --herdr-server) instead of silently looking in "default".
|
||||||
export HERDR_SERVER_NAME="$(resolve_herdr_workspace "$sess")"
|
export HERDR_SERVER_NAME="$(resolve_herdr_session "$sess")"
|
||||||
|
|
||||||
if ! herdr has-session -t "$sess" 2>/dev/null; then
|
if ! herdr has-session -t "$sess" 2>/dev/null; then
|
||||||
echo "ERROR: 에이전트 세션 '$sess'이 존재하지 않습니다. 작업을 위임하기 전에 먼저 에이전트 세션을 기동해 주세요." >&2
|
echo "ERROR: 에이전트 세션 '$sess'이 존재하지 않습니다. 작업을 위임하기 전에 먼저 에이전트 세션을 기동해 주세요." >&2
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ _changed = False
|
|||||||
for s in d.get('herdr_sessions', []):
|
for s in d.get('herdr_sessions', []):
|
||||||
if s.get('delegate_job_id') == _jid and s.get('status') == 'running':
|
if s.get('delegate_job_id') == _jid and s.get('status') == 'running':
|
||||||
_name = s.get('name')
|
_name = s.get('name')
|
||||||
_srv = s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
_srv = s.get('herdr_session') or s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
||||||
if _event == 'completed':
|
if _event == 'completed':
|
||||||
s['delegate_job_id'] = None
|
s['delegate_job_id'] = None
|
||||||
print('MQTT Monitor: job completed on ' + str(_name) + ' — session kept alive', flush=True)
|
print('MQTT Monitor: job completed on ' + str(_name) + ' — session kept alive', flush=True)
|
||||||
@@ -345,7 +345,7 @@ unique_servers = {'default'}
|
|||||||
if 'HERDR_SERVER_NAME' in os.environ:
|
if 'HERDR_SERVER_NAME' in os.environ:
|
||||||
unique_servers.add(os.environ['HERDR_SERVER_NAME'])
|
unique_servers.add(os.environ['HERDR_SERVER_NAME'])
|
||||||
for s in d.get('herdr_sessions', []):
|
for s in d.get('herdr_sessions', []):
|
||||||
srv = s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
srv = s.get('herdr_session') or s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
||||||
unique_servers.add(srv)
|
unique_servers.add(srv)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -399,7 +399,7 @@ if herdr_confirmed:
|
|||||||
# (없으면 herdr-dead stopped 세션을 'terminated' 로 덮어써 resumable 플래그가 소실됨)
|
# (없으면 herdr-dead stopped 세션을 'terminated' 로 덮어써 resumable 플래그가 소실됨)
|
||||||
if s.get('status') in ('terminated', 'archived', 'stopped'):
|
if s.get('status') in ('terminated', 'archived', 'stopped'):
|
||||||
continue
|
continue
|
||||||
srv = s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
srv = s.get('herdr_session') or s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
||||||
if (name, srv) not in alive_set:
|
if (name, srv) not in alive_set:
|
||||||
s['status'] = 'terminated'
|
s['status'] = 'terminated'
|
||||||
s['terminated_at'] = now_iso
|
s['terminated_at'] = now_iso
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ if [ -z "$UUID" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
HERDR_SERVER_NAME="$(resolve_herdr_workspace "$SESSION_NAME")"
|
HERDR_SERVER_NAME="$(resolve_herdr_session "$SESSION_NAME")"
|
||||||
export HERDR_SERVER_NAME
|
export HERDR_SERVER_NAME
|
||||||
|
|
||||||
# 2. If herdr is alive, print warning or attach.
|
# 2. If herdr is alive, print warning or attach.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ done
|
|||||||
[ -n "$UUID" ] || { echo "ERROR: --uuid required" >&2; exit 2; }
|
[ -n "$UUID" ] || { echo "ERROR: --uuid required" >&2; exit 2; }
|
||||||
[ -f "$AGENT_SESSIONS_YAML" ] || { echo "ERROR: $AGENT_SESSIONS_YAML not found" >&2; exit 1; }
|
[ -f "$AGENT_SESSIONS_YAML" ] || { echo "ERROR: $AGENT_SESSIONS_YAML not found" >&2; exit 1; }
|
||||||
|
|
||||||
HERDR_SERVER_NAME="$(resolve_herdr_workspace "$SESSION_NAME")"
|
HERDR_SERVER_NAME="$(resolve_herdr_session "$SESSION_NAME")"
|
||||||
export HERDR_SERVER_NAME
|
export HERDR_SERVER_NAME
|
||||||
|
|
||||||
# --agent 미지정 시 이름 suffix 로 fallback (P1-F: 가능하면 --agent 명시)
|
# --agent 미지정 시 이름 suffix 로 fallback (P1-F: 가능하면 --agent 명시)
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ def get_job_status(s):
|
|||||||
sessions_detail = []
|
sessions_detail = []
|
||||||
for s in d.get('herdr_sessions', []):
|
for s in d.get('herdr_sessions', []):
|
||||||
name = s.get('name', '?')
|
name = s.get('name', '?')
|
||||||
server = s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
server = s.get('herdr_session') or s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
||||||
jid, jstatus = get_job_status(s)
|
jid, jstatus = get_job_status(s)
|
||||||
pane = s.get('pane') or {}
|
pane = s.get('pane') or {}
|
||||||
sessions_detail.append({
|
sessions_detail.append({
|
||||||
@@ -197,7 +197,7 @@ if not sessions:
|
|||||||
print("(no sessions registered)")
|
print("(no sessions registered)")
|
||||||
for s in sessions:
|
for s in sessions:
|
||||||
name = s.get('name', '?')
|
name = s.get('name', '?')
|
||||||
server = s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
server = s.get('herdr_session') or s.get('herdr_workspace') or s.get('herdr_server') or 'default'
|
||||||
status = s.get('status', '?')
|
status = s.get('status', '?')
|
||||||
herdr = 'alive' if f"{name}|{server}" in alive else 'dead'
|
herdr = 'alive' if f"{name}|{server}" in alive else 'dead'
|
||||||
cmd = (s.get('pane') or {}).get('cmd', '?')
|
cmd = (s.get('pane') or {}).get('cmd', '?')
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ if [ "$PURGE" = "1" ]; then
|
|||||||
trap 'rm -f "$WORKSPACE_ROOT/.mam/purging-$SESSION_NAME"' EXIT
|
trap 'rm -f "$WORKSPACE_ROOT/.mam/purging-$SESSION_NAME"' EXIT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
HERDR_SERVER_NAME="$(resolve_herdr_workspace "$SESSION_NAME")"
|
HERDR_SERVER_NAME="$(resolve_herdr_session "$SESSION_NAME")"
|
||||||
export HERDR_SERVER_NAME
|
export HERDR_SERVER_NAME
|
||||||
|
|
||||||
# --agent 미지정 시 이름 suffix 로 fallback (P1-F)
|
# --agent 미지정 시 이름 suffix 로 fallback (P1-F)
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ d['herdr_sessions'] = [{{
|
|||||||
'name': '{session_name}',
|
'name': '{session_name}',
|
||||||
'status': 'running',
|
'status': 'running',
|
||||||
'role': 'Creator',
|
'role': 'Creator',
|
||||||
'herdr_workspace': 'my-custom-workspace',
|
'herdr_session': 'my-custom-workspace',
|
||||||
'pane': {{
|
'pane': {{
|
||||||
'cwd': 'WS_PLACEHOLDER',
|
'cwd': 'WS_PLACEHOLDER',
|
||||||
'pid': 7777,
|
'pid': 7777,
|
||||||
|
|||||||
@@ -104,15 +104,15 @@ def test_create_validate_env_key(mam_sandbox):
|
|||||||
# FEATURE 2: Resume Session (6 Test Cases)
|
# FEATURE 2: Resume Session (6 Test Cases)
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
def test_resume_resolve_herdr_workspace_default(mam_sandbox):
|
def test_resume_resolve_herdr_session_default(mam_sandbox):
|
||||||
"""Test resolve_herdr_workspace fallback behavior when session is not in YAML."""
|
"""Test resolve_herdr_session fallback behavior when session is not in YAML."""
|
||||||
res = run_lib_func(mam_sandbox, "resolve_herdr_workspace", "non-existent-session")
|
res = run_lib_func(mam_sandbox, "resolve_herdr_session", "non-existent-session")
|
||||||
assert res.returncode == 0
|
assert res.returncode == 0
|
||||||
assert res.stdout.strip() == "default"
|
assert res.stdout.strip() == "default"
|
||||||
|
|
||||||
def test_resume_resolve_herdr_workspace_env(mam_sandbox):
|
def test_resume_resolve_herdr_session_env(mam_sandbox):
|
||||||
"""Test resolve_herdr_workspace fallback to HERDR_SERVER_NAME env var."""
|
"""Test resolve_herdr_session fallback to HERDR_SERVER_NAME env var."""
|
||||||
res = run_lib_func(mam_sandbox, "resolve_herdr_workspace", "non-existent-session", env={"HERDR_SERVER_NAME": "custom_server"})
|
res = run_lib_func(mam_sandbox, "resolve_herdr_session", "non-existent-session", env={"HERDR_SERVER_NAME": "custom_server"})
|
||||||
assert res.returncode == 0
|
assert res.returncode == 0
|
||||||
assert res.stdout.strip() == "custom_server"
|
assert res.stdout.strip() == "custom_server"
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ def test_integration_create_options_combination(mam_sandbox, mock_herdr, mock_ag
|
|||||||
session = sessions[0]
|
session = sessions[0]
|
||||||
|
|
||||||
assert session["role"] == "Creator"
|
assert session["role"] == "Creator"
|
||||||
assert session["herdr_server"] == "custom_server"
|
assert session.get("herdr_session") == "custom_server"
|
||||||
assert session["delegate_job_id"] is not None
|
assert session["delegate_job_id"] is not None
|
||||||
assert session["status"] == "running"
|
assert session["status"] == "running"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user