Initial commit
This commit is contained in:
195
skills/spec-author/scripts/next-id.sh
Executable file
195
skills/spec-author/scripts/next-id.sh
Executable file
@@ -0,0 +1,195 @@
|
||||
#!/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 <spec-type> [--with-slug <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 <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
|
||||
Reference in New Issue
Block a user