feat: r0 coordinator tooling for orchestrator protocol
Implements the manual coordinator workflow for multi-session agent orchestration. Agents stop after one milestone (confirmed limitation); these tools let the human coordinator check status, generate continuation prompts, and chain sessions together. New: - tools/orchestrator/ — 5 scripts + shared library (_lib.sh) - mission-init.sh: initialize mission with milestones and state files - mission-status.sh: dashboard showing milestones, tasks, sessions - session-status.sh: check if agent is running/stale/dead - continue-prompt.sh: generate paste-ready continuation prompt - session-resume.sh: crash recovery with dirty state detection - guides/ORCHESTRATOR-PROTOCOL.md: agent-facing mission lifecycle guide - templates/docs/: mission manifest, scratchpad, continuation templates - templates/repo/.mosaic/orchestrator/mission.json: state file template Modified: - bin/mosaic: add 'coord' subcommand + resume advisory on launch - AGENTS.md: conditional loading for protocol guide + rule 37 - bin/mosaic-doctor: checks for new coordinator files - session hooks: mission detection on start, cleanup on end Usage: mosaic coord init|mission|status|continue|resume Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
53
templates/docs/MISSION-MANIFEST.md.template
Normal file
53
templates/docs/MISSION-MANIFEST.md.template
Normal file
@@ -0,0 +1,53 @@
|
||||
# Mission Manifest — ${MISSION_NAME}
|
||||
|
||||
> 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:** ${MISSION_STATEMENT}
|
||||
**Phase:** Intake
|
||||
**Current Milestone:** —
|
||||
**Progress:** 0 / ${MILESTONE_COUNT} milestones
|
||||
**Status:** not-started
|
||||
**Last Updated:** ${CREATED_AT}
|
||||
|
||||
## Success Criteria
|
||||
|
||||
${SUCCESS_CRITERIA}
|
||||
|
||||
## Milestones
|
||||
|
||||
| # | ID | Name | Status | Branch | Issue | Started | Completed |
|
||||
|---|-----|------|--------|--------|-------|---------|-----------|
|
||||
${MILESTONES_TABLE}
|
||||
|
||||
## Deployment
|
||||
|
||||
| Target | URL | Method |
|
||||
|--------|-----|--------|
|
||||
${DEPLOYMENT_TABLE}
|
||||
|
||||
## Coordination
|
||||
|
||||
- **Primary Agent:** ${PRIMARY_RUNTIME}
|
||||
- **Sibling Agents:** ${SIBLING_AGENTS}
|
||||
- **Shared Contracts:** ${SHARED_CONTRACTS}
|
||||
|
||||
## Token Budget
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Budget | ${TOKEN_BUDGET} |
|
||||
| Used | 0 |
|
||||
| Mode | normal |
|
||||
|
||||
## Session History
|
||||
|
||||
| Session | Runtime | Started | Duration | Ended Reason | Last Task |
|
||||
|---------|---------|---------|----------|--------------|-----------|
|
||||
|
||||
## Scratchpad
|
||||
|
||||
Path: `docs/scratchpads/${MISSION_ID}.md`
|
||||
36
templates/docs/continuation-prompt.md.template
Normal file
36
templates/docs/continuation-prompt.md.template
Normal file
@@ -0,0 +1,36 @@
|
||||
## 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}
|
||||
|
||||
## Resume Point
|
||||
|
||||
- **Current milestone:** ${CURRENT_MILESTONE_NAME} (${CURRENT_MILESTONE_ID})
|
||||
- **Next task:** ${NEXT_TASK_ID}
|
||||
- **Progress:** ${TASKS_DONE}/${TASKS_TOTAL} tasks (${PROGRESS_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. Continue execution from task **${NEXT_TASK_ID}**
|
||||
7. Follow Two-Phase Completion Protocol
|
||||
8. You are the SOLE writer of `docs/TASKS.md`
|
||||
27
templates/docs/mission-scratchpad.md.template
Normal file
27
templates/docs/mission-scratchpad.md.template
Normal file
@@ -0,0 +1,27 @@
|
||||
# Mission Scratchpad — ${MISSION_NAME}
|
||||
|
||||
> Append-only log. NEVER delete entries. NEVER overwrite sections.
|
||||
> This is the orchestrator's working memory across sessions.
|
||||
|
||||
## Original Mission Prompt
|
||||
|
||||
```
|
||||
${MISSION_PROMPT}
|
||||
```
|
||||
|
||||
## Planning Decisions
|
||||
|
||||
<!-- Record key decisions made during planning. Format: decision + rationale. -->
|
||||
|
||||
## Session Log
|
||||
|
||||
| Session | Date | Milestone | Tasks Done | Outcome |
|
||||
|---------|------|-----------|------------|---------|
|
||||
|
||||
## Open Questions
|
||||
|
||||
<!-- Unresolved items that need human input or cross-session investigation. -->
|
||||
|
||||
## Corrections
|
||||
|
||||
<!-- Record any corrections to earlier decisions or assumptions. -->
|
||||
14
templates/repo/.mosaic/orchestrator/mission.json
Normal file
14
templates/repo/.mosaic/orchestrator/mission.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"mission_id": "",
|
||||
"name": "",
|
||||
"description": "",
|
||||
"project_path": "",
|
||||
"created_at": "",
|
||||
"status": "inactive",
|
||||
"task_prefix": "",
|
||||
"quality_gates": "",
|
||||
"milestone_version": "0.0.1",
|
||||
"milestones": [],
|
||||
"sessions": []
|
||||
}
|
||||
@@ -8,6 +8,34 @@ source "$SCRIPT_DIR/common.sh"
|
||||
ensure_repo_root
|
||||
load_repo_hooks
|
||||
|
||||
# ─── Mission session cleanup (ORCHESTRATOR-PROTOCOL) ────────────────────────
|
||||
ORCH_DIR=".mosaic/orchestrator"
|
||||
MISSION_JSON="$ORCH_DIR/mission.json"
|
||||
SESSION_LOCK="$ORCH_DIR/session.lock"
|
||||
COORD_LIB="$HOME/.config/mosaic/tools/orchestrator/_lib.sh"
|
||||
|
||||
if [[ -f "$SESSION_LOCK" ]] && [[ -f "$COORD_LIB" ]] && command -v jq &>/dev/null; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$COORD_LIB"
|
||||
|
||||
sess_id="$(jq -r '.session_id // ""' "$SESSION_LOCK")"
|
||||
if [[ -n "$sess_id" && -f "$MISSION_JSON" ]]; then
|
||||
# Update mission.json: mark session ended
|
||||
updated="$(jq \
|
||||
--arg sid "$sess_id" \
|
||||
--arg ts "$(iso_now)" \
|
||||
--arg reason "completed" \
|
||||
'(.sessions[] | select(.session_id == $sid)) |= . + {
|
||||
ended_at: $ts,
|
||||
ended_reason: $reason
|
||||
}' "$MISSION_JSON")"
|
||||
echo "$updated" > "$MISSION_JSON.tmp" && mv "$MISSION_JSON.tmp" "$MISSION_JSON"
|
||||
echo "[agent-framework] Session $sess_id recorded in mission state"
|
||||
fi
|
||||
|
||||
session_lock_clear "."
|
||||
fi
|
||||
|
||||
if declare -F mosaic_hook_session_end >/dev/null 2>&1; then
|
||||
run_step "Run repo end hook" mosaic_hook_session_end
|
||||
else
|
||||
|
||||
@@ -16,6 +16,72 @@ if git rev-parse --is-inside-work-tree >/dev/null 2>&1 && has_remote; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─── Mission state detection (ORCHESTRATOR-PROTOCOL) ────────────────────────
|
||||
ORCH_DIR=".mosaic/orchestrator"
|
||||
MISSION_JSON="$ORCH_DIR/mission.json"
|
||||
COORD_LIB="$HOME/.config/mosaic/tools/orchestrator/_lib.sh"
|
||||
|
||||
if [[ -f "$MISSION_JSON" ]] && command -v jq &>/dev/null; then
|
||||
mission_status="$(jq -r '.status // "inactive"' "$MISSION_JSON")"
|
||||
|
||||
if [[ "$mission_status" == "active" || "$mission_status" == "paused" ]]; then
|
||||
mission_name="$(jq -r '.name // "unnamed"' "$MISSION_JSON")"
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "ACTIVE MISSION DETECTED"
|
||||
echo "========================================="
|
||||
echo " Mission: $mission_name"
|
||||
|
||||
# Extract key fields from manifest if present
|
||||
manifest="docs/MISSION-MANIFEST.md"
|
||||
if [[ -f "$manifest" ]]; then
|
||||
phase="$(grep -m1 '^\*\*Phase:\*\*' "$manifest" 2>/dev/null | sed 's/.*\*\*Phase:\*\* //' || true)"
|
||||
milestone="$(grep -m1 '^\*\*Current Milestone:\*\*' "$manifest" 2>/dev/null | sed 's/.*\*\*Current Milestone:\*\* //' || true)"
|
||||
progress="$(grep -m1 '^\*\*Progress:\*\*' "$manifest" 2>/dev/null | sed 's/.*\*\*Progress:\*\* //' || true)"
|
||||
[[ -n "$phase" ]] && echo " Phase: $phase"
|
||||
[[ -n "$milestone" ]] && echo " Milestone: $milestone"
|
||||
[[ -n "$progress" ]] && echo " Progress: $progress"
|
||||
fi
|
||||
|
||||
# Task counts
|
||||
if [[ -f "docs/TASKS.md" ]]; then
|
||||
total="$(grep -c '^|' "docs/TASKS.md" 2>/dev/null || echo 0)"
|
||||
done_count="$(grep -ci '| done \|| completed ' "docs/TASKS.md" 2>/dev/null || echo 0)"
|
||||
echo " Tasks: ~$done_count done of ~$((total - 2)) total"
|
||||
fi
|
||||
|
||||
# Scratchpad
|
||||
if [[ -d "docs/scratchpads" ]]; then
|
||||
latest_sp="$(ls -t docs/scratchpads/*.md 2>/dev/null | head -1 || true)"
|
||||
[[ -n "$latest_sp" ]] && echo " Scratchpad: $latest_sp"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " Resume: Read manifest + scratchpad before taking action."
|
||||
echo " Protocol: ~/.config/mosaic/guides/ORCHESTRATOR-PROTOCOL.md"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Register session if coordinator lib is available
|
||||
if [[ -f "$COORD_LIB" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$COORD_LIB"
|
||||
sess_id="$(next_session_id ".")"
|
||||
runtime="${MOSAIC_RUNTIME:-unknown}"
|
||||
session_lock_write "." "$sess_id" "$runtime" "$$"
|
||||
|
||||
# Append session to mission.json
|
||||
updated="$(jq \
|
||||
--arg sid "$sess_id" \
|
||||
--arg rt "$runtime" \
|
||||
--arg ts "$(iso_now)" \
|
||||
'.sessions += [{"session_id":$sid,"runtime":$rt,"started_at":$ts,"ended_at":"","ended_reason":"","milestone_at_end":"","tasks_completed":[],"last_task_id":""}]' \
|
||||
"$MISSION_JSON")"
|
||||
echo "$updated" > "$MISSION_JSON.tmp" && mv "$MISSION_JSON.tmp" "$MISSION_JSON"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if declare -F mosaic_hook_session_start >/dev/null 2>&1; then
|
||||
run_step "Run repo start hook" mosaic_hook_session_start
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user