feat: integrate framework files into monorepo under packages/mosaic/framework/
Moves all Mosaic framework runtime files from the separate bootstrap repo into the monorepo as canonical source. The @mosaic/mosaic npm package now ships the complete framework — bin scripts, runtime configs, tools, and templates — enabling standalone installation via npm install. Structure: packages/mosaic/framework/ ├── bin/ 28 CLI scripts (mosaic, mosaic-doctor, mosaic-sync-skills, etc.) ├── runtime/ Runtime adapters (claude, codex, opencode, pi, mcp) ├── tools/ Shell tooling (git, prdy, orchestrator, quality, etc.) ├── templates/ Agent and repo templates ├── defaults/ Default identity files (AGENTS.md, STANDARDS.md, SOUL.md, etc.) ├── install.sh Legacy bash installer └── remote-install.sh One-liner remote installer Key files with Pi support and recent fixes: - bin/mosaic: launch_pi() with skills-local loop - bin/mosaic-doctor: --fix auto-wiring for all 4 harnesses - bin/mosaic-sync-skills: Pi as 4th link target, symlink-aware find - bin/mosaic-link-runtime-assets: Pi settings.json patching - bin/mosaic-migrate-local-skills: Pi skill roots, symlink find - runtime/pi/RUNTIME.md + mosaic-extension.ts Package ships 251 framework files in the npm tarball (278KB compressed).
This commit is contained in:
78
packages/mosaic/framework/templates/repo/.mosaic/README.md
Normal file
78
packages/mosaic/framework/templates/repo/.mosaic/README.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Repo Mosaic Linkage
|
||||
|
||||
This repository is attached to the machine-wide Mosaic framework.
|
||||
|
||||
## Load Order for Agents
|
||||
|
||||
1. `~/.config/mosaic/STANDARDS.md`
|
||||
2. `AGENTS.md` (this repository)
|
||||
3. `.mosaic/repo-hooks.sh` (repo-specific automation hooks)
|
||||
|
||||
## Purpose
|
||||
|
||||
- Keep universal standards in `~/.config/mosaic`
|
||||
- Keep repo-specific behavior in this repo
|
||||
- Avoid copying large runtime configs into each project
|
||||
|
||||
## Optional Quality Rails
|
||||
|
||||
Use `.mosaic/quality-rails.yml` to track whether quality rails are enabled for this repo.
|
||||
|
||||
Apply a template:
|
||||
|
||||
```bash
|
||||
~/.config/mosaic/bin/mosaic-quality-apply --template <template> --target .
|
||||
```
|
||||
|
||||
Verify enforcement:
|
||||
|
||||
```bash
|
||||
~/.config/mosaic/bin/mosaic-quality-verify --target .
|
||||
```
|
||||
|
||||
## Optional Matrix Orchestrator Rail
|
||||
|
||||
Repo-local orchestrator state lives in `.mosaic/orchestrator/`.
|
||||
|
||||
Run one cycle:
|
||||
|
||||
```bash
|
||||
~/.config/mosaic/bin/mosaic-orchestrator-matrix-cycle
|
||||
~/.config/mosaic/bin/mosaic-orchestrator-run --once
|
||||
```
|
||||
|
||||
Run continuously:
|
||||
|
||||
```bash
|
||||
~/.config/mosaic/bin/mosaic-orchestrator-run --poll-sec 10
|
||||
```
|
||||
|
||||
Bridge events to Matrix:
|
||||
|
||||
```bash
|
||||
~/.config/mosaic/bin/mosaic-orchestrator-matrix-publish
|
||||
~/.config/mosaic/bin/mosaic-orchestrator-matrix-consume
|
||||
```
|
||||
|
||||
Run until queue is drained (syncs from `docs/tasks.md` first):
|
||||
|
||||
```bash
|
||||
~/.config/mosaic/bin/mosaic-orchestrator-drain
|
||||
```
|
||||
|
||||
Set worker command if auto-detect does not match your CLI:
|
||||
|
||||
```bash
|
||||
export MOSAIC_WORKER_EXEC="codex -p"
|
||||
# or
|
||||
export MOSAIC_WORKER_EXEC="opencode -p"
|
||||
```
|
||||
|
||||
Use repo helper (foreground or detached):
|
||||
|
||||
```bash
|
||||
bash scripts/agent/orchestrator-daemon.sh drain
|
||||
bash scripts/agent/orchestrator-daemon.sh start
|
||||
bash scripts/agent/orchestrator-daemon.sh status
|
||||
bash scripts/agent/orchestrator-daemon.sh stop
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"enabled": false,
|
||||
"transport": "matrix",
|
||||
"matrix": {
|
||||
"control_room_id": "",
|
||||
"workspace_id": "",
|
||||
"homeserver_url": "",
|
||||
"access_token": "",
|
||||
"bot_user_id": ""
|
||||
},
|
||||
"worker": {
|
||||
"runtime": "codex",
|
||||
"command_template": "bash scripts/agent/orchestrator-worker.sh {task_file}",
|
||||
"timeout_seconds": 7200,
|
||||
"max_attempts": 1
|
||||
},
|
||||
"quality_gates": ["pnpm lint", "pnpm typecheck", "pnpm test"]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"last_published_line": 0,
|
||||
"since": null
|
||||
}
|
||||
@@ -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": []
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"running_task_id": null,
|
||||
"updated_at": null
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"tasks": []
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
enabled: false
|
||||
template: ''
|
||||
|
||||
# Set enabled: true and choose one template:
|
||||
# - typescript-node
|
||||
# - typescript-nextjs
|
||||
# - monorepo
|
||||
#
|
||||
# Apply manually:
|
||||
# ~/.mosaic/bin/mosaic-quality-apply --template <template> --target <repo>
|
||||
17
packages/mosaic/framework/templates/repo/.mosaic/repo-hooks.sh
Executable file
17
packages/mosaic/framework/templates/repo/.mosaic/repo-hooks.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# Optional repo-specific hooks used by scripts/agent/*.sh
|
||||
|
||||
# Called by session-start.sh
|
||||
# mosaic_hook_session_start() {
|
||||
# echo "Run repo-specific startup checks"
|
||||
# }
|
||||
|
||||
# Called by critical.sh
|
||||
# mosaic_hook_critical() {
|
||||
# echo "Run repo-specific critical queries"
|
||||
# }
|
||||
|
||||
# Called by session-end.sh
|
||||
# mosaic_hook_session_end() {
|
||||
# echo "Run repo-specific end-of-session checks"
|
||||
# }
|
||||
29
packages/mosaic/framework/templates/repo/scripts/agent/common.sh
Executable file
29
packages/mosaic/framework/templates/repo/scripts/agent/common.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root() {
|
||||
git rev-parse --show-toplevel 2>/dev/null || pwd
|
||||
}
|
||||
|
||||
ensure_repo_root() {
|
||||
cd "$(repo_root)"
|
||||
}
|
||||
|
||||
has_remote() {
|
||||
git remote get-url origin >/dev/null 2>&1
|
||||
}
|
||||
|
||||
run_step() {
|
||||
local label="$1"
|
||||
shift
|
||||
echo "[agent-framework] $label"
|
||||
"$@"
|
||||
}
|
||||
|
||||
load_repo_hooks() {
|
||||
local hooks_file=".mosaic/repo-hooks.sh"
|
||||
if [[ -f "$hooks_file" ]]; then
|
||||
# shellcheck disable=SC1090
|
||||
source "$hooks_file"
|
||||
fi
|
||||
}
|
||||
16
packages/mosaic/framework/templates/repo/scripts/agent/critical.sh
Executable file
16
packages/mosaic/framework/templates/repo/scripts/agent/critical.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./common.sh
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
ensure_repo_root
|
||||
load_repo_hooks
|
||||
|
||||
if declare -F mosaic_hook_critical >/dev/null 2>&1; then
|
||||
run_step "Run repo critical hook" mosaic_hook_critical
|
||||
else
|
||||
echo "[agent-framework] No repo critical hook configured (.mosaic/repo-hooks.sh)"
|
||||
echo "[agent-framework] Define mosaic_hook_critical() for project-specific priority scans"
|
||||
fi
|
||||
44
packages/mosaic/framework/templates/repo/scripts/agent/log-limitation.sh
Executable file
44
packages/mosaic/framework/templates/repo/scripts/agent/log-limitation.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
TITLE="${1:-}"
|
||||
if [[ -z "$TITLE" ]]; then
|
||||
echo "Usage: $0 \"Short limitation title\"" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FILE="EVOLUTION.md"
|
||||
if [[ ! -f "$FILE" ]]; then
|
||||
echo "[agent-framework] $FILE not found. Create project-specific limitations log if needed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if command -v rg >/dev/null 2>&1; then
|
||||
last_num=$(rg -o "^### L-[0-9]{3}" "$FILE" | sed 's/^### L-//' | sort -n | tail -1)
|
||||
else
|
||||
last_num=$(grep -E "^### L-[0-9]{3}" "$FILE" | sed 's/^### L-//' | sort -n | tail -1)
|
||||
fi
|
||||
|
||||
if [[ -z "$last_num" ]]; then
|
||||
next_num="001"
|
||||
else
|
||||
next_num=$(printf "%03d" $((10#$last_num + 1)))
|
||||
fi
|
||||
|
||||
entry_id="L-$next_num"
|
||||
|
||||
cat <<EOF2
|
||||
|
||||
### $entry_id: $TITLE
|
||||
|
||||
| Aspect | Details |
|
||||
|--------|---------|
|
||||
| **Pain** | TODO |
|
||||
| **Impact** | TODO |
|
||||
| **Frequency** | TODO |
|
||||
| **Current Workaround** | TODO |
|
||||
| **Proposed Solution** | TODO |
|
||||
| **Platform Implication** | TODO |
|
||||
EOF2
|
||||
|
||||
echo "[agent-framework] Suggested limitation ID: $entry_id"
|
||||
102
packages/mosaic/framework/templates/repo/scripts/agent/orchestrator-daemon.sh
Executable file
102
packages/mosaic/framework/templates/repo/scripts/agent/orchestrator-daemon.sh
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./common.sh
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
ensure_repo_root
|
||||
|
||||
MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
|
||||
ORCH_DIR=".mosaic/orchestrator"
|
||||
PID_FILE="$ORCH_DIR/orchestrator.pid"
|
||||
LOG_FILE="$ORCH_DIR/logs/daemon.log"
|
||||
|
||||
usage() {
|
||||
cat <<USAGE
|
||||
Usage: $(basename "$0") <start|drain|stop|status> [--poll-sec N] [--no-sync]
|
||||
|
||||
Commands:
|
||||
start Run orchestrator drain loop in background (detached)
|
||||
drain Run orchestrator drain loop in foreground (until queue drained)
|
||||
stop Stop background orchestrator if running
|
||||
status Show background orchestrator status
|
||||
|
||||
Options:
|
||||
--poll-sec N Poll interval (default: 15)
|
||||
--no-sync Skip docs/TASKS.md -> orchestrator queue sync before run
|
||||
USAGE
|
||||
}
|
||||
|
||||
cmd="${1:-status}"
|
||||
if [[ $# -gt 0 ]]; then
|
||||
shift
|
||||
fi
|
||||
|
||||
poll_sec=15
|
||||
sync_arg=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--poll-sec)
|
||||
poll_sec="${2:-15}"
|
||||
shift 2
|
||||
;;
|
||||
--no-sync)
|
||||
sync_arg="--no-sync"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "[agent-framework] unknown argument: $1" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
mkdir -p "$ORCH_DIR/logs" "$ORCH_DIR/results"
|
||||
|
||||
is_running() {
|
||||
[[ -f "$PID_FILE" ]] || return 1
|
||||
local pid
|
||||
pid="$(cat "$PID_FILE" 2>/dev/null || true)"
|
||||
[[ -n "$pid" ]] || return 1
|
||||
kill -0 "$pid" 2>/dev/null
|
||||
}
|
||||
|
||||
case "$cmd" in
|
||||
start)
|
||||
if is_running; then
|
||||
echo "[agent-framework] orchestrator already running (pid=$(cat "$PID_FILE"))"
|
||||
exit 0
|
||||
fi
|
||||
nohup "$MOSAIC_HOME/bin/mosaic-orchestrator-drain" --poll-sec "$poll_sec" $sync_arg >"$LOG_FILE" 2>&1 &
|
||||
echo "$!" > "$PID_FILE"
|
||||
echo "[agent-framework] orchestrator started (pid=$!, log=$LOG_FILE)"
|
||||
;;
|
||||
drain)
|
||||
exec "$MOSAIC_HOME/bin/mosaic-orchestrator-drain" --poll-sec "$poll_sec" $sync_arg
|
||||
;;
|
||||
stop)
|
||||
if ! is_running; then
|
||||
echo "[agent-framework] orchestrator not running"
|
||||
rm -f "$PID_FILE"
|
||||
exit 0
|
||||
fi
|
||||
pid="$(cat "$PID_FILE")"
|
||||
kill "$pid" || true
|
||||
rm -f "$PID_FILE"
|
||||
echo "[agent-framework] orchestrator stopped (pid=$pid)"
|
||||
;;
|
||||
status)
|
||||
if is_running; then
|
||||
echo "[agent-framework] orchestrator running (pid=$(cat "$PID_FILE"), log=$LOG_FILE)"
|
||||
else
|
||||
echo "[agent-framework] orchestrator not running"
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
task_file="${1:-}"
|
||||
if [[ -z "$task_file" || ! -f "$task_file" ]]; then
|
||||
echo "[orchestrator-worker] missing task file argument" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
worker_exec="${MOSAIC_WORKER_EXEC:-}"
|
||||
if [[ -z "$worker_exec" ]]; then
|
||||
if command -v codex >/dev/null 2>&1; then
|
||||
worker_exec="codex -p"
|
||||
elif command -v opencode >/dev/null 2>&1; then
|
||||
worker_exec="opencode -p"
|
||||
else
|
||||
echo "[orchestrator-worker] set MOSAIC_WORKER_EXEC to your worker command (example: 'codex -p' or 'opencode -p')" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
prompt="$(python3 - "$task_file" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
task = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
|
||||
task_id = str(task.get("id", "TASK"))
|
||||
title = str(task.get("title", ""))
|
||||
description = str(task.get("description", ""))
|
||||
meta = task.get("metadata", {}) or {}
|
||||
issue = str(meta.get("issue", ""))
|
||||
repo = str(meta.get("repo", ""))
|
||||
branch = str(meta.get("branch", ""))
|
||||
depends = task.get("depends_on", [])
|
||||
if isinstance(depends, list):
|
||||
depends_str = ", ".join(str(x) for x in depends)
|
||||
else:
|
||||
depends_str = str(depends)
|
||||
|
||||
print(
|
||||
f"""Read ~/.config/mosaic/STANDARDS.md, then AGENTS.md and SOUL.md (if present).
|
||||
Complete this queued task fully.
|
||||
|
||||
Task ID: {task_id}
|
||||
Title: {title}
|
||||
Description: {description}
|
||||
Issue: {issue}
|
||||
Repo hint: {repo}
|
||||
Branch hint: {branch}
|
||||
Depends on: {depends_str}
|
||||
|
||||
Requirements:
|
||||
- Implement and verify the task end-to-end.
|
||||
- Keep changes scoped to this task.
|
||||
- Run project checks and tests relevant to touched code.
|
||||
- Return with a concise summary of what changed and verification results.
|
||||
"""
|
||||
)
|
||||
PY
|
||||
)"
|
||||
|
||||
PROMPT="$prompt" bash -lc "$worker_exec \"\$PROMPT\""
|
||||
48
packages/mosaic/framework/templates/repo/scripts/agent/session-end.sh
Executable file
48
packages/mosaic/framework/templates/repo/scripts/agent/session-end.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./common.sh
|
||||
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
|
||||
echo "[agent-framework] No repo end hook configured (.mosaic/repo-hooks.sh)"
|
||||
fi
|
||||
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
run_step "Show status" git status --short
|
||||
run_step "Show diff summary" git diff --stat
|
||||
fi
|
||||
92
packages/mosaic/framework/templates/repo/scripts/agent/session-start.sh
Executable file
92
packages/mosaic/framework/templates/repo/scripts/agent/session-start.sh
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./common.sh
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
ensure_repo_root
|
||||
load_repo_hooks
|
||||
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1 && has_remote; then
|
||||
if git diff --quiet && git diff --cached --quiet; then
|
||||
run_step "Pull latest changes" git pull --rebase
|
||||
else
|
||||
echo "[agent-framework] Skip pull: working tree has local changes"
|
||||
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 || true)"
|
||||
total="${total:-0}"
|
||||
done_count="$(grep -ci '| done \|| completed ' "docs/TASKS.md" 2>/dev/null || true)"
|
||||
done_count="${done_count:-0}"
|
||||
approx_total=$(( total > 2 ? total - 2 : 0 ))
|
||||
echo " Tasks: ~${done_count} done of ~${approx_total} 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
|
||||
echo "[agent-framework] No repo start hook configured (.mosaic/repo-hooks.sh)"
|
||||
fi
|
||||
Reference in New Issue
Block a user