fix(loop): fix wait_for_job hang bug and finalize Creator Self-Planning documentation

This commit is contained in:
2026-07-17 15:51:37 +09:00
parent 6c903420d8
commit be46484108
4 changed files with 157 additions and 17 deletions
+14 -8
View File
@@ -10,7 +10,7 @@
Run an autonomous planning-execution-review loop using multiple agents (Planner, Creator, Reviewers) in the workspace. It supports: Run an autonomous planning-execution-review loop using multiple agents (Planner, Creator, Reviewers) in the workspace. It supports:
- **Collaborative Planning** (`--plan` and `--plan-talk N`): Planner designs the solution, Creator challenges the plan for N turns to resolve edge cases, then implementation starts. - **Collaborative Planning** (`--plan` and `--plan-talk N`): Planner designs the solution, Creator challenges the plan for N turns to resolve edge cases, then implementation starts.
- **Existing Plan Execution** (default without `--plan`): Planner 에이전트에게 계획 작성을 위임하지 않고 기존에 승격된 계획서(`.agents/reports/<planner-session-name>/report-final.md`)의 내용을 로드하여 작업자(Creator)의 판단하에 즉시 구현을 시작합니다. - **Creator Self-Planning & Development** (default without `--plan`): Planner 에이전트에게 계획 작성을 위임하지 않고, 기존에 승격된 계획서가 있다면 이를 로드하여 코드를 구현하며, 계획서가 존재하지 않는 경우 작업자(Creator: developer/writer)가 스스로 구현 계획 및 설계 수립을 포함한 개발 전 과정을 직접 진행합니다.
- **Targeted Peer-Review** (`--reviewer`): Runs custom-selected reviewer agents to verify code changes. - **Targeted Peer-Review** (`--reviewer`): Runs custom-selected reviewer agents to verify code changes.
- **Total Peer-Review** (`--all-reviewer`): Enforces a unanimous PASS verdict from all registered reviewer sessions. - **Total Peer-Review** (`--all-reviewer`): Enforces a unanimous PASS verdict from all registered reviewer sessions.
- **Self-Review** (default): Creator verifies its code changes autonomously without peer reviews. - **Self-Review** (default): Creator verifies its code changes autonomously without peer reviews.
@@ -91,8 +91,12 @@ sequenceDiagram
Dev->>Plan: send critiques (Discussion) Dev->>Plan: send critiques (Discussion)
Plan-->>Dev: update plan & reach consensus Plan-->>Dev: update plan & reach consensus
end end
else Use Existing Plan (No --plan) else Use Existing Plan or Creator Self-Plan (No --plan)
Loop->>Dev: notify task execution using existing plan alt Existing Plan Found
Loop->>Dev: notify task execution using existing plan
else No Plan Found
Loop->>Dev: request Creator self-planning and code execution
end
end end
Loop->>Dev: delegate code implementation Loop->>Dev: delegate code implementation
@@ -110,7 +114,7 @@ sequenceDiagram
else Self-Review (default) else Self-Review (default)
Loop->>Dev: notify self-evaluation Loop->>Dev: notify self-evaluation
Dev-->>Loop: verification complete Dev-->>Loop: verification complete
fi end
end end
alt --cleanup enabled alt --cleanup enabled
@@ -122,8 +126,10 @@ sequenceDiagram
## Feedback Loop Cadence ## Feedback Loop Cadence
1. **Planning Phase**: 사용자가 요구사항을 제시하면 Planner가 프로젝트 구조를 파악하고 `implementation_plan.md`/`task.md`로 로드맵을 제공합니다. 사용자가 승인하면 다음 단계로 이행합니다. 1. **Planning Phase**:
2. **Execution Phase**: Creator가 배정된 태스크의 코드를 수정합니다. 진행 중 예상치 못한 설계 변경 필요성이 감지되면 작업을 멈추고 Planner에게 계획 수정을 먼저 위임합니다. 구현 완료 후 DoD(타입 매핑, 공유 자원 사이드 이펙트 방지, 문서-코드 정합성)를 자체 검증한 뒤 단일 커밋을 작성합니다. - **Collaborative Planning (`--plan`)**: Planner가 프로젝트 구조를 파악하고 `implementation_plan.md`/`task.md`로 로드맵을 제공하며, Creator와의 피드백 루프를 통해 정제됩니다.
- **Creator Self-Planning (No `--plan`)**: Planner의 개입 없이, 기존 계획서가 있다면 이를 기반으로 하고, 그렇지 않다면 Creator가 독자적으로 설계 및 태스크 단위를 구상한 후 구현에 착수합니다.
2. **Execution Phase**: Creator가 배정된 태스크의 코드를 수정합니다. `--plan` 모드 진행 중 예상치 못한 설계 변경 필요성이 감지되면 작업을 멈추고 Planner에게 계획 수정을 먼저 위임합니다. (Creator 자율 계획 모드에서는 Creator가 직접 설계를 변경하며 진행합니다.) 구현 완료 후 DoD(타입 매핑, 공유 자원 사이드 이펙트 방지, 문서-코드 정합성)를 자체 검증한 뒤 단일 커밋을 작성합니다.
3. **Review Phase**: Creator가 리뷰어 세션에 작업 완료 사실과 변경 범위(`git diff`)를 전달합니다. 리뷰어는 검증 후 리포트 **마지막에 단독 행**으로 판정을 남깁니다: 3. **Review Phase**: Creator가 리뷰어 세션에 작업 완료 사실과 변경 범위(`git diff`)를 전달합니다. 리뷰어는 검증 후 리포트 **마지막에 단독 행**으로 판정을 남깁니다:
- **반려 (`[VERDICT: NOT PASS]`)** → 피드백 요약을 Planner에게 전송하여 상위 레벨 계획(Rev.n)을 개시합니다. - **반려 (`[VERDICT: NOT PASS]`)** → 피드백 요약을 Planner에게 전송하여 상위 레벨 계획(Rev.n)을 개시합니다.
- **통과 (`[VERDICT: PASS]`)** → 모든 검토 사항이 해결되었음을 명시합니다. - **통과 (`[VERDICT: PASS]`)** → 모든 검토 사항이 해결되었음을 명시합니다.
@@ -138,7 +144,7 @@ sequenceDiagram
| 워크플로우 단계 | 해당 CLI 옵션 | 설명 | | 워크플로우 단계 | 해당 CLI 옵션 | 설명 |
| :--- | :--- | :--- | | :--- | :--- | :--- |
| **Phase 1: Planning** | `--plan` | Planner 에이전트를 기동하여 최초 계획 작성을 강제합니다. (옵션을 지정하지 않을 경우 새 계획서 작성을 생략하 기존 계획에 의거하여 즉시 구현에 착수합니다.) | | **Phase 1: Planning** | `--plan` | Planner 에이전트를 기동하여 최초 계획 작성을 강제합니다. (옵션을 지정하지 않을 경우 새 계획서 작성을 생략하며, 기존 계획서가 있는 경우 이를 로드하고, 없는 경우 Creator가 직접 계획 및 설계를 수립하여 즉시 구현에 착수합니다.) |
| **Phase 1: Debate** | `--plan-talk N` | Planner와 Creator가 상호 대화식 챌린지 루프를 `N`회 돌며 계획을 교차 정제합니다. | | **Phase 1: Debate** | `--plan-talk N` | Planner와 Creator가 상호 대화식 챌린지 루프를 `N`회 돌며 계획을 교차 정제합니다. |
| **Phase 2: Execution** | (기본값) | `--target-agent`로 명시한 주 작업 세션에 코딩 태스크를 주입합니다. | | **Phase 2: Execution** | (기본값) | `--target-agent`로 명시한 주 작업 세션에 코딩 태스크를 주입합니다. |
| **Phase 3: Review** | `--reviewer "A,B"` | 지정된 리뷰어 세션 리스트(`A`, `B` 등)에 교차 Peer Review를 위임합니다. | | **Phase 3: Review** | `--reviewer "A,B"` | 지정된 리뷰어 세션 리스트(`A`, `B` 등)에 교차 Peer Review를 위임합니다. |
@@ -150,7 +156,7 @@ sequenceDiagram
## Workflow ## Workflow
```bash ```bash
# 1. Existing-plan execution + Self-review (direct task execution using existing promoted plan) # 1. Creator Self-Planning & Development + Self-review (direct task execution using existing promoted plan or Creator's own self-plan)
bash .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh \ bash .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh \
--target-agent "<creator-session-name>" \ --target-agent "<creator-session-name>" \
--task "Fix typo in deploy/README.md" --task "Fix typo in deploy/README.md"
@@ -117,7 +117,7 @@ wait_for_job() {
status=$(python3 -c " status=$(python3 -c "
import json, os import json, os
try: try:
with open('.mam/jobs/$job_id/job.json') as f: with open('.mam/jobs/$job_id.json') as f:
print(json.load(f).get('status', 'unknown')) print(json.load(f).get('status', 'unknown'))
except Exception: except Exception:
print('unknown') print('unknown')
@@ -331,7 +331,7 @@ log_info "=== Phase 2: Code Implementation ==="
# cumulative and non-empty even after the Creator commits per DoD (P0-1). # cumulative and non-empty even after the Creator commits per DoD (P0-1).
BASE_COMMIT=$(git rev-parse HEAD 2>/dev/null || echo "") BASE_COMMIT=$(git rev-parse HEAD 2>/dev/null || echo "")
EXECUTION_PROMPT="다음 작업 목표를 완성해주세요: $TASK" EXECUTION_PROMPT="계획서가 존재하지 않으므로, 작업자(Creator)의 판단하에 스스로 구현 계획 및 설계를 수립한 뒤, 이를 바탕으로 코드를 구현하고 다음 작업 목표를 완성해주세요. 작업 목표: $TASK"
if [ -n "$CURRENT_PLAN" ]; then if [ -n "$CURRENT_PLAN" ]; then
EXECUTION_PROMPT="이미 수립된 다음 계획서에 입각하여 작업자의 판단하에 코드를 구현하고 작업 목표를 완성해주세요. 계획서:\n$CURRENT_PLAN\n\n작업 목표: $TASK" EXECUTION_PROMPT="이미 수립된 다음 계획서에 입각하여 작업자의 판단하에 코드를 구현하고 작업 목표를 완성해주세요. 계획서:\n$CURRENT_PLAN\n\n작업 목표: $TASK"
fi fi
@@ -0,0 +1,130 @@
#!/usr/bin/env bash
# resume_session.sh — resume a stopped session
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/lib.sh"
usage() {
cat <<EOF
Usage: $0 --workspace <path> --agent <claude|agy|hermes|cline> --session <name>
EOF
}
WORKSPACE=""
AGENT=""
SESSION_NAME=""
while [ $# -gt 0 ]; do
case "$1" in
--workspace) WORKSPACE="$2"; shift 2 ;;
--agent) AGENT="$2"; shift 2 ;;
--session) SESSION_NAME="$2"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) echo "ERROR: unknown arg: $1" >&2; exit 2 ;;
esac
done
[ -n "$WORKSPACE" ] || { echo "ERROR: --workspace required" >&2; exit 2; }
[ -n "$AGENT" ] || { echo "ERROR: --agent required" >&2; exit 2; }
[ -n "$SESSION_NAME" ] || { echo "ERROR: --session required" >&2; exit 2; }
# 1. Resolve the session id
UUID=$(bash "$(dirname "${BASH_SOURCE[0]}")/resolve_session_id.sh" \
--workspace "$WORKSPACE" --agent "$AGENT" --session "$SESSION_NAME")
if [ -z "$UUID" ]; then
echo "ERROR: No saved session for $WORKSPACE ($AGENT). Use multi-agent-mux-create first." >&2
exit 1
fi
export TMUX_SERVER_NAME="$(resolve_tmux_server "$SESSION_NAME")"
# 2. If tmux is alive, print warning or attach.
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
echo "tmux '$SESSION_NAME' already running."
# Just update YAML to make sure it's set to running
bash "$(dirname "${BASH_SOURCE[0]}")/update_yaml_resumed.sh" \
--session "$SESSION_NAME" --uuid "$UUID" --agent "$AGENT"
exit 0
fi
# 3. Resolve isolation settings for this session
ISO_ROOT=""
ISO_ENV=""
ISO_ARGS=""
ISO_DATA=$(env_python "$AGENT_SESSIONS_YAML" SESSION_NAME="$SESSION_NAME" <<'PYEOF'
import os, json, yaml, sqlite3
name = os.environ['SESSION_NAME']
yaml_path = os.environ['YAML_PATH']
db_path = os.path.splitext(yaml_path)[0] + '.db'
d = {}
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=60.0)
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
if row:
s = json.loads(row[0])
print(json.dumps(s.get('isolation') or {}))
raise SystemExit(0)
elif os.path.exists(yaml_path):
with open(yaml_path) as f:
d = yaml.safe_load(f) or {}
except Exception:
pass
for s in d.get('tmux_sessions', []):
if s.get('name') == name:
print(json.dumps(s.get('isolation') or {}))
raise SystemExit(0)
print("{}")
PYEOF
)
ISO_ROOT=$(printf '%s' "$ISO_DATA" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("root",""))')
if [ -n "$ISO_ROOT" ]; then
ISO_ENV="$(isolation_env_prefix "$AGENT" "$ISO_ROOT")"
ISO_ARGS="$(isolation_cmd_args "$AGENT" "$ISO_ROOT")"
echo "Re-applying isolation: root=$ISO_ROOT env=$ISO_ENV args=$ISO_ARGS"
fi
# Determine CMD_FULL with isolation applied
case "$AGENT" in
claude) CMD_FULL="claude --dangerously-skip-permissions -r $UUID" ;;
agy) CMD_FULL="agy --dangerously-skip-permissions --conversation $UUID" ;;
hermes) CMD_FULL="hermes --resume $UUID" ;;
cline) CMD_FULL="cline -i --id $UUID" ;;
esac
# Prepend env prefix and append command args (T4)
if [ -n "$ISO_ENV" ]; then
CMD_FULL="$ISO_ENV $CMD_FULL"
fi
if [ -n "$ISO_ARGS" ]; then
CMD_FULL="$CMD_FULL $ISO_ARGS"
fi
# 4. Spawn new tmux session + run agent with the saved id
case "$AGENT" in
claude)
if [ -z "$ISO_ROOT" ] && [ -x "$HOME/.local/bin/canary-projects-multi-agent-mux-creator-claude" ]; then
START_CMD="tmux new-session -d -s \"$SESSION_NAME\" -x 140 -y 40 -c \"$WORKSPACE\" \"$HOME/.local/bin/canary-projects-multi-agent-mux-creator-claude\""
else
START_CMD="tmux new-session -d -s \"$SESSION_NAME\" -x 140 -y 40 -c \"$WORKSPACE\" \"$CMD_FULL\""
fi
eval "$START_CMD"
# auto-handle trust / bypass dialogs
handle_startup_dialogs "$SESSION_NAME" 20
;;
agy|hermes|cline)
eval "tmux new-session -d -s \"$SESSION_NAME\" -x 140 -y 40 -c \"$WORKSPACE\" \"$CMD_FULL\""
;;
esac
# Wait for TUI readiness or let it settle
sleep 2
# 5. Update agent-sessions.yaml: status running, last_visible_status
bash "$(dirname "${BASH_SOURCE[0]}")/update_yaml_resumed.sh" \
--session "$SESSION_NAME" --uuid "$UUID" --agent "$AGENT"
echo "Successfully resumed $SESSION_NAME ($AGENT)"
+11 -7
View File
@@ -16,7 +16,7 @@ $ bash .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh \
[--max-loop N] \ [--max-loop N] \
[--verbose] \ [--verbose] \
[--cleanup] \ [--cleanup] \
--target-agent "canary-projects-multi-agent-mux-creator-claude" \ --target-agent "<creator-session-name>" \
--task "수행할 작업 목표" --task "수행할 작업 목표"
``` ```
@@ -24,7 +24,7 @@ $ bash .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh \
| 옵션명 | 기본값 | 분류 | 역할 및 안전 조치 | | 옵션명 | 기본값 | 분류 | 역할 및 안전 조치 |
|---|---|---|---| |---|---|---|---|
| `--plan` | 비활성 | 기능 | Planner 에이전트를 기동하여 협력 계획 수립 및 토론 단계 개시. | | `--plan` | 비활성 | 기능 | Planner 에이전트를 기동하여 협력 계획 수립 및 토론 단계 개시. (비활성화 시 기존 계획서를 로드하며, 계획서가 없는 경우 Creator가 직접 계획 및 설계를 수립하여 구동) |
| `--plan-talk N` | `1` | 안전 | 플래너-작업자 간 토론 왕복 횟수 상한선. 토큰 낭비 무한 토론 차단. | | `--plan-talk N` | `1` | 안전 | 플래너-작업자 간 토론 왕복 횟수 상한선. 토큰 낭비 무한 토론 차단. |
| `--reviewer "A,B"` | 비활성 | 기능 | 지정된 peer 리뷰어 에이전트 세션(들)에 피드백 루프 의뢰 (주 작업자 세션은 강제 제외). | | `--reviewer "A,B"` | 비활성 | 기능 | 지정된 peer 리뷰어 에이전트 세션(들)에 피드백 루프 의뢰 (주 작업자 세션은 강제 제외). |
| `--all-reviewer` | 비활성 | 기능 | 레지스트리 상의 모든 `role: reviewer` 세션들을 전수 자동 수집하여 의뢰 (주 작업자 세션은 강제 제외). | | `--all-reviewer` | 비활성 | 기능 | 레지스트리 상의 모든 `role: reviewer` 세션들을 전수 자동 수집하여 의뢰 (주 작업자 세션은 강제 제외). |
@@ -42,8 +42,8 @@ $ bash .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh \
sequenceDiagram sequenceDiagram
autonumber autonumber
actor User as 사용자 / run_loop.sh actor User as 사용자 / run_loop.sh
participant Plan as Planner Claude participant Plan as Planner Agent
participant Dev as Creator Claude participant Dev as Creator Agent
participant Rev as Reviewer Agents participant Rev as Reviewer Agents
User->>User: run_loop.sh 기동 (옵션 세트 검증 및 대상 예외 필터링) User->>User: run_loop.sh 기동 (옵션 세트 검증 및 대상 예외 필터링)
@@ -58,8 +58,12 @@ sequenceDiagram
Plan-->>Dev: 수정 반영 및 최종 계획 합의 Plan-->>Dev: 수정 반영 및 최종 계획 합의
end end
else --plan 미지정 else --plan 미지정
User->>Dev: Self-planning 지시 (스스로 계획 세워 즉시 시작) alt 기존 계획 존재 시
fi User->>Dev: 기존 계획서 로드 및 구현 지시
else 계획 미존재 시
User->>Dev: Self-planning 지시 (스스로 계획/설계 수립하여 구현)
end
end
%% Execution %% Execution
User->>Dev: delegate-job (작업 지시) User->>Dev: delegate-job (작업 지시)
@@ -77,7 +81,7 @@ sequenceDiagram
end end
else 리뷰어 미지정 else 리뷰어 미지정
User->>Dev: Self-Review 지시 (자가 검증 및 자율 종결) User->>Dev: Self-Review 지시 (자가 검증 및 자율 종결)
fi end
end end
%% Cleanup & Final Report %% Cleanup & Final Report