#!/usr/bin/env bash # Generate Spec from Template # Creates a new spec file in docs/specs/ from a template set -o pipefail TEMPLATE_NAME="${1:-.}" SPEC_ID="${2:-.}" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Find git repo root for reliable path resolution # This allows scripts to work when called from any directory in the repo if git -C "$SCRIPT_DIR" rev-parse --git-dir > /dev/null 2>&1; then PROJECT_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)" else # Fallback to relative path traversal (4 levels up from scripts/) # From: project-root/project-basics/skills/spec-author/scripts/ # To: project-root/ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)" fi # Specs are always stored in the git repo root under docs/specs/ SPECS_DIR="$PROJECT_ROOT/docs/specs" # Function to get folder name for spec type (same as template name) get_spec_folder() { local template=$1 case "$template" in business-requirement|technical-requirement|design-document|api-contract|data-model|component|plan|milestone|flow-schematic|deployment-procedure|configuration-schema) echo "$template" ;; *) echo "" ;; esac } # Color codes RED='\033[0;31m' GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' NC='\033[0m' # Print usage usage() { echo "Usage: generate-spec.sh [ | --next ]" echo "" echo "Template types:" echo " - business-requirement (brd-XXX-slug)" echo " - technical-requirement (prd-XXX-slug)" echo " - design-document (des-XXX-slug)" echo " - api-contract (api-XXX-slug)" echo " - data-model (data-XXX-slug)" echo " - component (cmp-XXX-slug)" echo " - plan (pln-XXX-slug)" echo " - milestone (mls-XXX-slug)" echo " - flow-schematic (flow-XXX-slug)" echo " - deployment-procedure (deploy-XXX-slug)" echo " - configuration-schema (config-XXX-slug)" echo "" echo "Spec ID: Use the full ID (e.g., brd-001-user-export)" echo " OR use --next to auto-generate next ID" echo "" echo "Examples:" echo " generate-spec.sh business-requirement brd-001-user-export" echo " Creates: docs/specs/business-requirement/brd-001-user-export.md" echo "" echo " generate-spec.sh business-requirement --next user-export" echo " Auto-determines next ID (e.g., brd-002-user-export)" echo "" echo " generate-spec.sh api-contract --next" echo " Auto-determines next ID without slug (e.g., api-001)" exit 1 } if [ "$TEMPLATE_NAME" = "-h" ] || [ "$TEMPLATE_NAME" = "--help" ] || [ -z "$TEMPLATE_NAME" ]; then usage fi # Handle --next flag for auto-generating next ID if [ "$SPEC_ID" = "--next" ]; then # Check if slug is provided as third argument SLUG="${3:-}" if [ -n "$SLUG" ]; then SPEC_ID=$("$SCRIPT_DIR/next-id.sh" "$TEMPLATE_NAME" --with-slug "$SLUG" --quiet) else SPEC_ID=$("$SCRIPT_DIR/next-id.sh" "$TEMPLATE_NAME" --quiet) fi if [ $? -ne 0 ]; then echo -e "${RED}✗ Error: Failed to determine next ID${NC}" exit 1 fi echo -e "${BLUE}Auto-generated ID: $SPEC_ID${NC}" echo "" elif [ -z "$SPEC_ID" ]; then usage fi # Check if template exists (try multiple locations in order of preference) # 1. project-basics/skills/spec-author/templates/ (plugin subdirectory in project) # 2. skills/spec-author/templates/ (plugin in root of project) # 3. templates/ (root-level templates directory) # 4. Current script directory/../templates (relative to script) TEMPLATE_FILE="" TEMPLATE_SEARCH_PATHS=( "$PROJECT_ROOT/project-basics/skills/spec-author/templates/$TEMPLATE_NAME.md" "$PROJECT_ROOT/skills/spec-author/templates/$TEMPLATE_NAME.md" "$PROJECT_ROOT/templates/$TEMPLATE_NAME.md" "$SCRIPT_DIR/../templates/$TEMPLATE_NAME.md" ) for path in "${TEMPLATE_SEARCH_PATHS[@]}"; do if [ -f "$path" ]; then TEMPLATE_FILE="$path" break fi done if [ -z "$TEMPLATE_FILE" ] || [ ! -f "$TEMPLATE_FILE" ]; then echo -e "${RED}✗ Error: Template not found${NC}" echo "Looked in:" for path in "${TEMPLATE_SEARCH_PATHS[@]}"; do echo " - $path" done echo "" echo "Run 'list-templates.sh' to see available templates" exit 1 fi # Get the folder name for this spec type SPEC_FOLDER=$(get_spec_folder "$TEMPLATE_NAME") if [ -z "$SPEC_FOLDER" ]; then echo -e "${RED}✗ Error: Unknown template type: $TEMPLATE_NAME${NC}" echo "Run 'list-templates.sh' to see available templates" exit 1 fi # Ensure specs type directory exists SPEC_TYPE_DIR="$SPECS_DIR/$SPEC_FOLDER" mkdir -p "$SPEC_TYPE_DIR" # Build output path OUTPUT_PATH="$SPEC_TYPE_DIR/$SPEC_ID.md" # Check if output file already exists if [ -f "$OUTPUT_PATH" ]; then echo -e "${YELLOW}⚠ File already exists: $OUTPUT_PATH${NC}" read -p "Overwrite? (y/n) " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo "Cancelled" exit 0 fi fi # Copy template to output location cp "$TEMPLATE_FILE" "$OUTPUT_PATH" # Get current date CURRENT_DATE=$(date +%Y-%m-%d) # Fill in some default values in the new spec sed -i '' "s/\[Date\]/$CURRENT_DATE/g" "$OUTPUT_PATH" 2>/dev/null || sed -i "s/\[Date\]/$CURRENT_DATE/g" "$OUTPUT_PATH" echo -e "${GREEN}✓ Spec created successfully!${NC}" echo "" echo "File: $OUTPUT_PATH" echo "Template: $(basename "$TEMPLATE_FILE")" echo "ID: $SPEC_ID" echo "" echo "Next steps:" echo "1. Open the file: $OUTPUT_PATH" echo "2. Fill in the ID and descriptive information" echo "3. Complete all TODO sections (marked with TODO)" echo "4. Remove placeholder text in [brackets]" echo "" echo "To check what needs to be completed:" echo " ./scripts/check-completeness.sh $OUTPUT_PATH" echo "" echo "To validate the spec:" echo " ./scripts/validate-spec.sh $OUTPUT_PATH"