fix: move mission context to top of system prompt + auto-inject initial prompt
Mission context was buried at the end of a 21K char system prompt and the agent ignored it. Two fixes: 1. Mission block now emits FIRST in build_runtime_prompt() so it's the most prominent instruction the agent sees 2. When an active mission exists and no user prompt is given, auto-inject an initial user message triggering the agent to read mission state files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
111
bin/mosaic
111
bin/mosaic
@@ -138,6 +138,44 @@ build_runtime_prompt() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Inject active mission context FIRST so the agent sees it immediately
|
||||||
|
local mission_file=".mosaic/orchestrator/mission.json"
|
||||||
|
if [[ -f "$mission_file" ]] && command -v jq &>/dev/null; then
|
||||||
|
local m_status
|
||||||
|
m_status="$(jq -r '.status // "inactive"' "$mission_file" 2>/dev/null)"
|
||||||
|
if [[ "$m_status" == "active" || "$m_status" == "paused" ]]; then
|
||||||
|
local m_name m_id m_count m_completed
|
||||||
|
m_name="$(jq -r '.name // "unnamed"' "$mission_file")"
|
||||||
|
m_id="$(jq -r '.mission_id // ""' "$mission_file")"
|
||||||
|
m_count="$(jq '.milestones | length' "$mission_file")"
|
||||||
|
m_completed="$(jq '[.milestones[] | select(.status == "completed")] | length' "$mission_file")"
|
||||||
|
|
||||||
|
cat <<MISSION_EOF
|
||||||
|
# ACTIVE MISSION — HARD GATE (Read Before Anything Else)
|
||||||
|
|
||||||
|
An active orchestration mission exists in this project. This is a BLOCKING requirement.
|
||||||
|
|
||||||
|
**Mission:** $m_name
|
||||||
|
**ID:** $m_id
|
||||||
|
**Status:** $m_status
|
||||||
|
**Milestones:** $m_completed / $m_count completed
|
||||||
|
|
||||||
|
## MANDATORY — Before ANY Response to the User
|
||||||
|
|
||||||
|
You MUST complete these steps before responding to any user message, including simple greetings:
|
||||||
|
|
||||||
|
1. Read \`~/.config/mosaic/guides/ORCHESTRATOR-PROTOCOL.md\` (mission lifecycle protocol)
|
||||||
|
2. Read \`docs/MISSION-MANIFEST.md\` for full mission scope, milestones, and success criteria
|
||||||
|
3. Read the latest scratchpad in \`docs/scratchpads/\` for session history, decisions, and corrections
|
||||||
|
4. Read \`docs/TASKS.md\` for current task state (what is done, what is next)
|
||||||
|
5. After reading all four, acknowledge the mission state to the user before proceeding
|
||||||
|
|
||||||
|
If the user gives a task, execute it within the mission context. If no task is given, present mission status and ask how to proceed.
|
||||||
|
|
||||||
|
MISSION_EOF
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
# Mosaic Launcher Runtime Contract (Hard Gate)
|
# Mosaic Launcher Runtime Contract (Hard Gate)
|
||||||
|
|
||||||
@@ -169,40 +207,6 @@ EOF
|
|||||||
|
|
||||||
printf '\n\n# Runtime-Specific Contract\n\n'
|
printf '\n\n# Runtime-Specific Contract\n\n'
|
||||||
cat "$runtime_file"
|
cat "$runtime_file"
|
||||||
|
|
||||||
# Inject active mission context if present in CWD
|
|
||||||
local mission_file=".mosaic/orchestrator/mission.json"
|
|
||||||
if [[ -f "$mission_file" ]] && command -v jq &>/dev/null; then
|
|
||||||
local status
|
|
||||||
status="$(jq -r '.status // "inactive"' "$mission_file" 2>/dev/null)"
|
|
||||||
if [[ "$status" == "active" || "$status" == "paused" ]]; then
|
|
||||||
local m_name m_id m_count m_completed
|
|
||||||
m_name="$(jq -r '.name // "unnamed"' "$mission_file")"
|
|
||||||
m_id="$(jq -r '.mission_id // ""' "$mission_file")"
|
|
||||||
m_count="$(jq '.milestones | length' "$mission_file")"
|
|
||||||
m_completed="$(jq '[.milestones[] | select(.status == "completed")] | length' "$mission_file")"
|
|
||||||
|
|
||||||
printf '\n\n# Active Mission Context\n\n'
|
|
||||||
cat <<MISSION_EOF
|
|
||||||
An active orchestration mission has been detected in this project.
|
|
||||||
|
|
||||||
**Mission:** $m_name
|
|
||||||
**ID:** $m_id
|
|
||||||
**Status:** $status
|
|
||||||
**Milestones:** $m_completed / $m_count completed
|
|
||||||
|
|
||||||
## MANDATORY First Actions
|
|
||||||
|
|
||||||
1. Load \`~/.config/mosaic/guides/ORCHESTRATOR-PROTOCOL.md\` (mission lifecycle protocol)
|
|
||||||
2. Read \`docs/MISSION-MANIFEST.md\` for full mission scope, milestones, and success criteria
|
|
||||||
3. Read \`docs/scratchpads/${m_id}.md\` for session history, decisions, and corrections
|
|
||||||
4. Read \`docs/TASKS.md\` for current task state (what is done, what is next)
|
|
||||||
5. Do NOT begin any coding or planning until you have read all four documents above
|
|
||||||
|
|
||||||
You are resuming an existing mission. The state files are the source of truth.
|
|
||||||
MISSION_EOF
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure runtime contract is present at the runtime's native config path.
|
# Ensure runtime contract is present at the runtime's native config path.
|
||||||
@@ -221,6 +225,22 @@ ensure_runtime_config() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Detect active mission and return an initial prompt if one exists.
|
||||||
|
# Sets MOSAIC_MISSION_PROMPT as a side effect.
|
||||||
|
_detect_mission_prompt() {
|
||||||
|
MOSAIC_MISSION_PROMPT=""
|
||||||
|
local mission_file=".mosaic/orchestrator/mission.json"
|
||||||
|
if [[ -f "$mission_file" ]] && command -v jq &>/dev/null; then
|
||||||
|
local m_status
|
||||||
|
m_status="$(jq -r '.status // "inactive"' "$mission_file" 2>/dev/null)"
|
||||||
|
if [[ "$m_status" == "active" || "$m_status" == "paused" ]]; then
|
||||||
|
local m_name
|
||||||
|
m_name="$(jq -r '.name // "unnamed"' "$mission_file")"
|
||||||
|
MOSAIC_MISSION_PROMPT="Active mission detected: ${m_name}. Read the mission state files and report status."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Launcher functions
|
# Launcher functions
|
||||||
launch_claude() {
|
launch_claude() {
|
||||||
check_mosaic_home
|
check_mosaic_home
|
||||||
@@ -234,8 +254,16 @@ launch_claude() {
|
|||||||
# Claude supports --append-system-prompt for direct injection
|
# Claude supports --append-system-prompt for direct injection
|
||||||
local runtime_prompt
|
local runtime_prompt
|
||||||
runtime_prompt="$(build_runtime_prompt "claude")"
|
runtime_prompt="$(build_runtime_prompt "claude")"
|
||||||
echo "[mosaic] Launching Claude Code..."
|
|
||||||
exec claude --append-system-prompt "$runtime_prompt" "$@"
|
# If active mission exists and no user prompt was given, inject initial prompt
|
||||||
|
_detect_mission_prompt
|
||||||
|
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"
|
||||||
|
else
|
||||||
|
echo "[mosaic] Launching Claude Code..."
|
||||||
|
exec claude --append-system-prompt "$runtime_prompt" "$@"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
launch_opencode() {
|
launch_opencode() {
|
||||||
@@ -289,8 +317,15 @@ launch_yolo() {
|
|||||||
# Claude uses an explicit dangerous permissions flag.
|
# Claude uses an explicit dangerous permissions flag.
|
||||||
local runtime_prompt
|
local runtime_prompt
|
||||||
runtime_prompt="$(build_runtime_prompt "claude")"
|
runtime_prompt="$(build_runtime_prompt "claude")"
|
||||||
echo "[mosaic] Launching Claude Code in YOLO mode (dangerous permissions enabled)..."
|
|
||||||
exec claude --dangerously-skip-permissions --append-system-prompt "$runtime_prompt" "$@"
|
_detect_mission_prompt
|
||||||
|
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"
|
||||||
|
else
|
||||||
|
echo "[mosaic] Launching Claude Code in YOLO mode (dangerous permissions enabled)..."
|
||||||
|
exec claude --dangerously-skip-permissions --append-system-prompt "$runtime_prompt" "$@"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
codex)
|
codex)
|
||||||
check_mosaic_home
|
check_mosaic_home
|
||||||
|
|||||||
Reference in New Issue
Block a user