#!/usr/bin/env bash set -euo pipefail # # mission-init.sh — Initialize a new orchestration mission # # Usage: # mission-init.sh --name [options] # # Options: # --name Mission name (required) # --project Project directory (default: CWD) # --prefix Task ID prefix (e.g., MS) # --milestones Milestone names, comma-separated # --quality-gates Quality gate command string # --version Milestone version (default: 0.0.1) # --description Mission description # --force Overwrite existing active mission SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/_lib.sh" # ─── Parse arguments ───────────────────────────────────────────────────────── NAME="" PROJECT="." PREFIX="" MILESTONES="" QUALITY_GATES="" VERSION="0.0.1" DESCRIPTION="" FORCE=false while [[ $# -gt 0 ]]; do case "$1" in --name) NAME="$2"; shift 2 ;; --project) PROJECT="$2"; shift 2 ;; --prefix) PREFIX="$2"; shift 2 ;; --milestones) MILESTONES="$2"; shift 2 ;; --quality-gates) QUALITY_GATES="$2"; shift 2 ;; --version) VERSION="$2"; shift 2 ;; --description) DESCRIPTION="$2"; shift 2 ;; --force) FORCE=true; shift ;; -h|--help) cat <<'USAGE' mission-init.sh — Initialize a new orchestration mission Usage: mission-init.sh --name [options] Options: --name Mission name (required) --project Project directory (default: CWD) --prefix Task ID prefix (e.g., MS) --milestones Milestone names, comma-separated --quality-gates Quality gate command string --version Milestone version (default: 0.0.1) --description Mission description --force Overwrite existing active mission Example: mosaic coord init \ --name "Security Remediation" \ --prefix SEC \ --milestones "Critical Fixes,High Priority,Code Quality" \ --quality-gates "pnpm lint && pnpm typecheck && pnpm test" USAGE exit 0 ;; *) echo "Unknown option: $1" >&2; exit 1 ;; esac done if [[ -z "$NAME" ]]; then echo -e "${C_RED}Error: --name is required${C_RESET}" >&2 exit 1 fi _require_jq # ─── Validate project ─────────────────────────────────────────────────────── od="$(orch_dir "$PROJECT")" if [[ ! -d "$od" ]]; then echo -e "${C_RED}Error: $od not found. Run 'mosaic bootstrap' first.${C_RESET}" >&2 exit 1 fi # Check for existing active mission mp="$(mission_path "$PROJECT")" if [[ -f "$mp" ]]; then existing_status="$(jq -r '.status // "inactive"' "$mp")" if [[ "$existing_status" == "active" || "$existing_status" == "paused" ]] && [[ "$FORCE" != true ]]; then existing_name="$(jq -r '.name // "unnamed"' "$mp")" echo -e "${C_YELLOW}Active mission exists: $existing_name (status: $existing_status)${C_RESET}" >&2 echo "Use --force to overwrite." >&2 exit 1 fi fi # ─── Generate mission ID ──────────────────────────────────────────────────── MISSION_ID="$(slugify "$NAME")-$(date +%Y%m%d)" # ─── Build milestones array ───────────────────────────────────────────────── milestones_json="[]" if [[ -n "$MILESTONES" ]]; then IFS=',' read -ra ms_array <<< "$MILESTONES" for i in "${!ms_array[@]}"; do ms_name="$(echo "${ms_array[$i]}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')" ms_id="phase-$(( i + 1 ))" ms_branch="$(slugify "$ms_name")" milestones_json="$(echo "$milestones_json" | jq \ --arg id "$ms_id" \ --arg name "$ms_name" \ --arg branch "$ms_branch" \ '. + [{ "id": $id, "name": $name, "status": "pending", "branch": $branch, "issue_ref": "", "started_at": "", "completed_at": "" }]')" done fi MILESTONE_COUNT="$(echo "$milestones_json" | jq 'length')" # ─── Write mission.json ───────────────────────────────────────────────────── mission_json="$(jq -n \ --arg mid "$MISSION_ID" \ --arg name "$NAME" \ --arg desc "$DESCRIPTION" \ --arg pp "$(cd "$PROJECT" && pwd)" \ --arg ts "$(iso_now)" \ --arg prefix "$PREFIX" \ --arg qg "$QUALITY_GATES" \ --arg ver "$VERSION" \ --argjson milestones "$milestones_json" \ '{ schema_version: 1, mission_id: $mid, name: $name, description: $desc, project_path: $pp, created_at: $ts, status: "active", task_prefix: $prefix, quality_gates: $qg, milestone_version: $ver, milestones: $milestones, sessions: [] }')" write_json "$mp" "$mission_json" # ─── Scaffold MISSION-MANIFEST.md ─────────────────────────────────────────── manifest_path="$PROJECT/$MANIFEST_FILE" mkdir -p "$(dirname "$manifest_path")" if [[ ! -f "$manifest_path" ]] || [[ "$FORCE" == true ]]; then # Build milestones table rows ms_table="" for i in $(seq 0 $(( MILESTONE_COUNT - 1 ))); do ms_id="$(echo "$milestones_json" | jq -r ".[$i].id")" ms_name="$(echo "$milestones_json" | jq -r ".[$i].name")" ms_table+="| $(( i + 1 )) | $ms_id | $ms_name | pending | — | — | — | — |"$'\n' done cat > "$manifest_path" < Persistent document tracking full mission scope, status, and session history. > Updated by the orchestrator at each phase transition and milestone completion. ## Mission **ID:** $MISSION_ID **Statement:** $DESCRIPTION **Phase:** Intake **Current Milestone:** — **Progress:** 0 / $MILESTONE_COUNT milestones **Status:** active **Last Updated:** $(date -u +"%Y-%m-%d %H:%M UTC") ## Success Criteria ## Milestones | # | ID | Name | Status | Branch | Issue | Started | Completed | |---|-----|------|--------|--------|-------|---------|-----------| $ms_table ## Deployment | Target | URL | Method | |--------|-----|--------| | — | — | — | ## Token Budget | Metric | Value | |--------|-------| | Budget | — | | Used | 0 | | Mode | normal | ## Session History | Session | Runtime | Started | Duration | Ended Reason | Last Task | |---------|---------|---------|----------|--------------|-----------| ## Scratchpad Path: \`docs/scratchpads/$MISSION_ID.md\` EOF fi # ─── Scaffold scratchpad ──────────────────────────────────────────────────── sp_dir="$PROJECT/$SCRATCHPAD_DIR" sp_file="$sp_dir/$MISSION_ID.md" mkdir -p "$sp_dir" if [[ ! -f "$sp_file" ]]; then cat > "$sp_file" < Append-only log. NEVER delete entries. NEVER overwrite sections. > This is the orchestrator's working memory across sessions. ## Original Mission Prompt \`\`\` (Paste the mission prompt here on first session) \`\`\` ## Planning Decisions ## Session Log | Session | Date | Milestone | Tasks Done | Outcome | |---------|------|-----------|------------|---------| ## Open Questions ## Corrections EOF fi # ─── Scaffold TASKS.md if absent ──────────────────────────────────────────── tasks_path="$PROJECT/$TASKS_MD" mkdir -p "$(dirname "$tasks_path")" if [[ ! -f "$tasks_path" ]]; then cat > "$tasks_path" < Single-writer: orchestrator only. Workers read but never modify. | id | status | milestone | description | pr | notes | |----|--------|-----------|-------------|----|-------| EOF fi # ─── Report ────────────────────────────────────────────────────────────────── runtime_cmd="$(coord_launch_command)" run_cmd="$(coord_run_command)" echo "" echo -e "${C_GREEN}${C_BOLD}Mission initialized: $NAME${C_RESET}" echo "" echo -e " ${C_CYAN}Mission ID:${C_RESET} $MISSION_ID" echo -e " ${C_CYAN}Milestones:${C_RESET} $MILESTONE_COUNT" echo -e " ${C_CYAN}State:${C_RESET} $(mission_path "$PROJECT")" echo -e " ${C_CYAN}Manifest:${C_RESET} $manifest_path" echo -e " ${C_CYAN}Scratchpad:${C_RESET} $sp_file" echo -e " ${C_CYAN}Tasks:${C_RESET} $tasks_path" echo "" echo "Next: Resume with '$run_cmd' (or launch directly with '$runtime_cmd')."