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.
Files changed (90) hide show
  1. package/README.md +504 -0
  2. package/bin/sedd.js +6 -0
  3. package/commands/sedd.clarify.md +435 -0
  4. package/commands/sedd.dashboard.md +145 -0
  5. package/commands/sedd.implement.md +326 -0
  6. package/commands/sedd.migrate.md +249 -0
  7. package/commands/sedd.specify.md +198 -0
  8. package/commands/sedd.tasks.md +176 -0
  9. package/dist/cli/check.d.ts +6 -0
  10. package/dist/cli/check.d.ts.map +1 -0
  11. package/dist/cli/check.js +134 -0
  12. package/dist/cli/check.js.map +1 -0
  13. package/dist/cli/clarify.d.ts +2 -0
  14. package/dist/cli/clarify.d.ts.map +1 -0
  15. package/dist/cli/clarify.js +116 -0
  16. package/dist/cli/clarify.js.map +1 -0
  17. package/dist/cli/index.d.ts +8 -0
  18. package/dist/cli/index.d.ts.map +1 -0
  19. package/dist/cli/index.js +175 -0
  20. package/dist/cli/index.js.map +1 -0
  21. package/dist/cli/init.d.ts +9 -0
  22. package/dist/cli/init.d.ts.map +1 -0
  23. package/dist/cli/init.js +236 -0
  24. package/dist/cli/init.js.map +1 -0
  25. package/dist/cli/migrate.d.ts +7 -0
  26. package/dist/cli/migrate.d.ts.map +1 -0
  27. package/dist/cli/migrate.js +197 -0
  28. package/dist/cli/migrate.js.map +1 -0
  29. package/dist/cli/specify.d.ts +7 -0
  30. package/dist/cli/specify.d.ts.map +1 -0
  31. package/dist/cli/specify.js +131 -0
  32. package/dist/cli/specify.js.map +1 -0
  33. package/dist/cli/status.d.ts +6 -0
  34. package/dist/cli/status.d.ts.map +1 -0
  35. package/dist/cli/status.js +118 -0
  36. package/dist/cli/status.js.map +1 -0
  37. package/dist/cli/tasks.d.ts +7 -0
  38. package/dist/cli/tasks.d.ts.map +1 -0
  39. package/dist/cli/tasks.js +165 -0
  40. package/dist/cli/tasks.js.map +1 -0
  41. package/dist/core/changelog.d.ts +30 -0
  42. package/dist/core/changelog.d.ts.map +1 -0
  43. package/dist/core/changelog.js +97 -0
  44. package/dist/core/changelog.js.map +1 -0
  45. package/dist/core/file-splitter.d.ts +39 -0
  46. package/dist/core/file-splitter.d.ts.map +1 -0
  47. package/dist/core/file-splitter.js +162 -0
  48. package/dist/core/file-splitter.js.map +1 -0
  49. package/dist/core/migration-manager.d.ts +76 -0
  50. package/dist/core/migration-manager.d.ts.map +1 -0
  51. package/dist/core/migration-manager.js +230 -0
  52. package/dist/core/migration-manager.js.map +1 -0
  53. package/dist/core/timestamps.d.ts +17 -0
  54. package/dist/core/timestamps.d.ts.map +1 -0
  55. package/dist/core/timestamps.js +37 -0
  56. package/dist/core/timestamps.js.map +1 -0
  57. package/dist/index.d.ts +8 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +7 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/types/index.d.ts +102 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/types/index.js +83 -0
  64. package/dist/types/index.js.map +1 -0
  65. package/dist/utils/git.d.ts +63 -0
  66. package/dist/utils/git.d.ts.map +1 -0
  67. package/dist/utils/git.js +179 -0
  68. package/dist/utils/git.js.map +1 -0
  69. package/hooks/README.md +220 -0
  70. package/hooks/check-roadmap.js +231 -0
  71. package/hooks/check-roadmap.ps1 +343 -0
  72. package/package.json +60 -0
  73. package/scripts/bash/sedd-clarify.sh +142 -0
  74. package/scripts/bash/sedd-complete-task.sh +108 -0
  75. package/scripts/bash/sedd-specify.sh +147 -0
  76. package/scripts/powershell/sedd-clarify.ps1 +222 -0
  77. package/scripts/powershell/sedd-complete-task.ps1 +143 -0
  78. package/scripts/powershell/sedd-specify.ps1 +192 -0
  79. package/scripts/powershell/sedd-status.ps1 +153 -0
  80. package/scripts/powershell/sedd-tasks.ps1 +176 -0
  81. package/templates/changelog-template.md +6 -0
  82. package/templates/clarify-template.md +66 -0
  83. package/templates/config-template.json +20 -0
  84. package/templates/decisions-template.md +56 -0
  85. package/templates/interfaces-template.ts +131 -0
  86. package/templates/meta-template.json +12 -0
  87. package/templates/progress-template.md +61 -0
  88. package/templates/sedd.schema.json +95 -0
  89. package/templates/spec-template.md +114 -0
  90. 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\"}"