diff --git a/bin/mosaic b/bin/mosaic index 426e9c4..9276bf5 100755 --- a/bin/mosaic +++ b/bin/mosaic @@ -56,6 +56,7 @@ PRD: init Create docs/PRD.md via guided runtime session update Update existing PRD via guided runtime session validate Check PRD completeness (bash-only) + status Quick PRD health check (one-liner) Coordinator (r0): coord Manual coordinator tools @@ -183,6 +184,40 @@ MISSION_EOF fi fi + # Inject PRD status so the agent knows requirements state + local prd_file="docs/PRD.md" + if [[ -f "$prd_file" ]]; then + local prd_sections=0 + local prd_assumptions=0 + for entry in "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" \ + "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)"; do + local pattern="${entry#*|}" + grep -qiE "$pattern" "$prd_file" 2>/dev/null && prd_sections=$((prd_sections + 1)) + done + prd_assumptions=$(grep -c 'ASSUMPTION:' "$prd_file" 2>/dev/null || echo 0) + + local prd_status="ready" + (( prd_sections < 10 )) && prd_status="incomplete ($prd_sections/10 sections)" + + cat <] [--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) + status [--project ] [--format short|json] Quick PRD health check (one-liner) Runtime: --claude Use Claude runtime (default) diff --git a/tools/prdy/prdy-status.sh b/tools/prdy/prdy-status.sh new file mode 100755 index 0000000..705cce2 --- /dev/null +++ b/tools/prdy/prdy-status.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +set -euo pipefail +# +# prdy-status.sh — Quick PRD health check (one-liner output) +# +# Usage: +# prdy-status.sh [--project ] [--format short|json] +# +# Exit codes: +# 0 = PRD ready (all required sections present) +# 1 = PRD incomplete +# 2 = PRD missing + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/_lib.sh" + +# ─── Parse arguments ───────────────────────────────────────────────────────── + +PROJECT="." +FORMAT="short" + +while [[ $# -gt 0 ]]; do + case "$1" in + --project) PROJECT="$2"; shift 2 ;; + --format) FORMAT="$2"; shift 2 ;; + -h|--help) + cat <<'USAGE' +prdy-status.sh — Quick PRD health check + +Usage: prdy-status.sh [--project ] [--format short|json] + +Options: + --project Project directory (default: CWD) + --format Output format: short (default) or json + +Exit codes: + 0 = PRD ready (all required sections present) + 1 = PRD incomplete + 2 = PRD missing +USAGE + exit 0 + ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac +done + +PROJECT="${PROJECT/#\~/$HOME}" + +# ─── Status check ──────────────────────────────────────────────────────────── + +PRD_PATH="$(find_prd "$PROJECT")" + +if [[ -z "$PRD_PATH" ]]; then + if [[ "$FORMAT" == "json" ]]; then + echo '{"status":"missing"}' + else + echo "PRD: missing" + fi + exit 2 +fi + +# Count present sections using the shared manifest +PRD_CONTENT="$(cat "$PRD_PATH")" +total=${#PRDY_REQUIRED_SECTIONS[@]} +present=0 + +for entry in "${PRDY_REQUIRED_SECTIONS[@]}"; do + pattern="${entry#*|}" + if echo "$PRD_CONTENT" | grep -qiE "$pattern"; then + present=$((present + 1)) + fi +done + +# Count additional metrics +fr_count=$(echo "$PRD_CONTENT" | grep -cE '^\- FR-[0-9]+:|^FR-[0-9]+:' || true) +us_count=$(echo "$PRD_CONTENT" | grep -cE '^#{1,4} US-[0-9]+' || true) +assumptions=$(echo "$PRD_CONTENT" | grep -c 'ASSUMPTION:' || true) + +if (( present == total )); then + status="ready" + exit_code=0 +else + status="incomplete" + exit_code=1 +fi + +if [[ "$FORMAT" == "json" ]]; then + printf '{"status":"%s","sections":%d,"total":%d,"frs":%d,"stories":%d,"assumptions":%d}\n' \ + "$status" "$present" "$total" "$fr_count" "$us_count" "$assumptions" +else + echo "PRD: $status ($present/$total sections, ${fr_count} FRs, ${us_count} stories, $assumptions assumptions)" +fi + +exit "$exit_code"