diff --git a/bin/mosaic b/bin/mosaic index 3c7499b..426e9c4 100755 --- a/bin/mosaic +++ b/bin/mosaic @@ -53,8 +53,8 @@ Management: PRD: prdy 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 <] Show mission progress dashboard status [--project ] Check agent session health continue [--project ] Generate continuation prompt for next session + run [--project ] Generate context and launch selected runtime + smoke Run orchestration behavior smoke checks resume [--project ] 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 <] [--name ] Create docs/PRD.md via guided Claude session - update [--project ] Update existing docs/PRD.md via Claude session + init [--project ] [--name ] Create docs/PRD.md via guided runtime session + update [--project ] Update existing docs/PRD.md via guided runtime session validate [--project ] 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) diff --git a/guides/ORCHESTRATOR-PROTOCOL.md b/guides/ORCHESTRATOR-PROTOCOL.md index 12a39c1..4fb0dba 100644 --- a/guides/ORCHESTRATOR-PROTOCOL.md +++ b/guides/ORCHESTRATOR-PROTOCOL.md @@ -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 ``` --- diff --git a/runtime/codex/RUNTIME.md b/runtime/codex/RUNTIME.md index 0ca1486..a1f4bd2 100644 --- a/runtime/codex/RUNTIME.md +++ b/runtime/codex/RUNTIME.md @@ -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/.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. diff --git a/tools/orchestrator/_lib.sh b/tools/orchestrator/_lib.sh index 69b50cf..1f38b40 100755 --- a/tools/orchestrator/_lib.sh +++ b/tools/orchestrator/_lib.sh @@ -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 < 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 <] [--milestone ] [--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 ] [--milestone ] [--print] + +Options: + --project Project directory (default: CWD) + --milestone 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 diff --git a/tools/orchestrator/session-status.sh b/tools/orchestrator/session-status.sh index 9ee4859..b035d0a 100755 --- a/tools/orchestrator/session-status.sh +++ b/tools/orchestrator/session-status.sh @@ -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 diff --git a/tools/orchestrator/smoke-test.sh b/tools/orchestrator/smoke-test.sh new file mode 100755 index 0000000..24b4513 --- /dev/null +++ b/tools/orchestrator/smoke-test.sh @@ -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 diff --git a/tools/prdy/_lib.sh b/tools/prdy/_lib.sh index cf24e21..7f5c8e9 100644 --- a/tools/prdy/_lib.sh +++ b/tools/prdy/_lib.sh @@ -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. diff --git a/tools/prdy/prdy-init.sh b/tools/prdy/prdy-init.sh index e09455a..d701622 100644 --- a/tools/prdy/prdy-init.sh +++ b/tools/prdy/prdy-init.sh @@ -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 ] [--name ] # -# 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 ] [--name ] Options: --project Project directory (default: CWD) - --name Feature or project name (optional, Claude will ask if omitted) + --name 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" -exec claude --dangerously-skip-permissions --append-system-prompt "$SYSTEM_PROMPT" "$KICKOFF" +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 <] # -# 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 ] Options: --project 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" -exec claude --dangerously-skip-permissions --append-system-prompt "$SYSTEM_PROMPT" "$KICKOFF" +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 <