Initial commit
This commit is contained in:
186
skills/spec-author/scripts/generate-spec.sh
Executable file
186
skills/spec-author/scripts/generate-spec.sh
Executable file
@@ -0,0 +1,186 @@
|
||||
#!/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"
|
||||
Reference in New Issue
Block a user