- Update .agents/MULTI_AGENT_RULES.md & .ko.md to align with TMUX concepts - Add .agents/INSTALL.md guide for MAM setup and workflows - Clean up legacy markdown reports under .agents/reports/ - Refactor MAM scripts in .agents/skills/ (rename resolve_herdr_session to resolve_herdr_workspace) - Improve workspace pane splitting/re-use logic in lib.sh - Reduce paste safety sleep in send_keys_safe and support linking ~/.claude.json
420 lines
17 KiB
Bash
Executable File
420 lines
17 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# create_session.sh — multi-agent-mux-create 의 부속 스크립트
|
|
# Usage:
|
|
# bash create_session.sh --workspace <path> --agent <claude|agy> --role <role> [--session <name>] [--wrapper]
|
|
#
|
|
# 동작:
|
|
# 1) preflight: herdr/claude/agy 가용성, workspace 존재
|
|
# 2) herdr 세션 이름 결정 (--session 없으면 자동)
|
|
# 3) herdr 세션 시작 (claude 는 wrapper 우선, agy 는 인라인)
|
|
# 4) pane 메타 캡처 (pid, cmd, cwd)
|
|
# 5) agent-sessions.yaml 에 herdr_sessions[] 엔트리 append
|
|
# 6) 검증 출력
|
|
#
|
|
# Exit codes:
|
|
# 0 = success
|
|
# 1 = preflight failure
|
|
# 2 = invalid args
|
|
# 3 = herdr session already exists (use multi-agent-mux-resume or delete first)
|
|
# 4 = agent-sessions.yaml append failure
|
|
set -euo pipefail
|
|
|
|
source "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/lib.sh"
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $0 --workspace <path> --agent <claude|agy|hermes|cline> --role <role> [options]
|
|
|
|
Options:
|
|
--workspace PATH project directory (required)
|
|
--agent AGENT claude | agy | hermes | cline (required)
|
|
--role ROLE assigned role (required)
|
|
--session NAME herdr session name (default: derived from workspace)
|
|
--wrapper force use of ~/.local/bin/<session> wrapper even if not present
|
|
--dry-run print commands without executing
|
|
--herdr-server NAME specify isolated herdr server name
|
|
--submit-job PROMPT submit a job to multi-agent-mux-delegate-job registry with the given prompt
|
|
--onboard automatically submit a project alignment/orientation job to the new agent
|
|
--no-isolate disable state isolation (shares global configuration/history)
|
|
[default: isolated mode is always active]
|
|
-h, --help this help
|
|
EOF
|
|
}
|
|
|
|
WORKSPACE=""
|
|
AGENT=""
|
|
ROLE=""
|
|
SESSION_NAME=""
|
|
USE_WRAPPER=0
|
|
DRY_RUN=0
|
|
HERDR_SERVER_OPT=""
|
|
SUBMIT_JOB_PROMPT=""
|
|
ONBOARD=0
|
|
ISOLATE=1
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--workspace) WORKSPACE="$2"; shift 2 ;;
|
|
--agent) AGENT="$2"; shift 2 ;;
|
|
--role) ROLE="$2"; shift 2 ;;
|
|
--session) SESSION_NAME="$2"; shift 2 ;;
|
|
--wrapper) USE_WRAPPER=1; shift ;;
|
|
--dry-run) DRY_RUN=1; shift ;;
|
|
--herdr-server) HERDR_SERVER_OPT="$2"; shift 2 ;;
|
|
--submit-job) SUBMIT_JOB_PROMPT="$2"; shift 2 ;;
|
|
--onboard) ONBOARD=1; shift ;;
|
|
--isolate) ISOLATE=1; shift ;; # legacy compatibility
|
|
--no-isolate) ISOLATE=0; shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "ERROR: unknown arg: $1" >&2; usage; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
if [ -n "$HERDR_SERVER_OPT" ]; then
|
|
export HERDR_SERVER_NAME="$HERDR_SERVER_OPT"
|
|
fi
|
|
|
|
# Preflight
|
|
[ -n "$WORKSPACE" ] || { echo "ERROR: --workspace required" >&2; usage; exit 2; }
|
|
[ -n "$AGENT" ] || { echo "ERROR: --agent required" >&2; usage; exit 2; }
|
|
[ -n "$ROLE" ] || { echo "ERROR: --role required" >&2; usage; exit 2; }
|
|
[ -d "$WORKSPACE" ] || { echo "ERROR: workspace $WORKSPACE not a directory" >&2; exit 1; }
|
|
command -v herdr >/dev/null || { echo "ERROR: herdr not installed" >&2; exit 1; }
|
|
command -v "$AGENT" >/dev/null || { echo "ERROR: $AGENT CLI not in PATH" >&2; exit 1; }
|
|
|
|
# Auth Check (OAuth check for agy, loggedIn check for claude, status for hermes)
|
|
if [ "$AGENT" = "claude" ]; then
|
|
if ! claude auth status 2>/dev/null | grep -q '"loggedIn":\s*true'; then
|
|
echo "ERROR: claude not logged in. Run 'claude auth login' first." >&2
|
|
exit 1
|
|
fi
|
|
elif [ "$AGENT" = "agy" ]; 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
|
|
elif [ "$AGENT" = "hermes" ]; then
|
|
if ! hermes status >/dev/null 2>&1; then
|
|
echo "ERROR: hermes is not functional. Run 'hermes setup' first." >&2
|
|
exit 1
|
|
fi
|
|
elif [ "$AGENT" = "cline" ]; then
|
|
if ! cline history --json >/dev/null 2>&1; then
|
|
echo "ERROR: cline is not functional or configured." >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# 세션 이름 — lib.sh::derive_session_name 이 단일 소스 (P0-A)
|
|
if [ -z "$SESSION_NAME" ]; then
|
|
SESSION_NAME="$(derive_session_name "$WORKSPACE" "$AGENT")"
|
|
fi
|
|
|
|
# 이미 살아있으면 실패
|
|
if _herdr has-session -t "$SESSION_NAME" 2>/dev/null; then
|
|
echo "ERROR: herdr session '$SESSION_NAME' already exists. Use multi-agent-mux-resume to attach, or multi-agent-mux-stop first." >&2
|
|
exit 3
|
|
fi
|
|
|
|
# T3: 세션 격리 프로비저닝 (all-L2) — 격리 홈 생성 + auth/설정 심링크 시딩
|
|
# (implementation_plan.session_isolation.md Rev.3 / Phase 0 실측 매트릭스 기준)
|
|
ISOLATION_UUID=""
|
|
ISOLATION_ROOT=""
|
|
ISOLATION_LEVER=""
|
|
ISOLATION_SEEDED=""
|
|
if [ "$ISOLATE" = "1" ]; then
|
|
command -v uuidgen >/dev/null || { echo "ERROR: uuidgen not found (required for --isolate)" >&2; exit 1; }
|
|
WORKSPACE_ABS="$(cd "$WORKSPACE" && pwd)"
|
|
ISOLATION_UUID="$(uuidgen)"
|
|
ISOLATION_ROOT="$WORKSPACE_ABS/.mam/agent_homes/$ISOLATION_UUID"
|
|
ISOLATION_LEVER="$(isolation_lever "$AGENT")"
|
|
if [ "$DRY_RUN" = "1" ]; then
|
|
echo "[dry-run] would provision isolation: lever=$ISOLATION_LEVER root=$ISOLATION_ROOT"
|
|
else
|
|
ISOLATION_SEEDED="$(provision_isolation "$AGENT" "$ISOLATION_ROOT")"
|
|
echo "isolation: lever=$ISOLATION_LEVER root=$ISOLATION_ROOT"
|
|
fi
|
|
fi
|
|
|
|
# herdr 세션 띄우기
|
|
LOCAL_BIN="${LOCAL_BIN:-$HOME/.local/bin}"
|
|
WRAPPER="$LOCAL_BIN/$SESSION_NAME"
|
|
|
|
# cmd_full 결정 — T4: isolation 디스패치(env prefix / CLI args)를 시작 명령에 주입.
|
|
# 격리 미사용 시 기존 문자열과 byte-identical (V4 회귀 0).
|
|
ISO_ENV_PREFIX=""
|
|
ISO_CMD_ARGS=""
|
|
if [ -n "$ISOLATION_ROOT" ]; then
|
|
ISO_ENV_PREFIX="$(isolation_env_prefix "$AGENT" "$ISOLATION_ROOT")"
|
|
ISO_CMD_ARGS="$(isolation_cmd_args "$AGENT" "$ISOLATION_ROOT")"
|
|
fi
|
|
|
|
# Resolve absolute path of the agent command to prevent herdr 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
|
|
claude) CMD_FULL="${ISO_ENV_PREFIX}${RESOLVED_BIN} --dangerously-skip-permissions" ;;
|
|
agy) CMD_FULL="${ISO_ENV_PREFIX}${RESOLVED_BIN} --dangerously-skip-permissions" ;;
|
|
hermes) CMD_FULL="${ISO_ENV_PREFIX}${RESOLVED_BIN}" ;;
|
|
cline) CMD_FULL="${RESOLVED_BIN} -i${ISO_CMD_ARGS:+ $ISO_CMD_ARGS}" ;;
|
|
esac
|
|
|
|
spawn() {
|
|
case "$AGENT" in
|
|
claude)
|
|
# 격리 시 wrapper 경로는 env 주입을 운반하지 못하므로 인라인 spawn 강제
|
|
if [ "$ISOLATE" != "1" ] && { { [ -x "$WRAPPER" ] && [ "$(basename "$WRAPPER")" != "claude" ]; } || [ "$USE_WRAPPER" = "1" ]; }; then
|
|
nohup "$WRAPPER" >/dev/null 2>&1 &
|
|
disown
|
|
else
|
|
_herdr new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" "$CMD_FULL"
|
|
fi
|
|
;;
|
|
agy|hermes|cline)
|
|
_herdr new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" "$CMD_FULL"
|
|
;;
|
|
*) echo "ERROR: --agent must be claude, agy, hermes or cline, got: $AGENT" >&2; exit 2 ;;
|
|
esac
|
|
}
|
|
|
|
if [ "$DRY_RUN" = "1" ]; then
|
|
echo "[dry-run] would spawn: herdr session '$SESSION_NAME' in $WORKSPACE (agent=$AGENT)"
|
|
exit 0
|
|
fi
|
|
|
|
spawn
|
|
|
|
# Trap for rolling back/cleaning up herdr session if script exits due to error
|
|
cleanup_herdr_on_error() {
|
|
local exit_code=$?
|
|
if [ $exit_code -ne 0 ]; then
|
|
echo "⚠️ Error occurred during initialization. Rolling back and killing herdr session '$SESSION_NAME'..." >&2
|
|
_herdr kill-session -t "$SESSION_NAME" 2>/dev/null || true
|
|
# T3 rollback: 이 세션용으로 프로비저닝한 격리 홈 제거 (경로 가드 후 rm)
|
|
if [ -n "$ISOLATION_ROOT" ] && [ -d "$ISOLATION_ROOT" ]; then
|
|
case "$ISOLATION_ROOT" in
|
|
*/.mam/agent_homes/*) rm -rf "$ISOLATION_ROOT" ;;
|
|
esac
|
|
fi
|
|
fi
|
|
}
|
|
trap cleanup_herdr_on_error EXIT
|
|
|
|
# TUI 준비 대기
|
|
if ! wait_for_tui_ready "$SESSION_NAME" "$AGENT"; then
|
|
echo "ERROR: agent TUI never became ready — aborting (rollback via trap)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# pane 메타 캡처
|
|
PANE_PID=$(_herdr list-panes -t "$SESSION_NAME" -F '#{pane_pid}' 2>/dev/null || echo "")
|
|
PANE_CWD=$(_herdr list-panes -t "$SESSION_NAME" -F '#{pane_current_path}' 2>/dev/null || echo "$WORKSPACE")
|
|
PANE_CMD=$(_herdr list-panes -t "$SESSION_NAME" -F '#{pane_current_command}' 2>/dev/null || echo "$AGENT")
|
|
HERDR_EPOCH=$(date +%s)
|
|
NOW_ISO=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
|
|
|
# 시작 명령 (CMD_FULL 은 spawn 전에 isolation 디스패치를 반영해 확정됨 — T4)
|
|
# NOTE: this must match what `spawn()` actually ran above — env-var-driven
|
|
# isolation (HERDR_SERVER_NAME picked up by the lib.sh shim), not a
|
|
# `--workspace <label>` flag (real `herdr agent start --workspace` wants an
|
|
# actual workspace id like "w2", which HERDR_SERVER_NAME is not).
|
|
START_CMD="HERDR_SERVER_NAME=${HERDR_SERVER_NAME:-default} herdr new-session -d -s \"$SESSION_NAME\" -x 140 -y 40 -c \"$WORKSPACE\" \"$CMD_FULL\""
|
|
|
|
# If --onboard is specified, automatically build the onboarding prompt
|
|
if [ "$ONBOARD" = "1" ] && [ -z "$SUBMIT_JOB_PROMPT" ]; then
|
|
SUBMIT_JOB_PROMPT="You are a newly spawned $ROLE Team Leader agent in this workspace. To align yourself with the project context, perform the following tasks:
|
|
1. Read the project documentation at README.md and the multi-agent protocol guidelines at .agents/MULTI_AGENT_RULES.md to understand the design rules.
|
|
2. Run 'git status' and 'git diff' to analyze the current modifications and active work in the repository.
|
|
3. Read .mam/agent-sessions.yaml to see other running agent sessions, their roles, and confirm your own assigned role: $ROLE.
|
|
4. Once you have fully comprehended the project state, publish a completed event (using publish_event.py) with the detail 'Onboarding complete; aligned with role $ROLE'."
|
|
fi
|
|
|
|
# agent-sessions.yaml 에 append
|
|
DELEGATE_JOB_ID=""
|
|
if [ -n "$SUBMIT_JOB_PROMPT" ]; then
|
|
delegate_agent=""
|
|
if [ "$AGENT" = "claude" ]; then
|
|
delegate_agent="claude-code"
|
|
elif [ "$AGENT" = "hermes" ]; then
|
|
delegate_agent="hermes-agent"
|
|
elif [ "$AGENT" = "cline" ]; then
|
|
delegate_agent="cline-agent"
|
|
else
|
|
delegate_agent="antigravity-cli"
|
|
fi
|
|
agent_session="herdr:$SESSION_NAME"
|
|
DELEGATE_JOB_ID=$(delegate_submit_job "$SUBMIT_JOB_PROMPT" "$delegate_agent" "$agent_session")
|
|
echo "Submitted delegated job: $DELEGATE_JOB_ID"
|
|
fi
|
|
|
|
if [ ! -f "$AGENT_SESSIONS_YAML" ]; then
|
|
mkdir -p "$(dirname "$AGENT_SESSIONS_YAML")"
|
|
echo "herdr_sessions: []" > "$AGENT_SESSIONS_YAML"
|
|
fi
|
|
|
|
# atomic_dump_yaml: flock + temp+rename + .bak + schema validate (P0-B).
|
|
# 모든 값은 환경변수로 전달 — heredoc interpolation 없음 (P1-B).
|
|
# 자식 pid 는 bash 에서 pgrep 으로 미리 구함 (P2: 도구명 필터).
|
|
CHILD_PID=0
|
|
if { [ "$AGENT" = "agy" ] || [ "$AGENT" = "hermes" ] || [ "$AGENT" = "cline" ]; } && [ -n "$PANE_PID" ]; then
|
|
CHILD_PID=$(pgrep -P "$PANE_PID" -x "$AGENT" 2>/dev/null | head -1 || true)
|
|
CHILD_PID="${CHILD_PID:-0}"
|
|
fi
|
|
|
|
atomic_dump_yaml "$AGENT_SESSIONS_YAML" \
|
|
SESSION_NAME="$SESSION_NAME" AGENT="$AGENT" NOW_ISO="$NOW_ISO" \
|
|
HERDR_EPOCH="$HERDR_EPOCH" PANE_PID="$PANE_PID" PANE_CWD="$PANE_CWD" \
|
|
CMD_FULL="$CMD_FULL" START_CMD="$START_CMD" CHILD_PID="$CHILD_PID" \
|
|
HERDR_SERVER_NAME="${HERDR_SERVER_NAME:-default}" \
|
|
DELEGATE_JOB_ID="$DELEGATE_JOB_ID" ROLE="$ROLE" \
|
|
ISOLATION_UUID="$ISOLATION_UUID" ISOLATION_ROOT="$ISOLATION_ROOT" \
|
|
ISOLATION_LEVER="$ISOLATION_LEVER" ISOLATION_SEEDED="$ISOLATION_SEEDED" <<'PYEOF'
|
|
name = os.environ['SESSION_NAME']
|
|
agent = os.environ['AGENT']
|
|
role = os.environ['ROLE']
|
|
pid = os.environ.get('PANE_PID', '')
|
|
epoch = os.environ.get('HERDR_EPOCH', '')
|
|
server_name = os.environ.get('HERDR_SERVER_NAME', 'default')
|
|
server_opt = f"-L {server_name} " if server_name and server_name != 'default' else ""
|
|
|
|
sessions = d.setdefault('herdr_sessions', [])
|
|
|
|
# P0-D: 같은 이름 엔트리가 status=running 이면만 거부. terminated/archived 는
|
|
# 재사용 가능 — 낡은 엔트리를 제거하고 새로 append (create -> delete -> create).
|
|
running_same = [s for s in sessions if s.get('name') == name and s.get('status') == 'running']
|
|
if running_same:
|
|
print(f"ERROR: {name} already running in agent-sessions.yaml", flush=True)
|
|
raise SystemExit(4)
|
|
sessions[:] = [s for s in sessions if s.get('name') != name]
|
|
|
|
entry = {
|
|
'name': name,
|
|
'status': 'running',
|
|
'role': role,
|
|
'herdr_session_created_at': os.environ['NOW_ISO'],
|
|
'herdr_session_epoch': int(epoch) if epoch.isdigit() else 0,
|
|
'herdr_server': server_name,
|
|
'delegate_job_id': os.environ.get('DELEGATE_JOB_ID', '') or None,
|
|
'pane': {
|
|
'index': 0,
|
|
'pid': int(pid) if pid.isdigit() else 0,
|
|
'cmd': agent,
|
|
'cmd_full': os.environ['CMD_FULL'],
|
|
'cwd': os.environ['PANE_CWD'],
|
|
},
|
|
'start_command': os.environ['START_CMD'],
|
|
# NOTE: `herdr session attach/stop/delete` operate on whole herdr
|
|
# *sessions* (server instances, e.g. "default") — NOT on an individual
|
|
# agent by its MAM name. Use the lib.sh tmux-compat shim commands
|
|
# instead (`source .agents/skills/lib.sh` first), scoped via the same
|
|
# env-var-driven isolation as start_command above.
|
|
'attach_command': f'HERDR_SERVER_NAME={server_name} herdr agent attach {name}',
|
|
'kill_command': f'HERDR_SERVER_NAME={server_name} herdr kill-session -t {name}',
|
|
}
|
|
|
|
# T5: isolation 블록 영속화 (all-L2) — resume/resolve/stop 이 재적용의 단일 소스로 사용
|
|
iso_uuid = os.environ.get('ISOLATION_UUID', '')
|
|
if iso_uuid:
|
|
entry['isolation'] = {
|
|
'uuid': iso_uuid,
|
|
'root': os.environ.get('ISOLATION_ROOT', ''),
|
|
'lever': os.environ.get('ISOLATION_LEVER', ''),
|
|
'seeded': [x for x in os.environ.get('ISOLATION_SEEDED', '').split(',') if x],
|
|
}
|
|
|
|
if agent == 'claude':
|
|
entry['tui'] = {
|
|
'model': '(unknown — capture after first message)',
|
|
'provider': 'anthropic',
|
|
'plan': '(unknown)',
|
|
'account': '(unknown — read from claude auth status)',
|
|
'version': '(unknown — read from TUI)',
|
|
}
|
|
entry['claude_session_id_own'] = None
|
|
entry['last_visible_status'] = "TUI started; awaiting first user message"
|
|
elif agent == 'agy':
|
|
cp = os.environ.get('CHILD_PID', '0')
|
|
entry['child_pid'] = int(cp) if cp.isdigit() else 0
|
|
entry['agy_conversation_id_own'] = None
|
|
entry['mcp_attachments'] = [
|
|
{
|
|
'name': 'stitch',
|
|
'transport': 'mcp-remote',
|
|
'endpoint': 'https://stitch.googleapis.com/mcp'
|
|
}
|
|
]
|
|
entry['last_visible_status'] = "TUI started; awaiting first user message"
|
|
elif agent == 'hermes':
|
|
cp = os.environ.get('CHILD_PID', '0')
|
|
entry['child_pid'] = int(cp) if cp.isdigit() else 0
|
|
entry['hermes_conversation_id_own'] = None
|
|
entry['last_visible_status'] = "TUI started; awaiting first user message"
|
|
elif agent == 'cline':
|
|
cp = os.environ.get('CHILD_PID', '0')
|
|
entry['child_pid'] = int(cp) if cp.isdigit() else 0
|
|
entry['cline_conversation_id_own'] = None
|
|
entry['last_visible_status'] = "TUI started; awaiting first user message"
|
|
|
|
sessions.append(entry)
|
|
|
|
snap = d.setdefault('snapshot', {})
|
|
snap['taken_at'] = os.environ['NOW_ISO']
|
|
snap['cwd'] = os.environ['PANE_CWD']
|
|
print(f"appended: {name}", flush=True)
|
|
PYEOF
|
|
|
|
echo
|
|
echo "=== created ==="
|
|
echo "herdr session: $SESSION_NAME (pane pid $PANE_PID, cmd $PANE_CMD, cwd $PANE_CWD)"
|
|
if [ -n "$DELEGATE_JOB_ID" ]; then
|
|
echo "delegate job: $DELEGATE_JOB_ID"
|
|
|
|
# Construct instructions matching multi-agent-mux-delegate-job format
|
|
py_bin="$(_delegate_py_bin)"
|
|
pub="$py_bin .agents/skills/multi-agent-mux-delegate-job/scripts/publish_event.py --job $DELEGATE_JOB_ID"
|
|
instructions="Your job_id is \"$DELEGATE_JOB_ID\" (the one just registered for THIS delegation).
|
|
|
|
On start run: $pub --event started.
|
|
On progress (optional): $pub --event progress --detail '<short status>'.
|
|
On success run: $pub --event completed --detail '<one-line summary>'.
|
|
On failure run: $pub --event error --detail '<one-line reason>'.
|
|
|
|
Task: $SUBMIT_JOB_PROMPT"
|
|
|
|
# Inject instructions into the herdr pane
|
|
rc=0
|
|
inject_instructions "$SESSION_NAME" "$instructions" "$DELEGATE_JOB_ID" || rc=$?
|
|
if [ "$rc" -ne 0 ]; then
|
|
delegate_publish_event "$DELEGATE_JOB_ID" error "instruction injection failed (prompt-lock, rc=$rc)"
|
|
exit 1
|
|
fi
|
|
|
|
delegate_publish_event "$DELEGATE_JOB_ID" started "multi-agent-mux session created and instructions injected"
|
|
WD_PID=$(start_watchdog "$DELEGATE_JOB_ID" "$WORKSPACE")
|
|
echo "watchdog PID: $WD_PID"
|
|
fi
|
|
# Clear cleanup trap as registration was fully successful
|
|
trap - EXIT
|
|
echo "agent-sessions.yaml updated"
|
|
echo
|
|
echo "Attach: herdr session attach $SESSION_NAME"
|
|
echo "Delete: use multi-agent-mux-stop skill"
|
|
echo "Resume: use multi-agent-mux-resume skill (after first message creates a session id)"
|