sedd 0.1.0
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.
- package/README.md +504 -0
- package/bin/sedd.js +6 -0
- package/commands/sedd.clarify.md +435 -0
- package/commands/sedd.dashboard.md +145 -0
- package/commands/sedd.implement.md +326 -0
- package/commands/sedd.migrate.md +249 -0
- package/commands/sedd.specify.md +198 -0
- package/commands/sedd.tasks.md +176 -0
- package/dist/cli/check.d.ts +6 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +134 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/clarify.d.ts +2 -0
- package/dist/cli/clarify.d.ts.map +1 -0
- package/dist/cli/clarify.js +116 -0
- package/dist/cli/clarify.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +175 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +9 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +236 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/migrate.d.ts +7 -0
- package/dist/cli/migrate.d.ts.map +1 -0
- package/dist/cli/migrate.js +197 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli/specify.d.ts +7 -0
- package/dist/cli/specify.d.ts.map +1 -0
- package/dist/cli/specify.js +131 -0
- package/dist/cli/specify.js.map +1 -0
- package/dist/cli/status.d.ts +6 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +118 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/tasks.d.ts +7 -0
- package/dist/cli/tasks.d.ts.map +1 -0
- package/dist/cli/tasks.js +165 -0
- package/dist/cli/tasks.js.map +1 -0
- package/dist/core/changelog.d.ts +30 -0
- package/dist/core/changelog.d.ts.map +1 -0
- package/dist/core/changelog.js +97 -0
- package/dist/core/changelog.js.map +1 -0
- package/dist/core/file-splitter.d.ts +39 -0
- package/dist/core/file-splitter.d.ts.map +1 -0
- package/dist/core/file-splitter.js +162 -0
- package/dist/core/file-splitter.js.map +1 -0
- package/dist/core/migration-manager.d.ts +76 -0
- package/dist/core/migration-manager.d.ts.map +1 -0
- package/dist/core/migration-manager.js +230 -0
- package/dist/core/migration-manager.js.map +1 -0
- package/dist/core/timestamps.d.ts +17 -0
- package/dist/core/timestamps.d.ts.map +1 -0
- package/dist/core/timestamps.js +37 -0
- package/dist/core/timestamps.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +102 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +83 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/git.d.ts +63 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +179 -0
- package/dist/utils/git.js.map +1 -0
- package/hooks/README.md +220 -0
- package/hooks/check-roadmap.js +231 -0
- package/hooks/check-roadmap.ps1 +343 -0
- package/package.json +60 -0
- package/scripts/bash/sedd-clarify.sh +142 -0
- package/scripts/bash/sedd-complete-task.sh +108 -0
- package/scripts/bash/sedd-specify.sh +147 -0
- package/scripts/powershell/sedd-clarify.ps1 +222 -0
- package/scripts/powershell/sedd-complete-task.ps1 +143 -0
- package/scripts/powershell/sedd-specify.ps1 +192 -0
- package/scripts/powershell/sedd-status.ps1 +153 -0
- package/scripts/powershell/sedd-tasks.ps1 +176 -0
- package/templates/changelog-template.md +6 -0
- package/templates/clarify-template.md +66 -0
- package/templates/config-template.json +20 -0
- package/templates/decisions-template.md +56 -0
- package/templates/interfaces-template.ts +131 -0
- package/templates/meta-template.json +12 -0
- package/templates/progress-template.md +61 -0
- package/templates/sedd.schema.json +95 -0
- package/templates/spec-template.md +114 -0
- package/templates/tasks-template.md +58 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
#!/usr/bin/env pwsh
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
SEDD Assertive Hook - UserPromptSubmit
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Forces skill activation and tracks migration tasks
|
|
7
|
+
#>
|
|
8
|
+
|
|
9
|
+
$ErrorActionPreference = 'SilentlyContinue'
|
|
10
|
+
|
|
11
|
+
#region Constants
|
|
12
|
+
|
|
13
|
+
$DEFAULT_CONFIG = @{
|
|
14
|
+
specsDir = '.sedd'
|
|
15
|
+
hooks = @{
|
|
16
|
+
assertive = $true
|
|
17
|
+
skills = @('langchain-expert', 'architecture-mapper', 'defect-analyzer')
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
$IGNORE_PATTERNS = @(
|
|
22
|
+
'^\/\w+',
|
|
23
|
+
'^\s*(oi|hi|hello|hey)\s*$',
|
|
24
|
+
'^\s*(obrigado|thanks?|thx)\s*$',
|
|
25
|
+
'^(sim|yes|no|não|ok|okay)\s*$',
|
|
26
|
+
'^\s*\?\s*$',
|
|
27
|
+
'^q\d+:',
|
|
28
|
+
'^(a|b|c|d|e)\s*$',
|
|
29
|
+
'^continue\s*$',
|
|
30
|
+
'^prossiga\s*$'
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
$SKILLS = @{
|
|
34
|
+
'langchain-expert' = @{
|
|
35
|
+
triggers = @(
|
|
36
|
+
'langchain', 'langgraph', 'agent', 'tool', 'graph', 'checkpoint',
|
|
37
|
+
'omniagent', 'subagent', '@langchain', 'stategraph',
|
|
38
|
+
'toolnode', 'basemessage', 'dynamicstructuredtool'
|
|
39
|
+
)
|
|
40
|
+
instruction = @"
|
|
41
|
+
[SKILL ACTIVATED: langchain-expert]
|
|
42
|
+
You MUST use the langchain-expert skill for this request.
|
|
43
|
+
Follow LangGraph 1.0+ patterns, check Context7 MCP for latest docs.
|
|
44
|
+
Key patterns: StateGraph, Annotation, ToolNode, DynamicStructuredTool, streamEvents.
|
|
45
|
+
"@
|
|
46
|
+
}
|
|
47
|
+
'architecture-mapper' = @{
|
|
48
|
+
triggers = @(
|
|
49
|
+
'arquitetura', 'architecture', 'estrutura', 'structure', 'mapear',
|
|
50
|
+
'flow', 'fluxo', 'diagram', 'onde fica', 'where is', 'como funciona', 'how does'
|
|
51
|
+
)
|
|
52
|
+
instruction = @"
|
|
53
|
+
[SKILL ACTIVATED: architecture-mapper]
|
|
54
|
+
You MUST map the architecture before answering.
|
|
55
|
+
Use Mermaid diagrams, identify related files, trace data flow.
|
|
56
|
+
"@
|
|
57
|
+
}
|
|
58
|
+
'defect-analyzer' = @{
|
|
59
|
+
triggers = @(
|
|
60
|
+
'bug', 'erro', 'error', 'não funciona', 'broken', 'fail',
|
|
61
|
+
'problema', 'issue', 'debug', 'crash', 'exception', 'fix'
|
|
62
|
+
)
|
|
63
|
+
instruction = @"
|
|
64
|
+
[SKILL ACTIVATED: defect-analyzer]
|
|
65
|
+
You MUST analyze the root cause systematically.
|
|
66
|
+
Check logs, trace execution path, identify failure point.
|
|
67
|
+
"@
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
$SEDD_COMMAND_PATTERNS = @(
|
|
72
|
+
@{ pattern = '(nova|new|criar|create).*(feature|funcionalidade)'; command = '/sedd.specify' }
|
|
73
|
+
@{ pattern = '(clarif|duvid|question|pergunt|requisit)'; command = '/sedd.clarify' }
|
|
74
|
+
@{ pattern = '(implement|execut|task|tarefa)'; command = '/sedd.implement' }
|
|
75
|
+
@{ pattern = '(migra|convert|antiga|legacy)'; command = '/sedd.migrate' }
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
#endregion
|
|
79
|
+
|
|
80
|
+
#region Functions
|
|
81
|
+
|
|
82
|
+
function Get-SeddConfig {
|
|
83
|
+
param([string]$Cwd)
|
|
84
|
+
|
|
85
|
+
$configPath = Join-Path $Cwd 'sedd.config.json'
|
|
86
|
+
if (-not (Test-Path $configPath)) { return $DEFAULT_CONFIG }
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
$userConfig = Get-Content $configPath -Raw | ConvertFrom-Json -AsHashtable
|
|
90
|
+
$merged = $DEFAULT_CONFIG.Clone()
|
|
91
|
+
foreach ($key in $userConfig.Keys) {
|
|
92
|
+
$merged[$key] = $userConfig[$key]
|
|
93
|
+
}
|
|
94
|
+
return $merged
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return $DEFAULT_CONFIG
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function Get-CurrentBranch {
|
|
102
|
+
param([string]$Cwd)
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
Push-Location $Cwd
|
|
106
|
+
$branch = (git rev-parse --abbrev-ref HEAD 2>$null)
|
|
107
|
+
Pop-Location
|
|
108
|
+
return if ($branch) { $branch.Trim() } else { '' }
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return ''
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function Test-FeatureBranch {
|
|
116
|
+
param([string]$Branch)
|
|
117
|
+
return $Branch -match '^\d{3}-'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function Test-ShouldIgnorePrompt {
|
|
121
|
+
param([string]$Prompt)
|
|
122
|
+
|
|
123
|
+
foreach ($pattern in $IGNORE_PATTERNS) {
|
|
124
|
+
if ($Prompt -match $pattern) { return $true }
|
|
125
|
+
}
|
|
126
|
+
return $false
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function Get-ActiveSkills {
|
|
130
|
+
param([string]$PromptLower)
|
|
131
|
+
|
|
132
|
+
$active = @()
|
|
133
|
+
foreach ($skillName in $SKILLS.Keys) {
|
|
134
|
+
$skill = $SKILLS[$skillName]
|
|
135
|
+
foreach ($trigger in $skill.triggers) {
|
|
136
|
+
if ($PromptLower.Contains($trigger)) {
|
|
137
|
+
$active += @{ name = $skillName; instruction = $skill.instruction }
|
|
138
|
+
break
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return $active
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function Get-SeddCommandSuggestions {
|
|
146
|
+
param([string]$PromptLower)
|
|
147
|
+
|
|
148
|
+
$suggestions = @()
|
|
149
|
+
foreach ($item in $SEDD_COMMAND_PATTERNS) {
|
|
150
|
+
if ($PromptLower -match $item.pattern) {
|
|
151
|
+
$suggestions += $item.command
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return $suggestions
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function Get-TasksFromContent {
|
|
158
|
+
param(
|
|
159
|
+
[string]$Content,
|
|
160
|
+
[string]$MigrationId
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
$pending = @()
|
|
164
|
+
$completed = 0
|
|
165
|
+
|
|
166
|
+
foreach ($line in ($Content -split "`n")) {
|
|
167
|
+
if ($line -match '^\s*-\s*\[\s*\]\s*(T\d{3}-\d{3})\s+(.+)') {
|
|
168
|
+
$pending += @{
|
|
169
|
+
id = $Matches[1]
|
|
170
|
+
migration = $MigrationId
|
|
171
|
+
text = ($Matches[2] -replace '`[^`]+`', '').Trim()
|
|
172
|
+
}
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
175
|
+
if ($line -match '^\s*-\s*\[x\]\s*T\d{3}-\d{3}') {
|
|
176
|
+
$completed++
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return @{ pending = $pending; completed = $completed }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function Get-TasksFromMigrations {
|
|
184
|
+
param(
|
|
185
|
+
[string]$FeatureDir,
|
|
186
|
+
[object]$MetaData
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
$allPending = @()
|
|
190
|
+
$totalCompleted = 0
|
|
191
|
+
|
|
192
|
+
foreach ($migId in $MetaData.migrations.PSObject.Properties.Name) {
|
|
193
|
+
$migInfo = $MetaData.migrations.$migId
|
|
194
|
+
$tasksFile = Join-Path $FeatureDir "$($migInfo.folder)/tasks.md"
|
|
195
|
+
|
|
196
|
+
if (-not (Test-Path $tasksFile)) { continue }
|
|
197
|
+
|
|
198
|
+
$content = Get-Content $tasksFile -Raw
|
|
199
|
+
$result = Get-TasksFromContent -Content $content -MigrationId $migId
|
|
200
|
+
$allPending += $result.pending
|
|
201
|
+
$totalCompleted += $result.completed
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return @{ pending = $allPending; completed = $totalCompleted }
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function Get-TasksFromLegacy {
|
|
208
|
+
param([string]$FeatureDir)
|
|
209
|
+
|
|
210
|
+
$tasksFile = Join-Path $FeatureDir 'tasks.md'
|
|
211
|
+
if (-not (Test-Path $tasksFile)) {
|
|
212
|
+
return @{ pending = @(); completed = 0 }
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
$content = Get-Content $tasksFile -Raw
|
|
216
|
+
return Get-TasksFromContent -Content $content -MigrationId $null
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function Find-FeatureDir {
|
|
220
|
+
param(
|
|
221
|
+
[string]$Cwd,
|
|
222
|
+
[string]$SpecsDir,
|
|
223
|
+
[string]$Branch
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
$primaryDir = Join-Path $Cwd "$SpecsDir/$Branch"
|
|
227
|
+
if (Test-Path $primaryDir) { return $primaryDir }
|
|
228
|
+
|
|
229
|
+
$legacyDir = Join-Path $Cwd "specs/$Branch"
|
|
230
|
+
if (Test-Path $legacyDir) { return $legacyDir }
|
|
231
|
+
|
|
232
|
+
return $null
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function Build-SeddContext {
|
|
236
|
+
param(
|
|
237
|
+
[string]$Branch,
|
|
238
|
+
[string]$CurrentMigration,
|
|
239
|
+
[int]$Completed,
|
|
240
|
+
[array]$Pending
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
if ($Pending.Count -eq 0) { return $null }
|
|
244
|
+
|
|
245
|
+
$total = $Completed + $Pending.Count
|
|
246
|
+
$migrationInfo = if ($CurrentMigration) { " | Migration: $CurrentMigration" } else { '' }
|
|
247
|
+
|
|
248
|
+
$tasksList = ($Pending | Select-Object -First 5 | ForEach-Object {
|
|
249
|
+
$text = if ($_.text.Length -gt 60) { $_.text.Substring(0, 60) + '...' } else { $_.text }
|
|
250
|
+
"- $($_.id): $text"
|
|
251
|
+
}) -join "`n"
|
|
252
|
+
|
|
253
|
+
$moreText = if ($Pending.Count -gt 5) { "`n... and $($Pending.Count - 5) more" } else { '' }
|
|
254
|
+
|
|
255
|
+
return @"
|
|
256
|
+
<sedd-context>
|
|
257
|
+
**Branch: $Branch**$migrationInfo | Progress: $Completed/$total tasks
|
|
258
|
+
|
|
259
|
+
Pending tasks:
|
|
260
|
+
$tasksList$moreText
|
|
261
|
+
|
|
262
|
+
Use ``/sedd.implement`` to execute tasks.
|
|
263
|
+
</sedd-context>
|
|
264
|
+
"@
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
#endregion
|
|
268
|
+
|
|
269
|
+
#region Main
|
|
270
|
+
|
|
271
|
+
function Main {
|
|
272
|
+
try {
|
|
273
|
+
$inputJson = [Console]::In.ReadToEnd()
|
|
274
|
+
if (-not $inputJson) { return }
|
|
275
|
+
|
|
276
|
+
$inputData = $inputJson | ConvertFrom-Json
|
|
277
|
+
$prompt = $inputData.prompt
|
|
278
|
+
$cwd = if ($inputData.cwd) { $inputData.cwd } else { Get-Location }
|
|
279
|
+
|
|
280
|
+
if (-not $prompt) { return }
|
|
281
|
+
if (Test-ShouldIgnorePrompt -Prompt $prompt) { return }
|
|
282
|
+
|
|
283
|
+
$config = Get-SeddConfig -Cwd $cwd
|
|
284
|
+
$specsDir = if ($config.specsDir) { $config.specsDir } else { '.sedd' }
|
|
285
|
+
$promptLower = $prompt.ToLower()
|
|
286
|
+
$parts = @()
|
|
287
|
+
|
|
288
|
+
# Detect and force skills
|
|
289
|
+
$activeSkills = Get-ActiveSkills -PromptLower $promptLower
|
|
290
|
+
if ($activeSkills.Count -gt 0) {
|
|
291
|
+
$instructions = ($activeSkills | ForEach-Object { $_.instruction }) -join "`n`n"
|
|
292
|
+
$parts += "<forced-skills>`n$instructions`n</forced-skills>"
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
# Check feature branch and tasks
|
|
296
|
+
$branch = Get-CurrentBranch -Cwd $cwd
|
|
297
|
+
if (Test-FeatureBranch -Branch $branch) {
|
|
298
|
+
$featureDir = Find-FeatureDir -Cwd $cwd -SpecsDir $specsDir -Branch $branch
|
|
299
|
+
|
|
300
|
+
if ($featureDir) {
|
|
301
|
+
$metaFile = Join-Path $featureDir '_meta.json'
|
|
302
|
+
$pending = @()
|
|
303
|
+
$completed = 0
|
|
304
|
+
$currentMigration = $null
|
|
305
|
+
|
|
306
|
+
if (Test-Path $metaFile) {
|
|
307
|
+
$metaData = Get-Content $metaFile -Raw | ConvertFrom-Json
|
|
308
|
+
$currentMigration = $metaData.currentMigration
|
|
309
|
+
$result = Get-TasksFromMigrations -FeatureDir $featureDir -MetaData $metaData
|
|
310
|
+
$pending = $result.pending
|
|
311
|
+
$completed = $result.completed
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
$result = Get-TasksFromLegacy -FeatureDir $featureDir
|
|
315
|
+
$pending = $result.pending
|
|
316
|
+
$completed = $result.completed
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
$context = Build-SeddContext -Branch $branch -CurrentMigration $currentMigration -Completed $completed -Pending $pending
|
|
320
|
+
if ($context) { $parts += $context }
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
# Suggest SEDD commands
|
|
325
|
+
$suggestions = Get-SeddCommandSuggestions -PromptLower $promptLower
|
|
326
|
+
if ($suggestions.Count -gt 0 -and -not $prompt.StartsWith('/sedd')) {
|
|
327
|
+
$parts += "<sedd-hint>Consider using: $($suggestions -join ', ')</sedd-hint>"
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
# Output
|
|
331
|
+
if ($parts.Count -gt 0) {
|
|
332
|
+
$output = @{ systemMessage = "`n" + ($parts -join "`n`n") + "`n" }
|
|
333
|
+
Write-Output ($output | ConvertTo-Json -Compress)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
# Silent exit on errors
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
Main
|
|
342
|
+
|
|
343
|
+
#endregion
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sedd",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SEDD - Spec & Expectation Driven Development. A phase-based specification workflow for AI-assisted development.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"sedd": "bin/sedd.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"bin",
|
|
14
|
+
"templates",
|
|
15
|
+
"commands",
|
|
16
|
+
"scripts",
|
|
17
|
+
"hooks"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"specification",
|
|
27
|
+
"driven-development",
|
|
28
|
+
"ai-coding",
|
|
29
|
+
"claude",
|
|
30
|
+
"cursor",
|
|
31
|
+
"copilot",
|
|
32
|
+
"llm",
|
|
33
|
+
"workflow",
|
|
34
|
+
"cli"
|
|
35
|
+
],
|
|
36
|
+
"author": "Kelvin R.C",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"homepage": "https://github.com/goldensrazer/sedd#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/goldensrazer/sedd/issues"
|
|
41
|
+
},
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/goldensrazer/sedd.git"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"chalk": "^5.3.0",
|
|
51
|
+
"commander": "^12.1.0",
|
|
52
|
+
"glob": "^10.3.10",
|
|
53
|
+
"inquirer": "^9.2.12"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/inquirer": "^9.0.7",
|
|
57
|
+
"@types/node": "^20.10.0",
|
|
58
|
+
"typescript": "^5.5.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SEDD Clarify - Creates a new migration with clarify/tasks/decisions files
|
|
3
|
+
# Usage: ./sedd-clarify.sh [branch]
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
BRANCH="${1:-$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo '')}"
|
|
8
|
+
|
|
9
|
+
if [[ ! "$BRANCH" =~ ^[0-9]{3}- ]]; then
|
|
10
|
+
echo "Error: Not on a feature branch (current: $BRANCH)"
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
# Load config
|
|
15
|
+
SPECS_DIR=".sedd"
|
|
16
|
+
if [ -f "sedd.config.json" ]; then
|
|
17
|
+
SPECS_DIR=$(grep -o '"specsDir"[[:space:]]*:[[:space:]]*"[^"]*"' sedd.config.json | cut -d'"' -f4)
|
|
18
|
+
[ -z "$SPECS_DIR" ] && SPECS_DIR=".sedd"
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Find feature directory
|
|
22
|
+
FEATURE_DIR="${SPECS_DIR}/${BRANCH}"
|
|
23
|
+
[ ! -d "$FEATURE_DIR" ] && FEATURE_DIR="specs/${BRANCH}"
|
|
24
|
+
|
|
25
|
+
if [ ! -d "$FEATURE_DIR" ]; then
|
|
26
|
+
echo "Error: Feature directory not found for branch: $BRANCH"
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# Check meta
|
|
31
|
+
META_PATH="$FEATURE_DIR/_meta.json"
|
|
32
|
+
if [ ! -f "$META_PATH" ]; then
|
|
33
|
+
echo "Error: _meta.json not found. Run /sedd.specify first."
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Get next migration ID
|
|
38
|
+
get_next_migration_id() {
|
|
39
|
+
local max_id=0
|
|
40
|
+
if command -v jq &> /dev/null; then
|
|
41
|
+
max_id=$(jq -r '.migrations | keys | map(tonumber) | max // 0' "$META_PATH")
|
|
42
|
+
else
|
|
43
|
+
# Fallback without jq
|
|
44
|
+
max_id=$(grep -oP '"id":\s*"\K[0-9]+' "$META_PATH" | sort -n | tail -1)
|
|
45
|
+
[ -z "$max_id" ] && max_id=0
|
|
46
|
+
fi
|
|
47
|
+
printf "%03d" $((max_id + 1))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
MIGRATION_ID=$(get_next_migration_id)
|
|
51
|
+
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
|
|
52
|
+
MIGRATION_FOLDER="${MIGRATION_ID}_${TIMESTAMP}"
|
|
53
|
+
MIGRATION_DIR="$FEATURE_DIR/$MIGRATION_FOLDER"
|
|
54
|
+
|
|
55
|
+
# Create migration directory
|
|
56
|
+
mkdir -p "$MIGRATION_DIR"
|
|
57
|
+
echo "Created migration: $MIGRATION_FOLDER"
|
|
58
|
+
|
|
59
|
+
# Get current migration for parent reference
|
|
60
|
+
CURRENT_MIGRATION=$(grep -oP '"currentMigration":\s*"\K[^"]+' "$META_PATH" 2>/dev/null || echo "")
|
|
61
|
+
|
|
62
|
+
# Create clarify.md
|
|
63
|
+
cat > "$MIGRATION_DIR/clarify.md" << EOF
|
|
64
|
+
# Clarification Session - Migration $MIGRATION_ID
|
|
65
|
+
|
|
66
|
+
**Timestamp:** $(date +"%Y-%m-%d %H:%M:%S")
|
|
67
|
+
**Branch:** $BRANCH
|
|
68
|
+
|
|
69
|
+
## Questions & Answers
|
|
70
|
+
|
|
71
|
+
<!-- Questions discussed during this clarification session -->
|
|
72
|
+
|
|
73
|
+
EOF
|
|
74
|
+
echo "Created: clarify.md"
|
|
75
|
+
|
|
76
|
+
# Create decisions.md
|
|
77
|
+
cat > "$MIGRATION_DIR/decisions.md" << EOF
|
|
78
|
+
# Decisions - Migration $MIGRATION_ID
|
|
79
|
+
|
|
80
|
+
**Timestamp:** $(date +"%Y-%m-%d %H:%M:%S")
|
|
81
|
+
|
|
82
|
+
## Decisions Made
|
|
83
|
+
|
|
84
|
+
| # | Decision | Rationale |
|
|
85
|
+
|---|----------|-----------|
|
|
86
|
+
|
|
87
|
+
EOF
|
|
88
|
+
echo "Created: decisions.md"
|
|
89
|
+
|
|
90
|
+
# Create tasks.md
|
|
91
|
+
cat > "$MIGRATION_DIR/tasks.md" << EOF
|
|
92
|
+
# Tasks - Migration $MIGRATION_ID
|
|
93
|
+
|
|
94
|
+
**Migration:** $MIGRATION_ID
|
|
95
|
+
**Timestamp:** $TIMESTAMP
|
|
96
|
+
**Parent:** ${CURRENT_MIGRATION:-none}
|
|
97
|
+
|
|
98
|
+
## Tasks
|
|
99
|
+
|
|
100
|
+
<!-- Tasks will be added here by /sedd.tasks -->
|
|
101
|
+
<!-- Format: - [ ] T${MIGRATION_ID}-001 [US1] Task description -->
|
|
102
|
+
|
|
103
|
+
EOF
|
|
104
|
+
echo "Created: tasks.md"
|
|
105
|
+
|
|
106
|
+
# Update _meta.json (simplified without jq)
|
|
107
|
+
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
108
|
+
|
|
109
|
+
if command -v jq &> /dev/null; then
|
|
110
|
+
# With jq
|
|
111
|
+
jq --arg id "$MIGRATION_ID" \
|
|
112
|
+
--arg ts "$TIMESTAMP" \
|
|
113
|
+
--arg folder "$MIGRATION_FOLDER" \
|
|
114
|
+
--arg parent "$CURRENT_MIGRATION" \
|
|
115
|
+
--arg now "$NOW" \
|
|
116
|
+
'.currentMigration = $id |
|
|
117
|
+
.migrations[$id] = {
|
|
118
|
+
"id": $id,
|
|
119
|
+
"timestamp": $ts,
|
|
120
|
+
"folder": $folder,
|
|
121
|
+
"parent": (if $parent == "" then null else $parent end),
|
|
122
|
+
"status": "pending",
|
|
123
|
+
"tasksTotal": 0,
|
|
124
|
+
"tasksCompleted": 0,
|
|
125
|
+
"createdAt": $now
|
|
126
|
+
}' "$META_PATH" > "$META_PATH.tmp" && mv "$META_PATH.tmp" "$META_PATH"
|
|
127
|
+
else
|
|
128
|
+
echo "Warning: jq not found. Please update _meta.json manually."
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
echo "Updated: _meta.json"
|
|
132
|
+
|
|
133
|
+
echo ""
|
|
134
|
+
echo "Migration $MIGRATION_ID created successfully!"
|
|
135
|
+
echo "Next steps:"
|
|
136
|
+
echo " 1. Add questions/answers to clarify.md"
|
|
137
|
+
echo " 2. Document decisions in decisions.md"
|
|
138
|
+
echo " 3. Run /sedd.tasks to generate tasks"
|
|
139
|
+
|
|
140
|
+
# Output JSON
|
|
141
|
+
echo "---SEDD-OUTPUT---"
|
|
142
|
+
echo "{\"success\":true,\"migrationId\":\"$MIGRATION_ID\",\"migrationFolder\":\"$MIGRATION_FOLDER\",\"migrationDir\":\"$MIGRATION_DIR\",\"files\":[\"clarify.md\",\"decisions.md\",\"tasks.md\"]}"
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SEDD Complete Task - Marks a task as completed
|
|
3
|
+
# Usage: ./sedd-complete-task.sh <task_id>
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
TASK_ID="$1"
|
|
8
|
+
|
|
9
|
+
if [ -z "$TASK_ID" ]; then
|
|
10
|
+
echo "Usage: ./sedd-complete-task.sh <task_id>"
|
|
11
|
+
echo "Example: ./sedd-complete-task.sh T001-001"
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# Validate task ID format
|
|
16
|
+
if [[ ! "$TASK_ID" =~ ^T([0-9]{3})-([0-9]{3})$ ]]; then
|
|
17
|
+
echo "Error: Invalid task ID format. Expected: T001-001"
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
MIG_ID="${BASH_REMATCH[1]}"
|
|
22
|
+
|
|
23
|
+
# Get current branch
|
|
24
|
+
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo '')
|
|
25
|
+
|
|
26
|
+
if [[ ! "$BRANCH" =~ ^[0-9]{3}- ]]; then
|
|
27
|
+
echo "Error: Not on a feature branch"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Load config
|
|
32
|
+
SPECS_DIR=".sedd"
|
|
33
|
+
if [ -f "sedd.config.json" ]; then
|
|
34
|
+
SPECS_DIR=$(grep -o '"specsDir"[[:space:]]*:[[:space:]]*"[^"]*"' sedd.config.json | cut -d'"' -f4)
|
|
35
|
+
[ -z "$SPECS_DIR" ] && SPECS_DIR=".sedd"
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Find feature directory
|
|
39
|
+
FEATURE_DIR="${SPECS_DIR}/${BRANCH}"
|
|
40
|
+
[ ! -d "$FEATURE_DIR" ] && FEATURE_DIR="specs/${BRANCH}"
|
|
41
|
+
|
|
42
|
+
if [ ! -d "$FEATURE_DIR" ]; then
|
|
43
|
+
echo "Error: Feature not found: $BRANCH"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Load meta
|
|
48
|
+
META_PATH="$FEATURE_DIR/_meta.json"
|
|
49
|
+
if [ ! -f "$META_PATH" ]; then
|
|
50
|
+
echo "Error: _meta.json not found"
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Find migration folder
|
|
55
|
+
MIG_FOLDER=$(grep -oP "\"folder\":\s*\"${MIG_ID}_[^\"]+\"" "$META_PATH" | cut -d'"' -f4)
|
|
56
|
+
|
|
57
|
+
if [ -z "$MIG_FOLDER" ]; then
|
|
58
|
+
echo "Error: Migration $MIG_ID not found"
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
TASKS_FILE="$FEATURE_DIR/$MIG_FOLDER/tasks.md"
|
|
63
|
+
|
|
64
|
+
if [ ! -f "$TASKS_FILE" ]; then
|
|
65
|
+
echo "Error: tasks.md not found"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Check if already completed
|
|
70
|
+
if grep -q "\[x\] $TASK_ID" "$TASKS_FILE"; then
|
|
71
|
+
echo "Task $TASK_ID is already completed"
|
|
72
|
+
exit 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Check if task exists
|
|
76
|
+
if ! grep -q "\[ \] $TASK_ID" "$TASKS_FILE"; then
|
|
77
|
+
echo "Error: Task $TASK_ID not found"
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Mark as complete
|
|
82
|
+
sed -i "s/\[ \] $TASK_ID/[x] $TASK_ID/g" "$TASKS_FILE"
|
|
83
|
+
echo "Completed: $TASK_ID"
|
|
84
|
+
|
|
85
|
+
# Update meta (requires jq)
|
|
86
|
+
if command -v jq &> /dev/null; then
|
|
87
|
+
COMPLETED=$(jq -r ".migrations[\"$MIG_ID\"].tasksCompleted" "$META_PATH")
|
|
88
|
+
TOTAL=$(jq -r ".migrations[\"$MIG_ID\"].tasksTotal" "$META_PATH")
|
|
89
|
+
NEW_COMPLETED=$((COMPLETED + 1))
|
|
90
|
+
|
|
91
|
+
if [ "$NEW_COMPLETED" -ge "$TOTAL" ]; then
|
|
92
|
+
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
93
|
+
jq --arg id "$MIG_ID" --arg now "$NOW" \
|
|
94
|
+
'.migrations[$id].tasksCompleted += 1 |
|
|
95
|
+
.migrations[$id].status = "completed" |
|
|
96
|
+
.migrations[$id].completedAt = $now' "$META_PATH" > "$META_PATH.tmp" && mv "$META_PATH.tmp" "$META_PATH"
|
|
97
|
+
echo "Migration $MIG_ID completed!"
|
|
98
|
+
else
|
|
99
|
+
jq --arg id "$MIG_ID" \
|
|
100
|
+
'.migrations[$id].tasksCompleted += 1' "$META_PATH" > "$META_PATH.tmp" && mv "$META_PATH.tmp" "$META_PATH"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
echo "Progress: $NEW_COMPLETED/$TOTAL tasks"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Output JSON
|
|
107
|
+
echo "---SEDD-OUTPUT---"
|
|
108
|
+
echo "{\"success\":true,\"taskId\":\"$TASK_ID\",\"migrationId\":\"$MIG_ID\"}"
|