Skip to content

Commit 1a71b03

Browse files
committed
Script and template tweaks
1 parent f04e01d commit 1a71b03

7 files changed

Lines changed: 138 additions & 48 deletions

File tree

scripts/bash/common.sh

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,47 @@ get_repo_root() {
1414

1515
# Get current branch, with fallback for non-git repositories
1616
get_current_branch() {
17+
# First check if SPECIFY_FEATURE environment variable is set
18+
if [[ -n "${SPECIFY_FEATURE:-}" ]]; then
19+
echo "$SPECIFY_FEATURE"
20+
return
21+
fi
22+
23+
# Then check git if available
1724
if git rev-parse --abbrev-ref HEAD >/dev/null 2>&1; then
1825
git rev-parse --abbrev-ref HEAD
19-
else
20-
echo "main" # Default branch name for non-git repos
26+
return
27+
fi
28+
29+
# For non-git repos, try to find the latest feature directory
30+
local repo_root=$(get_repo_root)
31+
local specs_dir="$repo_root/specs"
32+
33+
if [[ -d "$specs_dir" ]]; then
34+
local latest_feature=""
35+
local highest=0
36+
37+
for dir in "$specs_dir"/*; do
38+
if [[ -d "$dir" ]]; then
39+
local dirname=$(basename "$dir")
40+
if [[ "$dirname" =~ ^([0-9]{3})- ]]; then
41+
local number=${BASH_REMATCH[1]}
42+
number=$((10#$number))
43+
if [[ "$number" -gt "$highest" ]]; then
44+
highest=$number
45+
latest_feature=$dirname
46+
fi
47+
fi
48+
fi
49+
done
50+
51+
if [[ -n "$latest_feature" ]]; then
52+
echo "$latest_feature"
53+
return
54+
fi
2155
fi
56+
57+
echo "main" # Final fallback
2258
}
2359

2460
# Check if we have git available

scripts/bash/create-new-feature.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,14 @@ TEMPLATE="$REPO_ROOT/templates/spec-template.md"
6767
SPEC_FILE="$FEATURE_DIR/spec.md"
6868
if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"; fi
6969

70+
# Set the SPECIFY_FEATURE environment variable for the current session
71+
export SPECIFY_FEATURE="$BRANCH_NAME"
72+
7073
if $JSON_MODE; then
7174
printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
7275
else
7376
echo "BRANCH_NAME: $BRANCH_NAME"
7477
echo "SPEC_FILE: $SPEC_FILE"
7578
echo "FEATURE_NUM: $FEATURE_NUM"
79+
echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
7680
fi

scripts/bash/update-agent-context.sh

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,17 @@ set -o pipefail
4848
# Configuration and Global Variables
4949
#==============================================================================
5050

51-
REPO_ROOT=$(git rev-parse --show-toplevel)
52-
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
53-
FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH"
54-
NEW_PLAN="$FEATURE_DIR/plan.md"
51+
# Get script directory and load common functions
52+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
53+
source "$SCRIPT_DIR/common.sh"
54+
55+
# Get all paths and variables from common functions
56+
eval $(get_feature_paths)
57+
58+
NEW_PLAN="$IMPL_PLAN" # Alias for compatibility with existing code
5559
AGENT_TYPE="${1:-}"
5660

57-
# Agent-specific file paths
61+
# Agent-specific file paths
5862
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"
5963
GEMINI_FILE="$REPO_ROOT/GEMINI.md"
6064
COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"
@@ -108,22 +112,24 @@ trap cleanup EXIT INT TERM
108112
#==============================================================================
109113

110114
validate_environment() {
111-
# Check if we're in a git repository
112-
if ! git rev-parse --show-toplevel >/dev/null 2>&1; then
113-
log_error "Not in a git repository"
114-
exit 1
115-
fi
116-
117-
# Check if we have a current branch
115+
# Check if we have a current branch/feature (git or non-git)
118116
if [[ -z "$CURRENT_BRANCH" ]]; then
119-
log_error "Unable to determine current git branch"
117+
log_error "Unable to determine current feature"
118+
if [[ "$HAS_GIT" == "true" ]]; then
119+
log_info "Make sure you're on a feature branch"
120+
else
121+
log_info "Set SPECIFY_FEATURE environment variable or create a feature first"
122+
fi
120123
exit 1
121124
fi
122125

123126
# Check if plan.md exists
124127
if [[ ! -f "$NEW_PLAN" ]]; then
125128
log_error "No plan.md found at $NEW_PLAN"
126-
log_info "Make sure you're on a feature branch with a corresponding spec directory"
129+
log_info "Make sure you're working on a feature with a corresponding spec directory"
130+
if [[ "$HAS_GIT" != "true" ]]; then
131+
log_info "Use: export SPECIFY_FEATURE=your-feature-name or create a new feature first"
132+
fi
127133
exit 1
128134
fi
129135

@@ -142,9 +148,9 @@ extract_plan_field() {
142148
local field_pattern="$1"
143149
local plan_file="$2"
144150

145-
grep "^**${field_pattern}**: " "$plan_file" 2>/dev/null | \
151+
grep "^\*\*${field_pattern}\*\*: " "$plan_file" 2>/dev/null | \
146152
head -1 | \
147-
sed "s/^**${field_pattern}**: //" | \
153+
sed "s|^\*\*${field_pattern}\*\*: ||" | \
148154
grep -v "NEEDS CLARIFICATION" | \
149155
grep -v "^N/A$" || echo ""
150156
}
@@ -196,12 +202,9 @@ get_project_structure() {
196202
local project_type="$1"
197203

198204
if [[ "$project_type" == *"web"* ]]; then
199-
echo "backend/
200-
frontend/
201-
tests/"
205+
echo "backend/\\nfrontend/\\ntests/"
202206
else
203-
echo "src/
204-
tests/"
207+
echo "src/\\ntests/"
205208
fi
206209
}
207210

@@ -267,22 +270,26 @@ create_new_agent_file() {
267270
"s/\[PROJECT NAME\]/$project_name/"
268271
"s/\[DATE\]/$current_date/"
269272
"s/\[EXTRACTED FROM ALL PLAN.MD FILES\]/- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)/"
270-
"s|\[ACTUAL STRUCTURE FROM PLANS\]|$project_structure|"
273+
"s|\[ACTUAL STRUCTURE FROM PLANS\]|$project_structure|g"
271274
"s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$commands|"
272275
"s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$language_conventions|"
273276
"s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|- $CURRENT_BRANCH: Added $NEW_LANG + $NEW_FRAMEWORK|"
274277
)
275278

276279
for substitution in "${substitutions[@]}"; do
277-
if ! sed -i.bak "$substitution" "$temp_file"; then
280+
if ! sed -i.bak -e "$substitution" "$temp_file"; then
278281
log_error "Failed to perform substitution: $substitution"
279282
rm -f "$temp_file" "$temp_file.bak"
280283
return 1
281284
fi
282285
done
283286

287+
# Convert \n sequences to actual newlines
288+
sed -i.bak2 's/\\n/\
289+
/g' "$temp_file"
290+
284291
# Clean up backup files
285-
rm -f "$temp_file.bak"
292+
rm -f "$temp_file.bak" "$temp_file.bak2"
286293

287294
return 0
288295
}

scripts/powershell/common.ps1

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ function Get-RepoRoot {
1616
}
1717

1818
function Get-CurrentBranch {
19+
# First check if SPECIFY_FEATURE environment variable is set
20+
if ($env:SPECIFY_FEATURE) {
21+
return $env:SPECIFY_FEATURE
22+
}
23+
24+
# Then check git if available
1925
try {
2026
$result = git rev-parse --abbrev-ref HEAD 2>$null
2127
if ($LASTEXITCODE -eq 0) {
@@ -25,7 +31,30 @@ function Get-CurrentBranch {
2531
# Git command failed
2632
}
2733

28-
# Default branch name for non-git repos
34+
# For non-git repos, try to find the latest feature directory
35+
$repoRoot = Get-RepoRoot
36+
$specsDir = Join-Path $repoRoot "specs"
37+
38+
if (Test-Path $specsDir) {
39+
$latestFeature = ""
40+
$highest = 0
41+
42+
Get-ChildItem -Path $specsDir -Directory | ForEach-Object {
43+
if ($_.Name -match '^(\d{3})-') {
44+
$num = [int]$matches[1]
45+
if ($num -gt $highest) {
46+
$highest = $num
47+
$latestFeature = $_.Name
48+
}
49+
}
50+
}
51+
52+
if ($latestFeature) {
53+
return $latestFeature
54+
}
55+
}
56+
57+
# Final fallback
2958
return "main"
3059
}
3160

scripts/powershell/create-new-feature.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ if (Test-Path $template) {
7373
New-Item -ItemType File -Path $specFile | Out-Null
7474
}
7575

76+
# Set the SPECIFY_FEATURE environment variable for the current session
77+
$env:SPECIFY_FEATURE = $branchName
78+
7679
if ($Json) {
7780
$obj = [PSCustomObject]@{
7881
BRANCH_NAME = $branchName
@@ -86,4 +89,5 @@ if ($Json) {
8689
Write-Output "SPEC_FILE: $specFile"
8790
Write-Output "FEATURE_NUM: $featureNum"
8891
Write-Output "HAS_GIT: $hasGit"
92+
Write-Output "SPECIFY_FEATURE environment variable set to: $branchName"
8993
}

scripts/powershell/update-agent-context.ps1

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,30 @@
33
param([string]$AgentType)
44
$ErrorActionPreference = 'Stop'
55

6-
$repoRoot = git rev-parse --show-toplevel
7-
$currentBranch = git rev-parse --abbrev-ref HEAD
8-
$featureDir = Join-Path $repoRoot "specs/$currentBranch"
9-
$newPlan = Join-Path $featureDir 'plan.md'
10-
if (-not (Test-Path $newPlan)) { Write-Error "ERROR: No plan.md found at $newPlan"; exit 1 }
6+
# Load common functions
7+
. "$PSScriptRoot/common.ps1"
118

12-
$claudeFile = Join-Path $repoRoot 'CLAUDE.md'
13-
$geminiFile = Join-Path $repoRoot 'GEMINI.md'
14-
$copilotFile = Join-Path $repoRoot '.github/copilot-instructions.md'
15-
$cursorFile = Join-Path $repoRoot '.cursor/rules/specify-rules.mdc'
16-
$qwenFile = Join-Path $repoRoot 'QWEN.md'
17-
$agentsFile = Join-Path $repoRoot 'AGENTS.md'
18-
$windsurfFile = Join-Path $repoRoot '.windsurf/rules/specify-rules.md'
9+
# Get all paths and variables from common functions
10+
$paths = Get-FeaturePathsEnv
1911

20-
Write-Output "=== Updating agent context files for feature $currentBranch ==="
12+
$newPlan = $paths.IMPL_PLAN
13+
if (-not (Test-Path $newPlan)) {
14+
Write-Error "ERROR: No plan.md found at $newPlan"
15+
if (-not $paths.HAS_GIT) {
16+
Write-Output "Use: `$env:SPECIFY_FEATURE='your-feature-name' or create a new feature first"
17+
}
18+
exit 1
19+
}
20+
21+
$claudeFile = Join-Path $paths.REPO_ROOT 'CLAUDE.md'
22+
$geminiFile = Join-Path $paths.REPO_ROOT 'GEMINI.md'
23+
$copilotFile = Join-Path $paths.REPO_ROOT '.github/copilot-instructions.md'
24+
$cursorFile = Join-Path $paths.REPO_ROOT '.cursor/rules/specify-rules.mdc'
25+
$qwenFile = Join-Path $paths.REPO_ROOT 'QWEN.md'
26+
$agentsFile = Join-Path $paths.REPO_ROOT 'AGENTS.md'
27+
$windsurfFile = Join-Path $paths.REPO_ROOT '.windsurf/rules/specify-rules.md'
28+
29+
Write-Output "=== Updating agent context files for feature $($paths.CURRENT_BRANCH) ==="
2130

2231
function Get-PlanValue($pattern) {
2332
if (-not (Test-Path $newPlan)) { return '' }
@@ -34,12 +43,12 @@ $newProjectType = Get-PlanValue 'Project Type'
3443

3544
function Initialize-AgentFile($targetFile, $agentName) {
3645
if (Test-Path $targetFile) { return }
37-
$template = Join-Path $repoRoot '.specify/templates/agent-file-template.md'
46+
$template = Join-Path $paths.REPO_ROOT '.specify/templates/agent-file-template.md'
3847
if (-not (Test-Path $template)) { Write-Error "Template not found: $template"; return }
3948
$content = Get-Content $template -Raw
40-
$content = $content.Replace('[PROJECT NAME]', (Split-Path $repoRoot -Leaf))
49+
$content = $content.Replace('[PROJECT NAME]', (Split-Path $paths.REPO_ROOT -Leaf))
4150
$content = $content.Replace('[DATE]', (Get-Date -Format 'yyyy-MM-dd'))
42-
$content = $content.Replace('[EXTRACTED FROM ALL PLAN.MD FILES]', "- $newLang + $newFramework ($currentBranch)")
51+
$content = $content.Replace('[EXTRACTED FROM ALL PLAN.MD FILES]', "- $newLang + $newFramework ($($paths.CURRENT_BRANCH))")
4352
if ($newProjectType -match 'web') { $structure = "backend/`nfrontend/`ntests/" } else { $structure = "src/`ntests/" }
4453
$content = $content.Replace('[ACTUAL STRUCTURE FROM PLANS]', $structure)
4554
if ($newLang -match 'Python') { $commands = 'cd src && pytest && ruff check .' }
@@ -48,18 +57,18 @@ function Initialize-AgentFile($targetFile, $agentName) {
4857
else { $commands = "# Add commands for $newLang" }
4958
$content = $content.Replace('[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]', $commands)
5059
$content = $content.Replace('[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]', "${newLang}: Follow standard conventions")
51-
$content = $content.Replace('[LAST 3 FEATURES AND WHAT THEY ADDED]', "- ${currentBranch}: Added ${newLang} + ${newFramework}")
60+
$content = $content.Replace('[LAST 3 FEATURES AND WHAT THEY ADDED]', "- $($paths.CURRENT_BRANCH): Added ${newLang} + ${newFramework}")
5261
$content | Set-Content $targetFile -Encoding UTF8
5362
}
5463

5564
function Update-AgentFile($targetFile, $agentName) {
5665
if (-not (Test-Path $targetFile)) { Initialize-AgentFile $targetFile $agentName; return }
5766
$content = Get-Content $targetFile -Raw
58-
if ($newLang -and ($content -notmatch [regex]::Escape($newLang))) { $content = $content -replace '(## Active Technologies\n)', "`$1- $newLang + $newFramework ($currentBranch)`n" }
59-
if ($newDb -and $newDb -ne 'N/A' -and ($content -notmatch [regex]::Escape($newDb))) { $content = $content -replace '(## Active Technologies\n)', "`$1- $newDb ($currentBranch)`n" }
67+
if ($newLang -and ($content -notmatch [regex]::Escape($newLang))) { $content = $content -replace '(## Active Technologies\n)', "`$1- $newLang + $newFramework ($($paths.CURRENT_BRANCH))`n" }
68+
if ($newDb -and $newDb -ne 'N/A' -and ($content -notmatch [regex]::Escape($newDb))) { $content = $content -replace '(## Active Technologies\n)', "`$1- $newDb ($($paths.CURRENT_BRANCH))`n" }
6069
if ($content -match '## Recent Changes\n([\s\S]*?)(\n\n|$)') {
6170
$changesBlock = $matches[1].Trim().Split("`n")
62-
$changesBlock = ,"- ${currentBranch}: Added ${newLang} + ${newFramework}" + $changesBlock
71+
$changesBlock = ,"- $($paths.CURRENT_BRANCH): Added ${newLang} + ${newFramework}" + $changesBlock
6372
$changesBlock = $changesBlock | Where-Object { $_ } | Select-Object -First 3
6473
$joined = ($changesBlock -join "`n")
6574
$content = [regex]::Replace($content, '## Recent Changes\n([\s\S]*?)(\n\n|$)', "## Recent Changes`n$joined`n`n")

templates/plan-template.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ ios/ or android/
151151
- Quickstart test = story validation steps
152152

153153
5. **Update agent file incrementally** (O(1) operation):
154-
- Run `{SCRIPT}` for your AI assistant
154+
- Run `{SCRIPT}`
155+
**IMPORTANT**: Execute it exactly as specified above. Do not add or remove any arguments.
155156
- If exists: Add only NEW tech from current plan
156157
- Preserve manual additions between markers
157158
- Update recent changes (keep last 3)

0 commit comments

Comments
 (0)