@@ -24,8 +24,8 @@ Optional agent key to update a single agent. If omitted, updates all existing ag
2424Relies on common helper functions in common.ps1
2525#>
2626param (
27- [Parameter (Position = 0 )]
28- [ValidateSet (' claude' , ' gemini' , ' copilot' , ' cursor' , ' qwen' , ' opencode' , ' codex' , ' windsurf' , ' kilocode' , ' auggie' , ' roo' )]
27+ [Parameter (Position = 0 )]
28+ [ValidateSet (' claude' , ' gemini' , ' copilot' , ' cursor' , ' qwen' , ' opencode' , ' codex' , ' windsurf' , ' kilocode' , ' auggie' , ' roo' )]
2929 [string ]$AgentType
3030)
3131
@@ -37,23 +37,23 @@ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
3737
3838# Acquire environment paths
3939$envData = Get-FeaturePathsEnv
40- $REPO_ROOT = $envData.REPO_ROOT
40+ $REPO_ROOT = $envData.REPO_ROOT
4141$CURRENT_BRANCH = $envData.CURRENT_BRANCH
42- $HAS_GIT = $envData.HAS_GIT
43- $IMPL_PLAN = $envData.IMPL_PLAN
42+ $HAS_GIT = $envData.HAS_GIT
43+ $IMPL_PLAN = $envData.IMPL_PLAN
4444$NEW_PLAN = $IMPL_PLAN
4545
4646# Agent file paths
47- $CLAUDE_FILE = Join-Path $REPO_ROOT ' CLAUDE.md'
48- $GEMINI_FILE = Join-Path $REPO_ROOT ' GEMINI.md'
49- $COPILOT_FILE = Join-Path $REPO_ROOT ' .github/copilot-instructions.md'
50- $CURSOR_FILE = Join-Path $REPO_ROOT ' .cursor/rules/specify-rules.mdc'
51- $QWEN_FILE = Join-Path $REPO_ROOT ' QWEN.md'
52- $AGENTS_FILE = Join-Path $REPO_ROOT ' AGENTS.md'
47+ $CLAUDE_FILE = Join-Path $REPO_ROOT ' CLAUDE.md'
48+ $GEMINI_FILE = Join-Path $REPO_ROOT ' GEMINI.md'
49+ $COPILOT_FILE = Join-Path $REPO_ROOT ' .github/copilot-instructions.md'
50+ $CURSOR_FILE = Join-Path $REPO_ROOT ' .cursor/rules/specify-rules.mdc'
51+ $QWEN_FILE = Join-Path $REPO_ROOT ' QWEN.md'
52+ $AGENTS_FILE = Join-Path $REPO_ROOT ' AGENTS.md'
5353$WINDSURF_FILE = Join-Path $REPO_ROOT ' .windsurf/rules/specify-rules.md'
5454$KILOCODE_FILE = Join-Path $REPO_ROOT ' .kilocode/rules/specify-rules.md'
55- $AUGGIE_FILE = Join-Path $REPO_ROOT ' .augment/rules/specify-rules.md'
56- $ROO_FILE = Join-Path $REPO_ROOT ' .roo/rules/specify-rules.md'
55+ $AUGGIE_FILE = Join-Path $REPO_ROOT ' .augment/rules/specify-rules.md'
56+ $ROO_FILE = Join-Path $REPO_ROOT ' .roo/rules/specify-rules.md'
5757
5858$TEMPLATE_FILE = Join-Path $REPO_ROOT ' .specify/templates/agent-file-template.md'
5959
@@ -65,31 +65,31 @@ $script:NEW_PROJECT_TYPE = ''
6565
6666function Write-Info {
6767 param (
68- [Parameter (Mandatory = $true )]
68+ [Parameter (Mandatory = $true )]
6969 [string ]$Message
7070 )
7171 Write-Host " INFO: $Message "
7272}
7373
7474function Write-Success {
7575 param (
76- [Parameter (Mandatory = $true )]
76+ [Parameter (Mandatory = $true )]
7777 [string ]$Message
7878 )
7979 Write-Host " $ ( [char ]0x2713 ) $Message "
8080}
8181
8282function Write-WarningMsg {
8383 param (
84- [Parameter (Mandatory = $true )]
84+ [Parameter (Mandatory = $true )]
8585 [string ]$Message
8686 )
8787 Write-Warning $Message
8888}
8989
9090function Write-Err {
9191 param (
92- [Parameter (Mandatory = $true )]
92+ [Parameter (Mandatory = $true )]
9393 [string ]$Message
9494 )
9595 Write-Host " ERROR: $Message " - ForegroundColor Red
@@ -116,9 +116,9 @@ function Validate-Environment {
116116
117117function Extract-PlanField {
118118 param (
119- [Parameter (Mandatory = $true )]
119+ [Parameter (Mandatory = $true )]
120120 [string ]$FieldPattern ,
121- [Parameter (Mandatory = $true )]
121+ [Parameter (Mandatory = $true )]
122122 [string ]$PlanFile
123123 )
124124 if (-not (Test-Path $PlanFile )) { return ' ' }
@@ -127,21 +127,21 @@ function Extract-PlanField {
127127 Get-Content - LiteralPath $PlanFile - Encoding utf8 | ForEach-Object {
128128 if ($_ -match $regex ) {
129129 $val = $Matches [1 ].Trim()
130- if ($val -notin @ (' NEEDS CLARIFICATION' , ' N/A' )) { return $val }
130+ if ($val -notin @ (' NEEDS CLARIFICATION' , ' N/A' )) { return $val }
131131 }
132132 } | Select-Object - First 1
133133}
134134
135135function Parse-PlanData {
136136 param (
137- [Parameter (Mandatory = $true )]
137+ [Parameter (Mandatory = $true )]
138138 [string ]$PlanFile
139139 )
140140 if (-not (Test-Path $PlanFile )) { Write-Err " Plan file not found: $PlanFile " ; return $false }
141141 Write-Info " Parsing plan data from $PlanFile "
142- $script :NEW_LANG = Extract- PlanField - FieldPattern ' Language/Version' - PlanFile $PlanFile
143- $script :NEW_FRAMEWORK = Extract- PlanField - FieldPattern ' Primary Dependencies' - PlanFile $PlanFile
144- $script :NEW_DB = Extract- PlanField - FieldPattern ' Storage' - PlanFile $PlanFile
142+ $script :NEW_LANG = Extract- PlanField - FieldPattern ' Language/Version' - PlanFile $PlanFile
143+ $script :NEW_FRAMEWORK = Extract- PlanField - FieldPattern ' Primary Dependencies' - PlanFile $PlanFile
144+ $script :NEW_DB = Extract- PlanField - FieldPattern ' Storage' - PlanFile $PlanFile
145145 $script :NEW_PROJECT_TYPE = Extract- PlanField - FieldPattern ' Project Type' - PlanFile $PlanFile
146146
147147 if ($NEW_LANG ) { Write-Info " Found language: $NEW_LANG " } else { Write-WarningMsg ' No language information found in plan' }
@@ -153,54 +153,54 @@ function Parse-PlanData {
153153
154154function Format-TechnologyStack {
155155 param (
156- [Parameter (Mandatory = $false )]
156+ [Parameter (Mandatory = $false )]
157157 [string ]$Lang ,
158- [Parameter (Mandatory = $false )]
158+ [Parameter (Mandatory = $false )]
159159 [string ]$Framework
160160 )
161161 $parts = @ ()
162162 if ($Lang -and $Lang -ne ' NEEDS CLARIFICATION' ) { $parts += $Lang }
163- if ($Framework -and $Framework -notin @ (' NEEDS CLARIFICATION' , ' N/A' )) { $parts += $Framework }
163+ if ($Framework -and $Framework -notin @ (' NEEDS CLARIFICATION' , ' N/A' )) { $parts += $Framework }
164164 if (-not $parts ) { return ' ' }
165165 return ($parts -join ' + ' )
166166}
167167
168168function Get-ProjectStructure {
169169 param (
170- [Parameter (Mandatory = $false )]
170+ [Parameter (Mandatory = $false )]
171171 [string ]$ProjectType
172172 )
173173 if ($ProjectType -match ' web' ) { return " backend/`n frontend/`n tests/" } else { return " src/`n tests/" }
174174}
175175
176176function Get-CommandsForLanguage {
177177 param (
178- [Parameter (Mandatory = $false )]
178+ [Parameter (Mandatory = $false )]
179179 [string ]$Lang
180180 )
181181 switch - Regex ($Lang ) {
182- ' Python' { return " cd src; pytest; ruff check ." }
183- ' Rust' { return " cargo test; cargo clippy" }
184- ' JavaScript|TypeScript' { return " npm test; npm run lint" }
182+ ' Python' { return ' cd src; pytest; ruff check .' }
183+ ' Rust' { return ' cargo test; cargo clippy' }
184+ ' JavaScript|TypeScript' { return ' npm test; npm run lint' }
185185 default { return " # Add commands for $Lang " }
186186 }
187187}
188188
189189function Get-LanguageConventions {
190190 param (
191- [Parameter (Mandatory = $false )]
191+ [Parameter (Mandatory = $false )]
192192 [string ]$Lang
193193 )
194194 if ($Lang ) { " ${Lang} : Follow standard conventions" } else { ' General: Follow standard conventions' }
195195}
196196
197197function New-AgentFile {
198198 param (
199- [Parameter (Mandatory = $true )]
199+ [Parameter (Mandatory = $true )]
200200 [string ]$TargetFile ,
201- [Parameter (Mandatory = $true )]
201+ [Parameter (Mandatory = $true )]
202202 [string ]$ProjectName ,
203- [Parameter (Mandatory = $true )]
203+ [Parameter (Mandatory = $true )]
204204 [datetime ]$Date
205205 )
206206 if (-not (Test-Path $TEMPLATE_FILE )) { Write-Err " Template not found at $TEMPLATE_FILE " ; return $false }
@@ -216,11 +216,11 @@ function New-AgentFile {
216216 $escaped_branch = $CURRENT_BRANCH
217217
218218 $content = Get-Content - LiteralPath $temp - Raw - Encoding utf8
219- $content = $content -replace ' \[PROJECT NAME\]' , $ProjectName
220- $content = $content -replace ' \[DATE\]' , $Date.ToString (' yyyy-MM-dd' )
219+ $content = $content -replace ' \[PROJECT NAME\]' , $ProjectName
220+ $content = $content -replace ' \[DATE\]' , $Date.ToString (' yyyy-MM-dd' )
221221
222222 # Build the technology stack string safely
223- $techStackForTemplate = " "
223+ $techStackForTemplate = ' '
224224 if ($escaped_lang -and $escaped_framework ) {
225225 $techStackForTemplate = " - $escaped_lang + $escaped_framework ($escaped_branch )"
226226 } elseif ($escaped_lang ) {
@@ -229,16 +229,16 @@ function New-AgentFile {
229229 $techStackForTemplate = " - $escaped_framework ($escaped_branch )"
230230 }
231231
232- $content = $content -replace ' \[EXTRACTED FROM ALL PLAN.MD FILES\]' , $techStackForTemplate
232+ $content = $content -replace ' \[EXTRACTED FROM ALL PLAN.MD FILES\]' , $techStackForTemplate
233233 # For project structure we manually embed (keep newlines)
234234 $escapedStructure = [Regex ]::Escape($projectStructure )
235- $content = $content -replace ' \[ACTUAL STRUCTURE FROM PLANS\]' , $escapedStructure
235+ $content = $content -replace ' \[ACTUAL STRUCTURE FROM PLANS\]' , $escapedStructure
236236 # Replace escaped newlines placeholder after all replacements
237- $content = $content -replace ' \[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]' , $commands
238- $content = $content -replace ' \[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]' , $languageConventions
237+ $content = $content -replace ' \[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]' , $commands
238+ $content = $content -replace ' \[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]' , $languageConventions
239239
240240 # Build the recent changes string safely
241- $recentChangesForTemplate = " "
241+ $recentChangesForTemplate = ' '
242242 if ($escaped_lang -and $escaped_framework ) {
243243 $recentChangesForTemplate = " - ${escaped_branch} : Added ${escaped_lang} + ${escaped_framework} "
244244 } elseif ($escaped_lang ) {
@@ -247,9 +247,9 @@ function New-AgentFile {
247247 $recentChangesForTemplate = " - ${escaped_branch} : Added ${escaped_framework} "
248248 }
249249
250- $content = $content -replace ' \[LAST 3 FEATURES AND WHAT THEY ADDED\]' , $recentChangesForTemplate
250+ $content = $content -replace ' \[LAST 3 FEATURES AND WHAT THEY ADDED\]' , $recentChangesForTemplate
251251 # Convert literal \n sequences introduced by Escape to real newlines
252- $content = $content -replace ' \\n' , [Environment ]::NewLine
252+ $content = $content -replace ' \\n' , [Environment ]::NewLine
253253
254254 $parent = Split-Path - Parent $TargetFile
255255 if (-not (Test-Path $parent )) { New-Item - ItemType Directory - Path $parent | Out-Null }
@@ -260,9 +260,9 @@ function New-AgentFile {
260260
261261function Update-ExistingAgentFile {
262262 param (
263- [Parameter (Mandatory = $true )]
263+ [Parameter (Mandatory = $true )]
264264 [string ]$TargetFile ,
265- [Parameter (Mandatory = $true )]
265+ [Parameter (Mandatory = $true )]
266266 [datetime ]$Date
267267 )
268268 if (-not (Test-Path $TargetFile )) { return (New-AgentFile - TargetFile $TargetFile - ProjectName (Split-Path $REPO_ROOT - Leaf) - Date $Date ) }
@@ -275,21 +275,21 @@ function Update-ExistingAgentFile {
275275 $newTechEntries += " - $techStack ($CURRENT_BRANCH )"
276276 }
277277 }
278- if ($NEW_DB -and $NEW_DB -notin @ (' N/A' , ' NEEDS CLARIFICATION' )) {
278+ if ($NEW_DB -and $NEW_DB -notin @ (' N/A' , ' NEEDS CLARIFICATION' )) {
279279 $escapedDB = [Regex ]::Escape($NEW_DB )
280280 if (-not (Select-String - Pattern $escapedDB - Path $TargetFile - Quiet)) {
281281 $newTechEntries += " - $NEW_DB ($CURRENT_BRANCH )"
282282 }
283283 }
284284 $newChangeEntry = ' '
285285 if ($techStack ) { $newChangeEntry = " - ${CURRENT_BRANCH} : Added ${techStack} " }
286- elseif ($NEW_DB -and $NEW_DB -notin @ (' N/A' , ' NEEDS CLARIFICATION' )) { $newChangeEntry = " - ${CURRENT_BRANCH} : Added ${NEW_DB} " }
286+ elseif ($NEW_DB -and $NEW_DB -notin @ (' N/A' , ' NEEDS CLARIFICATION' )) { $newChangeEntry = " - ${CURRENT_BRANCH} : Added ${NEW_DB} " }
287287
288288 $lines = Get-Content - LiteralPath $TargetFile - Encoding utf8
289289 $output = New-Object System.Collections.Generic.List[string ]
290290 $inTech = $false ; $inChanges = $false ; $techAdded = $false ; $changeAdded = $false ; $existingChanges = 0
291291
292- for ($i = 0 ; $i -lt $lines.Count ; $i ++ ) {
292+ for ($i = 0 ; $i -lt $lines.Count ; $i ++ ) {
293293 $line = $lines [$i ]
294294 if ($line -eq ' ## Active Technologies' ) {
295295 $output.Add ($line )
@@ -316,7 +316,7 @@ function Update-ExistingAgentFile {
316316 continue
317317 }
318318 if ($line -match ' \*\*Last updated\*\*: .*\d{4}-\d{2}-\d{2}' ) {
319- $output.Add (($line -replace ' \d{4}-\d{2}-\d{2}' , $Date.ToString (' yyyy-MM-dd' )))
319+ $output.Add (($line -replace ' \d{4}-\d{2}-\d{2}' , $Date.ToString (' yyyy-MM-dd' )))
320320 continue
321321 }
322322 $output.Add ($line )
@@ -333,9 +333,9 @@ function Update-ExistingAgentFile {
333333
334334function Update-AgentFile {
335335 param (
336- [Parameter (Mandatory = $true )]
336+ [Parameter (Mandatory = $true )]
337337 [string ]$TargetFile ,
338- [Parameter (Mandatory = $true )]
338+ [Parameter (Mandatory = $true )]
339339 [string ]$AgentName
340340 )
341341 if (-not $TargetFile -or -not $AgentName ) { Write-Err ' Update-AgentFile requires TargetFile and AgentName' ; return $false }
@@ -361,38 +361,38 @@ function Update-AgentFile {
361361
362362function Update-SpecificAgent {
363363 param (
364- [Parameter (Mandatory = $true )]
364+ [Parameter (Mandatory = $true )]
365365 [string ]$Type
366366 )
367367 switch ($Type ) {
368- ' claude' { Update-AgentFile - TargetFile $CLAUDE_FILE - AgentName ' Claude Code' }
369- ' gemini' { Update-AgentFile - TargetFile $GEMINI_FILE - AgentName ' Gemini CLI' }
370- ' copilot' { Update-AgentFile - TargetFile $COPILOT_FILE - AgentName ' GitHub Copilot' }
371- ' cursor' { Update-AgentFile - TargetFile $CURSOR_FILE - AgentName ' Cursor IDE' }
372- ' qwen' { Update-AgentFile - TargetFile $QWEN_FILE - AgentName ' Qwen Code' }
373- ' opencode' { Update-AgentFile - TargetFile $AGENTS_FILE - AgentName ' opencode' }
374- ' codex' { Update-AgentFile - TargetFile $AGENTS_FILE - AgentName ' Codex CLI' }
368+ ' claude' { Update-AgentFile - TargetFile $CLAUDE_FILE - AgentName ' Claude Code' }
369+ ' gemini' { Update-AgentFile - TargetFile $GEMINI_FILE - AgentName ' Gemini CLI' }
370+ ' copilot' { Update-AgentFile - TargetFile $COPILOT_FILE - AgentName ' GitHub Copilot' }
371+ ' cursor' { Update-AgentFile - TargetFile $CURSOR_FILE - AgentName ' Cursor IDE' }
372+ ' qwen' { Update-AgentFile - TargetFile $QWEN_FILE - AgentName ' Qwen Code' }
373+ ' opencode' { Update-AgentFile - TargetFile $AGENTS_FILE - AgentName ' opencode' }
374+ ' codex' { Update-AgentFile - TargetFile $AGENTS_FILE - AgentName ' Codex CLI' }
375375 ' windsurf' { Update-AgentFile - TargetFile $WINDSURF_FILE - AgentName ' Windsurf' }
376376 ' kilocode' { Update-AgentFile - TargetFile $KILOCODE_FILE - AgentName ' Kilo Code' }
377- ' auggie' { Update-AgentFile - TargetFile $AUGGIE_FILE - AgentName ' Auggie CLI' }
378- ' roo' { Update-AgentFile - TargetFile $ROO_FILE - AgentName ' Roo Code' }
377+ ' auggie' { Update-AgentFile - TargetFile $AUGGIE_FILE - AgentName ' Auggie CLI' }
378+ ' roo' { Update-AgentFile - TargetFile $ROO_FILE - AgentName ' Roo Code' }
379379 default { Write-Err " Unknown agent type '$Type '" ; Write-Err ' Expected: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo' ; return $false }
380380 }
381381}
382382
383383function Update-AllExistingAgents {
384384 $found = $false
385385 $ok = $true
386- if (Test-Path $CLAUDE_FILE ) { if (-not (Update-AgentFile - TargetFile $CLAUDE_FILE - AgentName ' Claude Code' )) { $ok = $false }; $found = $true }
387- if (Test-Path $GEMINI_FILE ) { if (-not (Update-AgentFile - TargetFile $GEMINI_FILE - AgentName ' Gemini CLI' )) { $ok = $false }; $found = $true }
388- if (Test-Path $COPILOT_FILE ) { if (-not (Update-AgentFile - TargetFile $COPILOT_FILE - AgentName ' GitHub Copilot' )) { $ok = $false }; $found = $true }
389- if (Test-Path $CURSOR_FILE ) { if (-not (Update-AgentFile - TargetFile $CURSOR_FILE - AgentName ' Cursor IDE' )) { $ok = $false }; $found = $true }
390- if (Test-Path $QWEN_FILE ) { if (-not (Update-AgentFile - TargetFile $QWEN_FILE - AgentName ' Qwen Code' )) { $ok = $false }; $found = $true }
391- if (Test-Path $AGENTS_FILE ) { if (-not (Update-AgentFile - TargetFile $AGENTS_FILE - AgentName ' Codex/opencode' )) { $ok = $false }; $found = $true }
386+ if (Test-Path $CLAUDE_FILE ) { if (-not (Update-AgentFile - TargetFile $CLAUDE_FILE - AgentName ' Claude Code' )) { $ok = $false }; $found = $true }
387+ if (Test-Path $GEMINI_FILE ) { if (-not (Update-AgentFile - TargetFile $GEMINI_FILE - AgentName ' Gemini CLI' )) { $ok = $false }; $found = $true }
388+ if (Test-Path $COPILOT_FILE ) { if (-not (Update-AgentFile - TargetFile $COPILOT_FILE - AgentName ' GitHub Copilot' )) { $ok = $false }; $found = $true }
389+ if (Test-Path $CURSOR_FILE ) { if (-not (Update-AgentFile - TargetFile $CURSOR_FILE - AgentName ' Cursor IDE' )) { $ok = $false }; $found = $true }
390+ if (Test-Path $QWEN_FILE ) { if (-not (Update-AgentFile - TargetFile $QWEN_FILE - AgentName ' Qwen Code' )) { $ok = $false }; $found = $true }
391+ if (Test-Path $AGENTS_FILE ) { if (-not (Update-AgentFile - TargetFile $AGENTS_FILE - AgentName ' Codex/opencode' )) { $ok = $false }; $found = $true }
392392 if (Test-Path $WINDSURF_FILE ) { if (-not (Update-AgentFile - TargetFile $WINDSURF_FILE - AgentName ' Windsurf' )) { $ok = $false }; $found = $true }
393393 if (Test-Path $KILOCODE_FILE ) { if (-not (Update-AgentFile - TargetFile $KILOCODE_FILE - AgentName ' Kilo Code' )) { $ok = $false }; $found = $true }
394- if (Test-Path $AUGGIE_FILE ) { if (-not (Update-AgentFile - TargetFile $AUGGIE_FILE - AgentName ' Auggie CLI' )) { $ok = $false }; $found = $true }
395- if (Test-Path $ROO_FILE ) { if (-not (Update-AgentFile - TargetFile $ROO_FILE - AgentName ' Roo Code' )) { $ok = $false }; $found = $true }
394+ if (Test-Path $AUGGIE_FILE ) { if (-not (Update-AgentFile - TargetFile $AUGGIE_FILE - AgentName ' Auggie CLI' )) { $ok = $false }; $found = $true }
395+ if (Test-Path $ROO_FILE ) { if (-not (Update-AgentFile - TargetFile $ROO_FILE - AgentName ' Roo Code' )) { $ok = $false }; $found = $true }
396396 if (-not $found ) {
397397 Write-Info ' No existing agent files found, creating default Claude file...'
398398 if (-not (Update-AgentFile - TargetFile $CLAUDE_FILE - AgentName ' Claude Code' )) { $ok = $false }
@@ -418,8 +418,7 @@ function Main {
418418 if ($AgentType ) {
419419 Write-Info " Updating specific agent: $AgentType "
420420 if (-not (Update-SpecificAgent - Type $AgentType )) { $success = $false }
421- }
422- else {
421+ } else {
423422 Write-Info ' No agent specified, updating all existing agent files...'
424423 if (-not (Update-AllExistingAgents )) { $success = $false }
425424 }
0 commit comments