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:
Jason Woltje
2026-02-23 18:27:09 -06:00
parent fbf74c2736
commit abead17e0e
12 changed files with 517 additions and 41 deletions

View File

@@ -53,8 +53,8 @@ Management:
PRD:
prdy <subcommand> PRD creation and validation
init Create docs/PRD.md via Claude session
update Update existing PRD via Claude session
init Create docs/PRD.md via guided runtime session
update Update existing PRD via guided runtime session
validate Check PRD completeness (bash-only)
Coordinator (r0):
@@ -63,6 +63,7 @@ Coordinator (r0):
mission Show mission progress dashboard
status Check agent session health
continue Generate continuation prompt
run Generate context and launch selected runtime
resume Crash recovery
Options:
@@ -481,26 +482,59 @@ run_seq() {
run_coord() {
check_mosaic_home
local subcmd="${1:-help}"
shift || true
local runtime="claude"
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"
case "$subcmd" in
status|session)
exec bash "$tool_dir/session-status.sh" "$@"
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/session-status.sh" "$@"
;;
init)
exec bash "$tool_dir/mission-init.sh" "$@"
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/mission-init.sh" "$@"
;;
mission|progress)
exec bash "$tool_dir/mission-status.sh" "$@"
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/mission-status.sh" "$@"
;;
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)
exec bash "$tool_dir/session-resume.sh" "$@"
MOSAIC_COORD_RUNTIME="$runtime" exec bash "$tool_dir/session-resume.sh" "$@"
;;
help|*)
cat <<COORD_USAGE
@@ -511,12 +545,23 @@ Commands:
mission [--project <path>] Show mission progress dashboard
status [--project <path>] Check agent session health
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)
Runtime:
--claude Use Claude runtime hints/prompts (default)
--codex Use Codex runtime hints/prompts
Examples:
mosaic coord init --name "Security Fix" --milestones "Critical,High,Medium"
mosaic coord mission
mosaic coord --codex mission
mosaic coord continue --copy
mosaic coord run
mosaic coord run --codex
mosaic coord smoke
mosaic coord continue --codex --copy
COORD_USAGE
;;
@@ -552,33 +597,65 @@ _check_resumable_session() {
run_prdy() {
check_mosaic_home
local subcmd="${1:-help}"
shift || true
local runtime="claude"
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"
case "$subcmd" in
init)
exec bash "$tool_dir/prdy-init.sh" "$@"
MOSAIC_PRDY_RUNTIME="$runtime" exec bash "$tool_dir/prdy-init.sh" "$@"
;;
update)
exec bash "$tool_dir/prdy-update.sh" "$@"
MOSAIC_PRDY_RUNTIME="$runtime" exec bash "$tool_dir/prdy-update.sh" "$@"
;;
validate|check)
exec bash "$tool_dir/prdy-validate.sh" "$@"
MOSAIC_PRDY_RUNTIME="$runtime" exec bash "$tool_dir/prdy-validate.sh" "$@"
;;
help|*)
cat <<PRDY_USAGE
mosaic prdy — PRD creation and validation tools
Commands:
init [--project <path>] [--name <feature>] Create docs/PRD.md via guided Claude session
update [--project <path>] Update existing docs/PRD.md via Claude session
init [--project <path>] [--name <feature>] Create docs/PRD.md via guided runtime session
update [--project <path>] Update existing docs/PRD.md via guided runtime session
validate [--project <path>] Check PRD completeness against Mosaic guide (bash-only)
Runtime:
--claude Use Claude runtime (default)
--codex Use Codex runtime
Examples:
mosaic prdy init --name "User Authentication"
mosaic prdy update
mosaic prdy --codex init --name "User Authentication"
mosaic prdy validate
Output location: docs/PRD.md (per Mosaic PRD guide)

View File

@@ -131,9 +131,9 @@ If context usage is high, produce a handoff message:
4. Commit all state files
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
@@ -152,6 +152,16 @@ Continue **{mission}** from existing state.
4. Human launches new session and pastes the prompt
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
@@ -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 status` | Check if agent session is still running |
| `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 --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 →
status → mission → continue → launch agent → repeat
status → mission → run → repeat
```
---

View File

@@ -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...`
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
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.

View File

@@ -11,6 +11,7 @@ MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
ORCH_SUBDIR=".mosaic/orchestrator"
MISSION_FILE="mission.json"
SESSION_LOCK_FILE="session.lock"
NEXT_TASK_FILE="next-task.json"
MANIFEST_FILE="docs/MISSION-MANIFEST.md"
TASKS_MD="docs/TASKS.md"
SCRATCHPAD_DIR="docs/scratchpads"
@@ -42,6 +43,30 @@ _require_jq() {
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 ────────────────────────────────────────────
# Return the orchestrator directory for a project
@@ -56,6 +81,11 @@ mission_path() {
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
require_mission() {
local project="${1:-.}"
@@ -358,6 +388,113 @@ milestone_name() {
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
next_milestone_id() {
local project="${1:-.}"

View File

@@ -30,6 +30,8 @@ done
_require_jq
require_mission "$PROJECT"
target_runtime="$(coord_runtime)"
launch_cmd="$(coord_launch_command)"
# ─── Load mission data ──────────────────────────────────────────────────────
@@ -93,6 +95,22 @@ if (( session_count > 0 )); then
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
@@ -108,6 +126,7 @@ Continue **$mission_name** from existing state.
- **Scratchpad:** docs/scratchpads/${mission_id}.md
- **Protocol:** ~/.config/mosaic/guides/ORCHESTRATOR.md
- **Quality gates:** $quality_gates
- **Target runtime:** $target_runtime
## Resume Point
@@ -129,9 +148,10 @@ Continue **$mission_name** from existing state.
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:-next-pending}**
7. Follow Two-Phase Completion Protocol
8. You are the SOLE writer of \`docs/TASKS.md\`
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
)"

View File

@@ -270,6 +270,9 @@ 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 ""
@@ -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}Tasks:${C_RESET} $tasks_path"
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')."

View 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

View File

@@ -33,6 +33,8 @@ while [[ $# -gt 0 ]]; do
done
_require_jq
runtime_cmd="$(coord_launch_command)"
run_cmd="$(coord_run_command)"
# ─── Check session lock ─────────────────────────────────────────────────────
@@ -103,8 +105,9 @@ if ! lock_data="$(session_lock_read "$PROJECT")"; then
if [[ "$m_status" == "active" || "$m_status" == "paused" ]]; then
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 yolo claude Launch agent session"
echo " $runtime_cmd Launch agent session"
elif [[ "$m_status" == "completed" ]]; then
echo -e " ${C_DIM}Mission completed. Start a new one with: mosaic coord init${C_RESET}"
else

View 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

View File

@@ -41,6 +41,20 @@ _require_cmd() {
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 ───────────────────────────────────────────────────────────
# Find the PRD file in a project directory.

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env bash
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:
# 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
# written to docs/PRD.md.
@@ -24,15 +24,15 @@ while [[ $# -gt 0 ]]; do
--name) NAME="$2"; shift 2 ;;
-h|--help)
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>]
Options:
--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.
Examples:
@@ -51,7 +51,8 @@ PROJECT="${PROJECT/#\~/$HOME}"
# ─── Preflight checks ───────────────────────────────────────────────────────
_require_cmd "claude"
RUNTIME_CMD="$(prdy_runtime_command)"
_require_cmd "$RUNTIME_CMD"
# Check for existing PRD
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."
fi
# ─── Launch Claude ──────────────────────────────────────────────────────────
# ─── Launch runtime ──────────────────────────────────────────────────────────
info "Output target: $PROJECT/$PRD_CANONICAL"
info "Mode: PRD Creation (yolo)"
info "Mode: PRD Creation (yolo, runtime: $RUNTIME_CMD)"
echo ""
cd "$PROJECT"
if [[ "$RUNTIME_CMD" == "claude" ]]; then
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

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env bash
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:
# 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.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -21,14 +21,14 @@ while [[ $# -gt 0 ]]; do
--project) PROJECT="$2"; shift 2 ;;
-h|--help)
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>]
Options:
--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,
and ask what changes are needed.
@@ -47,7 +47,8 @@ PROJECT="${PROJECT/#\~/$HOME}"
# ─── Preflight checks ───────────────────────────────────────────────────────
_require_cmd "claude"
RUNTIME_CMD="$(prdy_runtime_command)"
_require_cmd "$RUNTIME_CMD"
# Require existing PRD
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."
# ─── Launch Claude ──────────────────────────────────────────────────────────
# ─── Launch runtime ──────────────────────────────────────────────────────────
info "Updating: $EXISTING"
info "Mode: PRD Update (yolo)"
info "Mode: PRD Update (yolo, runtime: $RUNTIME_CMD)"
echo ""
cd "$PROJECT"
if [[ "$RUNTIME_CMD" == "claude" ]]; then
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