Skip to content

Conversation

@TechPreacher
Copy link

Summary

Adds support for customizable branch naming patterns, allowing teams to configure how feature branches are named through a settings file.

Changes

New Features:

  • --settings flag for specify init to generate .specify/settings.toml
  • Configurable branch.template with placeholders: {number}, {short_name}, {username}, {email_prefix}
  • Per-user number scoping when using {username} prefix (eliminates race conditions in teams)
  • Git-compliant branch name validation before creation

Files Modified:

  • init.py - Added --settings flag and settings file generation
  • common.sh - Added TOML parsing, username resolution, validation functions
  • common.ps1 - PowerShell equivalents
  • create-new-feature.sh - Template loading and resolution
  • create-new-feature.ps1 - PowerShell equivalent
  • settings.toml - New default settings template
  • Documentation updates: README, quickstart, installation, upgrade guides

Example Usage

# Initialize project with settings file
specify init my-project --settings --ai copilot

# Configure custom template in .specify/settings.toml
[branch]
template = "{username}/{number}-{short_name}"

# Creates branches like: jsmith/001-add-login

Version

0.0.23

Integrates configurable branch templates using settings files so that branch names can include variables (e.g. {username}, {number}, {short_name}). Updates agent scripts, CLI initialization, and documentation to support both legacy and user-defined naming conventions, ensuring seamless team collaboration.
Introduces configuration support for branch templates via a settings file and updates utilities for placeholder resolution. Enhances branch naming with per-user numbering and integrates new CLI contracts, data models, and testing documentation for improved team workflows.
Implements settings file generation and TOML-based template resolution for custom branch naming.
Adds per-user number scoping and branch name validation in both Bash and PowerShell.
Updates docs, tasks, and version info to support the new branch template workflow.
Updates documentation and CLI logic to support flexible settings file generation.
Introduces a project path parameter for creating the settings file in a specified directory,
and clarifies usage of the --settings flag with various initialization options.
Copilot AI review requested due to automatic review settings January 23, 2026 12:24
Deletes numerous agent instructions, prompts, workflows, and templates used by SpecKit—including obsolete agents, checklist and plan templates, and related scripts—to streamline the repository for flexible branch naming.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds customizable branch naming via a TOML settings file, integrates that configuration into the feature-creation scripts (Bash/PowerShell), and introduces a full Spec Kit agent workflow (specify/plan/tasks/etc.) with corresponding templates and scripts, along with docs and version updates.

Changes:

  • Introduces .specify/settings.toml and a specify init --settings workflow, including a Python helper to generate a documented settings template.
  • Extends create-new-feature.sh / create-new-feature.ps1 and their shared common libraries to load branch templates from TOML, resolve {username}/{email_prefix}, apply per-prefix numbering, and validate branch names against Git rules.
  • Adds Spec Kit agent templates, Bash helper scripts, and documentation to support the end-to-end /speckit.* workflows, plus bumps the CLI to version 0.0.23 and documents the new behavior.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
templates/settings.toml New default project-level TOML settings template documenting branch.template options and placeholders.
src/specify_cli/init.py Adds SETTINGS_TEMPLATE, _init_settings_file(), and a --settings flag to init to create or also create a .specify/settings.toml file; wires in help text and example usage.
specs/001-custom-branch-templates/tasks.md Task breakdown for implementing branch templates, validation, username resolution, and settings CLI, used as internal project planning.
specs/001-custom-branch-templates/spec.md Formal feature spec defining user stories, functional requirements, and success criteria for customizable branch naming.
specs/001-custom-branch-templates/research.md Research notes and decisions for TOML parsing, username resolution, per-prefix number scoping, and branch validation rules.
specs/001-custom-branch-templates/quickstart.md Scenario-based quickstart validating templates, default behavior, username fallback, per-user numbering, and settings generation.
specs/001-custom-branch-templates/plan.md Implementation plan tying the spec to concrete repo structure and phases (research, design, implementation).
specs/001-custom-branch-templates/data-model.md Data model for settings, branch templates, variables, and validation rules (including {number}/{short_name} requirements).
specs/001-custom-branch-templates/contracts/cli.md CLI contract for specify init --settings and branch-template-related script behavior, including expected messages and exit codes.
specs/001-custom-branch-templates/checklists/requirements.md Requirements quality checklist for the custom-branch-templates spec, ensuring spec completeness before planning.
scripts/powershell/create-new-feature.ps1 Powershell feature-creation script extended to source common.ps1, load/apply branch templates, resolve variables, use prefix-scoped numbering, validate branch names, and truncate {short_name} safely to 244 bytes.
scripts/powershell/common.ps1 Adds TOML reading (Get-TomlValue, Get-BranchTemplate), username/email resolution, branch validation (Test-BranchName), and prefix-scoped highest-number lookup (Get-HighestNumberForPrefix).
scripts/bash/create-new-feature.sh Bash feature-creation script extended to source common.sh, load/apply branch templates, resolve variables, use prefix-scoped numbering, validate branch names, and attempt to truncate {short_name} for 244-byte compliance (currently with an incorrect length calculation).
scripts/bash/common.sh Adds TOML reader (get_toml_value, load_branch_template), username/email resolution helpers, branch name validator, and prefix-scoped highest-number lookup for Bash workflows.
pyproject.toml Bumps specify-cli project version from 0.0.22 to 0.0.23 for the new feature release.
memory/constitution.md Replaces placeholder project constitution with a concrete “Spec Kit Constitution” including principles, workflow, quality standards, and governance.
docs/upgrade.md Notes that .specify/settings.toml is user-owned and not modified by upgrades.
docs/quickstart.md Adds a “Customizing Branch Names” section demonstrating specify init --settings and documenting branch template variables.
docs/installation.md Documents how to initialize a settings file via specify init --settings in installation flows.
README.md Documents the new --settings flag and branch template configuration, variables, and examples.
CHANGELOG.md Adds 0.0.23 entry describing customizable branch templates, --settings init, validation, and script changes.
.specify/templates/tasks-template.md New generic tasks.md template used by /speckit.tasks, showing phased, story-based task structure.
.specify/templates/spec-template.md New generic spec.md template for user stories, requirements, and success criteria used by /speckit.specify.
.specify/templates/plan-template.md New generic plan.md template for technical context, constitution check, structure, and complexity tracking, used by /speckit.plan.
.specify/templates/checklist-template.md New generic checklist template for /speckit.checklist, defining checklist structure and numbering.
.specify/templates/agent-file-template.md Template for agent context files (e.g., Copilot instructions), including placeholders for tech stack, structure, commands, style, and recent changes.
.specify/scripts/bash/update-agent-context.sh Large Bash script that parses plan.md and updates agent context files (Claude, Copilot, etc.) with technologies, structure, commands, and recent changes.
.specify/scripts/bash/setup-plan.sh Bash helper to set up plan.md from the plan template for the current feature, with optional JSON output.
.specify/scripts/bash/create-new-feature.sh Bash helper (for agents) to create a new feature branch and spec directory using the existing branch-numbering and naming logic.
.specify/scripts/bash/common.sh Shared Bash helpers for .specify scripts: repo/feature detection, branch checking, and path exports.
.specify/scripts/bash/check-prerequisites.sh Consolidated Bash prerequisite checker for feature docs, used by agents to locate spec/plan/tasks and optional artifacts.
.specify/memory/constitution.md Generic, parameterized constitution template for new projects, with placeholders for principles, sections, and governance.
.github/prompts/speckit.taskstoissues.prompt.md Registers the speckit.taskstoissues agent with the GitHub prompt system.
.github/prompts/speckit.tasks.prompt.md Registers the speckit.tasks agent.
.github/prompts/speckit.specify.prompt.md Registers the speckit.specify agent.
.github/prompts/speckit.plan.prompt.md Registers the speckit.plan agent.
.github/prompts/speckit.implement.prompt.md Registers the speckit.implement agent.
.github/prompts/speckit.constitution.prompt.md Registers the speckit.constitution agent.
.github/prompts/speckit.clarify.prompt.md Registers the speckit.clarify agent.
.github/prompts/speckit.checklist.prompt.md Registers the speckit.checklist agent.
.github/prompts/speckit.analyze.prompt.md Registers the speckit.analyze agent.
.github/agents/speckit.taskstoissues.agent.md Defines the speckit.taskstoissues agent behavior to turn tasks into GitHub issues using the MCP issue_write tool.
.github/agents/speckit.tasks.agent.md Defines the speckit.tasks agent behavior to generate tasks.md from spec/plan/research/contracts with strict checklist and phase structure.
.github/agents/speckit.specify.agent.md Defines the speckit.specify agent behavior to create branch+spec, fill the spec template, validate spec quality, and write a spec-quality checklist.
.github/agents/speckit.plan.agent.md Defines the speckit.plan agent to fill in plan.md, generate research/data-model/contracts/quickstart, and update agent context.
.github/agents/speckit.implement.agent.md Defines the speckit.implement agent to execute implementation tasks from tasks.md, respecting checklists and prerequisites.
.github/agents/speckit.constitution.agent.md Defines the speckit.constitution agent to fill/update the constitution template and propagate principle changes.
.github/agents/speckit.clarify.agent.md Defines the speckit.clarify agent to iteratively clarify ambiguous requirements in spec.md and encode answers back into the spec.
.github/agents/speckit.checklist.agent.md Defines the speckit.checklist agent to generate “unit tests for requirements” checklists under checklists/.
.github/agents/speckit.analyze.agent.md Defines the speckit.analyze agent to cross-check consistency/coverage across spec, plan, and tasks.
.github/agents/copilot-instructions.md Auto-generated Copilot instructions for this repo; documents current stack and structure, but the Commands line still contains unresolved [ONLY COMMANDS FOR ACTIVE TECHNOLOGIES] placeholders.
Comments suppressed due to low confidence (1)

scripts/bash/create-new-feature.sh:333

  • The branch-name truncation logic here does not actually guarantee that the final BRANCH_NAME is within GitHub's 244-byte limit. The AVAILABLE_LENGTH calculation depends on ${#BRANCH_SUFFIX} and adds an extra constant (+ 12), so in many cases AVAILABLE_LENGTH will be larger than the maximum safe length for the {short_name} portion, and the recomputed BRANCH_NAME can still exceed MAX_BRANCH_LENGTH. This can lead to git checkout -b failing even after the "exceeded" warning is printed. To fix this, compute the maximum allowed length for the {short_name} segment purely from MAX_BRANCH_LENGTH and the template overhead (including the replacement of {number} with the 3-digit feature number), and cap the truncated suffix length to that value plus the current suffix length as an upper bound.
MAX_BRANCH_LENGTH=244
if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then
    ORIGINAL_BRANCH_NAME="$BRANCH_NAME"
    
    # For template-based names, truncate the short_name portion
    # Re-resolve with truncated short_name
    AVAILABLE_LENGTH=$((MAX_BRANCH_LENGTH - ${#RESOLVED_TEMPLATE} + ${#BRANCH_SUFFIX} + 12))  # +12 for {short_name} placeholder
    if [ $AVAILABLE_LENGTH -lt 10 ]; then
        AVAILABLE_LENGTH=10  # Minimum reasonable short_name length
    fi
    
    TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$AVAILABLE_LENGTH)
    TRUNCATED_SUFFIX=$(echo "$TRUNCATED_SUFFIX" | sed 's/-$//')
    
    # Re-resolve branch name with truncated suffix
    BRANCH_NAME="${RESOLVED_TEMPLATE//\{number\}/$FEATURE_NUM}"
    BRANCH_NAME="${BRANCH_NAME//\{short_name\}/$TRUNCATED_SUFFIX}"
    
    >&2 echo "[specify] Warning: Branch name exceeded GitHub's 244-byte limit"
    >&2 echo "[specify] Original: $ORIGINAL_BRANCH_NAME (${#ORIGINAL_BRANCH_NAME} bytes)"
    >&2 echo "[specify] Truncated to: $BRANCH_NAME (${#BRANCH_NAME} bytes)"

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +997 to +998
console.print("Use [cyan]--force[/cyan] to overwrite.")
raise typer.Exit(1)
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overwrite behavior for .specify/settings.toml when it already exists does not match the documented CLI contract in specs/001-custom-branch-templates/contracts/cli.md, which specifies an interactive overwrite prompt ("Overwrite? [y/N]") unless --force is provided. Here, the code simply prints a message and exits with code 1 when force is false, with no opportunity for the user to confirm overwriting. To align behavior with the contract, this branch should either implement the documented confirmation prompt or the contract/docs should be updated to describe the current non-interactive behavior.

Suggested change
console.print("Use [cyan]--force[/cyan] to overwrite.")
raise typer.Exit(1)
# Per CLI contract, prompt for confirmation unless --force is provided
console.print("Overwrite? [y/N]: ", end="")
try:
choice = readchar.readchar()
except Exception:
choice = ""
# Move to the next line after the keypress
console.print()
if str(choice).lower() not in ("y", "yes"):
console.print("[red]Aborted.[/red] Use [cyan]--force[/cyan] to overwrite without prompting.")
raise typer.Exit(1)
console.print(f"[yellow]Overwriting existing settings file:[/yellow] {settings_file}")

Copilot uses AI. Check for mistakes.
Introduces GitHub workflows and scripts to automate release processes including building, packaging, and deploying Spec Kit templates across multiple agents and script types. Establishes version bumping, release notes generation, and artifact updates to streamline deployment.
Removes outdated Spec Kit constitution structure and adds a new, flexible template
with placeholders for core principles, sections, and governance to standardize project setup.
Copilot AI review requested due to automatic review settings January 23, 2026 12:30
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

scripts/bash/create-new-feature.sh:333

  • The calculation of AVAILABLE_LENGTH here can still produce branch names longer than the intended MAX_BRANCH_LENGTH (244) because it assumes RESOLVED_TEMPLATE already reflects the substituted {short_name} and {number} lengths. In reality RESOLVED_TEMPLATE still contains the placeholders, so AVAILABLE_LENGTH=$((MAX_BRANCH_LENGTH - ${#RESOLVED_TEMPLATE} + ${#BRANCH_SUFFIX} + 12)) can yield a value that allows the recomposed BRANCH_NAME to exceed 244 characters. To reliably enforce the 244‑character limit, derive the available length for {short_name} from the template structure (similar to the PowerShell implementation using a separate template overhead) and/or re‑validate the final BRANCH_NAME length after recomposition.
MAX_BRANCH_LENGTH=244
if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then
    ORIGINAL_BRANCH_NAME="$BRANCH_NAME"
    
    # For template-based names, truncate the short_name portion
    # Re-resolve with truncated short_name
    AVAILABLE_LENGTH=$((MAX_BRANCH_LENGTH - ${#RESOLVED_TEMPLATE} + ${#BRANCH_SUFFIX} + 12))  # +12 for {short_name} placeholder
    if [ $AVAILABLE_LENGTH -lt 10 ]; then
        AVAILABLE_LENGTH=10  # Minimum reasonable short_name length
    fi
    
    TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$AVAILABLE_LENGTH)
    TRUNCATED_SUFFIX=$(echo "$TRUNCATED_SUFFIX" | sed 's/-$//')
    
    # Re-resolve branch name with truncated suffix
    BRANCH_NAME="${RESOLVED_TEMPLATE//\{number\}/$FEATURE_NUM}"
    BRANCH_NAME="${BRANCH_NAME//\{short_name\}/$TRUNCATED_SUFFIX}"
    
    >&2 echo "[specify] Warning: Branch name exceeded GitHub's 244-byte limit"
    >&2 echo "[specify] Original: $ORIGINAL_BRANCH_NAME (${#ORIGINAL_BRANCH_NAME} bytes)"
    >&2 echo "[specify] Truncated to: $BRANCH_NAME (${#BRANCH_NAME} bytes)"

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +376 to +407
$specsDir = Join-Path $RepoRoot 'specs'
$highest = 0

# Escape special regex characters in prefix
$escapedPrefix = [regex]::Escape($Prefix)

# Check specs directory for matching directories
if (Test-Path $specsDir) {
Get-ChildItem -Path $specsDir -Directory | ForEach-Object {
if ($_.Name -match "^$escapedPrefix(\d{3})-") {
$num = [int]$matches[1]
if ($num -gt $highest) {
$highest = $num
}
}
}
}

# Also check git branches if available
try {
$branches = git branch -a 2>$null
if ($LASTEXITCODE -eq 0 -and $branches) {
foreach ($branch in $branches) {
# Clean branch name
$cleanBranch = $branch.Trim() -replace '^\*?\s+', '' -replace '^remotes/[^/]+/', ''

# Check if branch matches prefix pattern
if ($cleanBranch -match "^$escapedPrefix(\d{3})-") {
$num = [int]$matches[1]
if ($num -gt $highest) {
$highest = $num
}
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get-HighestNumberForPrefix only inspects immediate child directories of specs (Get-ChildItem -Path $specsDir -Directory) and matches $_ .Name against ^$escapedPrefix(\d{3})-, but FEATURE_DIR is built as specs/$Branch, so for prefixes containing / (e.g. {username}/ or feature/{username}/) the actual layout is specs/<prefix>/<NNN>-<suffix> and the top-level directory names do not include the prefix plus number. This means existing specs for slashed prefixes are never counted when git is unavailable or has no matching branches, so per-prefix numbering silently falls back to 0. To make per-prefix scoping work reliably, update this function to traverse nested spec directories and match against the full relative path (or otherwise normalize the prefix so it aligns with the directory structure).

Copilot uses AI. Check for mistakes.
Comment on lines +241 to +259
# =============================================================================
# Branch Name Validation Functions
# =============================================================================

# Validate branch name against Git rules
# Args: $1 = branch name
# Returns: 0 if valid, 1 if invalid (prints error to stderr)
validate_branch_name() {
local name="$1"

# Cannot be empty
if [[ -z "$name" ]]; then
echo "Error: Branch name cannot be empty" >&2
return 1
fi

# Cannot start with hyphen
if [[ "$name" == -* ]]; then
echo "Error: Branch name cannot start with hyphen: $name" >&2
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The branch validation logic earlier in this file (check_feature_branch using the ^[0-9]{3}- pattern) is now inconsistent with the new template-based naming introduced here (e.g., {username}/{number}-{short_name}), which produces branches like jdoe/001-add-login that no longer start with a 3‑digit prefix. Scripts such as setup-plan.sh that call check_feature_branch will reject branches created by create-new-feature.sh when a prefix is configured, breaking the workflow for teams that customize branch.template. The validation should be updated to accept the configured template pattern (or at least to locate and validate the numeric {number} portion after any prefix) instead of hard‑coding a leading NNN- requirement, and related error messages should be generalized away from 001-feature-name.

Copilot uses AI. Check for mistakes.
Comment on lines +226 to +283
# =============================================================================
# Username and Email Resolution Functions
# =============================================================================

<#
.SYNOPSIS
Resolve {username} variable from Git config or OS fallback
.RETURNS
Normalized username (lowercase, hyphens for special chars)
#>
function Resolve-Username {
$username = $null

try {
$username = git config user.name 2>$null
}
catch {
# Git command failed
}

if (-not $username) {
# Fallback to OS username
$username = $env:USERNAME
if (-not $username) {
$username = $env:USER
}
if (-not $username) {
$username = 'unknown'
}
}

# Normalize: lowercase, replace non-alphanumeric with hyphens, collapse multiple hyphens
$normalized = $username.ToLower() -replace '[^a-z0-9]', '-' -replace '-+', '-' -replace '^-', '' -replace '-$', ''
return $normalized
}

<#
.SYNOPSIS
Resolve {email_prefix} variable from Git config
.RETURNS
Email prefix (portion before @) or empty string
#>
function Resolve-EmailPrefix {
$email = $null

try {
$email = git config user.email 2>$null
}
catch {
# Git command failed
}

if ($email -and $email -match '^([^@]+)@') {
return $matches[1].ToLower()
}

# Returns empty string if no email configured (per FR-002 clarification)
return ''
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test-FeatureBranch still enforces that feature branches match ^[0-9]{3}-, but the new template-based naming introduced below (e.g., {username}/{number}-{short_name}) generates branches like jdoe/001-add-login that do not start with a numeric prefix. Because scripts such as check-prerequisites.ps1 and setup-plan.ps1 call Test-FeatureBranch, enabling a prefixed branch.template will cause those scripts to report "Not on a feature branch" even for branches created by create-new-feature.ps1. Please update Test-FeatureBranch to validate against the configured template (or at least locate the {number} segment after any optional prefix) and adjust its error message so it doesn�t hard-code 001-feature-name as the only valid shape.

Copilot uses AI. Check for mistakes.
Comment on lines +946 to +973
# Settings file template content for branch template customization
SETTINGS_TEMPLATE = '''# Spec Kit Settings
# Documentation: https://github.github.io/spec-kit/
#
# This file configures project-level settings for the Spec Kit workflow.
# Place this file at .specify/settings.toml in your project root.
[branch]
# Template for generating feature branch names.
#
# Available variables:
# {number} - Auto-incrementing 3-digit feature number (001, 002, ...)
# {short_name} - Generated or provided short feature name
# {username} - Git user.name, normalized for branch names (lowercase, hyphens)
# {email_prefix} - Portion of Git user.email before the @ symbol
#
# Examples:
# "{number}-{short_name}" # 001-add-login (default, solo dev)
# "{username}/{number}-{short_name}" # johndoe/001-add-login (team)
# "feature/{username}/{number}-{short_name}" # feature/johndoe/001-add-login
# "users/{email_prefix}/{number}-{short_name}" # users/jsmith/001-add-login
#
# When using {username} or a static prefix, each prefix gets its own number
# sequence to avoid conflicts between team members.
#
# IMPORTANT: Template MUST contain both {number} and {short_name} placeholders.
template = "{number}-{short_name}"
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The settings template content is now duplicated in two places: here as SETTINGS_TEMPLATE and in templates/settings.toml. Keeping these two copies in sync will be error-prone over time (for example if you add new placeholders or documentation) and risks divergence between the CLI-generated file and the template-packaged file. Consider having _init_settings_file load the template from templates/settings.toml (or a single shared source) instead of maintaining two independent copies of the same text.

Copilot uses AI. Check for mistakes.
Comment on lines +315 to +352
# Escape special regex characters in prefix for grep
local escaped_prefix
escaped_prefix=$(printf '%s' "$prefix" | sed 's/[.[\*^$()+?{|\\]/\\&/g')

# Check specs directory for matching directories
if [[ -d "$specs_dir" ]]; then
for dir in "$specs_dir"/"${prefix}"*; do
[[ -d "$dir" ]] || continue
local dirname
dirname=$(basename "$dir")
# Extract number after prefix: prefix + 3-digit number
if [[ "$dirname" =~ ^${escaped_prefix}([0-9]{3})- ]]; then
local num=$((10#${BASH_REMATCH[1]}))
if [[ "$num" -gt "$highest" ]]; then
highest=$num
fi
fi
done
fi

# Also check git branches if available
if git rev-parse --show-toplevel >/dev/null 2>&1; then
local branches
branches=$(git branch -a 2>/dev/null || echo "")
if [[ -n "$branches" ]]; then
while IFS= read -r branch; do
# Clean branch name
local clean_branch
clean_branch=$(echo "$branch" | sed 's/^[* ]*//; s|^remotes/[^/]*/||')

# Check if branch matches prefix pattern
if [[ "$clean_branch" =~ ^${escaped_prefix}([0-9]{3})- ]]; then
local num=$((10#${BASH_REMATCH[1]}))
if [[ "$num" -gt "$highest" ]]; then
highest=$num
fi
fi
done <<< "$branches"
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_highest_for_prefix assumes that spec directories' basenames start with the prefix string (regex ^${escaped_prefix}([0-9]{3})-), but FEATURE_DIR is created as $SPECS_DIR/$BRANCH_NAME, so when the prefix contains path separators (e.g. {username}/ or feature/{username}/), the actual spec directory layout is specs/<prefix>/<NNN>-<suffix> and the basename is only NNN-suffix. As a result, this function never detects existing specs for prefixes that include /, so in non‑git repos or when branches are missing it will always return 0 and break per‑prefix numbering. Consider matching against the full relative path (or iterating recursively) instead of just the basename so that prefixes containing / correctly scope their numeric sequences.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant