feat: write session lock from all launcher paths
All launch paths (claude, codex, opencode, yolo variants) now write a session.lock before exec'ing, so `mosaic coord status` can detect running agent sessions. Stale locks from dead sessions are cleaned up automatically on next launch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
58
bin/mosaic
58
bin/mosaic
@@ -247,6 +247,47 @@ _detect_mission_prompt() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Write a session lock if an active mission exists in the current directory.
|
||||
# Called before exec so $$ captures the PID that will become the agent process.
|
||||
_write_launcher_session_lock() {
|
||||
local runtime="$1"
|
||||
local mission_file=".mosaic/orchestrator/mission.json"
|
||||
local lock_file=".mosaic/orchestrator/session.lock"
|
||||
|
||||
# Only write lock if mission exists and is active
|
||||
[[ -f "$mission_file" ]] || return 0
|
||||
command -v jq &>/dev/null || return 0
|
||||
|
||||
local m_status
|
||||
m_status="$(jq -r '.status // "inactive"' "$mission_file" 2>/dev/null)"
|
||||
[[ "$m_status" == "active" || "$m_status" == "paused" ]] || return 0
|
||||
|
||||
local session_id
|
||||
session_id="${runtime}-$(date +%Y%m%d-%H%M%S)-$$"
|
||||
|
||||
jq -n \
|
||||
--arg sid "$session_id" \
|
||||
--arg rt "$runtime" \
|
||||
--arg pid "$$" \
|
||||
--arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||
--arg pp "$(pwd)" \
|
||||
--arg mid "" \
|
||||
'{
|
||||
session_id: $sid,
|
||||
runtime: $rt,
|
||||
pid: ($pid | tonumber),
|
||||
started_at: $ts,
|
||||
project_path: $pp,
|
||||
milestone_id: $mid
|
||||
}' > "$lock_file"
|
||||
}
|
||||
|
||||
# Clean up session lock on exit (covers normal exit + signals).
|
||||
# Registered via trap after _write_launcher_session_lock succeeds.
|
||||
_cleanup_session_lock() {
|
||||
rm -f ".mosaic/orchestrator/session.lock" 2>/dev/null
|
||||
}
|
||||
|
||||
# Launcher functions
|
||||
launch_claude() {
|
||||
check_mosaic_home
|
||||
@@ -263,6 +304,8 @@ launch_claude() {
|
||||
|
||||
# If active mission exists and no user prompt was given, inject initial prompt
|
||||
_detect_mission_prompt
|
||||
_write_launcher_session_lock "claude"
|
||||
trap _cleanup_session_lock EXIT INT TERM
|
||||
if [[ -n "$MOSAIC_MISSION_PROMPT" && $# -eq 0 ]]; then
|
||||
echo "[mosaic] Launching Claude Code (active mission detected)..."
|
||||
exec claude --append-system-prompt "$runtime_prompt" "$MOSAIC_MISSION_PROMPT"
|
||||
@@ -283,6 +326,8 @@ launch_opencode() {
|
||||
|
||||
# OpenCode reads from ~/.config/opencode/AGENTS.md
|
||||
ensure_runtime_config "opencode" "$HOME/.config/opencode/AGENTS.md"
|
||||
_write_launcher_session_lock "opencode"
|
||||
trap _cleanup_session_lock EXIT INT TERM
|
||||
echo "[mosaic] Launching OpenCode..."
|
||||
exec opencode "$@"
|
||||
}
|
||||
@@ -298,6 +343,8 @@ launch_codex() {
|
||||
|
||||
# Codex reads from ~/.codex/instructions.md
|
||||
ensure_runtime_config "codex" "$HOME/.codex/instructions.md"
|
||||
_write_launcher_session_lock "codex"
|
||||
trap _cleanup_session_lock EXIT INT TERM
|
||||
echo "[mosaic] Launching Codex..."
|
||||
exec codex "$@"
|
||||
}
|
||||
@@ -325,6 +372,8 @@ launch_yolo() {
|
||||
runtime_prompt="$(build_runtime_prompt "claude")"
|
||||
|
||||
_detect_mission_prompt
|
||||
_write_launcher_session_lock "claude"
|
||||
trap _cleanup_session_lock EXIT INT TERM
|
||||
if [[ -n "$MOSAIC_MISSION_PROMPT" && $# -eq 0 ]]; then
|
||||
echo "[mosaic] Launching Claude Code in YOLO mode (active mission detected)..."
|
||||
exec claude --dangerously-skip-permissions --append-system-prompt "$runtime_prompt" "$MOSAIC_MISSION_PROMPT"
|
||||
@@ -342,6 +391,8 @@ launch_yolo() {
|
||||
|
||||
# Codex reads instructions.md from ~/.codex and supports a direct dangerous flag.
|
||||
ensure_runtime_config "codex" "$HOME/.codex/instructions.md"
|
||||
_write_launcher_session_lock "codex"
|
||||
trap _cleanup_session_lock EXIT INT TERM
|
||||
echo "[mosaic] Launching Codex in YOLO mode (dangerous permissions enabled)..."
|
||||
exec codex --dangerously-bypass-approvals-and-sandbox "$@"
|
||||
;;
|
||||
@@ -354,6 +405,8 @@ launch_yolo() {
|
||||
|
||||
# OpenCode defaults to allow-all permissions unless user config restricts them.
|
||||
ensure_runtime_config "opencode" "$HOME/.config/opencode/AGENTS.md"
|
||||
_write_launcher_session_lock "opencode"
|
||||
trap _cleanup_session_lock EXIT INT TERM
|
||||
echo "[mosaic] Launching OpenCode in YOLO mode..."
|
||||
exec opencode "$@"
|
||||
;;
|
||||
@@ -469,8 +522,9 @@ _check_resumable_session() {
|
||||
local pid
|
||||
pid="$(jq -r '.pid // 0' "$lock_file" 2>/dev/null)"
|
||||
if [[ -n "$pid" ]] && [[ "$pid" != "0" ]] && ! kill -0 "$pid" 2>/dev/null; then
|
||||
echo "[mosaic] Previous orchestration session detected (crashed)."
|
||||
echo "[mosaic] Run: mosaic coord resume"
|
||||
# Stale lock from a dead session — clean it up
|
||||
rm -f "$lock_file"
|
||||
echo "[mosaic] Cleaned up stale session lock (PID $pid no longer running)."
|
||||
echo ""
|
||||
fi
|
||||
elif [[ -f "$mission_file" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user