From ce2c4971aafe58496424110f6876a4dcc76a6705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Wed, 22 Oct 2025 09:33:10 +0200 Subject: [PATCH 1/9] Feature: allows the user to specify a branch prefix When running 'specify', the user can now indicate a branch prefix to use, in case they have in-house naming conventions for branches. Examples: /speckit.specify a feature. Add this stuff. /speckit.specify --branch-prefix bugfix. Solve the crash in fizzbuzz. It also introduces a config file so that you can configure your default branch names, since I personally end up defaulting to "feature" most of the time. --- CHANGELOG.md | 21 ++++++++ README.md | 45 ++++++++++++++++ scripts/bash/create-new-feature.sh | 62 +++++++++++++++++++++-- scripts/powershell/create-new-feature.ps1 | 47 +++++++++++++++-- src/specify_cli/__init__.py | 18 +++++++ templates/commands/specify.md | 40 ++++++++++++++- templates/config.json | 5 ++ 7 files changed, 226 insertions(+), 12 deletions(-) create mode 100644 templates/config.json diff --git a/CHANGELOG.md b/CHANGELOG.md index ea6729145d..371dcb8cea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,27 @@ All notable changes to the Specify CLI and templates are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +## [0.0.21] - 2025-10-22 + +### Added + +- **Configurable Branch Prefixes**: Branch names can now be prefixed with custom patterns (e.g., `feature/`, `bugfix/`) + - New `.specify/config.json` configuration file with `branch.prefix` setting + - Environment variable `SPECIFY_BRANCH_PREFIX` for per-session overrides + - **Per-feature override**: `--branch-prefix` / `-BranchPrefix` parameter for `create-new-feature` scripts + - Priority order: Command-line parameter > Environment variable > Config file > Default (no prefix) + - Automatically created during project initialization via `specify init` + - Examples: + - With `"prefix": "feature/"`: `001-user-auth` → `feature/001-user-auth` + - With `"prefix": "bugfix/"`: `001-fix-login` → `bugfix/001-fix-login` + - With `SPECIFY_BRANCH_PREFIX=dev/`: Overrides config file setting + - With `--branch-prefix "hotfix/"`: Overrides all other settings for that feature + - Supported in both bash and PowerShell variants of `create-new-feature` scripts + - AI agents can recognize and apply prefix from `/speckit.specify` command (e.g., `/speckit.specify Add login --branch-prefix feature/`) + - Python CLI includes `setup_config_file()` function to initialize configuration during project setup + ## [0.0.20] - 2025-10-14 ### Added diff --git a/README.md b/README.md index 1c7dda2151..3ea44d6d6a 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,51 @@ Additional commands for enhanced quality and validation: | Variable | Description | |------------------|------------------------------------------------------------------------------------------------| | `SPECIFY_FEATURE` | Override feature detection for non-Git repositories. Set to the feature directory name (e.g., `001-photo-albums`) to work on a specific feature when not using Git branches.
**Must be set in the context of the agent you're working with prior to using `/speckit.plan` or follow-up commands. | +| `SPECIFY_BRANCH_PREFIX` | Configure a prefix for git branch names (e.g., `feature/`, `bugfix/`). When set, this prefix is prepended to auto-generated branch names. Overrides the `branch.prefix` setting in `.specify/config.json`. Example: With prefix `feature/`, branch `001-user-auth` becomes `feature/001-user-auth`. | + +### Configuration File + +The `.specify/config.json` file allows you to configure project-specific settings. This file is automatically created when you initialize a new project with `specify init`. + +#### Branch Prefix Configuration + +You can configure a default branch prefix for your project that will be applied to all auto-generated branch names: + +```json +{ + "branch": { + "prefix": "feature/" + } +} +``` + +**Common patterns:** + +- **Feature branches:** `"prefix": "feature/"` → Creates branches like `feature/001-user-auth` +- **Bugfix branches:** `"prefix": "bugfix/"` → Creates branches like `bugfix/001-fix-login` +- **Development branches:** `"prefix": "dev/"` → Creates branches like `dev/001-new-api` +- **No prefix (default):** `"prefix": ""` → Creates branches like `001-user-auth` + +**Priority order:** + +1. `--branch-prefix` command-line parameter (highest priority, per-feature override) +2. `SPECIFY_BRANCH_PREFIX` environment variable (per-session override) +3. `.specify/config.json` file setting (project-wide default) +4. Default: no prefix (empty string) + +This allows you to set project-wide defaults in the config file, override them per-session using the environment variable, or specify them per-feature when creating a new specification. + +**Per-feature branch prefix:** + +When using the `/speckit.specify` command, you can specify a branch prefix for that specific feature: + +```text +/speckit.specify Add user authentication --branch-prefix feature/ +/speckit.specify Fix login timeout --branch-prefix bugfix/ +/speckit.specify Update API endpoints with prefix hotfix/ +``` + +The AI agent will recognize the prefix specification and pass it to the `create-new-feature` script. ## 📚 Core Philosophy diff --git a/scripts/bash/create-new-feature.sh b/scripts/bash/create-new-feature.sh index 53adbcef11..1a29c718e4 100644 --- a/scripts/bash/create-new-feature.sh +++ b/scripts/bash/create-new-feature.sh @@ -4,6 +4,7 @@ set -e JSON_MODE=false SHORT_NAME="" +BRANCH_PREFIX_ARG="" ARGS=() i=1 while [ $i -le $# ]; do @@ -26,17 +27,33 @@ while [ $i -le $# ]; do fi SHORT_NAME="$next_arg" ;; + --branch-prefix) + if [ $((i + 1)) -gt $# ]; then + echo 'Error: --branch-prefix requires a value' >&2 + exit 1 + fi + i=$((i + 1)) + next_arg="${!i}" + # Check if the next argument is another option (starts with --) + if [[ "$next_arg" == --* ]]; then + echo 'Error: --branch-prefix requires a value' >&2 + exit 1 + fi + BRANCH_PREFIX_ARG="$next_arg" + ;; --help|-h) - echo "Usage: $0 [--json] [--short-name ] " + echo "Usage: $0 [--json] [--short-name ] [--branch-prefix ] " echo "" echo "Options:" - echo " --json Output in JSON format" - echo " --short-name Provide a custom short name (2-4 words) for the branch" - echo " --help, -h Show this help message" + echo " --json Output in JSON format" + echo " --short-name Provide a custom short name (2-4 words) for the branch" + echo " --branch-prefix Override branch prefix (e.g., 'feature/', 'bugfix/')" + echo " --help, -h Show this help message" echo "" echo "Examples:" echo " $0 'Add user authentication system' --short-name 'user-auth'" echo " $0 'Implement OAuth2 integration for API'" + echo " $0 'Fix login bug' --branch-prefix 'bugfix/'" exit 0 ;; *) @@ -101,6 +118,33 @@ fi NEXT=$((HIGHEST + 1)) FEATURE_NUM=$(printf "%03d" "$NEXT") +# Function to get branch prefix from config or environment variable +get_branch_prefix() { + # Priority: 1. Command-line argument, 2. Environment variable, 3. Config file, 4. Default (empty) + if [ -n "$BRANCH_PREFIX_ARG" ]; then + echo "$BRANCH_PREFIX_ARG" + return + fi + + if [ -n "$SPECIFY_BRANCH_PREFIX" ]; then + echo "$SPECIFY_BRANCH_PREFIX" + return + fi + + local config_file="$REPO_ROOT/.specify/config.json" + if [ -f "$config_file" ]; then + # Use grep and sed to extract the prefix value from JSON + # This avoids requiring jq to be installed + local prefix=$(grep -o '"prefix"[[:space:]]*:[[:space:]]*"[^"]*"' "$config_file" | sed 's/.*"prefix"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/') + if [ -n "$prefix" ]; then + echo "$prefix" + return + fi + fi + + echo "" +} + # Function to generate branch name with stop word filtering and length filtering generate_branch_name() { local description="$1" @@ -157,7 +201,15 @@ else BRANCH_SUFFIX=$(generate_branch_name "$FEATURE_DESCRIPTION") fi -BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}" +# Get branch prefix from config or environment +BRANCH_PREFIX=$(get_branch_prefix) + +# Construct full branch name with optional prefix +if [ -n "$BRANCH_PREFIX" ]; then + BRANCH_NAME="${BRANCH_PREFIX}${FEATURE_NUM}-${BRANCH_SUFFIX}" +else + BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}" +fi # GitHub enforces a 244-byte limit on branch names # Validate and truncate if necessary diff --git a/scripts/powershell/create-new-feature.ps1 b/scripts/powershell/create-new-feature.ps1 index 83e286aca2..cff7e32e33 100644 --- a/scripts/powershell/create-new-feature.ps1 +++ b/scripts/powershell/create-new-feature.ps1 @@ -4,6 +4,7 @@ param( [switch]$Json, [string]$ShortName, + [string]$BranchPrefix, [switch]$Help, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$FeatureDescription @@ -12,16 +13,18 @@ $ErrorActionPreference = 'Stop' # Show help if requested if ($Help) { - Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-ShortName ] " + Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-ShortName ] [-BranchPrefix ] " Write-Host "" Write-Host "Options:" - Write-Host " -Json Output in JSON format" - Write-Host " -ShortName Provide a custom short name (2-4 words) for the branch" - Write-Host " -Help Show this help message" + Write-Host " -Json Output in JSON format" + Write-Host " -ShortName Provide a custom short name (2-4 words) for the branch" + Write-Host " -BranchPrefix Override branch prefix (e.g., 'feature/', 'bugfix/')" + Write-Host " -Help Show this help message" Write-Host "" Write-Host "Examples:" Write-Host " ./create-new-feature.ps1 'Add user authentication system' -ShortName 'user-auth'" Write-Host " ./create-new-feature.ps1 'Implement OAuth2 integration for API'" + Write-Host " ./create-new-feature.ps1 'Fix login bug' -BranchPrefix 'bugfix/'" exit 0 } @@ -91,6 +94,32 @@ if (Test-Path $specsDir) { $next = $highest + 1 $featureNum = ('{0:000}' -f $next) +# Function to get branch prefix from config or environment variable +function Get-BranchPrefix { + # Priority: 1. Command-line argument, 2. Environment variable, 3. Config file, 4. Default (empty) + if ($BranchPrefix) { + return $BranchPrefix + } + + if ($env:SPECIFY_BRANCH_PREFIX) { + return $env:SPECIFY_BRANCH_PREFIX + } + + $configFile = Join-Path $repoRoot '.specify/config.json' + if (Test-Path $configFile) { + try { + $config = Get-Content $configFile -Raw | ConvertFrom-Json + if ($config.branch -and $config.branch.prefix) { + return $config.branch.prefix + } + } catch { + # If JSON parsing fails, silently continue with default + } + } + + return "" +} + # Function to generate branch name with stop word filtering and length filtering function Get-BranchName { param([string]$Description) @@ -145,7 +174,15 @@ if ($ShortName) { $branchSuffix = Get-BranchName -Description $featureDesc } -$branchName = "$featureNum-$branchSuffix" +# Get branch prefix from config or environment +$branchPrefix = Get-BranchPrefix + +# Construct full branch name with optional prefix +if ($branchPrefix) { + $branchName = "$branchPrefix$featureNum-$branchSuffix" +} else { + $branchName = "$featureNum-$branchSuffix" +} # GitHub enforces a 244-byte limit on branch names # Validate and truncate if necessary diff --git a/src/specify_cli/__init__.py b/src/specify_cli/__init__.py index a33a1c61ac..547433178b 100644 --- a/src/specify_cli/__init__.py +++ b/src/specify_cli/__init__.py @@ -818,6 +818,23 @@ def download_and_extract_template(project_path: Path, ai_assistant: str, script_ return project_path +def setup_config_file(project_path: Path, tracker: StepTracker | None = None) -> None: + """Copy config.json from templates to .specify root if it doesn't already exist.""" + config_template = project_path / ".specify" / "templates" / "config.json" + config_dest = project_path / ".specify" / "config.json" + + # Only copy if template exists and destination doesn't exist (preserve user config) + if config_template.exists() and not config_dest.exists(): + try: + shutil.copy2(config_template, config_dest) + if tracker: + tracker.add("config", "Setup configuration file") + tracker.complete("config", "created") + except Exception as e: + if tracker: + tracker.add("config", "Setup configuration file") + tracker.error("config", str(e)) + def ensure_executable_scripts(project_path: Path, tracker: StepTracker | None = None) -> None: """Ensure POSIX .sh scripts under .specify/scripts (recursively) have execute bits (no-op on Windows).""" if os.name == "nt": @@ -1046,6 +1063,7 @@ def init( download_and_extract_template(project_path, selected_ai, selected_script, here, verbose=False, tracker=tracker, client=local_client, debug=debug, github_token=github_token) + setup_config_file(project_path, tracker=tracker) ensure_executable_scripts(project_path, tracker=tracker) if not no_git: diff --git a/templates/commands/specify.md b/templates/commands/specify.md index 03f681e573..e93cb7cc07 100644 --- a/templates/commands/specify.md +++ b/templates/commands/specify.md @@ -13,6 +13,37 @@ $ARGUMENTS You **MUST** consider the user input before proceeding (if not empty). +## Branch Prefix Option + +Users can optionally specify a branch prefix when creating a feature by including it in their command. Look for these patterns in the user input: + +- `--branch-prefix ` or `-BranchPrefix ` format +- Keywords like "use prefix", "with prefix", "as a feature branch", "as a bugfix", etc. + +**Common prefix patterns:** + +- `feature/` - For feature branches +- `bugfix/` or `fix/` - For bug fixes +- `hotfix/` - For urgent production fixes +- `refactor/` - For refactoring work +- `chore/` - For maintenance tasks + +**Examples of user input with branch prefix:** + +- "Add user authentication --branch-prefix feature/" +- "Fix login timeout as a bugfix" (infer `bugfix/` prefix) +- "Update payment API with prefix hotfix/" (use `hotfix/` prefix) + +**If branch prefix is specified:** + +1. Extract the prefix from the user input +2. Remove the prefix specification from the feature description before processing +3. Pass the prefix to the script using the appropriate parameter: + - Bash: `--branch-prefix "prefix-value"` + - PowerShell: `-BranchPrefix "prefix-value"` + +**If no prefix is specified:** The script will use the default from configuration (`.specify/config.json`) or environment variable. + ## Outline The text the user typed after `/speckit.specify` in the triggering message **is** the feature description. Assume you always have it available in this conversation even if `{ARGS}` appears literally below. Do not ask the user to repeat it unless they provided an empty command. @@ -36,8 +67,13 @@ Given that feature description, do this: **IMPORTANT**: - Append the short-name argument to the `{SCRIPT}` command with the 2-4 word short name you created in step 1. Keep the feature description as the final argument. - - Bash example: `--short-name "your-generated-short-name" "Feature description here"` - - PowerShell example: `-ShortName "your-generated-short-name" "Feature description here"` + - If a branch prefix was specified (see "Branch Prefix Option" above), include it as a parameter + - Bash examples: + - `--short-name "your-generated-short-name" "Feature description here"` + - `--short-name "user-auth" --branch-prefix "feature/" "Add user authentication"` + - PowerShell examples: + - `-ShortName "your-generated-short-name" "Feature description here"` + - `-ShortName "user-auth" -BranchPrefix "feature/" "Add user authentication"` - For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot") - You must only ever run this script once - The JSON is provided in the terminal as output - always refer to it to get the actual content you're looking for diff --git a/templates/config.json b/templates/config.json new file mode 100644 index 0000000000..a0da0c0a41 --- /dev/null +++ b/templates/config.json @@ -0,0 +1,5 @@ +{ + "branch": { + "prefix": "" + } +} From 7fdc1f41c5aeebb212aee25bfffd03306c503724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Wed, 22 Oct 2025 09:54:00 +0200 Subject: [PATCH 2/9] Feature: we can now specify a spec number This allows you to create branches which have a number that matches your issue number in Github (or any other tracker). --- README.md | 47 ++++++++++++ scripts/bash/create-new-feature.sh | 94 +++++++++++++++++++---- scripts/powershell/create-new-feature.ps1 | 68 ++++++++++++++-- templates/commands/specify.md | 42 +++++++++- 4 files changed, 229 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 3ea44d6d6a..050bb4b0ae 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,7 @@ Additional commands for enhanced quality and validation: |------------------|------------------------------------------------------------------------------------------------| | `SPECIFY_FEATURE` | Override feature detection for non-Git repositories. Set to the feature directory name (e.g., `001-photo-albums`) to work on a specific feature when not using Git branches.
**Must be set in the context of the agent you're working with prior to using `/speckit.plan` or follow-up commands. | | `SPECIFY_BRANCH_PREFIX` | Configure a prefix for git branch names (e.g., `feature/`, `bugfix/`). When set, this prefix is prepended to auto-generated branch names. Overrides the `branch.prefix` setting in `.specify/config.json`. Example: With prefix `feature/`, branch `001-user-auth` becomes `feature/001-user-auth`. | +| `SPECIFY_SPEC_NUMBER` | Override the auto-incremented spec number with a custom value (e.g., to match an issue tracker number). When set, the specified number is used instead of finding the next available number. Example: `SPECIFY_SPEC_NUMBER=42` creates spec `042-feature-name`. Can be overridden per-feature using the `--spec-number` parameter in `/speckit.specify`. | ### Configuration File @@ -298,6 +299,24 @@ When using the `/speckit.specify` command, you can specify a branch prefix for t The AI agent will recognize the prefix specification and pass it to the `create-new-feature` script. +**Per-feature spec number:** + +You can also specify a custom spec number to match your issue tracker: + +```text +/speckit.specify Add user authentication --spec-number 42 +/speckit.specify Fix payment bug for issue #123 --spec-number 123 +/speckit.specify Implement search API --spec-number 1234 --branch-prefix feature/ +``` + +**Spec number priority:** + +1. `--spec-number` command-line parameter (highest priority, per-feature override) +2. `SPECIFY_SPEC_NUMBER` environment variable (per-session override) +3. Auto-increment from existing specs (default) + +This allows you to align spec numbers with your issue tracker (GitHub Issues, Jira, Linear, etc.) while maintaining the structured workflow. + ## 📚 Core Philosophy Spec-Driven Development is a structured process that emphasizes: @@ -434,6 +453,8 @@ With your project principles established, you can now create the functional spec >[!IMPORTANT] >Be as explicit as possible about *what* you are trying to build and *why*. **Do not focus on the tech stack at this point**. +#### Basic Example + An example prompt: ```text @@ -455,6 +476,32 @@ see yours. You can edit any comments that you make, but you can't edit comments delete any comments that you made, but you can't delete comments anybody else made. ``` +#### Issue Tracker Integration + +You can align spec numbers with your issue tracker (GitHub Issues, Jira, Linear, etc.) by specifying a custom spec number: + +```text +/speckit.specify Add user authentication system --spec-number 42 +``` + +This creates spec `042-add-user-auth` matching issue #42 in your tracker. You can also combine with branch prefixes: + +```text +/speckit.specify Fix payment processing timeout --spec-number 123 --branch-prefix bugfix/ +``` + +This creates: +- Spec directory: `specs/123-fix-payment-timeout/` +- Git branch: `bugfix/123-fix-payment-timeout` + +**Common workflows:** + +- **GitHub Issues:** `--spec-number ` (e.g., `--spec-number 456`) +- **Jira Tickets:** `--spec-number ` (e.g., `--spec-number 789` for PROJ-789) +- **Linear Issues:** `--spec-number ` (e.g., `--spec-number 1234`) + +#### After Running /speckit.specify + After this prompt is entered, you should see Claude Code kick off the planning and spec drafting process. Claude Code will also trigger some of the built-in scripts to set up the repository. Once this step is completed, you should have a new branch created (e.g., `001-create-taskify`), as well as a new specification in the `specs/001-create-taskify` directory. diff --git a/scripts/bash/create-new-feature.sh b/scripts/bash/create-new-feature.sh index 1a29c718e4..423bc2b721 100644 --- a/scripts/bash/create-new-feature.sh +++ b/scripts/bash/create-new-feature.sh @@ -5,6 +5,7 @@ set -e JSON_MODE=false SHORT_NAME="" BRANCH_PREFIX_ARG="" +SPEC_NUM_ARG="" ARGS=() i=1 while [ $i -le $# ]; do @@ -41,19 +42,36 @@ while [ $i -le $# ]; do fi BRANCH_PREFIX_ARG="$next_arg" ;; + --spec-number) + if [ $((i + 1)) -gt $# ]; then + echo 'Error: --spec-number requires a value' >&2 + exit 1 + fi + i=$((i + 1)) + next_arg="${!i}" + # Check if the next argument is another option (starts with --) + if [[ "$next_arg" == --* ]]; then + echo 'Error: --spec-number requires a value' >&2 + exit 1 + fi + SPEC_NUM_ARG="$next_arg" + ;; --help|-h) - echo "Usage: $0 [--json] [--short-name ] [--branch-prefix ] " + echo "Usage: $0 [--json] [--short-name ] [--branch-prefix ] [--spec-number ] " echo "" echo "Options:" echo " --json Output in JSON format" echo " --short-name Provide a custom short name (2-4 words) for the branch" echo " --branch-prefix Override branch prefix (e.g., 'feature/', 'bugfix/')" + echo " --spec-number Specify a custom spec number (e.g., to match issue tracker)" echo " --help, -h Show this help message" echo "" echo "Examples:" echo " $0 'Add user authentication system' --short-name 'user-auth'" echo " $0 'Implement OAuth2 integration for API'" echo " $0 'Fix login bug' --branch-prefix 'bugfix/'" + echo " $0 'Add payment processing' --spec-number 42" + echo " $0 'Implement search feature' --spec-number 1234 --branch-prefix 'feature/'" exit 0 ;; *) @@ -104,19 +122,69 @@ cd "$REPO_ROOT" SPECS_DIR="$REPO_ROOT/specs" mkdir -p "$SPECS_DIR" -HIGHEST=0 -if [ -d "$SPECS_DIR" ]; then - for dir in "$SPECS_DIR"/*; do - [ -d "$dir" ] || continue - dirname=$(basename "$dir") - number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0") - number=$((10#$number)) - if [ "$number" -gt "$HIGHEST" ]; then HIGHEST=$number; fi - done -fi +# Function to get spec number from various sources +get_spec_number() { + # Priority: 1. Command-line argument, 2. Environment variable, 3. Auto-increment + if [ -n "$SPEC_NUM_ARG" ]; then + # Validate it's a positive integer + if ! [[ "$SPEC_NUM_ARG" =~ ^[0-9]+$ ]]; then + echo "Error: --spec-number must be a positive integer" >&2 + exit 1 + fi + + # Pad to at least 3 digits + if [ "$SPEC_NUM_ARG" -lt 100 ]; then + printf "%03d" "$SPEC_NUM_ARG" + else + echo "$SPEC_NUM_ARG" + fi + return + fi + + if [ -n "$SPECIFY_SPEC_NUMBER" ]; then + # Validate it's a positive integer + if ! [[ "$SPECIFY_SPEC_NUMBER" =~ ^[0-9]+$ ]]; then + echo "Error: SPECIFY_SPEC_NUMBER must be a positive integer" >&2 + exit 1 + fi + + # Pad to at least 3 digits + if [ "$SPECIFY_SPEC_NUMBER" -lt 100 ]; then + printf "%03d" "$SPECIFY_SPEC_NUMBER" + else + echo "$SPECIFY_SPEC_NUMBER" + fi + return + fi + + # Auto-increment: find highest existing number + local highest=0 + if [ -d "$SPECS_DIR" ]; then + for dir in "$SPECS_DIR"/*; do + [ -d "$dir" ] || continue + local dirname=$(basename "$dir") + local number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0") + number=$((10#$number)) + if [ "$number" -gt "$highest" ]; then highest=$number; fi + done + fi + + local next=$((highest + 1)) + printf "%03d" "$next" +} -NEXT=$((HIGHEST + 1)) -FEATURE_NUM=$(printf "%03d" "$NEXT") +FEATURE_NUM=$(get_spec_number) + +# Check for conflicts with existing spec numbers +for dir in "$SPECS_DIR"/*; do + [ -d "$dir" ] || continue + dirname=$(basename "$dir") + if [[ "$dirname" =~ ^${FEATURE_NUM}- ]]; then + echo "Error: Spec number $FEATURE_NUM already exists in directory: $dirname" >&2 + echo "Please choose a different spec number or remove the existing spec." >&2 + exit 1 + fi +done # Function to get branch prefix from config or environment variable get_branch_prefix() { diff --git a/scripts/powershell/create-new-feature.ps1 b/scripts/powershell/create-new-feature.ps1 index cff7e32e33..50d8868ebb 100644 --- a/scripts/powershell/create-new-feature.ps1 +++ b/scripts/powershell/create-new-feature.ps1 @@ -5,6 +5,7 @@ param( [switch]$Json, [string]$ShortName, [string]$BranchPrefix, + [string]$SpecNumber, [switch]$Help, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$FeatureDescription @@ -13,18 +14,21 @@ $ErrorActionPreference = 'Stop' # Show help if requested if ($Help) { - Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-ShortName ] [-BranchPrefix ] " + Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-ShortName ] [-BranchPrefix ] [-SpecNumber ] " Write-Host "" Write-Host "Options:" Write-Host " -Json Output in JSON format" Write-Host " -ShortName Provide a custom short name (2-4 words) for the branch" Write-Host " -BranchPrefix Override branch prefix (e.g., 'feature/', 'bugfix/')" + Write-Host " -SpecNumber Specify a custom spec number (e.g., to match issue tracker)" Write-Host " -Help Show this help message" Write-Host "" Write-Host "Examples:" Write-Host " ./create-new-feature.ps1 'Add user authentication system' -ShortName 'user-auth'" Write-Host " ./create-new-feature.ps1 'Implement OAuth2 integration for API'" Write-Host " ./create-new-feature.ps1 'Fix login bug' -BranchPrefix 'bugfix/'" + Write-Host " ./create-new-feature.ps1 'Add payment processing' -SpecNumber 42" + Write-Host " ./create-new-feature.ps1 'Implement search feature' -SpecNumber 1234 -BranchPrefix 'feature/'" exit 0 } @@ -82,17 +86,67 @@ Set-Location $repoRoot $specsDir = Join-Path $repoRoot 'specs' New-Item -ItemType Directory -Path $specsDir -Force | Out-Null -$highest = 0 +# Function to get spec number from various sources +function Get-SpecNumber { + # Priority: 1. Command-line argument, 2. Environment variable, 3. Auto-increment + if ($SpecNumber) { + # Validate it's a positive integer + $num = 0 + if (-not [int]::TryParse($SpecNumber, [ref]$num) -or $num -lt 0) { + Write-Error "Error: -SpecNumber must be a positive integer" + exit 1 + } + + # Pad to at least 3 digits + if ($num -lt 100) { + return ('{0:000}' -f $num) + } else { + return $SpecNumber + } + } + + if ($env:SPECIFY_SPEC_NUMBER) { + # Validate it's a positive integer + $num = 0 + if (-not [int]::TryParse($env:SPECIFY_SPEC_NUMBER, [ref]$num) -or $num -lt 0) { + Write-Error "Error: SPECIFY_SPEC_NUMBER must be a positive integer" + exit 1 + } + + # Pad to at least 3 digits + if ($num -lt 100) { + return ('{0:000}' -f $num) + } else { + return $env:SPECIFY_SPEC_NUMBER + } + } + + # Auto-increment: find highest existing number + $highest = 0 + if (Test-Path $specsDir) { + Get-ChildItem -Path $specsDir -Directory | ForEach-Object { + if ($_.Name -match '^(\d+)') { + $num = [int]$matches[1] + if ($num -gt $highest) { $highest = $num } + } + } + } + $next = $highest + 1 + return ('{0:000}' -f $next) +} + +$featureNum = Get-SpecNumber + +# Check for conflicts with existing spec numbers if (Test-Path $specsDir) { Get-ChildItem -Path $specsDir -Directory | ForEach-Object { - if ($_.Name -match '^(\d{3})') { - $num = [int]$matches[1] - if ($num -gt $highest) { $highest = $num } + if ($_.Name -match "^$featureNum-") { + Write-Error "Error: Spec number $featureNum already exists in directory: $($_.Name)" + Write-Error "Please choose a different spec number or remove the existing spec." + exit 1 } } } -$next = $highest + 1 -$featureNum = ('{0:000}' -f $next) # Function to get branch prefix from config or environment variable function Get-BranchPrefix { diff --git a/templates/commands/specify.md b/templates/commands/specify.md index e93cb7cc07..56e40ad9e2 100644 --- a/templates/commands/specify.md +++ b/templates/commands/specify.md @@ -13,6 +13,39 @@ $ARGUMENTS You **MUST** consider the user input before proceeding (if not empty). +## Spec Number Option + +Users can optionally specify a custom spec number when creating a feature by including it in their command. This is particularly useful for matching issue tracker numbers (GitHub issues, Jira tickets, etc.). + +**How to recognize spec number in user input:** + +- `--spec-number ` or `-SpecNumber ` format +- Keywords like "issue #42", "ticket 123", "for issue 1234" +- Direct number references: "spec 42", "number 99" + +**Examples of user input with spec number:** + +- "Add user authentication --spec-number 42" +- "Fix login timeout for issue #123" (extract `123`) +- "Implement payment API as spec 1234" (use `1234`) +- "Add search feature --spec-number 99 --branch-prefix feature/" + +**If spec number is specified:** + +1. Extract the number from the user input +2. Validate it's a positive integer +3. Remove the spec number specification from the feature description before processing +4. Pass the number to the script using the appropriate parameter: + - Bash: `--spec-number 42` + - PowerShell: `-SpecNumber 42` + +**If no spec number is specified:** The script will auto-increment from the highest existing spec number (default behavior). + +**Priority order:** +1. `--spec-number` CLI parameter (highest priority) +2. `SPECIFY_SPEC_NUMBER` environment variable +3. Auto-increment (default) + ## Branch Prefix Option Users can optionally specify a branch prefix when creating a feature by including it in their command. Look for these patterns in the user input: @@ -67,13 +100,18 @@ Given that feature description, do this: **IMPORTANT**: - Append the short-name argument to the `{SCRIPT}` command with the 2-4 word short name you created in step 1. Keep the feature description as the final argument. + - If a spec number was specified (see "Spec Number Option" above), include it as a parameter - If a branch prefix was specified (see "Branch Prefix Option" above), include it as a parameter - Bash examples: - `--short-name "your-generated-short-name" "Feature description here"` - - `--short-name "user-auth" --branch-prefix "feature/" "Add user authentication"` + - `--short-name "user-auth" "Add user authentication"` + - `--spec-number 42 --short-name "payment-api" "Add payment processing"` + - `--spec-number 1234 --short-name "user-auth" --branch-prefix "feature/" "Add user authentication"` - PowerShell examples: - `-ShortName "your-generated-short-name" "Feature description here"` - - `-ShortName "user-auth" -BranchPrefix "feature/" "Add user authentication"` + - `-ShortName "user-auth" "Add user authentication"` + - `-SpecNumber 42 -ShortName "payment-api" "Add payment processing"` + - `-SpecNumber 1234 -ShortName "user-auth" -BranchPrefix "feature/" "Add user authentication"` - For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot") - You must only ever run this script once - The JSON is provided in the terminal as output - always refer to it to get the actual content you're looking for From 18cb5934daf21867301f7b8baf104289a076c20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Wed, 22 Oct 2025 10:00:23 +0200 Subject: [PATCH 3/9] Expanded specify to given natural language examples This makes it clearer that the user may enter input such as: - "Branch type feature, number 303" or - "This is bugfix 31416" It should also allow for timestamp hotfixes, given they're only a number. --- templates/commands/specify.md | 51 +++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/templates/commands/specify.md b/templates/commands/specify.md index 56e40ad9e2..95c655fba9 100644 --- a/templates/commands/specify.md +++ b/templates/commands/specify.md @@ -22,6 +22,12 @@ Users can optionally specify a custom spec number when creating a feature by inc - `--spec-number ` or `-SpecNumber ` format - Keywords like "issue #42", "ticket 123", "for issue 1234" - Direct number references: "spec 42", "number 99" +- **Natural language patterns combining prefix and number:** + - "feature 303" → extract prefix `feature/` and number `303` + - "bugfix 666" → extract prefix `bugfix/` and number `666` + - "hotfix 42" → extract prefix `hotfix/` and number `42` + - "fix 123" → extract prefix `bugfix/` and number `123` (normalize "fix" to "bugfix") + - "chore 999" → extract prefix `chore/` and number `999` **Examples of user input with spec number:** @@ -29,15 +35,26 @@ Users can optionally specify a custom spec number when creating a feature by inc - "Fix login timeout for issue #123" (extract `123`) - "Implement payment API as spec 1234" (use `1234`) - "Add search feature --spec-number 99 --branch-prefix feature/" +- "feature 303 add shopping cart" (extract prefix `feature/` and number `303`) +- "bugfix 666 fix payment timeout" (extract prefix `bugfix/` and number `666`) **If spec number is specified:** 1. Extract the number from the user input -2. Validate it's a positive integer -3. Remove the spec number specification from the feature description before processing -4. Pass the number to the script using the appropriate parameter: +2. **If using natural language pattern** (e.g., "feature 303"): + - Extract the prefix type (feature, bugfix, hotfix, fix, chore, etc.) + - Normalize "fix" to "bugfix/" for consistency + - Add trailing slash to create proper prefix (e.g., "feature" → "feature/") + - Extract the number following the prefix type + - Remove the entire pattern from the feature description before processing +3. Validate the number is a positive integer +4. Remove the spec number specification from the feature description before processing +5. Pass the number to the script using the appropriate parameter: - Bash: `--spec-number 42` - PowerShell: `-SpecNumber 42` +6. If a prefix was also extracted from the natural language pattern, pass it too: + - Bash: `--spec-number 303 --branch-prefix "feature/"` + - PowerShell: `-SpecNumber 303 -BranchPrefix "feature/"` **If no spec number is specified:** The script will auto-increment from the highest existing spec number (default behavior). @@ -46,12 +63,26 @@ Users can optionally specify a custom spec number when creating a feature by inc 2. `SPECIFY_SPEC_NUMBER` environment variable 3. Auto-increment (default) +**Recognized prefix types for natural language patterns:** +- `feature` → `feature/` +- `bugfix` → `bugfix/` +- `fix` → `bugfix/` (normalized) +- `hotfix` → `hotfix/` +- `chore` → `chore/` +- `refactor` → `refactor/` + ## Branch Prefix Option Users can optionally specify a branch prefix when creating a feature by including it in their command. Look for these patterns in the user input: - `--branch-prefix ` or `-BranchPrefix ` format - Keywords like "use prefix", "with prefix", "as a feature branch", "as a bugfix", etc. +- **Natural language patterns** (also extracts spec number if present): + - "feature 303" → prefix `feature/` and number `303` + - "bugfix 666" → prefix `bugfix/` and number `666` + - "hotfix 42" → prefix `hotfix/` and number `42` + + The reference to prefix and number may come anywhere in the prompt. **Common prefix patterns:** @@ -66,12 +97,17 @@ Users can optionally specify a branch prefix when creating a feature by includin - "Add user authentication --branch-prefix feature/" - "Fix login timeout as a bugfix" (infer `bugfix/` prefix) - "Update payment API with prefix hotfix/" (use `hotfix/` prefix) +- "feature 303 implement shopping cart" (extract both prefix `feature/` and number `303`) +- "bugfix 666 resolve payment issue" (extract both prefix `bugfix/` and number `666`) **If branch prefix is specified:** 1. Extract the prefix from the user input -2. Remove the prefix specification from the feature description before processing -3. Pass the prefix to the script using the appropriate parameter: +2. **If using natural language pattern** (e.g., "feature 303"): + - The spec number will also be extracted (see "Spec Number Option" above) + - Both prefix and number are removed from the feature description before processing +3. Remove the prefix specification from the feature description before processing +4. Pass the prefix to the script using the appropriate parameter: - Bash: `--branch-prefix "prefix-value"` - PowerShell: `-BranchPrefix "prefix-value"` @@ -102,16 +138,21 @@ Given that feature description, do this: - Append the short-name argument to the `{SCRIPT}` command with the 2-4 word short name you created in step 1. Keep the feature description as the final argument. - If a spec number was specified (see "Spec Number Option" above), include it as a parameter - If a branch prefix was specified (see "Branch Prefix Option" above), include it as a parameter + - **Note:** Natural language patterns like "feature 303" or "bugfix 666" provide BOTH prefix and number - extract and pass both parameters - Bash examples: - `--short-name "your-generated-short-name" "Feature description here"` - `--short-name "user-auth" "Add user authentication"` - `--spec-number 42 --short-name "payment-api" "Add payment processing"` - `--spec-number 1234 --short-name "user-auth" --branch-prefix "feature/" "Add user authentication"` + - `--spec-number 303 --branch-prefix "feature/" --short-name "shopping-cart" "Add shopping cart"` (from "feature 303 add shopping cart") + - `--spec-number 666 --branch-prefix "bugfix/" --short-name "payment-timeout" "Fix payment timeout"` (from "bugfix 666 fix payment timeout") - PowerShell examples: - `-ShortName "your-generated-short-name" "Feature description here"` - `-ShortName "user-auth" "Add user authentication"` - `-SpecNumber 42 -ShortName "payment-api" "Add payment processing"` - `-SpecNumber 1234 -ShortName "user-auth" -BranchPrefix "feature/" "Add user authentication"` + - `-SpecNumber 303 -BranchPrefix "feature/" -ShortName "shopping-cart" "Add shopping cart"` (from "feature 303 add shopping cart") + - `-SpecNumber 666 -BranchPrefix "bugfix/" -ShortName "payment-timeout" "Fix payment timeout"` (from "bugfix 666 fix payment timeout") - For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot") - You must only ever run this script once - The JSON is provided in the terminal as output - always refer to it to get the actual content you're looking for From 0951aa90801523e4678e42874cfaa266b26d10ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Wed, 22 Oct 2025 10:00:44 +0200 Subject: [PATCH 4/9] Bumping pyproject.toml version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 567d48cd49..e4d2791bdb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "specify-cli" -version = "0.0.20" +version = "0.0.21" description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)." requires-python = ">=3.11" dependencies = [ From 3b39bf4dafb8c8e67a60785fdf24681bec2d4cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Fri, 31 Oct 2025 10:49:40 +0100 Subject: [PATCH 5/9] Updated common script to consider branch prefixes I had missed it during the original push. --- scripts/bash/common.sh | 34 ++++++++++++------ scripts/powershell/common.ps1 | 65 ++++++++++++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 16 deletions(-) diff --git a/scripts/bash/common.sh b/scripts/bash/common.sh index 6931eccc80..2839e71894 100644 --- a/scripts/bash/common.sh +++ b/scripts/bash/common.sh @@ -37,8 +37,9 @@ get_current_branch() { for dir in "$specs_dir"/*; do if [[ -d "$dir" ]]; then local dirname=$(basename "$dir") - if [[ "$dirname" =~ ^([0-9]{3})- ]]; then - local number=${BASH_REMATCH[1]} + # Support both formats: 001-name or feature/001-name + if [[ "$dirname" =~ ^(([a-z]+/)?([0-9]{3,}))- ]]; then + local number=${BASH_REMATCH[3]} number=$((10#$number)) if [[ "$number" -gt "$highest" ]]; then highest=$number @@ -72,9 +73,13 @@ check_feature_branch() { return 0 fi - if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then + # Support both simple format (001-name) and prefixed format (feature/001-name) + if [[ ! "$branch" =~ ^([a-z]+/)?[0-9]{3,}- ]]; then echo "ERROR: Not on a feature branch. Current branch: $branch" >&2 - echo "Feature branches should be named like: 001-feature-name" >&2 + echo "Feature branches should be named like:" >&2 + echo " - 001-feature-name" >&2 + echo " - feature/001-feature-name" >&2 + echo " - bugfix/042-fix-name" >&2 return 1 fi @@ -85,26 +90,33 @@ get_feature_dir() { echo "$1/specs/$2"; } # Find feature directory by numeric prefix instead of exact branch match # This allows multiple branches to work on the same spec (e.g., 004-fix-bug, 004-add-feature) +# Also handles branch names with prefixes like feature/004-name or bugfix/042-fix find_feature_dir_by_prefix() { local repo_root="$1" local branch_name="$2" local specs_dir="$repo_root/specs" - # Extract numeric prefix from branch (e.g., "004" from "004-whatever") - if [[ ! "$branch_name" =~ ^([0-9]{3})- ]]; then + # Extract numeric prefix from branch (e.g., "004" from "004-whatever" or "feature/004-whatever") + # Pattern: optional prefix (feature/, bugfix/, etc.) followed by at least 3 digits + if [[ ! "$branch_name" =~ ^(([a-z]+/)?([0-9]{3,}))- ]]; then # If branch doesn't have numeric prefix, fall back to exact match echo "$specs_dir/$branch_name" return fi - local prefix="${BASH_REMATCH[1]}" + local number="${BASH_REMATCH[3]}" # Just the numeric part - # Search for directories in specs/ that start with this prefix + # Search for directories in specs/ that contain this number + # Could be in format: 004-name or feature/004-name or bugfix/004-name local matches=() if [[ -d "$specs_dir" ]]; then - for dir in "$specs_dir"/"$prefix"-*; do + for dir in "$specs_dir"/*"$number"-*; do if [[ -d "$dir" ]]; then - matches+=("$(basename "$dir")") + local dirname=$(basename "$dir") + # Verify it actually matches our pattern (not just contains the number) + if [[ "$dirname" =~ ^(([a-z]+/)?$number)- ]]; then + matches+=("$dirname") + fi fi done fi @@ -118,7 +130,7 @@ find_feature_dir_by_prefix() { echo "$specs_dir/${matches[0]}" else # Multiple matches - this shouldn't happen with proper naming convention - echo "ERROR: Multiple spec directories found with prefix '$prefix': ${matches[*]}" >&2 + echo "ERROR: Multiple spec directories found with number '$number': ${matches[*]}" >&2 echo "Please ensure only one spec directory exists per numeric prefix." >&2 echo "$specs_dir/$branch_name" # Return something to avoid breaking the script fi diff --git a/scripts/powershell/common.ps1 b/scripts/powershell/common.ps1 index b0be273545..f9631ccf0b 100644 --- a/scripts/powershell/common.ps1 +++ b/scripts/powershell/common.ps1 @@ -40,8 +40,9 @@ function Get-CurrentBranch { $highest = 0 Get-ChildItem -Path $specsDir -Directory | ForEach-Object { - if ($_.Name -match '^(\d{3})-') { - $num = [int]$matches[1] + # Support both formats: 001-name or feature/001-name + if ($_.Name -match '^(([a-z]+/)?(\d{3,}))-') { + $num = [int]$matches[3] if ($num -gt $highest) { $highest = $num $latestFeature = $_.Name @@ -79,9 +80,13 @@ function Test-FeatureBranch { return $true } - if ($Branch -notmatch '^[0-9]{3}-') { + # Support both simple format (001-name) and prefixed format (feature/001-name) + if ($Branch -notmatch '^([a-z]+/)?[0-9]{3,}-') { Write-Output "ERROR: Not on a feature branch. Current branch: $Branch" - Write-Output "Feature branches should be named like: 001-feature-name" + Write-Output "Feature branches should be named like:" + Write-Output " - 001-feature-name" + Write-Output " - feature/001-feature-name" + Write-Output " - bugfix/042-fix-name" return $false } return $true @@ -92,11 +97,61 @@ function Get-FeatureDir { Join-Path $RepoRoot "specs/$Branch" } +# Find feature directory by numeric prefix instead of exact branch match +# This allows multiple branches to work on the same spec (e.g., 004-fix-bug, 004-add-feature) +# Also handles branch names with prefixes like feature/004-name or bugfix/042-fix +function Find-FeatureDirByPrefix { + param( + [string]$RepoRoot, + [string]$BranchName + ) + + $specsDir = Join-Path $RepoRoot "specs" + + # Extract numeric prefix from branch (e.g., "004" from "004-whatever" or "feature/004-whatever") + # Pattern: optional prefix (feature/, bugfix/, etc.) followed by at least 3 digits + if ($BranchName -notmatch '^(([a-z]+/)?(\d{3,}))-') { + # If branch doesn't have numeric prefix, fall back to exact match + return (Join-Path $specsDir $BranchName) + } + + $number = $matches[3] # Just the numeric part + + # Search for directories in specs/ that contain this number + # Could be in format: 004-name or feature/004-name or bugfix/004-name + $matchedDirs = @() + + if (Test-Path $specsDir) { + Get-ChildItem -Path $specsDir -Directory | Where-Object { + # Check if directory name contains our number and matches the pattern + $_.Name -match "^(([a-z]+/)?$number)-" + } | ForEach-Object { + $matchedDirs += $_.Name + } + } + + # Handle results + if ($matchedDirs.Count -eq 0) { + # No match found - return the branch name path (will fail later with clear error) + return (Join-Path $specsDir $BranchName) + } elseif ($matchedDirs.Count -eq 1) { + # Exactly one match - perfect! + return (Join-Path $specsDir $matchedDirs[0]) + } else { + # Multiple matches - this shouldn't happen with proper naming convention + Write-Warning "ERROR: Multiple spec directories found with number '$number': $($matchedDirs -join ', ')" + Write-Warning "Please ensure only one spec directory exists per numeric prefix." + return (Join-Path $specsDir $BranchName) # Return something to avoid breaking the script + } +} + function Get-FeaturePathsEnv { $repoRoot = Get-RepoRoot $currentBranch = Get-CurrentBranch $hasGit = Test-HasGit - $featureDir = Get-FeatureDir -RepoRoot $repoRoot -Branch $currentBranch + + # Use prefix-based lookup to support multiple branches per spec and branch prefixes + $featureDir = Find-FeatureDirByPrefix -RepoRoot $repoRoot -BranchName $currentBranch [PSCustomObject]@{ REPO_ROOT = $repoRoot From f891e52cb5de926706d004006f6513bf435f54e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Fri, 31 Oct 2025 10:57:33 +0100 Subject: [PATCH 6/9] More detailed branch pattern matching for specify It's sometimes missing cases - for instance, if a prompt says near the end that "This is feature 221", it may pick up on the feature number but not the branch type. Testing a more verbose, explicit approach. --- templates/commands/specify.md | 122 +++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 38 deletions(-) diff --git a/templates/commands/specify.md b/templates/commands/specify.md index 95c655fba9..beff4a946c 100644 --- a/templates/commands/specify.md +++ b/templates/commands/specify.md @@ -23,38 +23,74 @@ Users can optionally specify a custom spec number when creating a feature by inc - Keywords like "issue #42", "ticket 123", "for issue 1234" - Direct number references: "spec 42", "number 99" - **Natural language patterns combining prefix and number:** - - "feature 303" → extract prefix `feature/` and number `303` - - "bugfix 666" → extract prefix `bugfix/` and number `666` - - "hotfix 42" → extract prefix `hotfix/` and number `42` - - "fix 123" → extract prefix `bugfix/` and number `123` (normalize "fix" to "bugfix") - - "chore 999" → extract prefix `chore/` and number `999` + + **Detection algorithm (use in order):** + + 1. **First, look for adjacent prefix + number** (most common): + - Pattern: `[prefix_keyword] [number]` appearing together + - Examples: "feature 303", "bugfix 666", "hotfix 42", "fix 123" + - If found: Extract both prefix and number, done. + + 2. **If not found, scan the entire input more broadly**: + - Search **anywhere** in the input for prefix keywords: + - "feature" or "features" → `feature/` + - "bugfix" or "bug fix" or "fix" → `bugfix/` + - "hotfix" or "hot fix" → `hotfix/` + - "chore" → `chore/` + - "refactor" or "refactoring" → `refactor/` + - Search **anywhere** in the input for number patterns: "#221", "221", "issue 221", "ticket 221", "spec 221", "number 221" + - If BOTH prefix keyword AND number found: Combine them + - If only number found: Extract just the number (auto-prefix from config) + - If only prefix keyword found: Ignore (not enough information) + + 3. **Handle conflicts** (if multiple prefix keywords found): + - Use the keyword that appears closest to the number + - If equidistant, prefer more specific: "bugfix" > "fix" + - If still tied, use first occurrence (left to right) + + **This handles all these patterns:** + - "feature 303 add cart" ✓ (adjacent) + - "This is feature 221" ✓ (adjacent within sentence) + - "For issue #221, make it a feature" ✓ (separated, closest keyword) + - "#221 feature" ✓ (separated, number first) + - "issue #221" ✓ (just number) + - "Add shopping cart feature 303" ✓ (adjacent but later in sentence) **Examples of user input with spec number:** -- "Add user authentication --spec-number 42" -- "Fix login timeout for issue #123" (extract `123`) -- "Implement payment API as spec 1234" (use `1234`) -- "Add search feature --spec-number 99 --branch-prefix feature/" -- "feature 303 add shopping cart" (extract prefix `feature/` and number `303`) -- "bugfix 666 fix payment timeout" (extract prefix `bugfix/` and number `666`) +- "Add user authentication --spec-number 42" (explicit parameter) +- "Fix login timeout for issue #123" (extract `123` only) +- "Implement payment API as spec 1234" (extract `1234` only) +- "Add search feature --spec-number 99 --branch-prefix feature/" (explicit parameters) +- "feature 303 add shopping cart" (extract `feature/` and `303` - adjacent pattern) +- "bugfix 666 fix payment timeout" (extract `bugfix/` and `666` - adjacent pattern) +- "This is feature 221" (extract `feature/` and `221` - adjacent pattern in sentence) +- "For issue #221, make it a feature" (extract `feature/` and `221` - separated, keyword closest to number) +- "Add hotfix 42 for critical bug" (extract `hotfix/` and `42` - adjacent pattern) +- "#999 chore cleanup old files" (extract `chore/` and `999` - number first, then keyword) **If spec number is specified:** -1. Extract the number from the user input -2. **If using natural language pattern** (e.g., "feature 303"): - - Extract the prefix type (feature, bugfix, hotfix, fix, chore, etc.) +1. **Scan and extract** using the detection algorithm above: + - Look for adjacent patterns first (e.g., "feature 303") + - If not found, scan entire input for separated keywords and numbers + - Extract both prefix type and number if found together + +2. **Process extracted values:** - Normalize "fix" to "bugfix/" for consistency + - Normalize "bug fix" to "bugfix/" for consistency + - Normalize "hot fix" to "hotfix/" for consistency - Add trailing slash to create proper prefix (e.g., "feature" → "feature/") - - Extract the number following the prefix type - - Remove the entire pattern from the feature description before processing -3. Validate the number is a positive integer -4. Remove the spec number specification from the feature description before processing -5. Pass the number to the script using the appropriate parameter: - - Bash: `--spec-number 42` - - PowerShell: `-SpecNumber 42` -6. If a prefix was also extracted from the natural language pattern, pass it too: - - Bash: `--spec-number 303 --branch-prefix "feature/"` - - PowerShell: `-SpecNumber 303 -BranchPrefix "feature/"` + - Validate the number is a positive integer + +3. **Clean the feature description:** + - Remove the spec number from the description (e.g., "221" or "#221" or "issue 221") + - Remove the prefix keyword if it was used as a branch type indicator (e.g., remove "feature" from "This is feature 221" to get "This is") + - Clean up any resulting double spaces or hanging prepositions + +4. **Pass to script:** + - Bash: `--spec-number 42` and optionally `--branch-prefix "feature/"` + - PowerShell: `-SpecNumber 42` and optionally `-BranchPrefix "feature/"` **If no spec number is specified:** The script will auto-increment from the highest existing spec number (default behavior). @@ -64,12 +100,14 @@ Users can optionally specify a custom spec number when creating a feature by inc 3. Auto-increment (default) **Recognized prefix types for natural language patterns:** -- `feature` → `feature/` -- `bugfix` → `bugfix/` -- `fix` → `bugfix/` (normalized) -- `hotfix` → `hotfix/` +- `feature` or `features` → `feature/` +- `bugfix` or `bug fix` → `bugfix/` +- `fix` → `bugfix/` (normalized, lower priority if "bugfix" also present) +- `hotfix` or `hot fix` → `hotfix/` - `chore` → `chore/` -- `refactor` → `refactor/` +- `refactor` or `refactoring` → `refactor/` + +**Key principle:** Scan the ENTIRE user input for these keywords and numbers. They don't need to be adjacent or in any particular order. The algorithm will find them wherever they appear. ## Branch Prefix Option @@ -78,11 +116,16 @@ Users can optionally specify a branch prefix when creating a feature by includin - `--branch-prefix ` or `-BranchPrefix ` format - Keywords like "use prefix", "with prefix", "as a feature branch", "as a bugfix", etc. - **Natural language patterns** (also extracts spec number if present): - - "feature 303" → prefix `feature/` and number `303` - - "bugfix 666" → prefix `bugfix/` and number `666` - - "hotfix 42" → prefix `hotfix/` and number `42` + - Scan the entire input for prefix keywords: "feature", "bugfix", "hotfix", "chore", "refactor" + - These keywords can appear anywhere in the sentence, not just adjacent to a number + - Examples: + - "feature 303" → prefix `feature/` and number `303` (adjacent) + - "This is feature 221" → prefix `feature/` and number `221` (adjacent in sentence) + - "bugfix 666 fix timeout" → prefix `bugfix/` and number `666` (adjacent) + - "For issue #42, make it a hotfix" → prefix `hotfix/` and number `42` (separated) + - "#999 chore task" → prefix `chore/` and number `999` (number first) - The reference to prefix and number may come anywhere in the prompt. + **Key:** The reference to prefix and number may come anywhere in the prompt - scan the entire input. **Common prefix patterns:** @@ -94,11 +137,14 @@ Users can optionally specify a branch prefix when creating a feature by includin **Examples of user input with branch prefix:** -- "Add user authentication --branch-prefix feature/" -- "Fix login timeout as a bugfix" (infer `bugfix/` prefix) -- "Update payment API with prefix hotfix/" (use `hotfix/` prefix) -- "feature 303 implement shopping cart" (extract both prefix `feature/` and number `303`) -- "bugfix 666 resolve payment issue" (extract both prefix `bugfix/` and number `666`) +- "Add user authentication --branch-prefix feature/" (explicit parameter) +- "Fix login timeout as a bugfix" (infer `bugfix/` prefix from keyword) +- "Update payment API with prefix hotfix/" (explicit mention of prefix) +- "feature 303 implement shopping cart" (extract `feature/` and `303` - adjacent) +- "This is feature 221 for auth" (extract `feature/` and `221` - adjacent in sentence) +- "bugfix 666 resolve payment issue" (extract `bugfix/` and `666` - adjacent) +- "For issue #42, create hotfix branch" (extract `hotfix/` and `42` - separated) +- "Make #100 a chore task" (extract `chore/` and `100` - separated) **If branch prefix is specified:** From 112be123468cc0a08fcacbe80f1bd414c24259bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Sun, 23 Nov 2025 10:56:06 +0100 Subject: [PATCH 7/9] Prompt improvement for branch prefix --- templates/commands/specify.md | 73 ++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/templates/commands/specify.md b/templates/commands/specify.md index 8a0e18fc0f..75188250d4 100644 --- a/templates/commands/specify.md +++ b/templates/commands/specify.md @@ -28,12 +28,14 @@ Users can optionally specify a custom spec number when creating a feature by inc 1. **First, look for adjacent prefix + number** (most common): - Pattern: `[prefix_keyword] [number]` appearing together - - Examples: "feature 303", "bugfix 666", "hotfix 42", "fix 123" + - Pattern: `[prefix_keyword], number [number]` (e.g., "feature branch, number 123") + - Pattern: `[prefix_keyword] number [number]` (e.g., "feature number 123") + - Examples: "feature 303", "bugfix 666", "hotfix 42", "fix 123", "feature branch, number 9696" - If found: Extract both prefix and number, done. 2. **If not found, scan the entire input more broadly**: - Search **anywhere** in the input for prefix keywords: - - "feature" or "features" → `feature/` + - "feature" or "features" or "feature branch" → `feature/` - "bugfix" or "bug fix" or "fix" → `bugfix/` - "hotfix" or "hot fix" → `hotfix/` - "chore" → `chore/` @@ -50,6 +52,7 @@ Users can optionally specify a custom spec number when creating a feature by inc **This handles all these patterns:** - "feature 303 add cart" ✓ (adjacent) + - "feature branch, number 9696" ✓ (separated, explicit branch type) - "This is feature 221" ✓ (adjacent within sentence) - "For issue #221, make it a feature" ✓ (separated, closest keyword) - "#221 feature" ✓ (separated, number first) @@ -60,10 +63,11 @@ Users can optionally specify a custom spec number when creating a feature by inc - "Add user authentication --number 42" (explicit parameter) - "Fix login timeout for issue #123" (extract `123` only) -- "Implement payment API as spec 1234" (extract `1234` only) - "Add search feature --number 99 --branch-prefix feature/" (explicit parameters) +- "feature branch, number 9696" (extract `feature/` and `9696` - separated pattern) - "feature 303 add shopping cart" (extract `feature/` and `303` - adjacent pattern) - "bugfix 666 fix payment timeout" (extract `bugfix/` and `666` - adjacent pattern) +- "bugfix 666 fix payment timeout" (extract `bugfix/` and `666` - adjacent pattern) - "This is feature 221" (extract `feature/` and `221` - adjacent pattern in sentence) - "For issue #221, make it a feature" (extract `feature/` and `221` - separated, keyword closest to number) - "Add hotfix 42 for critical bug" (extract `hotfix/` and `42` - adjacent pattern) @@ -98,11 +102,11 @@ Users can optionally specify a custom spec number when creating a feature by inc 1. `--number` CLI parameter (highest priority) 2. `SPECIFY_SPEC_NUMBER` environment variable 3. Auto-increment (default) - **Recognized prefix types for natural language patterns:** -- `feature` or `features` → `feature/` +- `feature` or `features` or `feature branch` → `feature/` - `bugfix` or `bug fix` → `bugfix/` - `fix` → `bugfix/` (normalized, lower priority if "bugfix" also present) +- `fix` → `bugfix/` (normalized, lower priority if "bugfix" also present) - `hotfix` or `hot fix` → `hotfix/` - `chore` → `chore/` - `refactor` or `refactoring` → `refactor/` @@ -116,10 +120,11 @@ Users can optionally specify a branch prefix when creating a feature by includin - `--branch-prefix ` or `-BranchPrefix ` format - Keywords like "use prefix", "with prefix", "as a feature branch", "as a bugfix", etc. - **Natural language patterns** (also extracts spec number if present): - - Scan the entire input for prefix keywords: "feature", "bugfix", "hotfix", "chore", "refactor" + - Scan the entire input for prefix keywords: "feature", "feature branch", "bugfix", "hotfix", "chore", "refactor" - These keywords can appear anywhere in the sentence, not just adjacent to a number - Examples: - "feature 303" → prefix `feature/` and number `303` (adjacent) + - "feature branch, number 9696" → prefix `feature/` and number `9696` (separated) - "This is feature 221" → prefix `feature/` and number `221` (adjacent in sentence) - "bugfix 666 fix timeout" → prefix `bugfix/` and number `666` (adjacent) - "For issue #42, make it a hotfix" → prefix `hotfix/` and number `42` (separated) @@ -140,6 +145,7 @@ Users can optionally specify a branch prefix when creating a feature by includin - "Add user authentication --branch-prefix feature/" (explicit parameter) - "Fix login timeout as a bugfix" (infer `bugfix/` prefix from keyword) - "Update payment API with prefix hotfix/" (explicit mention of prefix) +- "feature branch, number 9696" (extract `feature/` and `9696` - separated) - "feature 303 implement shopping cart" (extract `feature/` and `303` - adjacent) - "This is feature 221 for auth" (extract `feature/` and `221` - adjacent in sentence) - "bugfix 666 resolve payment issue" (extract `bugfix/` and `666` - adjacent) @@ -165,17 +171,25 @@ The text the user typed after `/speckit.specify` in the triggering message **is* Given that feature description, do this: -1. **Generate a concise short name** (2-4 words) for the branch: - - Analyze the feature description and extract the most meaningful keywords - - Create a 2-4 word short name that captures the essence of the feature - - Use action-noun format when possible (e.g., "add-user-auth", "fix-payment-bug") - - Preserve technical terms and acronyms (OAuth2, API, JWT, etc.) - - Keep it concise but descriptive enough to understand the feature at a glance - - Examples: - - "I want to add user authentication" → "user-auth" - - "Implement OAuth2 integration for the API" → "oauth2-api-integration" - - "Create a dashboard for analytics" → "analytics-dashboard" - - "Fix payment processing timeout bug" → "fix-payment-timeout" +1. **Process Input & Generate Short Name**: + + a. **Extract & Clean**: + - Scan the **ENTIRE** input for spec numbers and branch prefixes using the algorithms defined in "Spec Number Option" and "Branch Prefix Option" sections. + - **EXTRACT** these values if found (e.g., "feature branch, number 9696" → prefix=`feature/`, number=`9696`). + - **REMOVE** the matched patterns from the input text to get the clean feature description. + - **Example**: Input "Fix login bug. feature branch, number 9696" → Description "Fix login bug.", Prefix "feature/", Number "9696". + + b. **Generate Short Name**: + - Analyze the **Clean Feature Description** (from step 1a) and extract the most meaningful keywords + - Create a 2-4 word short name that captures the essence of the feature + - Use action-noun format when possible (e.g., "add-user-auth", "fix-payment-bug") + - Preserve technical terms and acronyms (OAuth2, API, JWT, etc.) + - Keep it concise but descriptive enough to understand the feature at a glance + - Examples: + - "I want to add user authentication" → "user-auth" + - "Implement OAuth2 integration for the API" → "oauth2-api-integration" + - "Create a dashboard for analytics" → "analytics-dashboard" + - "Fix payment processing timeout bug" → "fix-payment-timeout" 2. **Check for existing branches before creating new one**: @@ -186,21 +200,22 @@ Given that feature description, do this: b. Find the highest feature number across all sources for the short-name: - Remote branches: `git ls-remote --heads origin | grep -E 'refs/heads/[0-9]+-$'` - - Local branches: `git branch | grep -E '^[* ]*[0-9]+-$'` - - Specs directories: Check for directories matching `specs/[0-9]+-` - - c. Determine the next available number: - - Extract all numbers from all three sources - - Find the highest number N - - Use N+1 for the new branch number - d. Run the script `{SCRIPT}` with the calculated number and short-name: - Pass `--number N+1` and `--short-name "your-short-name"` along with the feature description + - **CRITICAL**: Use the spec number and branch prefix **extracted in Step 1a** if available. - Bash example: `{SCRIPT} --json --number 5 --short-name "user-auth" "Add user authentication"` - PowerShell example: `{SCRIPT} -Json -Number 5 -ShortName "user-auth" "Add user authentication"` **IMPORTANT**: + - Check all three sources (remote branches, local branches, specs directories) to find the highest number + - Only match branches/directories with the exact short-name pattern + - If no existing branches/directories found with this short-name, start with number 1 + - Append the short-name argument to the `{SCRIPT}` command with the 2-4 word short name you created in step 1. Keep the feature description as the final argument. + - If a spec number was extracted in Step 1a, include it as a parameter + - If a branch prefix was extracted in Step 1a, include it as a parameter + - **Note:** Natural language patterns like "feature 303" or "bugfix 666" provide BOTH prefix and number - extract and pass both parameters + - Check all three sources (remote branches, local branches, specs directories) to find the highest number - Only match branches/directories with the exact short-name pattern - If no existing branches/directories found with this short-name, start with number 1 @@ -255,7 +270,13 @@ Given that feature description, do this: 7. Identify Key Entities (if data involved) 8. Return: SUCCESS (spec ready for planning) -5. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings. +5. Write the specification to SPEC_FILE using the template structure: + - Replace `[FEATURE NAME]` with a human-readable title derived from the description + - Replace `[###-feature-name]` with the **exact** `BRANCH_NAME` from the script output (including any prefix like `feature/` or `bugfix/`) + - Replace `[DATE]` with the current date + - Replace `"$ARGUMENTS"` with the original feature description + - Fill in the rest of the sections with concrete details derived from the feature description + - Preserve section order and headings 6. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria: From 13e9f64736b9b66131514435fac474dd5ed12eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Tue, 25 Nov 2025 17:36:16 +0100 Subject: [PATCH 8/9] Addressing copilot complaints --- scripts/bash/common.sh | 14 +++++----- scripts/bash/create-new-feature.sh | 5 +++- scripts/powershell/create-new-feature.ps1 | 8 ++++++ templates/commands/specify.md | 32 ++++++++++++----------- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/scripts/bash/common.sh b/scripts/bash/common.sh index 8db67daec9..36e736211e 100644 --- a/scripts/bash/common.sh +++ b/scripts/bash/common.sh @@ -110,14 +110,14 @@ find_feature_dir_by_prefix() { # Could be in format: 004-name or feature/004-name or bugfix/004-name local matches=() if [[ -d "$specs_dir" ]]; then - for dir in "$specs_dir"/*"$number"-*; do - if [[ -d "$dir" ]]; then - local dirname=$(basename "$dir") - # Verify it actually matches our pattern (not just contains the number) - if [[ "$dirname" =~ ^(([a-z]+/)?$number)- ]]; then - matches+=("$dirname") - fi + # Use find to search more precisely - avoid glob matching issues + while IFS= read -r -d '' dir; do + local dirname=$(basename "$dir") + # Verify it actually matches our pattern: starts with optional prefix/ then number- + if [[ "$dirname" =~ ^(([a-z]+/)?$number)- ]]; then + matches+=("$dirname") fi + done < <(find "$specs_dir" -mindepth 1 -maxdepth 1 -type d -print0) done fi diff --git a/scripts/bash/create-new-feature.sh b/scripts/bash/create-new-feature.sh index cbc49d90f2..c719feaa1d 100644 --- a/scripts/bash/create-new-feature.sh +++ b/scripts/bash/create-new-feature.sh @@ -263,7 +263,10 @@ fi # Determine branch number if [ -z "$BRANCH_NUMBER" ]; then - if [ "$HAS_GIT" = true ]; then + # Check environment variable first + if [ -n "$SPECIFY_SPEC_NUMBER" ]; then + BRANCH_NUMBER="$SPECIFY_SPEC_NUMBER" + elif [ "$HAS_GIT" = true ]; then # Check existing branches on remotes BRANCH_NUMBER=$(check_existing_branches "$BRANCH_SUFFIX" "$SPECS_DIR") else diff --git a/scripts/powershell/create-new-feature.ps1 b/scripts/powershell/create-new-feature.ps1 index 546db0c614..259b78a1be 100644 --- a/scripts/powershell/create-new-feature.ps1 +++ b/scripts/powershell/create-new-feature.ps1 @@ -42,6 +42,14 @@ if (-not $FeatureDescription -or $FeatureDescription.Count -eq 0) { $featureDesc = ($FeatureDescription -join ' ').Trim() +# Check environment variables +if ($Number -eq 0 -and $env:SPECIFY_SPEC_NUMBER) { + $Number = [int]$env:SPECIFY_SPEC_NUMBER +} +if (-not $BranchPrefix -and $env:SPECIFY_BRANCH_PREFIX) { + $BranchPrefix = $env:SPECIFY_BRANCH_PREFIX +} + # Resolve repository root. Prefer git information when available, but fall back # to searching for repository markers so the workflow still functions in repositories that # were initialized with --no-git. diff --git a/templates/commands/specify.md b/templates/commands/specify.md index 8836e9fa00..0ef42b5c2d 100644 --- a/templates/commands/specify.md +++ b/templates/commands/specify.md @@ -75,7 +75,6 @@ Users can optionally specify a custom spec number when creating a feature by inc - "feature branch, number 9696" (extract `feature/` and `9696` - separated pattern) - "feature 303 add shopping cart" (extract `feature/` and `303` - adjacent pattern) - "bugfix 666 fix payment timeout" (extract `bugfix/` and `666` - adjacent pattern) -- "bugfix 666 fix payment timeout" (extract `bugfix/` and `666` - adjacent pattern) - "This is feature 221" (extract `feature/` and `221` - adjacent pattern in sentence) - "For issue #221, make it a feature" (extract `feature/` and `221` - separated, keyword closest to number) - "Add hotfix 42 for critical bug" (extract `hotfix/` and `42` - adjacent pattern) @@ -114,7 +113,6 @@ Users can optionally specify a custom spec number when creating a feature by inc - `feature` or `features` or `feature branch` → `feature/` - `bugfix` or `bug fix` → `bugfix/` - `fix` → `bugfix/` (normalized, lower priority if "bugfix" also present) -- `fix` → `bugfix/` (normalized, lower priority if "bugfix" also present) - `hotfix` or `hot fix` → `hotfix/` - `chore` → `chore/` - `refactor` or `refactoring` → `refactor/` @@ -208,11 +206,22 @@ Given that feature description, do this: b. Find the highest feature number across all sources for the short-name: - Remote branches: `git ls-remote --heads origin | grep -E 'refs/heads/[0-9]+-$'` + - Local branches: `git branch | grep -E '^[* ]*[0-9]+-$'` + - Specs directories: Check for directories matching `specs/[0-9]+-` + + c. Determine the next available number: + - Extract all numbers from all three sources + - Find the highest number N + - Use N+1 for the new branch number + d. Run the script `{SCRIPT}` with the calculated number and short-name: - - Pass `--number N+1` and `--short-name "your-short-name"` along with the feature description - **CRITICAL**: Use the spec number and branch prefix **extracted in Step 1a** if available. - - Bash example: `{SCRIPT} --json --number 5 --short-name "user-auth" "Add user authentication"` - - PowerShell example: `{SCRIPT} -Json -Number 5 -ShortName "user-auth" "Add user authentication"` + - Pass `--number N+1` and `--short-name "your-short-name"` along with the feature description + - If branch prefix was extracted, also pass `--branch-prefix "prefix/"` + - Bash example without prefix: `{SCRIPT} --json --number 5 --short-name "user-auth" "Add user authentication"` + - Bash example with prefix: `{SCRIPT} --json --number 5 --branch-prefix "feature/" --short-name "user-auth" "Add user authentication"` + - PowerShell example without prefix: `{SCRIPT} -Json -Number 5 -ShortName "user-auth" "Add user authentication"` + - PowerShell example with prefix: `{SCRIPT} -Json -Number 5 -BranchPrefix "feature/" -ShortName "user-auth" "Add user authentication"` **IMPORTANT**: @@ -220,17 +229,10 @@ Given that feature description, do this: - Only match branches/directories with the exact short-name pattern - If no existing branches/directories found with this short-name, start with number 1 - Append the short-name argument to the `{SCRIPT}` command with the 2-4 word short name you created in step 1. Keep the feature description as the final argument. - - If a spec number was extracted in Step 1a, include it as a parameter - - If a branch prefix was extracted in Step 1a, include it as a parameter - - **Note:** Natural language patterns like "feature 303" or "bugfix 666" provide BOTH prefix and number - extract and pass both parameters + - **CRITICAL**: If a spec number was extracted in Step 1a, include `--number ` parameter (Bash) or `-SpecNumber ` (PowerShell) + - **CRITICAL**: If a branch prefix was extracted in Step 1a, include `--branch-prefix "prefix/"` parameter (Bash) or `-BranchPrefix "prefix/"` (PowerShell) + - **Note:** Natural language patterns like "feature 303" or "bugfix 666" provide BOTH prefix and number - you MUST extract and pass BOTH parameters to the script - - Check all three sources (remote branches, local branches, specs directories) to find the highest number - - Only match branches/directories with the exact short-name pattern - - If no existing branches/directories found with this short-name, start with number 1 - - Append the short-name argument to the `{SCRIPT}` command with the 2-4 word short name you created in step 1. Keep the feature description as the final argument. - - If a spec number was specified (see "Spec Number Option" above), include it as a parameter - - If a branch prefix was specified (see "Branch Prefix Option" above), include it as a parameter - - **Note:** Natural language patterns like "feature 303" or "bugfix 666" provide BOTH prefix and number - extract and pass both parameters - Bash examples: - `--short-name "your-generated-short-name" "Feature description here"` - `--short-name "user-auth" "Add user authentication"` From e14f0dc6348e3fb9abe65e0e61380d236e14ca2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Tue, 25 Nov 2025 18:52:04 +0100 Subject: [PATCH 9/9] Fixed syntax error --- scripts/bash/common.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/bash/common.sh b/scripts/bash/common.sh index 36e736211e..ef73e08e91 100644 --- a/scripts/bash/common.sh +++ b/scripts/bash/common.sh @@ -118,7 +118,6 @@ find_feature_dir_by_prefix() { matches+=("$dirname") fi done < <(find "$specs_dir" -mindepth 1 -maxdepth 1 -type d -print0) - done fi # Handle results