When --number 027 was passed, printf '%03d' interpreted it as octal,
converting 027 (octal) to 23 (decimal). Now forces base-10 with 10# prefix.
Bug: User passes --number 027, gets feature 023 instead of 027
Root cause: printf %03d treats leading zeros as octal notation
Fix: Use $((10#$BRANCH_NUMBER)) to force decimal interpretation
Example:
- Before: --number 027 → octal 027 → decimal 23 → feature 023
- After: --number 027 → decimal 27 → feature 027
Note: PowerShell version does not have this bug because [int] type
conversion in PowerShell does not treat leading zeros as octal.
The check_existing_branches (bash) and Get-NextBranchNumber (PowerShell)
functions no longer use the short_name parameter since they now find the
global maximum across ALL features. This commit:
1. Removes the unused parameter from function signatures
2. Updates all call sites to not pass the parameter
This prevents the scripts from failing when the function is called with
the wrong number of arguments.
The check_existing_branches (bash) and Get-NextBranchNumber (PowerShell)
functions were only looking for branches/specs matching the SAME short name
when determining the next feature number. This caused collisions where
multiple features could be assigned the same number if they had different
short names.
For example, if feature 023-ci-optimization existed, creating a new feature
with a different short name would incorrectly use 001 instead of 024.
This fix changes both functions to:
1. Use get_highest_from_branches() / Get-HighestNumberFromBranches to find
the highest number across ALL branches globally
2. Use get_highest_from_specs() / Get-HighestNumberFromSpecs to find the
highest number across ALL spec directories globally
3. Return the maximum of both + 1
The helper functions already existed but were not being used. This fix
properly utilizes them to ensure features are numbered sequentially
regardless of their short names.
Issue: Branch number collisions when creating features with different names
Impact: Prevents multiple features from sharing the same number prefix
Refactored both Bash and PowerShell create-new-feature scripts to modularize and deduplicate logic for determining the next feature number, including new helper functions for extracting the highest number from specs and branches. Improved branch name cleaning and generation. In update-agent-context scripts, removed redundant updates to AGENTS.md for Copilot, streamlining agent update logic.
- Use git ls-remote for more reliable remote branch detection
- Check remote branches, local branches, AND specs directories
- Match exact short-name pattern to avoid false positives
- Ensures no duplicate numbers across all sources
- Add --number parameter to create-new-feature scripts (bash & PowerShell)
- Add check_existing_branches() function to fetch and scan remote branches
- Update branch numbering logic to check remotes before creating new branches
- Update /speckit.specify command to document remote branch checking workflow
- Prevents duplicate branch numbers when branches exist on remotes but not locally
- Maintains backward compatibility with existing workflows
- Falls back to local directory scanning when Git is not available
Fix two critical bugs in the argument parsing logic that caused incorrect
behavior when --short-name parameter was used:
1. **Index offset bug**: The loop started at i=0 and used i < $#, which
incorrectly processed $0 (script name) as the first argument and
skipped the last actual parameter. Changed to i=1 and i <= $# to
properly iterate through actual command-line arguments ($1 to $#).
2. **Boundary condition bug**: The condition `[ $((i + 1)) -ge $# ]`
incorrectly flagged valid arguments as missing. When --short-name was
at position $#-1, the next position $# was valid but treated as
out-of-bounds. Changed to `[ $((i + 1)) -gt $# ]` for correct validation.
3. **Enhanced validation**: Added check to ensure --short-name value is
not another option (doesn't start with --).
**Before**:
- `script --json "desc" --short-name "test"` → Error: requires a value
- `script --json "desc1" "desc2" --short-name` → Generated wrong branch name
**After**:
- `script --json "desc" --short-name "test"` → Works correctly
- `script --json "desc1" "desc2" --short-name` → Proper error message
This ensures the script correctly supports both parameter orders:
- `[--json] [--short-name <name>] <feature_description>`
- `[--json] <feature_description> [--short-name <name>]`