feat: add multi-runtime support (coord run, prdy --codex) and next-task capsule
- 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>
This commit is contained in:
109
bin/mosaic
109
bin/mosaic
@@ -53,8 +53,8 @@ Management:
|
|||||||
|
|
||||||
PRD:
|
PRD:
|
||||||
prdy <subcommand> PRD creation and validation
|
prdy <subcommand> PRD creation and validation
|
||||||
init Create docs/PRD.md via Claude session
|
init Create docs/PRD.md via guided runtime session
|
||||||
update Update existing PRD via Claude session
|
update Update existing PRD via guided runtime session
|
||||||
validate Check PRD completeness (bash-only)
|
validate Check PRD completeness (bash-only)
|
||||||
|
|
||||||
Coordinator (r0):
|
Coordinator (r0):
|
||||||
@@ -63,6 +63,7 @@ Coordinator (r0):
|
|||||||
mission Show mission progress dashboard
|
mission Show mission progress dashboard
|
||||||
status Check agent session health
|
status Check agent session health
|
||||||
continue Generate continuation prompt
|
continue Generate continuation prompt
|
||||||
|
run Generate context and launch selected runtime
|
||||||
resume Crash recovery
|
resume Crash recovery
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
@@ -481,26 +482,59 @@ run_seq() {
|
|||||||
|
|
||||||
run_coord() {
|
run_coord() {
|
||||||
check_mosaic_home
|
check_mosaic_home
|
||||||
local subcmd="${1:-help}"
|
local runtime="claude"
|
||||||
shift || true
|
local runtime_flag=""
|
||||||
|
local -a coord_args=()
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--claude|--codex)
|
||||||
|
local selected_runtime="${1#--}"
|
||||||
|
if [[ -n "$runtime_flag" ]] && [[ "$runtime" != "$selected_runtime" ]]; then
|
||||||
|
echo "[mosaic] ERROR: --claude and --codex are mutually exclusive for 'mosaic coord'." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
runtime="$selected_runtime"
|
||||||
|
runtime_flag="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
coord_args+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
local subcmd="${coord_args[0]:-help}"
|
||||||
|
if (( ${#coord_args[@]} > 1 )); then
|
||||||
|
set -- "${coord_args[@]:1}"
|
||||||
|
else
|
||||||
|
set --
|
||||||
|
fi
|
||||||
|
|
||||||
local tool_dir="$MOSAIC_HOME/tools/orchestrator"
|
local tool_dir="$MOSAIC_HOME/tools/orchestrator"
|
||||||
|
|
||||||
case "$subcmd" in
|
case "$subcmd" in
|
||||||
status|session)
|
status|session)
|
||||||
exec bash "$tool_dir/session-status.sh" "$@"
|
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/session-status.sh" "$@"
|
||||||
;;
|
;;
|
||||||
init)
|
init)
|
||||||
exec bash "$tool_dir/mission-init.sh" "$@"
|
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/mission-init.sh" "$@"
|
||||||
;;
|
;;
|
||||||
mission|progress)
|
mission|progress)
|
||||||
exec bash "$tool_dir/mission-status.sh" "$@"
|
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/mission-status.sh" "$@"
|
||||||
;;
|
;;
|
||||||
continue|next)
|
continue|next)
|
||||||
exec bash "$tool_dir/continue-prompt.sh" "$@"
|
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/continue-prompt.sh" "$@"
|
||||||
|
;;
|
||||||
|
run|start)
|
||||||
|
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/session-run.sh" "$@"
|
||||||
|
;;
|
||||||
|
smoke|test)
|
||||||
|
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/smoke-test.sh" "$@"
|
||||||
;;
|
;;
|
||||||
resume|recover)
|
resume|recover)
|
||||||
exec bash "$tool_dir/session-resume.sh" "$@"
|
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/session-resume.sh" "$@"
|
||||||
;;
|
;;
|
||||||
help|*)
|
help|*)
|
||||||
cat <<COORD_USAGE
|
cat <<COORD_USAGE
|
||||||
@@ -511,12 +545,23 @@ Commands:
|
|||||||
mission [--project <path>] Show mission progress dashboard
|
mission [--project <path>] Show mission progress dashboard
|
||||||
status [--project <path>] Check agent session health
|
status [--project <path>] Check agent session health
|
||||||
continue [--project <path>] Generate continuation prompt for next session
|
continue [--project <path>] Generate continuation prompt for next session
|
||||||
|
run [--project <path>] Generate context and launch selected runtime
|
||||||
|
smoke Run orchestration behavior smoke checks
|
||||||
resume [--project <path>] Crash recovery (detect dirty state, generate fix)
|
resume [--project <path>] Crash recovery (detect dirty state, generate fix)
|
||||||
|
|
||||||
|
Runtime:
|
||||||
|
--claude Use Claude runtime hints/prompts (default)
|
||||||
|
--codex Use Codex runtime hints/prompts
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
mosaic coord init --name "Security Fix" --milestones "Critical,High,Medium"
|
mosaic coord init --name "Security Fix" --milestones "Critical,High,Medium"
|
||||||
mosaic coord mission
|
mosaic coord mission
|
||||||
|
mosaic coord --codex mission
|
||||||
mosaic coord continue --copy
|
mosaic coord continue --copy
|
||||||
|
mosaic coord run
|
||||||
|
mosaic coord run --codex
|
||||||
|
mosaic coord smoke
|
||||||
|
mosaic coord continue --codex --copy
|
||||||
|
|
||||||
COORD_USAGE
|
COORD_USAGE
|
||||||
;;
|
;;
|
||||||
@@ -552,33 +597,65 @@ _check_resumable_session() {
|
|||||||
|
|
||||||
run_prdy() {
|
run_prdy() {
|
||||||
check_mosaic_home
|
check_mosaic_home
|
||||||
local subcmd="${1:-help}"
|
local runtime="claude"
|
||||||
shift || true
|
local runtime_flag=""
|
||||||
|
local -a prdy_args=()
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--claude|--codex)
|
||||||
|
local selected_runtime="${1#--}"
|
||||||
|
if [[ -n "$runtime_flag" ]] && [[ "$runtime" != "$selected_runtime" ]]; then
|
||||||
|
echo "[mosaic] ERROR: --claude and --codex are mutually exclusive for 'mosaic prdy'." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
runtime="$selected_runtime"
|
||||||
|
runtime_flag="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
prdy_args+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
local subcmd="${prdy_args[0]:-help}"
|
||||||
|
if (( ${#prdy_args[@]} > 1 )); then
|
||||||
|
set -- "${prdy_args[@]:1}"
|
||||||
|
else
|
||||||
|
set --
|
||||||
|
fi
|
||||||
|
|
||||||
local tool_dir="$MOSAIC_HOME/tools/prdy"
|
local tool_dir="$MOSAIC_HOME/tools/prdy"
|
||||||
|
|
||||||
case "$subcmd" in
|
case "$subcmd" in
|
||||||
init)
|
init)
|
||||||
exec bash "$tool_dir/prdy-init.sh" "$@"
|
MOSAIC_PRDY_RUNTIME="$runtime" exec bash "$tool_dir/prdy-init.sh" "$@"
|
||||||
;;
|
;;
|
||||||
update)
|
update)
|
||||||
exec bash "$tool_dir/prdy-update.sh" "$@"
|
MOSAIC_PRDY_RUNTIME="$runtime" exec bash "$tool_dir/prdy-update.sh" "$@"
|
||||||
;;
|
;;
|
||||||
validate|check)
|
validate|check)
|
||||||
exec bash "$tool_dir/prdy-validate.sh" "$@"
|
MOSAIC_PRDY_RUNTIME="$runtime" exec bash "$tool_dir/prdy-validate.sh" "$@"
|
||||||
;;
|
;;
|
||||||
help|*)
|
help|*)
|
||||||
cat <<PRDY_USAGE
|
cat <<PRDY_USAGE
|
||||||
mosaic prdy — PRD creation and validation tools
|
mosaic prdy — PRD creation and validation tools
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
init [--project <path>] [--name <feature>] Create docs/PRD.md via guided Claude session
|
init [--project <path>] [--name <feature>] Create docs/PRD.md via guided runtime session
|
||||||
update [--project <path>] Update existing docs/PRD.md via Claude session
|
update [--project <path>] Update existing docs/PRD.md via guided runtime session
|
||||||
validate [--project <path>] Check PRD completeness against Mosaic guide (bash-only)
|
validate [--project <path>] Check PRD completeness against Mosaic guide (bash-only)
|
||||||
|
|
||||||
|
Runtime:
|
||||||
|
--claude Use Claude runtime (default)
|
||||||
|
--codex Use Codex runtime
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
mosaic prdy init --name "User Authentication"
|
mosaic prdy init --name "User Authentication"
|
||||||
mosaic prdy update
|
mosaic prdy update
|
||||||
|
mosaic prdy --codex init --name "User Authentication"
|
||||||
mosaic prdy validate
|
mosaic prdy validate
|
||||||
|
|
||||||
Output location: docs/PRD.md (per Mosaic PRD guide)
|
Output location: docs/PRD.md (per Mosaic PRD guide)
|
||||||
|
|||||||
@@ -131,9 +131,9 @@ If context usage is high, produce a handoff message:
|
|||||||
4. Commit all state files
|
4. Commit all state files
|
||||||
5. The coordinator will generate a continuation prompt for the next session
|
5. The coordinator will generate a continuation prompt for the next session
|
||||||
|
|
||||||
### Continuation Prompt Format
|
### Continuation Prompt and Capsule Format
|
||||||
|
|
||||||
The coordinator generates this (via `mosaic coord continue`):
|
The coordinator generates this (via `mosaic coord continue`) and writes a machine-readable capsule at `.mosaic/orchestrator/next-task.json`:
|
||||||
|
|
||||||
```
|
```
|
||||||
## Continuation Mission
|
## Continuation Mission
|
||||||
@@ -152,6 +152,16 @@ Continue **{mission}** from existing state.
|
|||||||
4. Human launches new session and pastes the prompt
|
4. Human launches new session and pastes the prompt
|
||||||
5. New agent reads manifest, scratchpad, TASKS.md and continues
|
5. New agent reads manifest, scratchpad, TASKS.md and continues
|
||||||
|
|
||||||
|
### Between Sessions (r0 assisted)
|
||||||
|
|
||||||
|
Use `mosaic coord run` to remove copy/paste steps:
|
||||||
|
|
||||||
|
1. Agent stops
|
||||||
|
2. Human runs `mosaic coord run [--claude|--codex]`
|
||||||
|
3. Coordinator regenerates continuation prompt + `next-task.json`
|
||||||
|
4. Coordinator launches selected runtime with scoped kickoff context
|
||||||
|
5. New session resumes from next task
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Failure Taxonomy Quick Reference
|
## 7. Failure Taxonomy Quick Reference
|
||||||
@@ -194,6 +204,7 @@ In r0, the Coordinator is Jason + shell scripts. No daemon. No automation.
|
|||||||
| `mosaic coord mission` | Show mission progress dashboard |
|
| `mosaic coord mission` | Show mission progress dashboard |
|
||||||
| `mosaic coord status` | Check if agent session is still running |
|
| `mosaic coord status` | Check if agent session is still running |
|
||||||
| `mosaic coord continue` | Generate continuation prompt for next session |
|
| `mosaic coord continue` | Generate continuation prompt for next session |
|
||||||
|
| `mosaic coord run [--claude|--codex]` | Generate continuation context and launch runtime |
|
||||||
| `mosaic coord resume` | Crash recovery (detect dirty state, generate fix) |
|
| `mosaic coord resume` | Crash recovery (detect dirty state, generate fix) |
|
||||||
| `mosaic coord resume --clean-lock` | Clear stale session lock after review |
|
| `mosaic coord resume --clean-lock` | Clear stale session lock after review |
|
||||||
|
|
||||||
@@ -201,7 +212,7 @@ In r0, the Coordinator is Jason + shell scripts. No daemon. No automation.
|
|||||||
|
|
||||||
```
|
```
|
||||||
init → launch agent → [agent works] → agent stops →
|
init → launch agent → [agent works] → agent stops →
|
||||||
status → mission → continue → launch agent → repeat
|
status → mission → run → repeat
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -16,6 +16,21 @@ This file applies only to Codex runtime behavior.
|
|||||||
8. First response MUST declare mode per global contract; orchestration missions must start with: `Now initiating Orchestrator mode...`
|
8. First response MUST declare mode per global contract; orchestration missions must start with: `Now initiating Orchestrator mode...`
|
||||||
9. Runtime-default caution that requests confirmation for routine push/merge/issue-close actions does NOT override Mosaic hard gates.
|
9. Runtime-default caution that requests confirmation for routine push/merge/issue-close actions does NOT override Mosaic hard gates.
|
||||||
|
|
||||||
|
## Strict Orchestrator Profile (Codex)
|
||||||
|
|
||||||
|
For orchestration missions, prefer `mosaic coord run --codex` over manual launch/paste.
|
||||||
|
|
||||||
|
When launched through coordinator run flow, Codex MUST:
|
||||||
|
|
||||||
|
1. Treat `.mosaic/orchestrator/next-task.json` as authoritative execution capsule.
|
||||||
|
2. Read mission files before asking clarifying questions:
|
||||||
|
- `~/.config/mosaic/guides/ORCHESTRATOR-PROTOCOL.md`
|
||||||
|
- `docs/MISSION-MANIFEST.md`
|
||||||
|
- `docs/scratchpads/<mission-id>.md`
|
||||||
|
- `docs/TASKS.md`
|
||||||
|
3. Avoid pre-execution question loops. Questions are allowed only for Mosaic escalation triggers (missing access/credentials, destructive irreversible action, legal/compliance unknowns, conflicting objectives, hard budget cap).
|
||||||
|
4. Start execution on the `next_task` from capsule as soon as required files are loaded.
|
||||||
|
|
||||||
## Memory Override
|
## Memory Override
|
||||||
|
|
||||||
Do NOT write durable memory to `~/.codex/` or any Codex-native session memory. All durable memory MUST be written to `~/.config/mosaic/memory/` per `~/.config/mosaic/guides/MEMORY.md`. Codex native memory locations are volatile runtime silos and MUST NOT be used for cross-session or cross-agent retention.
|
Do NOT write durable memory to `~/.codex/` or any Codex-native session memory. All durable memory MUST be written to `~/.config/mosaic/memory/` per `~/.config/mosaic/guides/MEMORY.md`. Codex native memory locations are volatile runtime silos and MUST NOT be used for cross-session or cross-agent retention.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
|
|||||||
ORCH_SUBDIR=".mosaic/orchestrator"
|
ORCH_SUBDIR=".mosaic/orchestrator"
|
||||||
MISSION_FILE="mission.json"
|
MISSION_FILE="mission.json"
|
||||||
SESSION_LOCK_FILE="session.lock"
|
SESSION_LOCK_FILE="session.lock"
|
||||||
|
NEXT_TASK_FILE="next-task.json"
|
||||||
MANIFEST_FILE="docs/MISSION-MANIFEST.md"
|
MANIFEST_FILE="docs/MISSION-MANIFEST.md"
|
||||||
TASKS_MD="docs/TASKS.md"
|
TASKS_MD="docs/TASKS.md"
|
||||||
SCRATCHPAD_DIR="docs/scratchpads"
|
SCRATCHPAD_DIR="docs/scratchpads"
|
||||||
@@ -42,6 +43,30 @@ _require_jq() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coord_runtime() {
|
||||||
|
local runtime="${MOSAIC_COORD_RUNTIME:-claude}"
|
||||||
|
case "$runtime" in
|
||||||
|
claude|codex) echo "$runtime" ;;
|
||||||
|
*) echo "claude" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
coord_launch_command() {
|
||||||
|
local runtime
|
||||||
|
runtime="$(coord_runtime)"
|
||||||
|
echo "mosaic $runtime"
|
||||||
|
}
|
||||||
|
|
||||||
|
coord_run_command() {
|
||||||
|
local runtime
|
||||||
|
runtime="$(coord_runtime)"
|
||||||
|
if [[ "$runtime" == "claude" ]]; then
|
||||||
|
echo "mosaic coord run"
|
||||||
|
else
|
||||||
|
echo "mosaic coord run --$runtime"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ─── Project / state file access ────────────────────────────────────────────
|
# ─── Project / state file access ────────────────────────────────────────────
|
||||||
|
|
||||||
# Return the orchestrator directory for a project
|
# Return the orchestrator directory for a project
|
||||||
@@ -56,6 +81,11 @@ mission_path() {
|
|||||||
echo "$(orch_dir "$project")/$MISSION_FILE"
|
echo "$(orch_dir "$project")/$MISSION_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_task_capsule_path() {
|
||||||
|
local project="${1:-.}"
|
||||||
|
echo "$(orch_dir "$project")/$NEXT_TASK_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
# Exit with error if mission.json is missing or inactive
|
# Exit with error if mission.json is missing or inactive
|
||||||
require_mission() {
|
require_mission() {
|
||||||
local project="${1:-.}"
|
local project="${1:-.}"
|
||||||
@@ -358,6 +388,113 @@ milestone_name() {
|
|||||||
jq -r --arg id "$mid" '.milestones[] | select(.id == $id) | .name // empty' "$mp"
|
jq -r --arg id "$mid" '.milestones[] | select(.id == $id) | .name // empty' "$mp"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ─── Next-task capsule helpers ───────────────────────────────────────────────
|
||||||
|
|
||||||
|
write_next_task_capsule() {
|
||||||
|
local project="${1:-.}"
|
||||||
|
local runtime="${2:-claude}"
|
||||||
|
local mission_id="${3:-}"
|
||||||
|
local mission_name="${4:-}"
|
||||||
|
local project_path="${5:-}"
|
||||||
|
local quality_gates="${6:-}"
|
||||||
|
local current_ms_id="${7:-}"
|
||||||
|
local current_ms_name="${8:-}"
|
||||||
|
local next_task="${9:-}"
|
||||||
|
local tasks_done="${10:-0}"
|
||||||
|
local tasks_total="${11:-0}"
|
||||||
|
local pct="${12:-0}"
|
||||||
|
local current_branch="${13:-}"
|
||||||
|
|
||||||
|
_require_jq || return 1
|
||||||
|
mkdir -p "$(orch_dir "$project")"
|
||||||
|
|
||||||
|
local payload
|
||||||
|
payload="$(jq -n \
|
||||||
|
--arg generated_at "$(iso_now)" \
|
||||||
|
--arg runtime "$runtime" \
|
||||||
|
--arg mission_id "$mission_id" \
|
||||||
|
--arg mission_name "$mission_name" \
|
||||||
|
--arg project_path "$project_path" \
|
||||||
|
--arg quality_gates "$quality_gates" \
|
||||||
|
--arg current_ms_id "$current_ms_id" \
|
||||||
|
--arg current_ms_name "$current_ms_name" \
|
||||||
|
--arg next_task "$next_task" \
|
||||||
|
--arg current_branch "$current_branch" \
|
||||||
|
--arg tasks_done "$tasks_done" \
|
||||||
|
--arg tasks_total "$tasks_total" \
|
||||||
|
--arg pct "$pct" \
|
||||||
|
'{
|
||||||
|
generated_at: $generated_at,
|
||||||
|
runtime: $runtime,
|
||||||
|
mission_id: $mission_id,
|
||||||
|
mission_name: $mission_name,
|
||||||
|
project_path: $project_path,
|
||||||
|
quality_gates: $quality_gates,
|
||||||
|
current_milestone: {
|
||||||
|
id: $current_ms_id,
|
||||||
|
name: $current_ms_name
|
||||||
|
},
|
||||||
|
next_task: $next_task,
|
||||||
|
progress: {
|
||||||
|
tasks_done: ($tasks_done | tonumber),
|
||||||
|
tasks_total: ($tasks_total | tonumber),
|
||||||
|
pct: ($pct | tonumber)
|
||||||
|
},
|
||||||
|
current_branch: $current_branch
|
||||||
|
}')"
|
||||||
|
|
||||||
|
write_json "$(next_task_capsule_path "$project")" "$payload"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_codex_strict_kickoff() {
|
||||||
|
local project="${1:-.}"
|
||||||
|
local continuation_prompt="${2:-}"
|
||||||
|
|
||||||
|
_require_jq || return 1
|
||||||
|
|
||||||
|
local capsule_path
|
||||||
|
capsule_path="$(next_task_capsule_path "$project")"
|
||||||
|
local capsule='{}'
|
||||||
|
if [[ -f "$capsule_path" ]]; then
|
||||||
|
capsule="$(cat "$capsule_path")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local mission_id next_task project_path quality_gates
|
||||||
|
mission_id="$(echo "$capsule" | jq -r '.mission_id // "unknown"')"
|
||||||
|
next_task="$(echo "$capsule" | jq -r '.next_task // "none"')"
|
||||||
|
project_path="$(echo "$capsule" | jq -r '.project_path // "."')"
|
||||||
|
quality_gates="$(echo "$capsule" | jq -r '.quality_gates // "none"')"
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
Now initiating Orchestrator mode...
|
||||||
|
|
||||||
|
STRICT EXECUTION PROFILE FOR CODEX (HARD GATE)
|
||||||
|
- Do NOT ask clarifying questions before your first tool actions unless a Mosaic escalation trigger is hit.
|
||||||
|
- Your first actions must be reading mission state files in order.
|
||||||
|
- Treat the next-task capsule as authoritative execution input.
|
||||||
|
|
||||||
|
REQUIRED FIRST ACTIONS (IN ORDER)
|
||||||
|
1. Read ~/.config/mosaic/guides/ORCHESTRATOR-PROTOCOL.md
|
||||||
|
2. Read docs/MISSION-MANIFEST.md
|
||||||
|
3. Read docs/scratchpads/${mission_id}.md
|
||||||
|
4. Read docs/TASKS.md
|
||||||
|
5. Begin execution on next task: ${next_task}
|
||||||
|
|
||||||
|
WORKING CONTEXT
|
||||||
|
- Project: ${project_path}
|
||||||
|
- Quality gates: ${quality_gates}
|
||||||
|
- Capsule file: .mosaic/orchestrator/next-task.json
|
||||||
|
|
||||||
|
Task capsule (JSON):
|
||||||
|
\`\`\`json
|
||||||
|
${capsule}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
Continuation prompt:
|
||||||
|
${continuation_prompt}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
# Get next milestone after the given one
|
# Get next milestone after the given one
|
||||||
next_milestone_id() {
|
next_milestone_id() {
|
||||||
local project="${1:-.}"
|
local project="${1:-.}"
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ done
|
|||||||
|
|
||||||
_require_jq
|
_require_jq
|
||||||
require_mission "$PROJECT"
|
require_mission "$PROJECT"
|
||||||
|
target_runtime="$(coord_runtime)"
|
||||||
|
launch_cmd="$(coord_launch_command)"
|
||||||
|
|
||||||
# ─── Load mission data ──────────────────────────────────────────────────────
|
# ─── Load mission data ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -93,6 +95,22 @@ if (( session_count > 0 )); then
|
|||||||
fi
|
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 ────────────────────────────────────────────────────────
|
# ─── Generate prompt ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
prompt="$(cat <<EOF
|
prompt="$(cat <<EOF
|
||||||
@@ -108,6 +126,7 @@ Continue **$mission_name** from existing state.
|
|||||||
- **Scratchpad:** docs/scratchpads/${mission_id}.md
|
- **Scratchpad:** docs/scratchpads/${mission_id}.md
|
||||||
- **Protocol:** ~/.config/mosaic/guides/ORCHESTRATOR.md
|
- **Protocol:** ~/.config/mosaic/guides/ORCHESTRATOR.md
|
||||||
- **Quality gates:** $quality_gates
|
- **Quality gates:** $quality_gates
|
||||||
|
- **Target runtime:** $target_runtime
|
||||||
|
|
||||||
## Resume Point
|
## Resume Point
|
||||||
|
|
||||||
@@ -129,9 +148,10 @@ Continue **$mission_name** from existing state.
|
|||||||
3. Read \`docs/scratchpads/${mission_id}.md\` for session history and decisions
|
3. Read \`docs/scratchpads/${mission_id}.md\` for session history and decisions
|
||||||
4. Read \`docs/TASKS.md\` for current task state
|
4. Read \`docs/TASKS.md\` for current task state
|
||||||
5. \`git pull --rebase\` to sync latest changes
|
5. \`git pull --rebase\` to sync latest changes
|
||||||
6. Continue execution from task **${next_task:-next-pending}**
|
6. Launch runtime with \`$launch_cmd\`
|
||||||
7. Follow Two-Phase Completion Protocol
|
7. Continue execution from task **${next_task:-next-pending}**
|
||||||
8. You are the SOLE writer of \`docs/TASKS.md\`
|
8. Follow Two-Phase Completion Protocol
|
||||||
|
9. You are the SOLE writer of \`docs/TASKS.md\`
|
||||||
EOF
|
EOF
|
||||||
)"
|
)"
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,9 @@ fi
|
|||||||
|
|
||||||
# ─── Report ──────────────────────────────────────────────────────────────────
|
# ─── Report ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
runtime_cmd="$(coord_launch_command)"
|
||||||
|
run_cmd="$(coord_run_command)"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${C_GREEN}${C_BOLD}Mission initialized: $NAME${C_RESET}"
|
echo -e "${C_GREEN}${C_BOLD}Mission initialized: $NAME${C_RESET}"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -280,4 +283,4 @@ echo -e " ${C_CYAN}Manifest:${C_RESET} $manifest_path"
|
|||||||
echo -e " ${C_CYAN}Scratchpad:${C_RESET} $sp_file"
|
echo -e " ${C_CYAN}Scratchpad:${C_RESET} $sp_file"
|
||||||
echo -e " ${C_CYAN}Tasks:${C_RESET} $tasks_path"
|
echo -e " ${C_CYAN}Tasks:${C_RESET} $tasks_path"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Next: Launch an agent session with 'mosaic claude' or generate a prompt with 'mosaic coord continue'"
|
echo "Next: Resume with '$run_cmd' (or launch directly with '$runtime_cmd')."
|
||||||
|
|||||||
80
tools/orchestrator/session-run.sh
Executable file
80
tools/orchestrator/session-run.sh
Executable file
@@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
#
|
||||||
|
# session-run.sh — Generate continuation context and launch target runtime.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# session-run.sh [--project <path>] [--milestone <id>] [--print]
|
||||||
|
#
|
||||||
|
# Behavior:
|
||||||
|
# - Builds continuation prompt + next-task capsule.
|
||||||
|
# - Launches selected runtime (default: claude, override via MOSAIC_COORD_RUNTIME).
|
||||||
|
# - For codex, injects strict orchestration kickoff to reduce clarification loops.
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/_lib.sh"
|
||||||
|
|
||||||
|
PROJECT="."
|
||||||
|
MILESTONE=""
|
||||||
|
PRINT=false
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--project) PROJECT="$2"; shift 2 ;;
|
||||||
|
--milestone) MILESTONE="$2"; shift 2 ;;
|
||||||
|
--print) PRINT=true; shift ;;
|
||||||
|
-h|--help)
|
||||||
|
cat <<'USAGE'
|
||||||
|
Usage: session-run.sh [--project <path>] [--milestone <id>] [--print]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--project <path> Project directory (default: CWD)
|
||||||
|
--milestone <id> Force specific milestone context
|
||||||
|
--print Print launch prompt only (no runtime launch)
|
||||||
|
USAGE
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*) echo "Unknown option: $1" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
PROJECT="${PROJECT/#\~/$HOME}"
|
||||||
|
PROJECT="$(cd "$PROJECT" && pwd)"
|
||||||
|
|
||||||
|
_require_jq
|
||||||
|
require_mission "$PROJECT"
|
||||||
|
|
||||||
|
runtime="$(coord_runtime)"
|
||||||
|
launch_cmd="$(coord_launch_command)"
|
||||||
|
|
||||||
|
continue_cmd=(bash "$SCRIPT_DIR/continue-prompt.sh" --project "$PROJECT")
|
||||||
|
if [[ -n "$MILESTONE" ]]; then
|
||||||
|
continue_cmd+=(--milestone "$MILESTONE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
continuation_prompt="$(MOSAIC_COORD_RUNTIME="$runtime" "${continue_cmd[@]}")"
|
||||||
|
|
||||||
|
if [[ "$runtime" == "codex" ]]; then
|
||||||
|
launch_prompt="$(build_codex_strict_kickoff "$PROJECT" "$continuation_prompt")"
|
||||||
|
else
|
||||||
|
launch_prompt="$continuation_prompt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$PRINT" == true ]]; then
|
||||||
|
echo "$launch_prompt"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${C_CYAN}Launching orchestration runtime: ${launch_cmd}${C_RESET}"
|
||||||
|
echo -e "${C_CYAN}Project:${C_RESET} $PROJECT"
|
||||||
|
echo -e "${C_CYAN}Capsule:${C_RESET} $(next_task_capsule_path "$PROJECT")"
|
||||||
|
|
||||||
|
cd "$PROJECT"
|
||||||
|
if [[ "$runtime" == "claude" ]]; then
|
||||||
|
exec "$MOSAIC_HOME/bin/mosaic" claude "$launch_prompt"
|
||||||
|
elif [[ "$runtime" == "codex" ]]; then
|
||||||
|
exec "$MOSAIC_HOME/bin/mosaic" codex "$launch_prompt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${C_RED}Unsupported coord runtime: $runtime${C_RESET}" >&2
|
||||||
|
exit 1
|
||||||
@@ -33,6 +33,8 @@ while [[ $# -gt 0 ]]; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
_require_jq
|
_require_jq
|
||||||
|
runtime_cmd="$(coord_launch_command)"
|
||||||
|
run_cmd="$(coord_run_command)"
|
||||||
|
|
||||||
# ─── Check session lock ─────────────────────────────────────────────────────
|
# ─── Check session lock ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -103,8 +105,9 @@ if ! lock_data="$(session_lock_read "$PROJECT")"; then
|
|||||||
|
|
||||||
if [[ "$m_status" == "active" || "$m_status" == "paused" ]]; then
|
if [[ "$m_status" == "active" || "$m_status" == "paused" ]]; then
|
||||||
echo -e " ${C_BOLD}Next steps:${C_RESET}"
|
echo -e " ${C_BOLD}Next steps:${C_RESET}"
|
||||||
|
echo " $run_cmd Auto-generate context and launch"
|
||||||
echo " mosaic coord continue Generate continuation prompt"
|
echo " mosaic coord continue Generate continuation prompt"
|
||||||
echo " mosaic yolo claude Launch agent session"
|
echo " $runtime_cmd Launch agent session"
|
||||||
elif [[ "$m_status" == "completed" ]]; then
|
elif [[ "$m_status" == "completed" ]]; then
|
||||||
echo -e " ${C_DIM}Mission completed. Start a new one with: mosaic coord init${C_RESET}"
|
echo -e " ${C_DIM}Mission completed. Start a new one with: mosaic coord init${C_RESET}"
|
||||||
else
|
else
|
||||||
|
|||||||
78
tools/orchestrator/smoke-test.sh
Executable file
78
tools/orchestrator/smoke-test.sh
Executable file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
#
|
||||||
|
# smoke-test.sh — Behavior smoke checks for coord continue/run workflows.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# smoke-test.sh
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/_lib.sh"
|
||||||
|
|
||||||
|
PASS=0
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
pass_case() {
|
||||||
|
echo "PASS: $1"
|
||||||
|
PASS=$((PASS + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fail_case() {
|
||||||
|
echo "FAIL: $1" >&2
|
||||||
|
FAIL=$((FAIL + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_project="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$tmp_project"' EXIT
|
||||||
|
|
||||||
|
mkdir -p "$tmp_project/.mosaic/orchestrator" "$tmp_project/docs/scratchpads"
|
||||||
|
|
||||||
|
cat > "$tmp_project/.mosaic/orchestrator/mission.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"mission_id": "smoke-mission-20260223",
|
||||||
|
"name": "Smoke Mission",
|
||||||
|
"status": "active",
|
||||||
|
"project_path": "SMOKE_PROJECT",
|
||||||
|
"quality_gates": "pnpm lint && pnpm test",
|
||||||
|
"milestones": [
|
||||||
|
{ "id": "M1", "name": "Milestone One", "status": "pending" }
|
||||||
|
],
|
||||||
|
"sessions": []
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
cat > "$tmp_project/docs/MISSION-MANIFEST.md" <<'MD'
|
||||||
|
# Mission Manifest
|
||||||
|
MD
|
||||||
|
|
||||||
|
cat > "$tmp_project/docs/scratchpads/smoke-mission-20260223.md" <<'MD'
|
||||||
|
# Scratchpad
|
||||||
|
MD
|
||||||
|
|
||||||
|
cat > "$tmp_project/docs/TASKS.md" <<'MD'
|
||||||
|
| id | status | milestone | description | pr | notes |
|
||||||
|
|----|--------|-----------|-------------|----|-------|
|
||||||
|
| T-001 | pending | M1 | Smoke task | | |
|
||||||
|
MD
|
||||||
|
|
||||||
|
codex_continue_output="$(MOSAIC_COORD_RUNTIME=codex bash "$SCRIPT_DIR/continue-prompt.sh" --project "$tmp_project")"
|
||||||
|
capsule_file="$tmp_project/.mosaic/orchestrator/next-task.json"
|
||||||
|
|
||||||
|
if [[ -f "$capsule_file" ]]; then pass_case "continue writes next-task capsule"; else fail_case "continue writes next-task capsule"; fi
|
||||||
|
if jq -e '.runtime == "codex"' "$capsule_file" >/dev/null 2>&1; then pass_case "capsule runtime is codex"; else fail_case "capsule runtime is codex"; fi
|
||||||
|
if jq -e '.next_task == "T-001"' "$capsule_file" >/dev/null 2>&1; then pass_case "capsule next_task is T-001"; else fail_case "capsule next_task is T-001"; fi
|
||||||
|
if grep -Fq 'Target runtime:** codex' <<< "$codex_continue_output"; then pass_case "continue prompt contains target runtime codex"; else fail_case "continue prompt contains target runtime codex"; fi
|
||||||
|
|
||||||
|
codex_run_prompt="$(MOSAIC_COORD_RUNTIME=codex bash "$SCRIPT_DIR/session-run.sh" --project "$tmp_project" --print)"
|
||||||
|
if [[ "$(printf '%s\n' "$codex_run_prompt" | head -n1)" == "Now initiating Orchestrator mode..." ]]; then pass_case "codex run prompt first line is mode declaration"; else fail_case "codex run prompt first line is mode declaration"; fi
|
||||||
|
if grep -Fq 'Do NOT ask clarifying questions before your first tool actions' <<< "$codex_run_prompt"; then pass_case "codex run prompt includes no-questions hard gate"; else fail_case "codex run prompt includes no-questions hard gate"; fi
|
||||||
|
if grep -Fq '"next_task": "T-001"' <<< "$codex_run_prompt"; then pass_case "codex run prompt embeds capsule json"; else fail_case "codex run prompt embeds capsule json"; fi
|
||||||
|
|
||||||
|
claude_run_prompt="$(MOSAIC_COORD_RUNTIME=claude bash "$SCRIPT_DIR/session-run.sh" --project "$tmp_project" --print)"
|
||||||
|
if [[ "$(printf '%s\n' "$claude_run_prompt" | head -n1)" == "## Continuation Mission" ]]; then pass_case "claude run prompt remains continuation prompt format"; else fail_case "claude run prompt remains continuation prompt format"; fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Smoke test summary: pass=$PASS fail=$FAIL"
|
||||||
|
if (( FAIL > 0 )); then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -41,6 +41,20 @@ _require_cmd() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prdy_runtime() {
|
||||||
|
local runtime="${MOSAIC_PRDY_RUNTIME:-claude}"
|
||||||
|
case "$runtime" in
|
||||||
|
claude|codex) echo "$runtime" ;;
|
||||||
|
*) echo "claude" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
prdy_runtime_command() {
|
||||||
|
local runtime
|
||||||
|
runtime="$(prdy_runtime)"
|
||||||
|
echo "$runtime"
|
||||||
|
}
|
||||||
|
|
||||||
# ─── PRD detection ───────────────────────────────────────────────────────────
|
# ─── PRD detection ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
# Find the PRD file in a project directory.
|
# Find the PRD file in a project directory.
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
#
|
#
|
||||||
# prdy-init.sh — Create a new PRD via guided Claude session
|
# prdy-init.sh — Create a new PRD via guided runtime session
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# prdy-init.sh [--project <path>] [--name <feature>]
|
# prdy-init.sh [--project <path>] [--name <feature>]
|
||||||
#
|
#
|
||||||
# Launches a dedicated Claude Code session in yolo mode with a specialized
|
# Launches a dedicated runtime session in yolo mode with a specialized
|
||||||
# system prompt that guides the user through PRD creation. The output is
|
# system prompt that guides the user through PRD creation. The output is
|
||||||
# written to docs/PRD.md.
|
# written to docs/PRD.md.
|
||||||
|
|
||||||
@@ -24,15 +24,15 @@ while [[ $# -gt 0 ]]; do
|
|||||||
--name) NAME="$2"; shift 2 ;;
|
--name) NAME="$2"; shift 2 ;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
cat <<'USAGE'
|
cat <<'USAGE'
|
||||||
prdy-init.sh — Create a new PRD via guided Claude session
|
prdy-init.sh — Create a new PRD via guided runtime session
|
||||||
|
|
||||||
Usage: prdy-init.sh [--project <path>] [--name <feature>]
|
Usage: prdy-init.sh [--project <path>] [--name <feature>]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--project <path> Project directory (default: CWD)
|
--project <path> Project directory (default: CWD)
|
||||||
--name <feature> Feature or project name (optional, Claude will ask if omitted)
|
--name <feature> Feature or project name (optional, runtime will ask if omitted)
|
||||||
|
|
||||||
Launches Claude Code in yolo mode with a PRD-focused system prompt.
|
Launches the selected runtime in yolo mode with a PRD-focused prompt.
|
||||||
The agent will ask clarifying questions, then write docs/PRD.md.
|
The agent will ask clarifying questions, then write docs/PRD.md.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -51,7 +51,8 @@ PROJECT="${PROJECT/#\~/$HOME}"
|
|||||||
|
|
||||||
# ─── Preflight checks ───────────────────────────────────────────────────────
|
# ─── Preflight checks ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
_require_cmd "claude"
|
RUNTIME_CMD="$(prdy_runtime_command)"
|
||||||
|
_require_cmd "$RUNTIME_CMD"
|
||||||
|
|
||||||
# Check for existing PRD
|
# Check for existing PRD
|
||||||
EXISTING="$(find_prd "$PROJECT")"
|
EXISTING="$(find_prd "$PROJECT")"
|
||||||
@@ -77,11 +78,29 @@ else
|
|||||||
KICKOFF="Create docs/PRD.md for this project. Read the project context first, then ask the user what they want to build. Ask clarifying questions before writing the PRD."
|
KICKOFF="Create docs/PRD.md for this project. Read the project context first, then ask the user what they want to build. Ask clarifying questions before writing the PRD."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ─── Launch Claude ───────────────────────────────────────────────────────────
|
# ─── Launch runtime ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
info "Output target: $PROJECT/$PRD_CANONICAL"
|
info "Output target: $PROJECT/$PRD_CANONICAL"
|
||||||
info "Mode: PRD Creation (yolo)"
|
info "Mode: PRD Creation (yolo, runtime: $RUNTIME_CMD)"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
cd "$PROJECT"
|
cd "$PROJECT"
|
||||||
|
if [[ "$RUNTIME_CMD" == "claude" ]]; then
|
||||||
exec claude --dangerously-skip-permissions --append-system-prompt "$SYSTEM_PROMPT" "$KICKOFF"
|
exec claude --dangerously-skip-permissions --append-system-prompt "$SYSTEM_PROMPT" "$KICKOFF"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$RUNTIME_CMD" == "codex" ]]; then
|
||||||
|
CODEX_PROMPT="$(cat <<EOF
|
||||||
|
Follow this PRD contract exactly.
|
||||||
|
|
||||||
|
$SYSTEM_PROMPT
|
||||||
|
|
||||||
|
Task:
|
||||||
|
$KICKOFF
|
||||||
|
EOF
|
||||||
|
)"
|
||||||
|
exec codex --dangerously-bypass-approvals-and-sandbox "$CODEX_PROMPT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fail "Unsupported runtime: $RUNTIME_CMD"
|
||||||
|
exit 1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
#
|
#
|
||||||
# prdy-update.sh — Update an existing PRD via guided Claude session
|
# prdy-update.sh — Update an existing PRD via guided runtime session
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# prdy-update.sh [--project <path>]
|
# prdy-update.sh [--project <path>]
|
||||||
#
|
#
|
||||||
# Launches a dedicated Claude Code session in yolo mode with a specialized
|
# Launches a dedicated runtime session in yolo mode with a specialized
|
||||||
# system prompt that reads the existing PRD and guides targeted modifications.
|
# system prompt that reads the existing PRD and guides targeted modifications.
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
@@ -21,14 +21,14 @@ while [[ $# -gt 0 ]]; do
|
|||||||
--project) PROJECT="$2"; shift 2 ;;
|
--project) PROJECT="$2"; shift 2 ;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
cat <<'USAGE'
|
cat <<'USAGE'
|
||||||
prdy-update.sh — Update an existing PRD via guided Claude session
|
prdy-update.sh — Update an existing PRD via guided runtime session
|
||||||
|
|
||||||
Usage: prdy-update.sh [--project <path>]
|
Usage: prdy-update.sh [--project <path>]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--project <path> Project directory (default: CWD)
|
--project <path> Project directory (default: CWD)
|
||||||
|
|
||||||
Launches Claude Code in yolo mode with a PRD-update system prompt.
|
Launches the selected runtime in yolo mode with a PRD-update prompt.
|
||||||
The agent will read the existing docs/PRD.md, summarize its state,
|
The agent will read the existing docs/PRD.md, summarize its state,
|
||||||
and ask what changes are needed.
|
and ask what changes are needed.
|
||||||
|
|
||||||
@@ -47,7 +47,8 @@ PROJECT="${PROJECT/#\~/$HOME}"
|
|||||||
|
|
||||||
# ─── Preflight checks ───────────────────────────────────────────────────────
|
# ─── Preflight checks ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
_require_cmd "claude"
|
RUNTIME_CMD="$(prdy_runtime_command)"
|
||||||
|
_require_cmd "$RUNTIME_CMD"
|
||||||
|
|
||||||
# Require existing PRD
|
# Require existing PRD
|
||||||
EXISTING="$(find_prd "$PROJECT")"
|
EXISTING="$(find_prd "$PROJECT")"
|
||||||
@@ -65,11 +66,29 @@ SYSTEM_PROMPT="$(build_prdy_system_prompt "update")"
|
|||||||
|
|
||||||
KICKOFF="Read the existing PRD at ${EXISTING}, summarize its current state, then ask what changes or additions are needed."
|
KICKOFF="Read the existing PRD at ${EXISTING}, summarize its current state, then ask what changes or additions are needed."
|
||||||
|
|
||||||
# ─── Launch Claude ───────────────────────────────────────────────────────────
|
# ─── Launch runtime ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
info "Updating: $EXISTING"
|
info "Updating: $EXISTING"
|
||||||
info "Mode: PRD Update (yolo)"
|
info "Mode: PRD Update (yolo, runtime: $RUNTIME_CMD)"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
cd "$PROJECT"
|
cd "$PROJECT"
|
||||||
|
if [[ "$RUNTIME_CMD" == "claude" ]]; then
|
||||||
exec claude --dangerously-skip-permissions --append-system-prompt "$SYSTEM_PROMPT" "$KICKOFF"
|
exec claude --dangerously-skip-permissions --append-system-prompt "$SYSTEM_PROMPT" "$KICKOFF"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$RUNTIME_CMD" == "codex" ]]; then
|
||||||
|
CODEX_PROMPT="$(cat <<EOF
|
||||||
|
Follow this PRD contract exactly.
|
||||||
|
|
||||||
|
$SYSTEM_PROMPT
|
||||||
|
|
||||||
|
Task:
|
||||||
|
$KICKOFF
|
||||||
|
EOF
|
||||||
|
)"
|
||||||
|
exec codex --dangerously-bypass-approvals-and-sandbox "$CODEX_PROMPT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fail "Unsupported runtime: $RUNTIME_CMD"
|
||||||
|
exit 1
|
||||||
|
|||||||
Reference in New Issue
Block a user