doit-toolkit-cli 0.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. doit_cli/__init__.py +1356 -0
  2. doit_cli/cli/__init__.py +26 -0
  3. doit_cli/cli/analytics_command.py +616 -0
  4. doit_cli/cli/context_command.py +213 -0
  5. doit_cli/cli/diagram_command.py +304 -0
  6. doit_cli/cli/fixit_command.py +641 -0
  7. doit_cli/cli/hooks_command.py +211 -0
  8. doit_cli/cli/init_command.py +613 -0
  9. doit_cli/cli/memory_command.py +293 -0
  10. doit_cli/cli/status_command.py +117 -0
  11. doit_cli/cli/sync_prompts_command.py +248 -0
  12. doit_cli/cli/validate_command.py +196 -0
  13. doit_cli/cli/verify_command.py +204 -0
  14. doit_cli/cli/workflow_mixin.py +224 -0
  15. doit_cli/cli/xref_command.py +555 -0
  16. doit_cli/formatters/__init__.py +8 -0
  17. doit_cli/formatters/base.py +38 -0
  18. doit_cli/formatters/json_formatter.py +126 -0
  19. doit_cli/formatters/markdown_formatter.py +97 -0
  20. doit_cli/formatters/rich_formatter.py +257 -0
  21. doit_cli/main.py +49 -0
  22. doit_cli/models/__init__.py +139 -0
  23. doit_cli/models/agent.py +74 -0
  24. doit_cli/models/analytics_models.py +384 -0
  25. doit_cli/models/context_config.py +464 -0
  26. doit_cli/models/crossref_models.py +182 -0
  27. doit_cli/models/diagram_models.py +363 -0
  28. doit_cli/models/fixit_models.py +355 -0
  29. doit_cli/models/hook_config.py +125 -0
  30. doit_cli/models/project.py +91 -0
  31. doit_cli/models/results.py +121 -0
  32. doit_cli/models/search_models.py +228 -0
  33. doit_cli/models/status_models.py +195 -0
  34. doit_cli/models/sync_models.py +146 -0
  35. doit_cli/models/template.py +77 -0
  36. doit_cli/models/validation_models.py +175 -0
  37. doit_cli/models/workflow_models.py +319 -0
  38. doit_cli/prompts/__init__.py +5 -0
  39. doit_cli/prompts/fixit_prompts.py +344 -0
  40. doit_cli/prompts/interactive.py +390 -0
  41. doit_cli/rules/__init__.py +5 -0
  42. doit_cli/rules/builtin_rules.py +160 -0
  43. doit_cli/services/__init__.py +79 -0
  44. doit_cli/services/agent_detector.py +168 -0
  45. doit_cli/services/analytics_service.py +218 -0
  46. doit_cli/services/architecture_generator.py +290 -0
  47. doit_cli/services/backup_service.py +204 -0
  48. doit_cli/services/config_loader.py +113 -0
  49. doit_cli/services/context_loader.py +1121 -0
  50. doit_cli/services/coverage_calculator.py +142 -0
  51. doit_cli/services/crossref_service.py +237 -0
  52. doit_cli/services/cycle_time_calculator.py +134 -0
  53. doit_cli/services/date_inferrer.py +349 -0
  54. doit_cli/services/diagram_service.py +337 -0
  55. doit_cli/services/drift_detector.py +109 -0
  56. doit_cli/services/entity_parser.py +301 -0
  57. doit_cli/services/er_diagram_generator.py +197 -0
  58. doit_cli/services/fixit_service.py +699 -0
  59. doit_cli/services/github_service.py +192 -0
  60. doit_cli/services/hook_manager.py +258 -0
  61. doit_cli/services/hook_validator.py +528 -0
  62. doit_cli/services/input_validator.py +322 -0
  63. doit_cli/services/memory_search.py +527 -0
  64. doit_cli/services/mermaid_validator.py +334 -0
  65. doit_cli/services/prompt_transformer.py +91 -0
  66. doit_cli/services/prompt_writer.py +133 -0
  67. doit_cli/services/query_interpreter.py +428 -0
  68. doit_cli/services/report_exporter.py +219 -0
  69. doit_cli/services/report_generator.py +256 -0
  70. doit_cli/services/requirement_parser.py +112 -0
  71. doit_cli/services/roadmap_summarizer.py +209 -0
  72. doit_cli/services/rule_engine.py +443 -0
  73. doit_cli/services/scaffolder.py +215 -0
  74. doit_cli/services/score_calculator.py +172 -0
  75. doit_cli/services/section_parser.py +204 -0
  76. doit_cli/services/spec_scanner.py +327 -0
  77. doit_cli/services/state_manager.py +355 -0
  78. doit_cli/services/status_reporter.py +143 -0
  79. doit_cli/services/task_parser.py +347 -0
  80. doit_cli/services/template_manager.py +710 -0
  81. doit_cli/services/template_reader.py +158 -0
  82. doit_cli/services/user_journey_generator.py +214 -0
  83. doit_cli/services/user_story_parser.py +232 -0
  84. doit_cli/services/validation_service.py +188 -0
  85. doit_cli/services/validator.py +232 -0
  86. doit_cli/services/velocity_tracker.py +173 -0
  87. doit_cli/services/workflow_engine.py +405 -0
  88. doit_cli/templates/agent-file-template.md +28 -0
  89. doit_cli/templates/checklist-template.md +39 -0
  90. doit_cli/templates/commands/doit.checkin.md +363 -0
  91. doit_cli/templates/commands/doit.constitution.md +187 -0
  92. doit_cli/templates/commands/doit.documentit.md +485 -0
  93. doit_cli/templates/commands/doit.fixit.md +181 -0
  94. doit_cli/templates/commands/doit.implementit.md +265 -0
  95. doit_cli/templates/commands/doit.planit.md +262 -0
  96. doit_cli/templates/commands/doit.reviewit.md +355 -0
  97. doit_cli/templates/commands/doit.roadmapit.md +368 -0
  98. doit_cli/templates/commands/doit.scaffoldit.md +458 -0
  99. doit_cli/templates/commands/doit.specit.md +521 -0
  100. doit_cli/templates/commands/doit.taskit.md +304 -0
  101. doit_cli/templates/commands/doit.testit.md +277 -0
  102. doit_cli/templates/config/context.yaml +134 -0
  103. doit_cli/templates/config/hooks.yaml +93 -0
  104. doit_cli/templates/config/validation-rules.yaml +64 -0
  105. doit_cli/templates/github-issue-templates/epic.yml +78 -0
  106. doit_cli/templates/github-issue-templates/feature.yml +116 -0
  107. doit_cli/templates/github-issue-templates/task.yml +129 -0
  108. doit_cli/templates/hooks/.gitkeep +0 -0
  109. doit_cli/templates/hooks/post-commit.sh +25 -0
  110. doit_cli/templates/hooks/post-merge.sh +75 -0
  111. doit_cli/templates/hooks/pre-commit.sh +17 -0
  112. doit_cli/templates/hooks/pre-push.sh +18 -0
  113. doit_cli/templates/memory/completed_roadmap.md +50 -0
  114. doit_cli/templates/memory/constitution.md +125 -0
  115. doit_cli/templates/memory/roadmap.md +61 -0
  116. doit_cli/templates/plan-template.md +146 -0
  117. doit_cli/templates/scripts/bash/check-prerequisites.sh +166 -0
  118. doit_cli/templates/scripts/bash/common.sh +156 -0
  119. doit_cli/templates/scripts/bash/create-new-feature.sh +297 -0
  120. doit_cli/templates/scripts/bash/setup-plan.sh +61 -0
  121. doit_cli/templates/scripts/bash/update-agent-context.sh +675 -0
  122. doit_cli/templates/scripts/powershell/check-prerequisites.ps1 +148 -0
  123. doit_cli/templates/scripts/powershell/common.ps1 +137 -0
  124. doit_cli/templates/scripts/powershell/create-new-feature.ps1 +283 -0
  125. doit_cli/templates/scripts/powershell/setup-plan.ps1 +61 -0
  126. doit_cli/templates/scripts/powershell/update-agent-context.ps1 +406 -0
  127. doit_cli/templates/spec-template.md +159 -0
  128. doit_cli/templates/tasks-template.md +313 -0
  129. doit_cli/templates/vscode-settings.json +14 -0
  130. doit_toolkit_cli-0.1.9.dist-info/METADATA +324 -0
  131. doit_toolkit_cli-0.1.9.dist-info/RECORD +134 -0
  132. doit_toolkit_cli-0.1.9.dist-info/WHEEL +4 -0
  133. doit_toolkit_cli-0.1.9.dist-info/entry_points.txt +2 -0
  134. doit_toolkit_cli-0.1.9.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,406 @@
1
+ #!/usr/bin/env pwsh
2
+ <#!
3
+ .SYNOPSIS
4
+ Update agent context files with information from plan.md (PowerShell version)
5
+
6
+ .DESCRIPTION
7
+ Mirrors the behavior of scripts/bash/update-agent-context.sh:
8
+ 1. Environment Validation
9
+ 2. Plan Data Extraction
10
+ 3. Agent File Management (create from template or update existing)
11
+ 4. Content Generation (technology stack, recent changes, timestamp)
12
+ 5. Multi-Agent Support (claude, copilot)
13
+
14
+ .PARAMETER AgentType
15
+ Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist).
16
+
17
+ .EXAMPLE
18
+ ./update-agent-context.ps1 -AgentType claude
19
+
20
+ .EXAMPLE
21
+ ./update-agent-context.ps1 # Updates all existing agent files
22
+
23
+ .NOTES
24
+ Relies on common helper functions in common.ps1
25
+ #>
26
+ param(
27
+ [Parameter(Position=0)]
28
+ [ValidateSet('claude','copilot')]
29
+ [string]$AgentType
30
+ )
31
+
32
+ $ErrorActionPreference = 'Stop'
33
+
34
+ # Import common helpers
35
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
36
+ . (Join-Path $ScriptDir 'common.ps1')
37
+
38
+ # Acquire environment paths
39
+ $envData = Get-FeaturePathsEnv
40
+ $REPO_ROOT = $envData.REPO_ROOT
41
+ $CURRENT_BRANCH = $envData.CURRENT_BRANCH
42
+ $HAS_GIT = $envData.HAS_GIT
43
+ $IMPL_PLAN = $envData.IMPL_PLAN
44
+ $NEW_PLAN = $IMPL_PLAN
45
+
46
+ # Agent file paths
47
+ $CLAUDE_FILE = Join-Path $REPO_ROOT 'CLAUDE.md'
48
+ $COPILOT_FILE = Join-Path $REPO_ROOT '.github/agents/copilot-instructions.md'
49
+
50
+ $TEMPLATE_FILE = Join-Path $REPO_ROOT '.doit/templates/agent-file-template.md'
51
+
52
+ # Parsed plan data placeholders
53
+ $script:NEW_LANG = ''
54
+ $script:NEW_FRAMEWORK = ''
55
+ $script:NEW_DB = ''
56
+ $script:NEW_PROJECT_TYPE = ''
57
+
58
+ function Write-Info {
59
+ param(
60
+ [Parameter(Mandatory=$true)]
61
+ [string]$Message
62
+ )
63
+ Write-Host "INFO: $Message"
64
+ }
65
+
66
+ function Write-Success {
67
+ param(
68
+ [Parameter(Mandatory=$true)]
69
+ [string]$Message
70
+ )
71
+ Write-Host "$([char]0x2713) $Message"
72
+ }
73
+
74
+ function Write-WarningMsg {
75
+ param(
76
+ [Parameter(Mandatory=$true)]
77
+ [string]$Message
78
+ )
79
+ Write-Warning $Message
80
+ }
81
+
82
+ function Write-Err {
83
+ param(
84
+ [Parameter(Mandatory=$true)]
85
+ [string]$Message
86
+ )
87
+ Write-Host "ERROR: $Message" -ForegroundColor Red
88
+ }
89
+
90
+ function Validate-Environment {
91
+ if (-not $CURRENT_BRANCH) {
92
+ Write-Err 'Unable to determine current feature'
93
+ if ($HAS_GIT) { Write-Info "Make sure you're on a feature branch" } else { Write-Info 'Set SPECIFY_FEATURE environment variable or create a feature first' }
94
+ exit 1
95
+ }
96
+ if (-not (Test-Path $NEW_PLAN)) {
97
+ Write-Err "No plan.md found at $NEW_PLAN"
98
+ Write-Info 'Ensure you are working on a feature with a corresponding spec directory'
99
+ if (-not $HAS_GIT) { Write-Info 'Use: $env:SPECIFY_FEATURE=your-feature-name or create a new feature first' }
100
+ exit 1
101
+ }
102
+ if (-not (Test-Path $TEMPLATE_FILE)) {
103
+ Write-Err "Template file not found at $TEMPLATE_FILE"
104
+ Write-Info 'Run specify init to scaffold .doit/templates, or add agent-file-template.md there.'
105
+ exit 1
106
+ }
107
+ }
108
+
109
+ function Extract-PlanField {
110
+ param(
111
+ [Parameter(Mandatory=$true)]
112
+ [string]$FieldPattern,
113
+ [Parameter(Mandatory=$true)]
114
+ [string]$PlanFile
115
+ )
116
+ if (-not (Test-Path $PlanFile)) { return '' }
117
+ # Lines like **Language/Version**: Python 3.12
118
+ $regex = "^\*\*$([Regex]::Escape($FieldPattern))\*\*: (.+)$"
119
+ Get-Content -LiteralPath $PlanFile -Encoding utf8 | ForEach-Object {
120
+ if ($_ -match $regex) {
121
+ $val = $Matches[1].Trim()
122
+ if ($val -notin @('NEEDS CLARIFICATION','N/A')) { return $val }
123
+ }
124
+ } | Select-Object -First 1
125
+ }
126
+
127
+ function Parse-PlanData {
128
+ param(
129
+ [Parameter(Mandatory=$true)]
130
+ [string]$PlanFile
131
+ )
132
+ if (-not (Test-Path $PlanFile)) { Write-Err "Plan file not found: $PlanFile"; return $false }
133
+ Write-Info "Parsing plan data from $PlanFile"
134
+ $script:NEW_LANG = Extract-PlanField -FieldPattern 'Language/Version' -PlanFile $PlanFile
135
+ $script:NEW_FRAMEWORK = Extract-PlanField -FieldPattern 'Primary Dependencies' -PlanFile $PlanFile
136
+ $script:NEW_DB = Extract-PlanField -FieldPattern 'Storage' -PlanFile $PlanFile
137
+ $script:NEW_PROJECT_TYPE = Extract-PlanField -FieldPattern 'Project Type' -PlanFile $PlanFile
138
+
139
+ if ($NEW_LANG) { Write-Info "Found language: $NEW_LANG" } else { Write-WarningMsg 'No language information found in plan' }
140
+ if ($NEW_FRAMEWORK) { Write-Info "Found framework: $NEW_FRAMEWORK" }
141
+ if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Info "Found database: $NEW_DB" }
142
+ if ($NEW_PROJECT_TYPE) { Write-Info "Found project type: $NEW_PROJECT_TYPE" }
143
+ return $true
144
+ }
145
+
146
+ function Format-TechnologyStack {
147
+ param(
148
+ [Parameter(Mandatory=$false)]
149
+ [string]$Lang,
150
+ [Parameter(Mandatory=$false)]
151
+ [string]$Framework
152
+ )
153
+ $parts = @()
154
+ if ($Lang -and $Lang -ne 'NEEDS CLARIFICATION') { $parts += $Lang }
155
+ if ($Framework -and $Framework -notin @('NEEDS CLARIFICATION','N/A')) { $parts += $Framework }
156
+ if (-not $parts) { return '' }
157
+ return ($parts -join ' + ')
158
+ }
159
+
160
+ function Get-ProjectStructure {
161
+ param(
162
+ [Parameter(Mandatory=$false)]
163
+ [string]$ProjectType
164
+ )
165
+ if ($ProjectType -match 'web') { return "backend/`nfrontend/`ntests/" } else { return "src/`ntests/" }
166
+ }
167
+
168
+ function Get-CommandsForLanguage {
169
+ param(
170
+ [Parameter(Mandatory=$false)]
171
+ [string]$Lang
172
+ )
173
+ switch -Regex ($Lang) {
174
+ 'Python' { return "cd src; pytest; ruff check ." }
175
+ 'Rust' { return "cargo test; cargo clippy" }
176
+ 'JavaScript|TypeScript' { return "npm test; npm run lint" }
177
+ default { return "# Add commands for $Lang" }
178
+ }
179
+ }
180
+
181
+ function Get-LanguageConventions {
182
+ param(
183
+ [Parameter(Mandatory=$false)]
184
+ [string]$Lang
185
+ )
186
+ if ($Lang) { "${Lang}: Follow standard conventions" } else { 'General: Follow standard conventions' }
187
+ }
188
+
189
+ function New-AgentFile {
190
+ param(
191
+ [Parameter(Mandatory=$true)]
192
+ [string]$TargetFile,
193
+ [Parameter(Mandatory=$true)]
194
+ [string]$ProjectName,
195
+ [Parameter(Mandatory=$true)]
196
+ [datetime]$Date
197
+ )
198
+ if (-not (Test-Path $TEMPLATE_FILE)) { Write-Err "Template not found at $TEMPLATE_FILE"; return $false }
199
+ $temp = New-TemporaryFile
200
+ Copy-Item -LiteralPath $TEMPLATE_FILE -Destination $temp -Force
201
+
202
+ $projectStructure = Get-ProjectStructure -ProjectType $NEW_PROJECT_TYPE
203
+ $commands = Get-CommandsForLanguage -Lang $NEW_LANG
204
+ $languageConventions = Get-LanguageConventions -Lang $NEW_LANG
205
+
206
+ $escaped_lang = $NEW_LANG
207
+ $escaped_framework = $NEW_FRAMEWORK
208
+ $escaped_branch = $CURRENT_BRANCH
209
+
210
+ $content = Get-Content -LiteralPath $temp -Raw -Encoding utf8
211
+ $content = $content -replace '\[PROJECT NAME\]',$ProjectName
212
+ $content = $content -replace '\[DATE\]',$Date.ToString('yyyy-MM-dd')
213
+
214
+ # Build the technology stack string safely
215
+ $techStackForTemplate = ""
216
+ if ($escaped_lang -and $escaped_framework) {
217
+ $techStackForTemplate = "- $escaped_lang + $escaped_framework ($escaped_branch)"
218
+ } elseif ($escaped_lang) {
219
+ $techStackForTemplate = "- $escaped_lang ($escaped_branch)"
220
+ } elseif ($escaped_framework) {
221
+ $techStackForTemplate = "- $escaped_framework ($escaped_branch)"
222
+ }
223
+
224
+ $content = $content -replace '\[EXTRACTED FROM ALL PLAN.MD FILES\]',$techStackForTemplate
225
+ # For project structure we manually embed (keep newlines)
226
+ $escapedStructure = [Regex]::Escape($projectStructure)
227
+ $content = $content -replace '\[ACTUAL STRUCTURE FROM PLANS\]',$escapedStructure
228
+ # Replace escaped newlines placeholder after all replacements
229
+ $content = $content -replace '\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]',$commands
230
+ $content = $content -replace '\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]',$languageConventions
231
+
232
+ # Build the recent changes string safely
233
+ $recentChangesForTemplate = ""
234
+ if ($escaped_lang -and $escaped_framework) {
235
+ $recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_lang} + ${escaped_framework}"
236
+ } elseif ($escaped_lang) {
237
+ $recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_lang}"
238
+ } elseif ($escaped_framework) {
239
+ $recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_framework}"
240
+ }
241
+
242
+ $content = $content -replace '\[LAST 3 FEATURES AND WHAT THEY ADDED\]',$recentChangesForTemplate
243
+ # Convert literal \n sequences introduced by Escape to real newlines
244
+ $content = $content -replace '\\n',[Environment]::NewLine
245
+
246
+ $parent = Split-Path -Parent $TargetFile
247
+ if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent | Out-Null }
248
+ Set-Content -LiteralPath $TargetFile -Value $content -NoNewline -Encoding utf8
249
+ Remove-Item $temp -Force
250
+ return $true
251
+ }
252
+
253
+ function Update-ExistingAgentFile {
254
+ param(
255
+ [Parameter(Mandatory=$true)]
256
+ [string]$TargetFile,
257
+ [Parameter(Mandatory=$true)]
258
+ [datetime]$Date
259
+ )
260
+ if (-not (Test-Path $TargetFile)) { return (New-AgentFile -TargetFile $TargetFile -ProjectName (Split-Path $REPO_ROOT -Leaf) -Date $Date) }
261
+
262
+ $techStack = Format-TechnologyStack -Lang $NEW_LANG -Framework $NEW_FRAMEWORK
263
+ $newTechEntries = @()
264
+ if ($techStack) {
265
+ $escapedTechStack = [Regex]::Escape($techStack)
266
+ if (-not (Select-String -Pattern $escapedTechStack -Path $TargetFile -Quiet)) {
267
+ $newTechEntries += "- $techStack ($CURRENT_BRANCH)"
268
+ }
269
+ }
270
+ if ($NEW_DB -and $NEW_DB -notin @('N/A','NEEDS CLARIFICATION')) {
271
+ $escapedDB = [Regex]::Escape($NEW_DB)
272
+ if (-not (Select-String -Pattern $escapedDB -Path $TargetFile -Quiet)) {
273
+ $newTechEntries += "- $NEW_DB ($CURRENT_BRANCH)"
274
+ }
275
+ }
276
+ $newChangeEntry = ''
277
+ if ($techStack) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${techStack}" }
278
+ elseif ($NEW_DB -and $NEW_DB -notin @('N/A','NEEDS CLARIFICATION')) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${NEW_DB}" }
279
+
280
+ $lines = Get-Content -LiteralPath $TargetFile -Encoding utf8
281
+ $output = New-Object System.Collections.Generic.List[string]
282
+ $inTech = $false; $inChanges = $false; $techAdded = $false; $changeAdded = $false; $existingChanges = 0
283
+
284
+ for ($i=0; $i -lt $lines.Count; $i++) {
285
+ $line = $lines[$i]
286
+ if ($line -eq '## Active Technologies') {
287
+ $output.Add($line)
288
+ $inTech = $true
289
+ continue
290
+ }
291
+ if ($inTech -and $line -match '^##\s') {
292
+ if (-not $techAdded -and $newTechEntries.Count -gt 0) { $newTechEntries | ForEach-Object { $output.Add($_) }; $techAdded = $true }
293
+ $output.Add($line); $inTech = $false; continue
294
+ }
295
+ if ($inTech -and [string]::IsNullOrWhiteSpace($line)) {
296
+ if (-not $techAdded -and $newTechEntries.Count -gt 0) { $newTechEntries | ForEach-Object { $output.Add($_) }; $techAdded = $true }
297
+ $output.Add($line); continue
298
+ }
299
+ if ($line -eq '## Recent Changes') {
300
+ $output.Add($line)
301
+ if ($newChangeEntry) { $output.Add($newChangeEntry); $changeAdded = $true }
302
+ $inChanges = $true
303
+ continue
304
+ }
305
+ if ($inChanges -and $line -match '^##\s') { $output.Add($line); $inChanges = $false; continue }
306
+ if ($inChanges -and $line -match '^- ') {
307
+ if ($existingChanges -lt 2) { $output.Add($line); $existingChanges++ }
308
+ continue
309
+ }
310
+ if ($line -match '\*\*Last updated\*\*: .*\d{4}-\d{2}-\d{2}') {
311
+ $output.Add(($line -replace '\d{4}-\d{2}-\d{2}',$Date.ToString('yyyy-MM-dd')))
312
+ continue
313
+ }
314
+ $output.Add($line)
315
+ }
316
+
317
+ # Post-loop check: if we're still in the Active Technologies section and haven't added new entries
318
+ if ($inTech -and -not $techAdded -and $newTechEntries.Count -gt 0) {
319
+ $newTechEntries | ForEach-Object { $output.Add($_) }
320
+ }
321
+
322
+ Set-Content -LiteralPath $TargetFile -Value ($output -join [Environment]::NewLine) -Encoding utf8
323
+ return $true
324
+ }
325
+
326
+ function Update-AgentFile {
327
+ param(
328
+ [Parameter(Mandatory=$true)]
329
+ [string]$TargetFile,
330
+ [Parameter(Mandatory=$true)]
331
+ [string]$AgentName
332
+ )
333
+ if (-not $TargetFile -or -not $AgentName) { Write-Err 'Update-AgentFile requires TargetFile and AgentName'; return $false }
334
+ Write-Info "Updating $AgentName context file: $TargetFile"
335
+ $projectName = Split-Path $REPO_ROOT -Leaf
336
+ $date = Get-Date
337
+
338
+ $dir = Split-Path -Parent $TargetFile
339
+ if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir | Out-Null }
340
+
341
+ if (-not (Test-Path $TargetFile)) {
342
+ if (New-AgentFile -TargetFile $TargetFile -ProjectName $projectName -Date $date) { Write-Success "Created new $AgentName context file" } else { Write-Err 'Failed to create new agent file'; return $false }
343
+ } else {
344
+ try {
345
+ if (Update-ExistingAgentFile -TargetFile $TargetFile -Date $date) { Write-Success "Updated existing $AgentName context file" } else { Write-Err 'Failed to update agent file'; return $false }
346
+ } catch {
347
+ Write-Err "Cannot access or update existing file: $TargetFile. $_"
348
+ return $false
349
+ }
350
+ }
351
+ return $true
352
+ }
353
+
354
+ function Update-SpecificAgent {
355
+ param(
356
+ [Parameter(Mandatory=$true)]
357
+ [string]$Type
358
+ )
359
+ switch ($Type) {
360
+ 'claude' { Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code' }
361
+ 'copilot' { Update-AgentFile -TargetFile $COPILOT_FILE -AgentName 'GitHub Copilot' }
362
+ default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|copilot'; return $false }
363
+ }
364
+ }
365
+
366
+ function Update-AllExistingAgents {
367
+ $found = $false
368
+ $ok = $true
369
+ if (Test-Path $CLAUDE_FILE) { if (-not (Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code')) { $ok = $false }; $found = $true }
370
+ if (Test-Path $COPILOT_FILE) { if (-not (Update-AgentFile -TargetFile $COPILOT_FILE -AgentName 'GitHub Copilot')) { $ok = $false }; $found = $true }
371
+ if (-not $found) {
372
+ Write-Info 'No existing agent files found, creating default Claude file...'
373
+ if (-not (Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code')) { $ok = $false }
374
+ }
375
+ return $ok
376
+ }
377
+
378
+ function Print-Summary {
379
+ Write-Host ''
380
+ Write-Info 'Summary of changes:'
381
+ if ($NEW_LANG) { Write-Host " - Added language: $NEW_LANG" }
382
+ if ($NEW_FRAMEWORK) { Write-Host " - Added framework: $NEW_FRAMEWORK" }
383
+ if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host " - Added database: $NEW_DB" }
384
+ Write-Host ''
385
+ Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|copilot]'
386
+ }
387
+
388
+ function Main {
389
+ Validate-Environment
390
+ Write-Info "=== Updating agent context files for feature $CURRENT_BRANCH ==="
391
+ if (-not (Parse-PlanData -PlanFile $NEW_PLAN)) { Write-Err 'Failed to parse plan data'; exit 1 }
392
+ $success = $true
393
+ if ($AgentType) {
394
+ Write-Info "Updating specific agent: $AgentType"
395
+ if (-not (Update-SpecificAgent -Type $AgentType)) { $success = $false }
396
+ }
397
+ else {
398
+ Write-Info 'No agent specified, updating all existing agent files...'
399
+ if (-not (Update-AllExistingAgents)) { $success = $false }
400
+ }
401
+ Print-Summary
402
+ if ($success) { Write-Success 'Agent context update completed successfully'; exit 0 } else { Write-Err 'Agent context update completed with errors'; exit 1 }
403
+ }
404
+
405
+ Main
406
+
@@ -0,0 +1,159 @@
1
+ # Feature Specification: [FEATURE NAME]
2
+
3
+ **Feature Branch**: `[###-feature-name]`
4
+ **Created**: [DATE]
5
+ **Status**: Draft
6
+ **Input**: User description: "$ARGUMENTS"
7
+
8
+ ## User Scenarios & Testing *(mandatory)*
9
+
10
+ <!--
11
+ IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance.
12
+ Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them,
13
+ you should still have a viable MVP (Minimum Viable Product) that delivers value.
14
+
15
+ Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical.
16
+ Think of each story as a standalone slice of functionality that can be:
17
+ - Developed independently
18
+ - Tested independently
19
+ - Deployed independently
20
+ - Demonstrated to users independently
21
+ -->
22
+
23
+ ### User Story 1 - [Brief Title] (Priority: P1)
24
+
25
+ [Describe this user journey in plain language]
26
+
27
+ **Why this priority**: [Explain the value and why it has this priority level]
28
+
29
+ **Independent Test**: [Describe how this can be tested independently - e.g., "Can be fully tested by [specific action] and delivers [specific value]"]
30
+
31
+ **Acceptance Scenarios**:
32
+
33
+ 1. **Given** [initial state], **When** [action], **Then** [expected outcome]
34
+ 2. **Given** [initial state], **When** [action], **Then** [expected outcome]
35
+
36
+ ---
37
+
38
+ ### User Story 2 - [Brief Title] (Priority: P2)
39
+
40
+ [Describe this user journey in plain language]
41
+
42
+ **Why this priority**: [Explain the value and why it has this priority level]
43
+
44
+ **Independent Test**: [Describe how this can be tested independently]
45
+
46
+ **Acceptance Scenarios**:
47
+
48
+ 1. **Given** [initial state], **When** [action], **Then** [expected outcome]
49
+
50
+ ---
51
+
52
+ ### User Story 3 - [Brief Title] (Priority: P3)
53
+
54
+ [Describe this user journey in plain language]
55
+
56
+ **Why this priority**: [Explain the value and why it has this priority level]
57
+
58
+ **Independent Test**: [Describe how this can be tested independently]
59
+
60
+ **Acceptance Scenarios**:
61
+
62
+ 1. **Given** [initial state], **When** [action], **Then** [expected outcome]
63
+
64
+ ---
65
+
66
+ [Add more user stories as needed, each with an assigned priority]
67
+
68
+ ### Edge Cases
69
+
70
+ <!--
71
+ ACTION REQUIRED: The content in this section represents placeholders.
72
+ Fill them out with the right edge cases.
73
+ -->
74
+
75
+ - What happens when [boundary condition]?
76
+ - How does system handle [error scenario]?
77
+
78
+ ## User Journey Visualization
79
+
80
+ <!--
81
+ AUTO-GENERATED: This section is populated by /doit.specit based on user stories above.
82
+ The flowchart shows each user story as a subgraph with key actions.
83
+ Regenerate by running /doit.specit again.
84
+ -->
85
+
86
+ <!-- BEGIN:AUTO-GENERATED section="user-journey" -->
87
+ ```mermaid
88
+ flowchart LR
89
+ subgraph "User Story 1 - [Title]"
90
+ US1_S[Start] --> US1_A[Action] --> US1_E[End]
91
+ end
92
+ subgraph "User Story 2 - [Title]"
93
+ US2_S[Start] --> US2_A[Action] --> US2_E[End]
94
+ end
95
+ ```
96
+ <!-- END:AUTO-GENERATED -->
97
+
98
+ ## Entity Relationships *(include if Key Entities defined)*
99
+
100
+ <!--
101
+ AUTO-GENERATED: This section is populated by /doit.specit when Key Entities are defined.
102
+ Shows entity relationships as an ER diagram.
103
+ If no entities are defined, this entire section should be omitted (not left empty).
104
+ -->
105
+
106
+ <!-- BEGIN:AUTO-GENERATED section="entity-relationships" -->
107
+ ```mermaid
108
+ erDiagram
109
+ ENTITY1 ||--o{ ENTITY2 : "relationship"
110
+
111
+ ENTITY1 {
112
+ string id PK
113
+ string name
114
+ }
115
+ ENTITY2 {
116
+ string id PK
117
+ string entity1_id FK
118
+ }
119
+ ```
120
+ <!-- END:AUTO-GENERATED -->
121
+
122
+ ## Requirements *(mandatory)*
123
+
124
+ <!--
125
+ ACTION REQUIRED: The content in this section represents placeholders.
126
+ Fill them out with the right functional requirements.
127
+ -->
128
+
129
+ ### Functional Requirements
130
+
131
+ - **FR-001**: System MUST [specific capability, e.g., "allow users to create accounts"]
132
+ - **FR-002**: System MUST [specific capability, e.g., "validate email addresses"]
133
+ - **FR-003**: Users MUST be able to [key interaction, e.g., "reset their password"]
134
+ - **FR-004**: System MUST [data requirement, e.g., "persist user preferences"]
135
+ - **FR-005**: System MUST [behavior, e.g., "log all security events"]
136
+
137
+ *Example of marking unclear requirements:*
138
+
139
+ - **FR-006**: System MUST authenticate users via [NEEDS CLARIFICATION: auth method not specified - email/password, SSO, OAuth?]
140
+ - **FR-007**: System MUST retain user data for [NEEDS CLARIFICATION: retention period not specified]
141
+
142
+ ### Key Entities *(include if feature involves data)*
143
+
144
+ - **[Entity 1]**: [What it represents, key attributes without implementation]
145
+ - **[Entity 2]**: [What it represents, relationships to other entities]
146
+
147
+ ## Success Criteria *(mandatory)*
148
+
149
+ <!--
150
+ ACTION REQUIRED: Define measurable success criteria.
151
+ These must be technology-agnostic and measurable.
152
+ -->
153
+
154
+ ### Measurable Outcomes
155
+
156
+ - **SC-001**: [Measurable metric, e.g., "Users can complete account creation in under 2 minutes"]
157
+ - **SC-002**: [Measurable metric, e.g., "System handles 1000 concurrent users without degradation"]
158
+ - **SC-003**: [User satisfaction metric, e.g., "90% of users successfully complete primary task on first attempt"]
159
+ - **SC-004**: [Business metric, e.g., "Reduce support tickets related to [X] by 50%"]