fix(fleet): consume model_hint + fix socket-default trap (#626)
Two spawn-side blockers found building the live PoC roster.
FIX 1 — model_hint not consumed: start-agent-session.sh built 'mosaic yolo
$RUNTIME' with no --model, so pi workers ignored the roster's model. Now
generateAgentEnv emits MOSAIC_AGENT_MODEL=<hint> and the launcher appends
${MOSAIC_AGENT_MODEL:+--model $MOSAIC_AGENT_MODEL} → workers run on e.g.
openai-codex/gpt-5.5:high.
FIX 2 — socket default trap: an ABSENT roster socket silently became
mosaic-factory in THREE places (parseRosterText fallback; the
mosaic-agent@.service Environment= default + ExecStop :-mosaic-factory;
start-agent-session :-mosaic-factory). The live PoC runs on the DEFAULT tmux
socket (socket_name absent). Now absent ⇒ '' ⇒ the literal default socket (no
-L) consistently across spawn, the systemd unit, fleet ps/watch observe, and
the onboarding cheat-sheet:
- socketArgs(name) → name ? ['-L', name] : []; replaces all ~15 -L sites in
fleet.ts. parseRosterText fallback '' (was DEFAULT_SOCKET_NAME).
- shellEnvValue('') now emits a BARE 'VAR=' (not ''), so a socket-less .env can
never yield a literal socket named "''" under systemd EnvironmentFile.
- start-agent-session.sh _tmux wrapper passes -L only when a socket is set;
mosaic-agent@.service drops the socket default + uses a conditional ExecStop.
CONTAINMENT: all 6 shipped presets set socket_name: mosaic-factory explicitly,
so they are unaffected — only socket-less rosters (the PoC) get default-socket
behavior. DEFAULT_SOCKET_NAME exported as a constant for explicit isolation.
Verified: 158 fleet + 201 fleet-adjacent tests green (socketArgs none/named,
model_hint→env, explicit-socket renders -L, socket-less bare env); shell bash -n
+ end-to-end sim (socket-less→no -L, model→--model); tsc/eslint/prettier/
sanitize clean.
Refs #626
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsgTQzV5YUGk1JtCLP4B83
This commit is contained in:
@@ -2,8 +2,12 @@
|
||||
set -euo pipefail
|
||||
|
||||
AGENT_NAME=${1:-${MOSAIC_AGENT_NAME:-}}
|
||||
MOSAIC_TMUX_SOCKET=${MOSAIC_TMUX_SOCKET:-mosaic-factory}
|
||||
# Absent socket ⇒ the LITERAL default tmux socket (no -L). The roster's
|
||||
# socket_name is honored when set; absent never silently becomes mosaic-factory
|
||||
# (spawn stays consistent with the onboarding cheat-sheet + fleet ps observe).
|
||||
MOSAIC_TMUX_SOCKET=${MOSAIC_TMUX_SOCKET:-}
|
||||
MOSAIC_AGENT_RUNTIME=${MOSAIC_AGENT_RUNTIME:-pi}
|
||||
MOSAIC_AGENT_MODEL=${MOSAIC_AGENT_MODEL:-}
|
||||
MOSAIC_AGENT_WORKDIR=${MOSAIC_AGENT_WORKDIR:-$HOME}
|
||||
MOSAIC_AGENT_COMMAND=${MOSAIC_AGENT_COMMAND:-}
|
||||
MOSAIC_HEARTBEAT_RUN_DIR=${MOSAIC_HEARTBEAT_RUN_DIR:-${MOSAIC_HOME:-$HOME/.config/mosaic}/fleet/run}
|
||||
@@ -19,13 +23,25 @@ if ! command -v tmux >/dev/null 2>&1; then
|
||||
exit 69
|
||||
fi
|
||||
|
||||
if tmux -L "$MOSAIC_TMUX_SOCKET" has-session -t "=${AGENT_NAME}:0.0" 2>/dev/null; then
|
||||
echo "Mosaic agent session already running: $AGENT_NAME on socket $MOSAIC_TMUX_SOCKET"
|
||||
# tmux wrapper: pass -L only when a socket is configured. An absent/empty socket
|
||||
# means the default tmux socket (no -L), keeping spawn == observe == cheat-sheet.
|
||||
_tmux() {
|
||||
if [ -n "$MOSAIC_TMUX_SOCKET" ]; then
|
||||
tmux -L "$MOSAIC_TMUX_SOCKET" "$@"
|
||||
else
|
||||
tmux "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if _tmux has-session -t "=${AGENT_NAME}:0.0" 2>/dev/null; then
|
||||
echo "Mosaic agent session already running: $AGENT_NAME on socket ${MOSAIC_TMUX_SOCKET:-(default)}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "$MOSAIC_AGENT_COMMAND" ]; then
|
||||
MOSAIC_AGENT_COMMAND="mosaic yolo $MOSAIC_AGENT_RUNTIME"
|
||||
# Map the roster's per-agent model_hint to `--model` so workers launch on the
|
||||
# configured model (e.g. pi on openai-codex/gpt-5.5:high). Omitted when unset.
|
||||
MOSAIC_AGENT_COMMAND="mosaic yolo $MOSAIC_AGENT_RUNTIME${MOSAIC_AGENT_MODEL:+ --model $MOSAIC_AGENT_MODEL}"
|
||||
fi
|
||||
|
||||
# ── Derive a runtime-bin PATH prefix ─────────────────────────────────────────
|
||||
@@ -107,13 +123,13 @@ fi
|
||||
mkdir -p "$MOSAIC_AGENT_WORKDIR"
|
||||
|
||||
# ── Launch the tmux session (no exec — we continue to wire the heartbeat) ────
|
||||
tmux -L "$MOSAIC_TMUX_SOCKET" new-session -d -s "$AGENT_NAME" -c "$MOSAIC_AGENT_WORKDIR" \
|
||||
_tmux new-session -d -s "$AGENT_NAME" -c "$MOSAIC_AGENT_WORKDIR" \
|
||||
bash -c "$PANE_SHELL_SNIPPET"
|
||||
|
||||
# ── Resolve the pane PID (retry briefly to let the session initialise) ────────
|
||||
PANE_PID=""
|
||||
for _retry in 1 2 3 4 5; do
|
||||
PANE_PID=$(tmux -L "$MOSAIC_TMUX_SOCKET" list-panes \
|
||||
PANE_PID=$(_tmux list-panes \
|
||||
-t "=${AGENT_NAME}:0.0" -F '#{pane_pid}' 2>/dev/null || true)
|
||||
[ -n "$PANE_PID" ] && break
|
||||
sleep 0.2
|
||||
|
||||
Reference in New Issue
Block a user