docs(bug-report): add upstream bug fix report artifact
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
# [Bug Fix & PR Proposal] Multi-Agent Mux (MAM) Resume & 런타임 제어 결함 보고서
|
||||
|
||||
- **대상 프로젝트:** Multi-Agent Mux (MAM) Skills (`multi-agent-mux-*`, `lib.sh`, `lib_py`)
|
||||
- **보고 일자:** 2026-08-30
|
||||
- **작성자:** GAIA Canary Project Team
|
||||
- **심각도:** High (다중 에이전트 복원 누락, 세션 복원 실패, TUI 타임아웃 유발)
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive Summary (요약)
|
||||
|
||||
MAM 스킬을 이용해 복수의 에이전트(`claude`, `grok`, `agy`, `opencode`)를 생성하고 일괄 복원(`/multi-agent-mux-resume`)하는 과정에서 발견된 **4가지 핵심 버그**와 이에 대한 수정 패치 내역입니다.
|
||||
|
||||
1. **`lib.sh::_resolve_herdr_pane_id`의 과도한 Fallback 매칭 버그** (세션 오인으로 인한 복원 누락)
|
||||
2. **`opencode.py::resume_spec`의 `--session` 플래그 누락 버그** (기존 대화 복원 실패)
|
||||
3. **`opencode.py::ready_tokens`의 ASCII 배너 미인식 버그** (TUI 준비 감지 타임아웃)
|
||||
4. **다중 에이전트 생성/복원 시 유휴 페인(Idle Pane) 미재사용 및 분할 경합** (Grid 레이아웃 깨짐)
|
||||
|
||||
---
|
||||
|
||||
## 2. 세부 결함 분석 및 수정 패치 (Detailed Bugs & Patches)
|
||||
|
||||
### Bug 1: `_resolve_herdr_pane_id`의 Generic `agent_kind` 오인 매칭
|
||||
|
||||
#### 📌 문제 현상
|
||||
- `resume_session.sh` 실행 시 `herdr has-session -t creator-agy-01`을 호출하여 세션 생존 여부를 검사합니다.
|
||||
- `creator-agy-01` 페인이 실제로 종료된 상태임에도 `has-session`이 `true(0)`를 반환하며 `"herdr 'creator-agy-01' already running. Attaching..."` 메시지와 함께 새로운 페인 생성을 건너뛰어 에이전트가 복원되지 않는 문제가 발생했습니다.
|
||||
|
||||
#### 🔍 근본 원인 (Root Cause)
|
||||
[`lib.sh`](.agents/skills/lib.sh)의 `_resolve_herdr_pane_id` 내 파이썬 fallback 코드에서 세션명(`tn`/`tsa`) 일치 검색에 실패했을 때, `agent_kind`(`agy`) 타입 검사를 무조건 수행합니다.
|
||||
워크스페이스 내에 다른 단일 `agy`(예: Orchestrator 세션)가 1개라도 실행 중이면 `len(matching) == 1`에 걸려 **전혀 다른 페인을 `creator-agy-01`로 오인 반환**했습니다.
|
||||
|
||||
#### 🔧 해결 코드 (Diff)
|
||||
```diff
|
||||
--- a/.agents/skills/lib.sh
|
||||
+++ b/.agents/skills/lib.sh
|
||||
@@ -436,7 +436,7 @@ _resolve_herdr_pane_id() {
|
||||
- if agent_kind:
|
||||
+ if agent_kind and (tn == agent_kind or tsa == agent_kind):
|
||||
matching = [p.get('pane_id') for p in panes if p.get('agent') == agent_kind and p.get('pane_id')]
|
||||
if len(matching) == 1:
|
||||
print(matching[0])
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Bug 2: `OpenCodeAgentAdapter.resume_spec`의 `--session` 옵션 누락
|
||||
|
||||
#### 📌 문제 현상
|
||||
- `reviewer-opencode-01`을 `/multi-agent-mux-resume`로 재개할 때, 기존 대화 ID(`ses_...`)가 존재함에도 복원 플래그가 붙지 않고 새로운 빈 세션(`opencode --auto --agent build`)으로 시작되는 문제가 발생했습니다.
|
||||
|
||||
#### 🔍 근본 원인 (Root Cause)
|
||||
[`lib_py/agents/adapters/opencode.py`](.agents/skills/lib_py/agents/adapters/opencode.py)의 `resume_spec` 함수에 `if materialized and session_uuid:` 조건이 걸려 있어, 호출자가 `materialized` 플래그를 넘기지 않거나 `False`일 경우 `--session <id>` 플래그가 누락되었습니다.
|
||||
|
||||
#### 🔧 해결 코드 (Diff)
|
||||
```diff
|
||||
--- a/.agents/skills/lib_py/agents/adapters/opencode.py
|
||||
+++ b/.agents/skills/lib_py/agents/adapters/opencode.py
|
||||
@@ -188,4 +188,4 @@ class OpenCodeAgentAdapter(BaseAgentAdapter):
|
||||
def resume_spec(self, binary: str, session_uuid: str, materialized: bool = False) -> str:
|
||||
- if materialized and session_uuid:
|
||||
+ if session_uuid:
|
||||
return f"{binary} --session {session_uuid} --auto --agent build"
|
||||
return f"{binary} --auto --agent build"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Bug 3: `OpenCodeAgentAdapter.ready_tokens`의 ASCII 배너 미인식
|
||||
|
||||
#### 📌 문제 현상
|
||||
- `opencode` 에이전트 신규 생성 시 `wait_for_tui_ready` 함수가 TUI 렌더링 완료를 감지하지 못하고 30초 대기 루프에 진입하여 타임아웃을 유발했습니다.
|
||||
|
||||
#### 🔍 근본 원인 (Root Cause)
|
||||
OpenCode CLI 초기 기동 시 상단 로고가 일반 영문 텍스트가 아닌 ASCII 아트 특수문자 블록(`█▀▀█...`)으로 그려집니다. 기존 `ready_tokens = 'OpenCode|Chat'`은 일반 텍스트 매칭만 기대하여 TUI 렌더링 감지에 실패했습니다.
|
||||
|
||||
#### 🔧 해결 코드 (Diff)
|
||||
```diff
|
||||
--- a/.agents/skills/lib_py/agents/adapters/opencode.py
|
||||
+++ b/.agents/skills/lib_py/agents/adapters/opencode.py
|
||||
@@ -22,3 +22,3 @@ class OpenCodeAgentAdapter(BaseAgentAdapter):
|
||||
@property
|
||||
def ready_tokens(self) -> str:
|
||||
- return 'OpenCode|Chat'
|
||||
+ return 'OpenCode|Chat|Ask anything|tab agents|ctrl\\+p|Build auto|commands'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Bug 4: Herdr 유휴 페인(Idle Pane) 미재사용 및 분할 레이아웃 경합
|
||||
|
||||
#### 📌 문제 현상
|
||||
- 다중 에이전트 생성/복원 과정에서 워크스페이스 내에 에이전트가 종료된 빈 유휴 페인(`p.agent == None`)이 이미 존재함에도 불구하고 무조건 `pane split`을 호출하여 불필요하게 페인이 증식하거나 2x2 그리드 레이아웃이 깨지는 문제가 발생했습니다.
|
||||
|
||||
#### 🔍 근본 원인 (Root Cause)
|
||||
`lib.sh`의 `new-session` 구현부에서 `existing_ws`가 감지되었을 때 해당 워크스페이스의 유휴 페인을 먼저 탐색하지 않고 곧바로 `pane split`을 수행했습니다.
|
||||
|
||||
#### 🔧 해결 코드 (Diff)
|
||||
```diff
|
||||
--- a/.agents/skills/lib.sh
|
||||
+++ b/.agents/skills/lib.sh
|
||||
@@ -702,4 +702,18 @@ _init_herdr_isolation() {
|
||||
ws_id=""
|
||||
target_pane=""
|
||||
if [ -n "$existing_ws" ]; then
|
||||
+ idle_pane=$(_real_herdr pane list 2>/dev/null | TARGET_WS="$existing_ws" python3 -c "
|
||||
+import sys, json, os
|
||||
+tws = os.environ.get('TARGET_WS', '')
|
||||
+try:
|
||||
+ d = json.loads(sys.stdin.read())
|
||||
+ panes = d.get('result', {}).get('panes', [])
|
||||
+ for p in panes:
|
||||
+ if p.get('workspace_id') == tws and not p.get('agent') and p.get('pane_id'):
|
||||
+ print(p.get('pane_id'))
|
||||
+ break
|
||||
+except Exception:
|
||||
+ pass
|
||||
+" 2>/dev/null || echo "")
|
||||
+ if [ -n "$idle_pane" ]; then
|
||||
+ target_pane="$idle_pane"
|
||||
+ fi
|
||||
+ fi
|
||||
+ if [ -n "$existing_ws" ] && [ -z "$target_pane" ]; then
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 검증 결과 (Verification Results)
|
||||
|
||||
위 4가지 패치를 적용한 후 4개 이종 에이전트 동시 복원 및 TUI 준비 감지, Graceful Stop, 재복원 사이클을 모두 통과했습니다.
|
||||
|
||||
```text
|
||||
agent-sessions status — 2026-08-30T00:09:58Z (herdr_confirmed=False)
|
||||
======================================================================================================================================================
|
||||
NAME SOCKET WORKSPACE YAML HERDR CMD RESUME JOB_ID JOB_STATUS DRIFT
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
planner-reviewer-claude-01 mam-gaia-exp mam-agents running alive claude yes 271a2a78 cancelled -
|
||||
reviewer-creator-grok-01 mam-gaia-exp mam-agents running alive grok yes bad791a0 cancelled -
|
||||
creator-agy-01 mam-gaia-exp mam-agents running alive agy yes 4314d052 cancelled -
|
||||
reviewer-opencode-01 mam-gaia-exp mam-agents running alive opencode yes 7ac72973 cancelled -
|
||||
========================================================================================================================================
|
||||
alive herdr: ['creator-agy-01|mam-gaia-exp', 'planner-reviewer-claude-01|mam-gaia-exp', 'reviewer-creator-grok-01|mam-gaia-exp', 'reviewer-opencode-01|mam-gaia-exp']
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 권장 상류(Upstream) 조치 사항
|
||||
|
||||
1. `lib.sh`의 `_resolve_herdr_pane_id`에서 fallback `agent_kind` 매칭 범위를 타겟 이름이 generic한 경우로 제한.
|
||||
2. `lib_py/agents/adapters/opencode.py`의 `resume_spec` 및 `ready_tokens` 패치 반영.
|
||||
3. `lib.sh`의 `new-session` 처리 시 기존 유휴 페인 재사용 로직 공식 반영.
|
||||
Reference in New Issue
Block a user