- coord/prdy subcommands now accept --claude/--codex runtime flags - New `mosaic coord run` generates continuation context and launches selected runtime, replacing manual copy/paste workflow - Next-task capsule (.mosaic/orchestrator/next-task.json) provides machine-readable execution context for deterministic session launches - Codex strict orchestrator profile added to runtime/codex/RUNTIME.md - Orchestrator protocol updated with between-session run flow - New smoke-test.sh for orchestration behavior verification Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
174 lines
5.8 KiB
Bash
Executable File
174 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
#
|
|
# continue-prompt.sh — Generate continuation prompt for next orchestrator session
|
|
#
|
|
# Usage:
|
|
# continue-prompt.sh [--project <path>] [--milestone <id>] [--copy]
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/_lib.sh"
|
|
|
|
# ─── Parse arguments ─────────────────────────────────────────────────────────
|
|
|
|
PROJECT="."
|
|
MILESTONE=""
|
|
COPY=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--project) PROJECT="$2"; shift 2 ;;
|
|
--milestone) MILESTONE="$2"; shift 2 ;;
|
|
--copy) COPY=true; shift ;;
|
|
-h|--help)
|
|
echo "Usage: continue-prompt.sh [--project <path>] [--milestone <id>] [--copy]"
|
|
exit 0
|
|
;;
|
|
*) echo "Unknown option: $1" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
_require_jq
|
|
require_mission "$PROJECT"
|
|
target_runtime="$(coord_runtime)"
|
|
launch_cmd="$(coord_launch_command)"
|
|
|
|
# ─── Load mission data ──────────────────────────────────────────────────────
|
|
|
|
mission="$(load_mission "$PROJECT")"
|
|
mission_name="$(echo "$mission" | jq -r '.name')"
|
|
mission_id="$(echo "$mission" | jq -r '.mission_id')"
|
|
quality_gates="$(echo "$mission" | jq -r '.quality_gates // "—"')"
|
|
project_path="$(echo "$mission" | jq -r '.project_path')"
|
|
|
|
# Determine current milestone
|
|
if [[ -n "$MILESTONE" ]]; then
|
|
current_ms_id="$MILESTONE"
|
|
else
|
|
current_ms_id="$(current_milestone_id "$PROJECT")"
|
|
fi
|
|
|
|
current_ms_name=""
|
|
if [[ -n "$current_ms_id" ]]; then
|
|
current_ms_name="$(milestone_name "$PROJECT" "$current_ms_id")"
|
|
fi
|
|
|
|
# Task counts
|
|
task_counts="$(count_tasks_md "$PROJECT")"
|
|
tasks_total="$(echo "$task_counts" | jq '.total')"
|
|
tasks_done="$(echo "$task_counts" | jq '.done')"
|
|
pct=0
|
|
(( tasks_total > 0 )) && pct=$(( (tasks_done * 100) / tasks_total ))
|
|
|
|
# Next task
|
|
next_task="$(find_next_task "$PROJECT")"
|
|
|
|
# Current branch
|
|
current_branch=""
|
|
if git -C "$PROJECT" rev-parse --is-inside-work-tree &>/dev/null; then
|
|
current_branch="$(git -C "$PROJECT" branch --show-current 2>/dev/null || echo "—")"
|
|
fi
|
|
|
|
# Previous session info
|
|
session_count="$(echo "$mission" | jq '.sessions | length')"
|
|
prev_session_id="—"
|
|
prev_runtime="—"
|
|
prev_duration="—"
|
|
prev_ended_reason="—"
|
|
prev_last_task="—"
|
|
|
|
if (( session_count > 0 )); then
|
|
last_idx=$(( session_count - 1 ))
|
|
prev_session_id="$(echo "$mission" | jq -r ".sessions[$last_idx].session_id // \"—\"")"
|
|
prev_runtime="$(echo "$mission" | jq -r ".sessions[$last_idx].runtime // \"—\"")"
|
|
prev_ended_reason="$(echo "$mission" | jq -r ".sessions[$last_idx].ended_reason // \"—\"")"
|
|
prev_last_task="$(echo "$mission" | jq -r ".sessions[$last_idx].last_task_id // \"—\"")"
|
|
|
|
s_start="$(echo "$mission" | jq -r ".sessions[$last_idx].started_at // \"\"")"
|
|
s_end="$(echo "$mission" | jq -r ".sessions[$last_idx].ended_at // \"\"")"
|
|
if [[ -n "$s_start" && -n "$s_end" && "$s_end" != "" ]]; then
|
|
s_epoch="$(iso_to_epoch "$s_start")"
|
|
e_epoch="$(iso_to_epoch "$s_end")"
|
|
if (( e_epoch > 0 && s_epoch > 0 )); then
|
|
prev_duration="$(format_duration $(( e_epoch - s_epoch )))"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Write machine-readable next-task capsule for deterministic runtime launches.
|
|
write_next_task_capsule \
|
|
"$PROJECT" \
|
|
"$target_runtime" \
|
|
"$mission_id" \
|
|
"$mission_name" \
|
|
"$project_path" \
|
|
"$quality_gates" \
|
|
"$current_ms_id" \
|
|
"$current_ms_name" \
|
|
"$next_task" \
|
|
"$tasks_done" \
|
|
"$tasks_total" \
|
|
"$pct" \
|
|
"$current_branch"
|
|
|
|
# ─── Generate prompt ────────────────────────────────────────────────────────
|
|
|
|
prompt="$(cat <<EOF
|
|
## Continuation Mission
|
|
|
|
Continue **$mission_name** from existing state.
|
|
|
|
## Setup
|
|
|
|
- **Project:** $project_path
|
|
- **State:** docs/TASKS.md (already populated — ${tasks_done}/${tasks_total} tasks complete)
|
|
- **Manifest:** docs/MISSION-MANIFEST.md
|
|
- **Scratchpad:** docs/scratchpads/${mission_id}.md
|
|
- **Protocol:** ~/.config/mosaic/guides/ORCHESTRATOR.md
|
|
- **Quality gates:** $quality_gates
|
|
- **Target runtime:** $target_runtime
|
|
|
|
## Resume Point
|
|
|
|
- **Current milestone:** ${current_ms_name:-—} (${current_ms_id:-—})
|
|
- **Next task:** ${next_task:-—}
|
|
- **Progress:** ${tasks_done}/${tasks_total} tasks (${pct}%)
|
|
- **Branch:** ${current_branch:-—}
|
|
|
|
## Previous Session Context
|
|
|
|
- **Session:** $prev_session_id ($prev_runtime, $prev_duration)
|
|
- **Ended:** $prev_ended_reason
|
|
- **Last completed task:** $prev_last_task
|
|
|
|
## Instructions
|
|
|
|
1. Read \`~/.config/mosaic/guides/ORCHESTRATOR.md\` for full protocol
|
|
2. Read \`docs/MISSION-MANIFEST.md\` for mission scope and status
|
|
3. Read \`docs/scratchpads/${mission_id}.md\` for session history and decisions
|
|
4. Read \`docs/TASKS.md\` for current task state
|
|
5. \`git pull --rebase\` to sync latest changes
|
|
6. Launch runtime with \`$launch_cmd\`
|
|
7. Continue execution from task **${next_task:-next-pending}**
|
|
8. Follow Two-Phase Completion Protocol
|
|
9. You are the SOLE writer of \`docs/TASKS.md\`
|
|
EOF
|
|
)"
|
|
|
|
# ─── Output ──────────────────────────────────────────────────────────────────
|
|
|
|
if [[ "$COPY" == true ]]; then
|
|
if command -v wl-copy &>/dev/null; then
|
|
echo "$prompt" | wl-copy
|
|
echo -e "${C_GREEN}Continuation prompt copied to clipboard (wl-copy)${C_RESET}" >&2
|
|
elif command -v xclip &>/dev/null; then
|
|
echo "$prompt" | xclip -selection clipboard
|
|
echo -e "${C_GREEN}Continuation prompt copied to clipboard (xclip)${C_RESET}" >&2
|
|
else
|
|
echo -e "${C_YELLOW}No clipboard tool found (wl-copy or xclip). Printing to stdout.${C_RESET}" >&2
|
|
echo "$prompt"
|
|
fi
|
|
else
|
|
echo "$prompt"
|
|
fi
|