187 lines
5.8 KiB
Bash
Executable File
187 lines
5.8 KiB
Bash
Executable File
#!/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 <template-type> [<spec-id> | --next <slug>]"
|
|
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 <slug> 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"
|