spec-gen-cli 1.2.6 → 1.2.8

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 (198) hide show
  1. package/README.md +175 -55
  2. package/dist/api/analyze.d.ts.map +1 -1
  3. package/dist/api/analyze.js +6 -1
  4. package/dist/api/analyze.js.map +1 -1
  5. package/dist/api/audit.d.ts +10 -0
  6. package/dist/api/audit.d.ts.map +1 -0
  7. package/dist/api/audit.js +117 -0
  8. package/dist/api/audit.js.map +1 -0
  9. package/dist/api/generate.d.ts.map +1 -1
  10. package/dist/api/generate.js +10 -1
  11. package/dist/api/generate.js.map +1 -1
  12. package/dist/api/index.d.ts +3 -2
  13. package/dist/api/index.d.ts.map +1 -1
  14. package/dist/api/index.js +1 -0
  15. package/dist/api/index.js.map +1 -1
  16. package/dist/api/run.d.ts.map +1 -1
  17. package/dist/api/run.js +5 -1
  18. package/dist/api/run.js.map +1 -1
  19. package/dist/api/types.d.ts +15 -4
  20. package/dist/api/types.d.ts.map +1 -1
  21. package/dist/cli/commands/analyze.d.ts +3 -0
  22. package/dist/cli/commands/analyze.d.ts.map +1 -1
  23. package/dist/cli/commands/analyze.js +112 -17
  24. package/dist/cli/commands/analyze.js.map +1 -1
  25. package/dist/cli/commands/audit.d.ts +9 -0
  26. package/dist/cli/commands/audit.d.ts.map +1 -0
  27. package/dist/cli/commands/audit.js +98 -0
  28. package/dist/cli/commands/audit.js.map +1 -0
  29. package/dist/cli/commands/drift.d.ts.map +1 -1
  30. package/dist/cli/commands/drift.js +8 -10
  31. package/dist/cli/commands/drift.js.map +1 -1
  32. package/dist/cli/commands/generate.d.ts.map +1 -1
  33. package/dist/cli/commands/generate.js +15 -37
  34. package/dist/cli/commands/generate.js.map +1 -1
  35. package/dist/cli/commands/mcp.d.ts +102 -2
  36. package/dist/cli/commands/mcp.d.ts.map +1 -1
  37. package/dist/cli/commands/mcp.js +134 -2
  38. package/dist/cli/commands/mcp.js.map +1 -1
  39. package/dist/cli/commands/run.d.ts.map +1 -1
  40. package/dist/cli/commands/run.js +9 -47
  41. package/dist/cli/commands/run.js.map +1 -1
  42. package/dist/cli/commands/setup.d.ts +17 -0
  43. package/dist/cli/commands/setup.d.ts.map +1 -0
  44. package/dist/cli/commands/setup.js +201 -0
  45. package/dist/cli/commands/setup.js.map +1 -0
  46. package/dist/cli/commands/verify.d.ts.map +1 -1
  47. package/dist/cli/commands/verify.js +7 -8
  48. package/dist/cli/commands/verify.js.map +1 -1
  49. package/dist/cli/index.js +14 -8
  50. package/dist/cli/index.js.map +1 -1
  51. package/dist/constants.d.ts +14 -0
  52. package/dist/constants.d.ts.map +1 -1
  53. package/dist/constants.js +14 -0
  54. package/dist/constants.js.map +1 -1
  55. package/dist/core/analyzer/ai-config-generator.d.ts +54 -0
  56. package/dist/core/analyzer/ai-config-generator.d.ts.map +1 -0
  57. package/dist/core/analyzer/ai-config-generator.js +85 -0
  58. package/dist/core/analyzer/ai-config-generator.js.map +1 -0
  59. package/dist/core/analyzer/artifact-generator.d.ts +27 -2
  60. package/dist/core/analyzer/artifact-generator.d.ts.map +1 -1
  61. package/dist/core/analyzer/artifact-generator.js +86 -8
  62. package/dist/core/analyzer/artifact-generator.js.map +1 -1
  63. package/dist/core/analyzer/codebase-digest.d.ts.map +1 -1
  64. package/dist/core/analyzer/codebase-digest.js +12 -11
  65. package/dist/core/analyzer/codebase-digest.js.map +1 -1
  66. package/dist/core/analyzer/env-extractor.d.ts +33 -0
  67. package/dist/core/analyzer/env-extractor.d.ts.map +1 -0
  68. package/dist/core/analyzer/env-extractor.js +196 -0
  69. package/dist/core/analyzer/env-extractor.js.map +1 -0
  70. package/dist/core/analyzer/http-route-parser.d.ts +36 -1
  71. package/dist/core/analyzer/http-route-parser.d.ts.map +1 -1
  72. package/dist/core/analyzer/http-route-parser.js +276 -0
  73. package/dist/core/analyzer/http-route-parser.js.map +1 -1
  74. package/dist/core/analyzer/middleware-extractor.d.ts +29 -0
  75. package/dist/core/analyzer/middleware-extractor.d.ts.map +1 -0
  76. package/dist/core/analyzer/middleware-extractor.js +195 -0
  77. package/dist/core/analyzer/middleware-extractor.js.map +1 -0
  78. package/dist/core/analyzer/schema-extractor.d.ts +41 -0
  79. package/dist/core/analyzer/schema-extractor.d.ts.map +1 -0
  80. package/dist/core/analyzer/schema-extractor.js +229 -0
  81. package/dist/core/analyzer/schema-extractor.js.map +1 -0
  82. package/dist/core/analyzer/spec-snapshot-generator.d.ts +17 -0
  83. package/dist/core/analyzer/spec-snapshot-generator.d.ts.map +1 -0
  84. package/dist/core/analyzer/spec-snapshot-generator.js +201 -0
  85. package/dist/core/analyzer/spec-snapshot-generator.js.map +1 -0
  86. package/dist/core/analyzer/ui-component-extractor.d.ts +43 -0
  87. package/dist/core/analyzer/ui-component-extractor.d.ts.map +1 -0
  88. package/dist/core/analyzer/ui-component-extractor.js +245 -0
  89. package/dist/core/analyzer/ui-component-extractor.js.map +1 -0
  90. package/dist/core/generator/openspec-format-generator.d.ts.map +1 -1
  91. package/dist/core/generator/openspec-format-generator.js +8 -0
  92. package/dist/core/generator/openspec-format-generator.js.map +1 -1
  93. package/dist/core/generator/spec-pipeline.d.ts +9 -0
  94. package/dist/core/generator/spec-pipeline.d.ts.map +1 -1
  95. package/dist/core/generator/spec-pipeline.js +94 -2
  96. package/dist/core/generator/spec-pipeline.js.map +1 -1
  97. package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -1
  98. package/dist/core/generator/stages/stage1-survey.js +43 -0
  99. package/dist/core/generator/stages/stage1-survey.js.map +1 -1
  100. package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -1
  101. package/dist/core/generator/stages/stage2-entities.js +6 -2
  102. package/dist/core/generator/stages/stage2-entities.js.map +1 -1
  103. package/dist/core/generator/stages/stage3-services.d.ts.map +1 -1
  104. package/dist/core/generator/stages/stage3-services.js +9 -2
  105. package/dist/core/generator/stages/stage3-services.js.map +1 -1
  106. package/dist/core/generator/stages/stage4-api.d.ts.map +1 -1
  107. package/dist/core/generator/stages/stage4-api.js +6 -2
  108. package/dist/core/generator/stages/stage4-api.js.map +1 -1
  109. package/dist/core/services/llm-service.d.ts +26 -10
  110. package/dist/core/services/llm-service.d.ts.map +1 -1
  111. package/dist/core/services/llm-service.js +171 -16
  112. package/dist/core/services/llm-service.js.map +1 -1
  113. package/dist/core/services/mcp-handlers/analysis.d.ts +32 -1
  114. package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -1
  115. package/dist/core/services/mcp-handlers/analysis.js +185 -2
  116. package/dist/core/services/mcp-handlers/analysis.js.map +1 -1
  117. package/dist/core/verifier/verification-engine.d.ts +67 -6
  118. package/dist/core/verifier/verification-engine.d.ts.map +1 -1
  119. package/dist/core/verifier/verification-engine.js +316 -90
  120. package/dist/core/verifier/verification-engine.js.map +1 -1
  121. package/dist/types/index.d.ts +70 -1
  122. package/dist/types/index.d.ts.map +1 -1
  123. package/dist/types/pipeline.d.ts +9 -0
  124. package/dist/types/pipeline.d.ts.map +1 -1
  125. package/dist/utils/command-helpers.d.ts +30 -0
  126. package/dist/utils/command-helpers.d.ts.map +1 -1
  127. package/dist/utils/command-helpers.js +69 -1
  128. package/dist/utils/command-helpers.js.map +1 -1
  129. package/examples/bmad/README.md +113 -0
  130. package/examples/bmad/agents/architect.md +226 -0
  131. package/examples/bmad/agents/dev-brownfield.md +69 -0
  132. package/examples/bmad/setup/architect.customize.yaml +14 -0
  133. package/examples/bmad/tasks/implement-story.md +254 -0
  134. package/examples/bmad/tasks/onboarding.md +169 -0
  135. package/examples/bmad/tasks/refactor.md +178 -0
  136. package/examples/bmad/tasks/sprint-planning.md +168 -0
  137. package/examples/bmad/templates/story.md +108 -0
  138. package/examples/cline-workflows/spec-gen-analyze-codebase.md +100 -0
  139. package/examples/cline-workflows/spec-gen-check-spec-drift.md +102 -0
  140. package/examples/cline-workflows/spec-gen-execute-refactor.md +194 -0
  141. package/examples/cline-workflows/spec-gen-implement-feature.md +238 -0
  142. package/examples/cline-workflows/spec-gen-plan-refactor.md +255 -0
  143. package/examples/cline-workflows/spec-gen-refactor-codebase.md +16 -0
  144. package/examples/drift-demo/openspec/config.yaml +14 -0
  145. package/examples/drift-demo/openspec/specs/architecture/spec.md +30 -0
  146. package/examples/drift-demo/openspec/specs/auth/spec.md +71 -0
  147. package/examples/drift-demo/openspec/specs/database/spec.md +33 -0
  148. package/examples/drift-demo/openspec/specs/overview/spec.md +20 -0
  149. package/examples/drift-demo/openspec/specs/projects/spec.md +55 -0
  150. package/examples/drift-demo/openspec/specs/tasks/spec.md +78 -0
  151. package/examples/drift-demo/package.json +21 -0
  152. package/examples/drift-demo/src/auth/auth-middleware.ts +30 -0
  153. package/examples/drift-demo/src/auth/auth-routes.ts +29 -0
  154. package/examples/drift-demo/src/auth/auth-service.ts +45 -0
  155. package/examples/drift-demo/src/database/connection.ts +27 -0
  156. package/examples/drift-demo/src/index.ts +16 -0
  157. package/examples/drift-demo/src/projects/project-model.ts +15 -0
  158. package/examples/drift-demo/src/projects/project-service.ts +34 -0
  159. package/examples/drift-demo/src/tasks/task-model.ts +37 -0
  160. package/examples/drift-demo/src/tasks/task-routes.ts +53 -0
  161. package/examples/drift-demo/src/tasks/task-service.ts +60 -0
  162. package/examples/drift-demo/src/utils/validation.ts +11 -0
  163. package/examples/drift-demo/tests/auth.test.ts +4 -0
  164. package/examples/drift-demo/tests/tasks.test.ts +4 -0
  165. package/examples/drift-demo/tsconfig.json +10 -0
  166. package/examples/drift-test/run-drift-test.sh +1087 -0
  167. package/examples/gsd/README.md +119 -0
  168. package/examples/gsd/commands/gsd/spec-gen-drift.md +111 -0
  169. package/examples/gsd/commands/gsd/spec-gen-orient.md +191 -0
  170. package/examples/mistral-vibe/README.md +101 -0
  171. package/examples/mistral-vibe/antipatterns-template.md +18 -0
  172. package/examples/mistral-vibe/skills/spec-gen-analyze-codebase/SKILL.md +123 -0
  173. package/examples/mistral-vibe/skills/spec-gen-brainstorm/SKILL.md +379 -0
  174. package/examples/mistral-vibe/skills/spec-gen-debug/SKILL.md +320 -0
  175. package/examples/mistral-vibe/skills/spec-gen-execute-refactor/SKILL.md +210 -0
  176. package/examples/mistral-vibe/skills/spec-gen-generate/SKILL.md +245 -0
  177. package/examples/mistral-vibe/skills/spec-gen-implement-story/SKILL.md +274 -0
  178. package/examples/mistral-vibe/skills/spec-gen-plan-refactor/SKILL.md +251 -0
  179. package/examples/openspec-analysis/README.md +59 -0
  180. package/examples/openspec-analysis/SUMMARY.md +72 -0
  181. package/examples/openspec-analysis/config.json +16 -0
  182. package/examples/openspec-analysis/dependencies.mermaid +35 -0
  183. package/examples/openspec-analysis/dependency-graph.json +12116 -0
  184. package/examples/openspec-analysis/llm-context.json +119 -0
  185. package/examples/openspec-analysis/repo-structure.json +871 -0
  186. package/examples/openspec-cli/README.md +67 -0
  187. package/examples/openspec-cli/openspec/config.yaml +26 -0
  188. package/examples/openspec-cli/openspec/specs/architecture/spec.md +178 -0
  189. package/examples/openspec-cli/openspec/specs/artifact-graph/spec.md +143 -0
  190. package/examples/openspec-cli/openspec/specs/cli/spec.md +138 -0
  191. package/examples/openspec-cli/openspec/specs/overview/spec.md +60 -0
  192. package/examples/openspec-cli/openspec/specs/parsing/spec.md +123 -0
  193. package/examples/openspec-cli/openspec/specs/validation/spec.md +108 -0
  194. package/examples/spec-kit/README.md +104 -0
  195. package/examples/spec-kit/commands/drift.md +87 -0
  196. package/examples/spec-kit/commands/orient.md +138 -0
  197. package/examples/spec-kit/extension.yml +54 -0
  198. package/package.json +3 -6
@@ -0,0 +1,255 @@
1
+ # spec-gen: Plan Refactor
2
+
3
+ Identify the highest-priority refactoring target using static analysis, assess
4
+ its blast radius, and produce a detailed written plan — saved to
5
+ `.spec-gen/refactor-plan.md` — that `/spec-gen-execute-refactor` can follow
6
+ step by step without losing context.
7
+
8
+ This workflow makes **no code changes**. It only reads and writes the plan file.
9
+
10
+ ## Step 1: Confirm the project directory
11
+
12
+ Ask the user which project to analyse, or confirm the current workspace root.
13
+
14
+ <ask_followup_question>
15
+ <question>Which project directory should I plan the refactor for?</question>
16
+ <options>["Current workspace root", "Enter a different path"]</options>
17
+ </ask_followup_question>
18
+
19
+ ## Step 2: Run static analysis
20
+
21
+ Analyse the project. If analysis already ran recently, skip unless the user
22
+ requests a fresh run.
23
+
24
+ <use_mcp_tool>
25
+ <server_name>spec-gen</server_name>
26
+ <tool_name>analyze_codebase</tool_name>
27
+ <arguments>{"directory": "$DIRECTORY"}</arguments>
28
+ </use_mcp_tool>
29
+
30
+ ## Step 3: Get the full refactoring report
31
+
32
+ Retrieve the prioritised list of functions with structural issues.
33
+
34
+ <use_mcp_tool>
35
+ <server_name>spec-gen</server_name>
36
+ <tool_name>get_refactor_report</tool_name>
37
+ <arguments>{"directory": "$DIRECTORY"}</arguments>
38
+ </use_mcp_tool>
39
+
40
+ Present the top 5 candidates in a table: function, file, issues, priority score.
41
+
42
+ ## Step 3b: Check for duplicate code (optional enrichment)
43
+
44
+ Call `get_duplicate_report` to surface clones that overlap with the top candidates.
45
+ If the target function (or any callee) appears in a clone group, note it in the plan:
46
+ consolidated duplicates reduce blast radius before extracting logic.
47
+
48
+ <use_mcp_tool>
49
+ <server_name>spec-gen</server_name>
50
+ <tool_name>get_duplicate_report</tool_name>
51
+ <arguments>{"directory": "$DIRECTORY"}</arguments>
52
+ </use_mcp_tool>
53
+
54
+ If a top candidate appears in a clone group, prepend a **Deduplication note** to the plan:
55
+ > "⚠️ `<function>` has N near-clones. Consolidate them first to reduce the blast radius
56
+ > of this refactor."
57
+
58
+ Before asking the user to pick a target, **check test coverage for the files
59
+ containing the top candidates**. Detect the coverage tool from the project
60
+ (look for `package.json` scripts, `pytest.ini`, `Cargo.toml`, `go.mod`, etc.)
61
+ and run it scoped to those files only:
62
+
63
+ - Node.js → `npm test -- --coverage --collectCoverageFrom="<files>"`
64
+ - Python → `pytest --cov=<module> --cov-report=term-missing`
65
+ - Rust → `cargo tarpaulin --include-files <files>`
66
+ - Go → `go test -cover ./...` (filter relevant packages)
67
+
68
+ For each candidate file, present a compact coverage badge:
69
+
70
+ | Function | File | Priority | Coverage |
71
+ |---|---|---|---|
72
+ | ... | ... | ... | 72% ✅ / 35% ⚠️ / 0% 🚫 |
73
+
74
+ Apply these thresholds to annotate each row:
75
+
76
+ | Coverage | Badge | Meaning |
77
+ |---|---|---|
78
+ | ≥ 70% lines | ✅ | Safe to refactor |
79
+ | 40–69% lines | ⚠️ | Write characterisation tests first |
80
+ | < 40% lines | 🛑 | Strongly discouraged — recommend tests first |
81
+ | 0% (no tests) | 🚫 | Blocked — propose a test harness before proceeding |
82
+
83
+ If **all top candidates are below 40%**, tell the user:
84
+ > "Every high-priority target has insufficient test coverage (< 40%). Refactoring
85
+ > without tests risks introducing silent regressions. I recommend writing a
86
+ > minimal test harness for at least one target before proceeding. Would you like
87
+ > me to suggest test cases based on the function signatures?"
88
+
89
+ Then ask the user which one to tackle first, or pick the top one by default.
90
+ Prefer candidates with higher coverage when scores are otherwise close.
91
+
92
+ ## Step 4: Assess impact
93
+
94
+ For the chosen function, get the full impact analysis.
95
+
96
+ <use_mcp_tool>
97
+ <server_name>spec-gen</server_name>
98
+ <tool_name>analyze_impact</tool_name>
99
+ <arguments>{"directory": "$DIRECTORY", "symbol": "$FUNCTION_NAME"}</arguments>
100
+ </use_mcp_tool>
101
+
102
+ Note:
103
+ - Risk score (0–100) and what it means
104
+ - Recommended strategy (extract / split / facade / delegate)
105
+ - Upstream callers and downstream callees (keep the top 5 of each for the plan)
106
+
107
+ ## Step 5: Visualise the call neighbourhood
108
+
109
+ Render the subgraph to map callers and callees precisely.
110
+
111
+ <use_mcp_tool>
112
+ <server_name>spec-gen</server_name>
113
+ <tool_name>get_subgraph</tool_name>
114
+ <arguments>{"directory": "$DIRECTORY", "functionName": "$FUNCTION_NAME", "direction": "both", "format": "mermaid"}</arguments>
115
+ </use_mcp_tool>
116
+
117
+ Show the Mermaid diagram to the user.
118
+
119
+ ## Step 6: Find safe entry points
120
+
121
+ Identify low-risk leaf functions that can be extracted first (bottom-up).
122
+
123
+ <use_mcp_tool>
124
+ <server_name>spec-gen</server_name>
125
+ <tool_name>get_low_risk_refactor_candidates</tool_name>
126
+ <arguments>{"directory": "$DIRECTORY", "filePattern": "$TARGET_FILE", "limit": 5}</arguments>
127
+ </use_mcp_tool>
128
+
129
+ Cross-reference with the subgraph from Step 5: a candidate is a good first
130
+ extraction if it already appears as a callee of the target function.
131
+
132
+ ## Step 6b: Find insertion points for extracted helpers
133
+
134
+ Before designing the change sequence, identify where extracted functions should land.
135
+ This avoids creating helpers in the wrong file or layer.
136
+
137
+ <use_mcp_tool>
138
+ <server_name>spec-gen</server_name>
139
+ <tool_name>suggest_insertion_points</tool_name>
140
+ <arguments>{"directory": "$DIRECTORY", "query": "extract helper from $FUNCTION_NAME", "limit": 5}</arguments>
141
+ </use_mcp_tool>
142
+
143
+ For each candidate returned, note its role (entry_point / orchestrator / hub / utility / internal)
144
+ and the suggested strategy. Cross-reference with the subgraph from Step 5: prefer candidates
145
+ that already call into — or are called by — the target function.
146
+
147
+ ## Step 7: Design the change sequence
148
+
149
+ Based on the recommended strategy from Step 4, design an ordered sequence of
150
+ atomic changes. Each change must specify:
151
+
152
+ - **What**: the exact block of logic to move (line range or description)
153
+ - **New name**: the function or method name to give it
154
+ - **Target file**: the file where it will live after the move
155
+ - If the logic belongs to an existing module: name that file
156
+ - If no suitable module exists: propose a new file path (e.g.
157
+ `src/services/validation.ts`) and justify the choice
158
+ - **Target class** (if applicable): the class or namespace to place it in
159
+ - **Callers to update**: list every call site that will need updating
160
+
161
+ For each strategy, apply these rules:
162
+
163
+ - **split**: decompose the function into N sub-functions; each sub-function
164
+ stays in the same file unless it clearly belongs elsewhere
165
+ - **extract**: pull out a helper; place it in the nearest cohesive module or
166
+ create a new file if none exists
167
+ - **facade**: keep the original signature, delegate body to smaller functions;
168
+ create a private companion module if the file would exceed 300 lines
169
+ - **delegate**: move ownership logic to callers; update each caller file listed
170
+ in the upstream chain
171
+
172
+ Present the full change sequence to the user for review and ask for confirmation
173
+ before writing the plan file.
174
+
175
+ ## Step 8: Write the plan file
176
+
177
+ Create `.spec-gen/refactor-plan.md` in the project directory with the following
178
+ structure (fill every section — leave nothing as "TBD"):
179
+
180
+ ```markdown
181
+ # Refactor Plan
182
+
183
+ Generated: <ISO date>
184
+ Workflow: /spec-gen-plan-refactor → /spec-gen-execute-refactor
185
+
186
+ ## Target
187
+
188
+ - **Function**: <name>
189
+ - **File**: <relative path>
190
+ - **Lines**: <start>–<end> (read the file to confirm)
191
+ - **Risk score**: <0–100>
192
+ - **Strategy**: <extract | split | facade | delegate>
193
+ - **Priority score before refactor**: <value>
194
+
195
+ ## Why
196
+
197
+ - <issue 1 from refactor report>
198
+ - <issue 2>
199
+ - ...
200
+
201
+ ## Callers (upstream — must not break)
202
+
203
+ | Caller | File |
204
+ |---|---|
205
+ | <name> | <path> |
206
+
207
+ ## Callees (downstream — candidates for extraction)
208
+
209
+ | Callee | File |
210
+ |---|---|
211
+ | <name> | <path> |
212
+
213
+ ## Coverage baseline
214
+
215
+ - **File**: <target file>
216
+ - **Coverage**: <X>% lines, <Y>% branches
217
+ - **Status**: ✅ safe / ⚠️ caution / 🛑 discouraged
218
+ - **Test command**: <exact command to run>
219
+
220
+ ## Change sequence
221
+
222
+ Apply in order. Do not skip ahead. Run tests after each step.
223
+
224
+ ### Change 1 — <short label>
225
+
226
+ - **What**: extract lines <start>–<end> (logic: <one-line description>)
227
+ - **New function name**: `<name>`
228
+ - **Target file**: `<path>` (<new file | existing file — reason>)
229
+ - **Target class**: `<ClassName>` or none
230
+ - **Call sites to update**: <list each file:line>
231
+ - **Expected diff**: +<N> lines in <new/existing file>, -<M> lines in <source file>
232
+
233
+ ### Change 2 — <short label>
234
+
235
+ ...
236
+
237
+ ## Acceptance criteria
238
+
239
+ - Priority score drops below <target score> in `get_refactor_report`
240
+ - Function exits the top-5 list
241
+ - Full test suite passes (green)
242
+ - `git diff --stat` shows only the expected files
243
+
244
+ ## Restore point
245
+
246
+ Run before starting execute:
247
+ ```bash
248
+ git log --oneline -1
249
+ ```
250
+ Note the hash here: <to be filled by execute workflow>
251
+ ```
252
+
253
+ Once the file is written, tell the user:
254
+ > "Plan written to `.spec-gen/refactor-plan.md`. Review it, then run
255
+ > `/spec-gen-execute-refactor` to apply the changes."
@@ -0,0 +1,16 @@
1
+ # spec-gen: Refactor Codebase (redirected)
2
+
3
+ This workflow has been split into two focused workflows for better reliability
4
+ with limited models:
5
+
6
+ - **`/spec-gen-plan-refactor`** — static analysis, impact assessment, and
7
+ written plan saved to `.spec-gen/refactor-plan.md` (no code changes)
8
+ - **`/spec-gen-execute-refactor`** — reads the plan and applies changes
9
+ incrementally, with tests after each step
10
+
11
+ Tell the user:
12
+ > "The `/spec-gen-refactor-codebase` workflow has been split. Please use:
13
+ > 1. `/spec-gen-plan-refactor` to analyse the codebase and write a plan
14
+ > 2. `/spec-gen-execute-refactor` to apply the plan
15
+ >
16
+ > This two-step approach is more reliable, especially with smaller models."
@@ -0,0 +1,14 @@
1
+ schema: spec-driven
2
+ context: |
3
+ TaskFlow — a task management REST API built with Express.js and PostgreSQL.
4
+
5
+ Tech stack: TypeScript, Express.js, PostgreSQL, JWT auth, bcrypt
6
+ Architecture: Layered (routes → services → database)
7
+
8
+ spec-gen:
9
+ generatedAt: "2025-06-15T00:00:00.000Z"
10
+ domains:
11
+ - auth
12
+ - tasks
13
+ - projects
14
+ - database
@@ -0,0 +1,30 @@
1
+ # Architecture Specification
2
+
3
+ > Generated by spec-gen v1.0.0 on 2025-06-15
4
+
5
+ ## Purpose
6
+
7
+ Describes the overall system architecture and how components interact.
8
+
9
+ ## Requirements
10
+
11
+ ### Requirement: LayeredArchitecture
12
+
13
+ The system SHALL follow a three-layer architecture:
14
+ 1. **Routes** (Express routers) handle HTTP concerns
15
+ 2. **Services** contain business logic
16
+ 3. **Database** handles persistence
17
+
18
+ ### Requirement: EntryPoint
19
+
20
+ The system SHALL expose a single entry point (`src/index.ts`) that mounts all route
21
+ modules and starts an Express server on PORT (default 3000).
22
+
23
+ ### Requirement: HealthEndpoint
24
+
25
+ The system SHALL expose a public GET /health endpoint returning `{ "status": "ok" }`.
26
+
27
+ ## Technical Notes
28
+
29
+ - **Implementation**: `src/index.ts`
30
+ - **Dependencies**: express
@@ -0,0 +1,71 @@
1
+ # Auth Specification
2
+
3
+ > Generated by spec-gen v1.0.0 on 2025-06-15
4
+ > Source files: src/auth/auth-service.ts, src/auth/auth-middleware.ts, src/auth/auth-routes.ts
5
+
6
+ ## Purpose
7
+
8
+ Handles user authentication (login, registration, JWT management) and request-level
9
+ authorization via middleware.
10
+
11
+ ## Requirements
12
+
13
+ ### Requirement: UserLogin
14
+
15
+ The system SHALL authenticate users by email and password, returning a signed JWT on success.
16
+
17
+ #### Scenario: SuccessfulLogin
18
+ - **GIVEN** a registered user with email "alice@test.com" and a valid password
19
+ - **WHEN** POST /api/auth/login is called with those credentials
20
+ - **THEN** the system returns a JWT token, expiry time, and userId with status 200
21
+
22
+ #### Scenario: InvalidCredentials
23
+ - **GIVEN** an incorrect password
24
+ - **WHEN** POST /api/auth/login is called
25
+ - **THEN** the system returns status 401 with error "Invalid credentials"
26
+
27
+ #### Scenario: MissingFields
28
+ - **GIVEN** a request body without email or password
29
+ - **WHEN** POST /api/auth/login is called
30
+ - **THEN** the system returns status 400 with error "Email and password required"
31
+
32
+ ### Requirement: UserRegistration
33
+
34
+ The system SHALL register new users with email, password, and name, hashing the password with bcrypt (cost factor 12).
35
+
36
+ #### Scenario: SuccessfulRegistration
37
+ - **GIVEN** a unique email "bob@test.com"
38
+ - **WHEN** POST /api/auth/register is called
39
+ - **THEN** the system creates the user and returns a JWT with status 201
40
+
41
+ #### Scenario: DuplicateEmail
42
+ - **GIVEN** an email that already exists
43
+ - **WHEN** POST /api/auth/register is called
44
+ - **THEN** the system returns status 409 with error "Email already registered"
45
+
46
+ ### Requirement: JWTTokenManagement
47
+
48
+ The system SHALL sign tokens with a configurable secret (JWT_SECRET env var, defaulting to "dev-secret") and 24-hour expiry.
49
+
50
+ ### Requirement: RequestAuthorization
51
+
52
+ The system SHALL protect routes via `requireAuth` middleware that validates Bearer tokens and injects `userId` and `userRole` into the request.
53
+
54
+ #### Scenario: MissingToken
55
+ - **GIVEN** a request without an Authorization header
56
+ - **WHEN** the request reaches a protected route
57
+ - **THEN** the system returns status 401 with error "Missing authorization header"
58
+
59
+ #### Scenario: ExpiredToken
60
+ - **GIVEN** a request with an expired JWT
61
+ - **WHEN** the request reaches a protected route
62
+ - **THEN** the system returns status 401 with error "Invalid or expired token"
63
+
64
+ ### Requirement: RoleBasedAccess
65
+
66
+ The system SHALL support role-based access control via `requireRole` middleware that checks `userRole` against a required role.
67
+
68
+ ## Technical Notes
69
+
70
+ - **Implementation**: `src/auth/auth-service.ts`, `src/auth/auth-middleware.ts`, `src/auth/auth-routes.ts`
71
+ - **Dependencies**: jsonwebtoken, bcrypt
@@ -0,0 +1,33 @@
1
+ # Database Specification
2
+
3
+ > Generated by spec-gen v1.0.0 on 2025-06-15
4
+ > Source files: src/database/connection.ts
5
+
6
+ ## Purpose
7
+
8
+ Manages PostgreSQL connection pooling and provides a health check endpoint.
9
+
10
+ ## Requirements
11
+
12
+ ### Requirement: ConnectionPooling
13
+
14
+ The system SHALL maintain a PostgreSQL connection pool with max 20 connections and 30-second idle timeout.
15
+
16
+ ### Requirement: HealthCheck
17
+
18
+ The system SHALL expose a health check function that verifies database connectivity by executing `SELECT 1`.
19
+
20
+ #### Scenario: HealthyDatabase
21
+ - **GIVEN** a running PostgreSQL instance
22
+ - **WHEN** healthCheck is called
23
+ - **THEN** the function returns true
24
+
25
+ #### Scenario: UnhealthyDatabase
26
+ - **GIVEN** a down PostgreSQL instance
27
+ - **WHEN** healthCheck is called
28
+ - **THEN** the function returns false
29
+
30
+ ## Technical Notes
31
+
32
+ - **Implementation**: `src/database/connection.ts`
33
+ - **Dependencies**: pg (node-postgres)
@@ -0,0 +1,20 @@
1
+ # System Overview
2
+
3
+ > Generated by spec-gen v1.0.0 on 2025-06-15
4
+
5
+ ## Purpose
6
+
7
+ TaskFlow is a task management REST API that enables teams to organize work into
8
+ projects and tasks with role-based access control and real-time status tracking.
9
+
10
+ ## Domains
11
+
12
+ - **auth**: Authentication (login, registration, JWT tokens) and authorization (role-based middleware)
13
+ - **tasks**: Task CRUD operations, status transitions, filtering, and assignment
14
+ - **projects**: Project management, membership, and archival
15
+ - **database**: PostgreSQL connection pooling and health checks
16
+
17
+ ## API Surface
18
+
19
+ All endpoints live under `/api/` and require Bearer token authentication except
20
+ `/api/auth/login`, `/api/auth/register`, and `/health`.
@@ -0,0 +1,55 @@
1
+ # Projects Specification
2
+
3
+ > Generated by spec-gen v1.0.0 on 2025-06-15
4
+ > Source files: src/projects/project-model.ts, src/projects/project-service.ts
5
+
6
+ ## Purpose
7
+
8
+ Manages projects that group tasks together, including membership and archival.
9
+
10
+ ## Entities
11
+
12
+ ### Project
13
+
14
+ | Property | Type | Description |
15
+ |----------|------|-------------|
16
+ | id | string | Unique project identifier (format: proj_{timestamp}) |
17
+ | name | string | Project name (required, trimmed) |
18
+ | description | string | Description (defaults to "") |
19
+ | ownerId | string | User who created the project |
20
+ | members | string[] | User IDs with access (owner is auto-added) |
21
+ | isArchived | boolean | Whether the project is archived |
22
+
23
+ ## Requirements
24
+
25
+ ### Requirement: ProjectCreation
26
+
27
+ The system SHALL create projects with a required name, auto-adding the creator as owner and first member.
28
+
29
+ #### Scenario: ValidCreation
30
+ - **GIVEN** a valid project name
31
+ - **WHEN** createProject is called
32
+ - **THEN** the system creates the project with the creator as owner and member
33
+
34
+ ### Requirement: ProjectMembership
35
+
36
+ The system SHALL allow adding members to a project, preventing duplicate membership.
37
+
38
+ #### Scenario: DuplicateMember
39
+ - **GIVEN** a user who is already a member
40
+ - **WHEN** addMember is called
41
+ - **THEN** the system throws "User is already a member"
42
+
43
+ ### Requirement: ProjectArchival
44
+
45
+ The system SHALL allow only the project owner to archive a project.
46
+
47
+ #### Scenario: NonOwnerArchival
48
+ - **GIVEN** a user who is not the project owner
49
+ - **WHEN** archiveProject is called
50
+ - **THEN** the system throws "Only the owner can archive a project"
51
+
52
+ ## Technical Notes
53
+
54
+ - **Implementation**: `src/projects/project-model.ts`, `src/projects/project-service.ts`
55
+ - **Dependencies**: auth domain
@@ -0,0 +1,78 @@
1
+ # Tasks Specification
2
+
3
+ > Generated by spec-gen v1.0.0 on 2025-06-15
4
+ > Source files: src/tasks/task-model.ts, src/tasks/task-service.ts, src/tasks/task-routes.ts
5
+
6
+ ## Purpose
7
+
8
+ Manages the full lifecycle of tasks: creation, retrieval, updates (including status
9
+ transitions), deletion, and filtered listing within projects.
10
+
11
+ ## Entities
12
+
13
+ ### Task
14
+
15
+ | Property | Type | Description |
16
+ |----------|------|-------------|
17
+ | id | string | Unique task identifier (format: task_{timestamp}) |
18
+ | title | string | Task title (required, trimmed) |
19
+ | description | string | Detailed description (defaults to "") |
20
+ | status | TaskStatus | One of: todo, in_progress, done, cancelled |
21
+ | priority | TaskPriority | One of: low, medium, high, urgent |
22
+ | assigneeId | string \| null | User ID of assignee |
23
+ | projectId | string | Parent project ID (required) |
24
+ | createdBy | string | User ID of creator |
25
+ | dueDate | Date \| null | Optional due date |
26
+ | tags | string[] | User-defined tags |
27
+
28
+ ## Requirements
29
+
30
+ ### Requirement: TaskCreation
31
+
32
+ The system SHALL create tasks with a required title and projectId, defaulting status to "todo" and priority to "medium".
33
+
34
+ #### Scenario: ValidCreation
35
+ - **GIVEN** a valid title and projectId
36
+ - **WHEN** POST /api/tasks is called
37
+ - **THEN** the system creates the task with default status "todo" and returns it with status 201
38
+
39
+ #### Scenario: MissingTitle
40
+ - **GIVEN** a request body without a title
41
+ - **WHEN** POST /api/tasks is called
42
+ - **THEN** the system returns status 400 with error "Task title is required"
43
+
44
+ ### Requirement: TaskStatusTransitions
45
+
46
+ The system SHALL enforce valid status transitions:
47
+ - todo → in_progress, cancelled
48
+ - in_progress → done, todo, cancelled
49
+ - done → todo
50
+ - cancelled → todo
51
+
52
+ #### Scenario: ValidTransition
53
+ - **GIVEN** a task with status "todo"
54
+ - **WHEN** the status is updated to "in_progress"
55
+ - **THEN** the transition succeeds
56
+
57
+ #### Scenario: InvalidTransition
58
+ - **GIVEN** a task with status "todo"
59
+ - **WHEN** the status is updated to "done"
60
+ - **THEN** the system throws "Cannot transition from todo to done"
61
+
62
+ ### Requirement: TaskCRUD
63
+
64
+ The system SHALL support Get, Update (PATCH), Delete, and List operations for tasks. All task routes require authentication.
65
+
66
+ #### Scenario: TaskNotFound
67
+ - **GIVEN** a non-existent task ID
68
+ - **WHEN** GET /api/tasks/:id is called
69
+ - **THEN** the system returns status 404
70
+
71
+ ### Requirement: TaskFiltering
72
+
73
+ The system SHALL support filtering tasks by projectId (required), status, and assigneeId via query parameters.
74
+
75
+ ## Technical Notes
76
+
77
+ - **Implementation**: `src/tasks/task-model.ts`, `src/tasks/task-service.ts`, `src/tasks/task-routes.ts`
78
+ - **Dependencies**: auth domain (requireAuth middleware)
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "taskflow-api",
3
+ "version": "2.1.0",
4
+ "description": "Task management REST API — brownfield Express.js app",
5
+ "main": "src/index.ts",
6
+ "scripts": {
7
+ "dev": "ts-node src/index.ts",
8
+ "build": "tsc",
9
+ "test": "vitest run"
10
+ },
11
+ "dependencies": {
12
+ "express": "^4.18.2",
13
+ "jsonwebtoken": "^9.0.0",
14
+ "bcrypt": "^5.1.0",
15
+ "pg": "^8.11.0"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.3.0",
19
+ "vitest": "^1.0.0"
20
+ }
21
+ }
@@ -0,0 +1,30 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ import { AuthService } from './auth-service.js';
3
+
4
+ const authService = new AuthService();
5
+
6
+ export function requireAuth(req: Request, res: Response, next: NextFunction) {
7
+ const header = req.headers.authorization;
8
+ if (!header?.startsWith('Bearer ')) {
9
+ return res.status(401).json({ error: 'Missing authorization header' });
10
+ }
11
+
12
+ const token = header.slice(7);
13
+ const payload = authService.verifyToken(token);
14
+ if (!payload) {
15
+ return res.status(401).json({ error: 'Invalid or expired token' });
16
+ }
17
+
18
+ (req as any).userId = payload.userId;
19
+ (req as any).userRole = payload.role;
20
+ next();
21
+ }
22
+
23
+ export function requireRole(role: string) {
24
+ return (req: Request, res: Response, next: NextFunction) => {
25
+ if ((req as any).userRole !== role) {
26
+ return res.status(403).json({ error: 'Insufficient permissions' });
27
+ }
28
+ next();
29
+ };
30
+ }
@@ -0,0 +1,29 @@
1
+ import { Router } from 'express';
2
+ import { AuthService } from './auth-service.js';
3
+
4
+ const router = Router();
5
+ const authService = new AuthService();
6
+
7
+ router.post('/login', async (req, res) => {
8
+ try {
9
+ const { email, password } = req.body;
10
+ if (!email || !password) return res.status(400).json({ error: 'Email and password required' });
11
+ const result = await authService.login(email, password);
12
+ res.json(result);
13
+ } catch (err: any) {
14
+ res.status(401).json({ error: err.message });
15
+ }
16
+ });
17
+
18
+ router.post('/register', async (req, res) => {
19
+ try {
20
+ const { email, password, name } = req.body;
21
+ if (!email || !password || !name) return res.status(400).json({ error: 'All fields required' });
22
+ const result = await authService.register(email, password, name);
23
+ res.status(201).json(result);
24
+ } catch (err: any) {
25
+ res.status(409).json({ error: err.message });
26
+ }
27
+ });
28
+
29
+ export { router as authRouter };