- 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>
280 lines
9.1 KiB
Bash
280 lines
9.1 KiB
Bash
#!/usr/bin/env bash
|
||
#
|
||
# _lib.sh — Shared functions for mosaic prdy tools
|
||
#
|
||
# Usage: source ~/.config/mosaic/tools/prdy/_lib.sh
|
||
#
|
||
# Provides PRD detection, section validation, and system prompt generation
|
||
# for interactive PRD creation/update sessions.
|
||
|
||
MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
|
||
PRD_CANONICAL="docs/PRD.md"
|
||
PRD_JSON_ALT="docs/PRD.json"
|
||
|
||
# ─── Color support ───────────────────────────────────────────────────────────
|
||
|
||
if [[ -t 1 ]]; then
|
||
C_GREEN='\033[0;32m'
|
||
C_RED='\033[0;31m'
|
||
C_YELLOW='\033[0;33m'
|
||
C_CYAN='\033[0;36m'
|
||
C_BOLD='\033[1m'
|
||
C_DIM='\033[2m'
|
||
C_RESET='\033[0m'
|
||
else
|
||
C_GREEN='' C_RED='' C_YELLOW='' C_CYAN='' C_BOLD='' C_DIM='' C_RESET=''
|
||
fi
|
||
|
||
ok() { echo -e " ${C_GREEN}✓${C_RESET} $1"; }
|
||
warn() { echo -e " ${C_YELLOW}⚠${C_RESET} $1" >&2; }
|
||
fail() { echo -e " ${C_RED}✗${C_RESET} $1" >&2; }
|
||
info() { echo -e " ${C_CYAN}ℹ${C_RESET} $1"; }
|
||
step() { echo -e "\n${C_BOLD}$1${C_RESET}"; }
|
||
|
||
# ─── Dependency checks ──────────────────────────────────────────────────────
|
||
|
||
_require_cmd() {
|
||
local cmd="$1"
|
||
if ! command -v "$cmd" &>/dev/null; then
|
||
fail "'$cmd' is required but not installed"
|
||
return 1
|
||
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.
|
||
# Returns the path (relative to project root) or empty string.
|
||
find_prd() {
|
||
local project="${1:-.}"
|
||
if [[ -f "$project/$PRD_CANONICAL" ]]; then
|
||
echo "$project/$PRD_CANONICAL"
|
||
elif [[ -f "$project/$PRD_JSON_ALT" ]]; then
|
||
echo "$project/$PRD_JSON_ALT"
|
||
fi
|
||
}
|
||
|
||
# ─── Section validation manifest ─────────────────────────────────────────────
|
||
|
||
# 10 required sections per ~/.config/mosaic/guides/PRD.md
|
||
# Each entry: "label|grep_pattern" (extended regex, case-insensitive via grep -iE)
|
||
PRDY_REQUIRED_SECTIONS=(
|
||
"Problem Statement|^#{2,3} .*(problem statement|objective)"
|
||
"Scope / Non-Goals|^#{2,3} .*(scope|non.goal|out of scope|in.scope)"
|
||
"User Stories / Requirements|^#{2,3} .*(user stor|stakeholder|user.*requirement)"
|
||
"Functional Requirements|^#{2,3} .*functional requirement"
|
||
"Non-Functional Requirements|^#{2,3} .*non.functional"
|
||
"Acceptance Criteria|^#{2,3} .*acceptance criteria|\*\*acceptance criteria\*\*|- \[ \]"
|
||
"Technical Considerations|^#{2,3} .*(technical consideration|constraint|dependenc)"
|
||
"Risks / Open Questions|^#{2,3} .*(risk|open question)"
|
||
"Success Metrics / Testing|^#{2,3} .*(success metric|test|verification)"
|
||
"Milestones / Delivery|^#{2,3} .*(milestone|delivery|scope version)"
|
||
)
|
||
|
||
# ─── System prompt builder ───────────────────────────────────────────────────
|
||
|
||
# Build the specialized system prompt for PRD sessions.
|
||
# Usage: build_prdy_system_prompt <mode>
|
||
# mode: "init" or "update"
|
||
build_prdy_system_prompt() {
|
||
local mode="${1:-init}"
|
||
local guide_file="$MOSAIC_HOME/guides/PRD.md"
|
||
local template_file="$MOSAIC_HOME/templates/docs/PRD.md.template"
|
||
|
||
cat <<'PROMPT_HEADER'
|
||
# Mosaic PRD Agent — Behavioral Contract
|
||
|
||
You are a specialized PRD (Product Requirements Document) agent. Your sole purpose is to help the user create or update a comprehensive PRD document.
|
||
|
||
## Mode Declaration (Hard Gate)
|
||
|
||
PROMPT_HEADER
|
||
|
||
if [[ "$mode" == "init" ]]; then
|
||
cat <<'INIT_MODE'
|
||
Your first response MUST start with: "Now initiating PRD Creation mode..."
|
||
|
||
You are creating a NEW PRD. The output file is `docs/PRD.md`.
|
||
|
||
## Workflow
|
||
|
||
1. Read the project directory to understand context (README, package.json, existing docs, source structure)
|
||
2. Ask the user 3-5 clarifying questions with lettered options (A/B/C/D) so they can answer "1A, 2C, 3B"
|
||
3. Focus questions on: problem/goal, target users, scope boundaries, milestone structure, success criteria
|
||
4. After answers (or if the description is sufficiently complete), generate the full PRD
|
||
5. Write to `docs/PRD.md` (create `docs/` directory if it doesn't exist)
|
||
6. After writing, tell the user: "PRD written to docs/PRD.md. Run `mosaic prdy validate` to verify completeness."
|
||
|
||
INIT_MODE
|
||
else
|
||
cat <<'UPDATE_MODE'
|
||
Your first response MUST start with: "Now initiating PRD Update mode..."
|
||
|
||
You are UPDATING an existing PRD. Read `docs/PRD.md` (or `docs/PRD.json`) first.
|
||
|
||
## Workflow
|
||
|
||
1. Read the existing PRD file completely
|
||
2. Summarize the current state to the user (title, status, milestone count, open questions)
|
||
3. Ask the user what changes or additions are needed
|
||
4. Make targeted modifications — do NOT rewrite sections that don't need changes
|
||
5. Preserve existing user stories, FRs, and acceptance criteria unless explicitly asked to change them
|
||
6. After writing, tell the user: "PRD updated. Run `mosaic prdy validate` to verify completeness."
|
||
|
||
UPDATE_MODE
|
||
fi
|
||
|
||
cat <<'CONSTRAINTS'
|
||
## Hard Constraints
|
||
|
||
MUST:
|
||
- Save output to `docs/PRD.md` only
|
||
- Include ALL 10 required sections from the Mosaic PRD guide (included below)
|
||
- Number functional requirements as FR-1, FR-2, ... in sequence
|
||
- Group user stories under named Milestones (e.g., "Milestone 0.0.4 — Foundation")
|
||
- Format user stories as US-NNN with Description and Acceptance Criteria checkboxes
|
||
- Mark all guessed decisions with `ASSUMPTION:` and rationale
|
||
- Include a Metadata block (Owner, Date, Status, Mission ID, Scope Version)
|
||
- Write for junior developers and AI agents — explicit, unambiguous, no jargon
|
||
- Include "Typecheck and lint pass" in acceptance criteria for code stories
|
||
- Include "Verify in browser using dev-browser skill" for UI stories
|
||
|
||
MUST NOT:
|
||
- Write any implementation code
|
||
- Modify any files other than `docs/PRD.md`
|
||
- Skip clarifying questions when the feature description is ambiguous
|
||
- Begin implementation of any requirements
|
||
- Invent requirements silently — all guesses must be marked with ASSUMPTION
|
||
|
||
CONSTRAINTS
|
||
|
||
cat <<'STRUCTURE'
|
||
## Required PRD Structure (Gold Standard)
|
||
|
||
Follow this exact structure. Every section is required.
|
||
|
||
```
|
||
# PRD: {Feature/Project Name}
|
||
|
||
## Metadata
|
||
- **Owner:** {name}
|
||
- **Date:** {yyyy-mm-dd}
|
||
- **Status:** draft|planning|approved|in-progress|completed
|
||
- **Mission ID:** {kebab-case-id-yyyymmdd}
|
||
- **Scope Version:** {e.g., 0.0.4 → 0.0.5 → 0.1.0}
|
||
|
||
## Introduction
|
||
Narrative overview: what this is, the context it lives in, what exists before this work.
|
||
|
||
## Problem Statement
|
||
Numbered list of specific pain points being solved.
|
||
|
||
## Goals
|
||
Bullet list of measurable objectives.
|
||
|
||
## Milestones
|
||
Named milestones (e.g., "Milestone 0.0.4 — Design System Foundation").
|
||
Each milestone has a one-paragraph description of its theme.
|
||
|
||
## User Stories (grouped under milestones)
|
||
|
||
### Milestone X.Y.Z — {Theme Name}
|
||
|
||
#### US-001: {Title}
|
||
**Description:** As a {user}, I want {feature} so that {benefit}.
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Specific verifiable criterion
|
||
- [ ] Another criterion
|
||
- [ ] Typecheck and lint pass
|
||
- [ ] [UI stories only] Verify in browser using dev-browser skill
|
||
|
||
---
|
||
|
||
## Functional Requirements
|
||
Numbered FR-1 through FR-N. Group by subsystem if applicable.
|
||
Each: "FR-N: {subject} must {behavior}"
|
||
|
||
## Non-Goals (Out of Scope)
|
||
Numbered list of explicit exclusions with brief rationale.
|
||
|
||
## Design Considerations
|
||
- Design references (mockups, existing design systems)
|
||
- Key visual/UX elements
|
||
- Component hierarchy
|
||
|
||
## Technical Considerations
|
||
|
||
### Dependencies
|
||
Libraries, packages, external services required.
|
||
|
||
### Build & CI
|
||
Build pipeline, CI gates, quality checks.
|
||
|
||
### Deployment
|
||
Target infrastructure, deployment method, image tagging strategy.
|
||
|
||
### Risks
|
||
Technical risks that could affect delivery.
|
||
|
||
## Success Metrics
|
||
Numbered list of measurable success conditions.
|
||
|
||
## Open Questions
|
||
Numbered list. For unresolved items, add:
|
||
(ASSUMPTION: {best-guess decision} — {rationale})
|
||
```
|
||
|
||
STRUCTURE
|
||
|
||
cat <<'QUESTIONS'
|
||
## Clarifying Question Format
|
||
|
||
When asking clarifying questions, use numbered questions with lettered options:
|
||
|
||
```
|
||
1. What is the primary goal?
|
||
A. Option one
|
||
B. Option two
|
||
C. Option three
|
||
D. Other: [please specify]
|
||
|
||
2. What is the target scope?
|
||
A. Minimal viable
|
||
B. Full-featured
|
||
C. Backend only
|
||
D. Frontend only
|
||
```
|
||
|
||
Tell the user they can answer with shorthand like "1A, 2C, 3B" for quick iteration.
|
||
|
||
QUESTIONS
|
||
|
||
# Include the live PRD guide
|
||
if [[ -f "$guide_file" ]]; then
|
||
printf '\n## Mosaic PRD Guide (Authoritative Rules)\n\n'
|
||
cat "$guide_file"
|
||
fi
|
||
|
||
# Include the template as reference
|
||
if [[ -f "$template_file" ]]; then
|
||
printf '\n## PRD Template Reference\n\n```markdown\n'
|
||
cat "$template_file"
|
||
printf '\n```\n'
|
||
fi
|
||
}
|