#!/usr/bin/env bash # Next Spec ID Script # Determines the next available ID number for a spec type set -o pipefail SPEC_TYPE="${1:-.}" 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" # Color codes RED='\033[0;31m' GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' NC='\033[0m' # Map spec types to their prefixes and folder names get_spec_info() { local type=$1 case "$type" in business-requirement) echo "brd:business-requirement" ;; technical-requirement) echo "prd:technical-requirement" ;; design-document) echo "des:design-document" ;; api-contract) echo "api:api-contract" ;; data-model) echo "data:data-model" ;; component) echo "cmp:component" ;; plan) echo "pln:plan" ;; milestone) echo "mls:milestone" ;; flow-schematic) echo "flow:flow-schematic" ;; deployment-procedure) echo "deploy:deployment-procedure" ;; configuration-schema) echo "config:configuration-schema" ;; *) echo "" ;; esac } # Print usage usage() { echo "Usage: next-id.sh [--with-slug ]" echo "" echo "Determines the next available ID number for a spec type." echo "" echo "Spec types:" echo " - business-requirement" echo " - technical-requirement" echo " - design-document" echo " - api-contract" echo " - data-model" echo " - component" echo " - plan" echo " - milestone" echo " - flow-schematic" echo " - deployment-procedure" echo " - configuration-schema" echo "" echo "Options:" echo " --with-slug Include slug in output (e.g., brd-001-my-feature)" echo " --quiet Only output the ID, no formatting" echo "" echo "Examples:" echo " next-id.sh business-requirement" echo " Output: brd-001" echo "" echo " next-id.sh business-requirement --with-slug user-export" echo " Output: brd-001-user-export" echo "" echo " next-id.sh api-contract --quiet" echo " Output: api-001" exit 1 } # Parse arguments SLUG="" QUIET=false if [ "$SPEC_TYPE" = "-h" ] || [ "$SPEC_TYPE" = "--help" ] || [ -z "$SPEC_TYPE" ]; then usage fi shift while [[ $# -gt 0 ]]; do case $1 in --with-slug) SLUG="$2" shift 2 ;; --quiet) QUIET=true shift ;; *) echo -e "${RED}✗ Unknown option: $1${NC}" >&2 usage ;; esac done # Get spec info SPEC_INFO=$(get_spec_info "$SPEC_TYPE") if [ -z "$SPEC_INFO" ]; then echo -e "${RED}✗ Error: Unknown spec type: $SPEC_TYPE${NC}" >&2 echo "Run 'next-id.sh --help' to see available types" >&2 exit 1 fi PREFIX=$(echo "$SPEC_INFO" | cut -d: -f1) FOLDER=$(echo "$SPEC_INFO" | cut -d: -f2) SPEC_TYPE_DIR="$SPECS_DIR/$FOLDER" # Find highest existing ID number MAX_ID=0 if [ -d "$SPEC_TYPE_DIR" ]; then # Look for files matching the pattern: prefix-NNN-*.md for file in "$SPEC_TYPE_DIR/$PREFIX"-*.md; do if [ -f "$file" ]; then # Extract the number part (NNN) filename=$(basename "$file" .md) # Remove prefix and leading dash rest="${filename#$PREFIX-}" # Extract just the number (first field before next dash) num=$(echo "$rest" | cut -d- -f1) # Check if it's a valid number if [[ "$num" =~ ^[0-9]+$ ]]; then if [ "$num" -gt "$MAX_ID" ]; then MAX_ID=$num fi fi fi done fi # Calculate next ID NEXT_NUM=$((MAX_ID + 1)) NEXT_ID=$(printf "%s-%03d" "$PREFIX" "$NEXT_NUM") # Add slug if provided if [ -n "$SLUG" ]; then FULL_ID="$NEXT_ID-$SLUG" else FULL_ID="$NEXT_ID" fi # Output if [ "$QUIET" = true ]; then echo "$FULL_ID" else echo -e "${GREEN}Next available ID for $SPEC_TYPE:${NC}" echo -e "${BLUE}$FULL_ID${NC}" echo "" if [ "$MAX_ID" -gt 0 ]; then echo "Last ID: $PREFIX-$(printf "%03d" "$MAX_ID")" else echo "No existing specs found (this will be the first)" fi fi