specweave 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 (288) hide show
  1. package/INSTALL.md +848 -0
  2. package/LICENSE +21 -0
  3. package/README.md +675 -0
  4. package/SPECWEAVE.md +665 -0
  5. package/bin/install-agents.sh +57 -0
  6. package/bin/install-all.sh +49 -0
  7. package/bin/install-commands.sh +56 -0
  8. package/bin/install-skills.sh +57 -0
  9. package/bin/specweave.js +81 -0
  10. package/dist/adapters/adapter-base.d.ts +50 -0
  11. package/dist/adapters/adapter-base.d.ts.map +1 -0
  12. package/dist/adapters/adapter-base.js +146 -0
  13. package/dist/adapters/adapter-base.js.map +1 -0
  14. package/dist/adapters/adapter-interface.d.ts +108 -0
  15. package/dist/adapters/adapter-interface.d.ts.map +1 -0
  16. package/dist/adapters/adapter-interface.js +9 -0
  17. package/dist/adapters/adapter-interface.js.map +1 -0
  18. package/dist/adapters/claude/adapter.d.ts +54 -0
  19. package/dist/adapters/claude/adapter.d.ts.map +1 -0
  20. package/dist/adapters/claude/adapter.js +184 -0
  21. package/dist/adapters/claude/adapter.js.map +1 -0
  22. package/dist/adapters/copilot/adapter.d.ts +42 -0
  23. package/dist/adapters/copilot/adapter.d.ts.map +1 -0
  24. package/dist/adapters/copilot/adapter.js +239 -0
  25. package/dist/adapters/copilot/adapter.js.map +1 -0
  26. package/dist/adapters/cursor/adapter.d.ts +42 -0
  27. package/dist/adapters/cursor/adapter.d.ts.map +1 -0
  28. package/dist/adapters/cursor/adapter.js +297 -0
  29. package/dist/adapters/cursor/adapter.js.map +1 -0
  30. package/dist/adapters/generic/adapter.d.ts +40 -0
  31. package/dist/adapters/generic/adapter.d.ts.map +1 -0
  32. package/dist/adapters/generic/adapter.js +155 -0
  33. package/dist/adapters/generic/adapter.js.map +1 -0
  34. package/dist/cli/commands/init.d.ts +6 -0
  35. package/dist/cli/commands/init.d.ts.map +1 -0
  36. package/dist/cli/commands/init.js +247 -0
  37. package/dist/cli/commands/init.js.map +1 -0
  38. package/dist/cli/commands/install.d.ts +7 -0
  39. package/dist/cli/commands/install.d.ts.map +1 -0
  40. package/dist/cli/commands/install.js +160 -0
  41. package/dist/cli/commands/install.js.map +1 -0
  42. package/dist/cli/commands/list.d.ts +6 -0
  43. package/dist/cli/commands/list.d.ts.map +1 -0
  44. package/dist/cli/commands/list.js +154 -0
  45. package/dist/cli/commands/list.js.map +1 -0
  46. package/package.json +90 -0
  47. package/src/adapters/README.md +312 -0
  48. package/src/adapters/adapter-base.ts +146 -0
  49. package/src/adapters/adapter-interface.ts +120 -0
  50. package/src/adapters/claude/README.md +241 -0
  51. package/src/adapters/claude/adapter.ts +157 -0
  52. package/src/adapters/copilot/.github/copilot/instructions.md +376 -0
  53. package/src/adapters/copilot/README.md +200 -0
  54. package/src/adapters/copilot/adapter.ts +210 -0
  55. package/src/adapters/cursor/.cursor/context/docs-context.md +62 -0
  56. package/src/adapters/cursor/.cursor/context/increments-context.md +71 -0
  57. package/src/adapters/cursor/.cursor/context/strategy-context.md +73 -0
  58. package/src/adapters/cursor/.cursor/context/tests-context.md +89 -0
  59. package/src/adapters/cursor/.cursorrules +325 -0
  60. package/src/adapters/cursor/README.md +243 -0
  61. package/src/adapters/cursor/adapter.ts +268 -0
  62. package/src/adapters/generic/README.md +277 -0
  63. package/src/adapters/generic/SPECWEAVE-MANUAL.md +676 -0
  64. package/src/adapters/generic/adapter.ts +159 -0
  65. package/src/adapters/registry.yaml +126 -0
  66. package/src/agents/architect/AGENT.md +416 -0
  67. package/src/agents/devops/AGENT.md +1738 -0
  68. package/src/agents/docs-writer/AGENT.md +239 -0
  69. package/src/agents/performance/AGENT.md +228 -0
  70. package/src/agents/pm/AGENT.md +751 -0
  71. package/src/agents/qa-lead/AGENT.md +150 -0
  72. package/src/agents/security/AGENT.md +179 -0
  73. package/src/agents/sre/AGENT.md +582 -0
  74. package/src/agents/sre/modules/backend-diagnostics.md +481 -0
  75. package/src/agents/sre/modules/database-diagnostics.md +509 -0
  76. package/src/agents/sre/modules/infrastructure.md +561 -0
  77. package/src/agents/sre/modules/monitoring.md +439 -0
  78. package/src/agents/sre/modules/security-incidents.md +421 -0
  79. package/src/agents/sre/modules/ui-diagnostics.md +302 -0
  80. package/src/agents/sre/playbooks/01-high-cpu-usage.md +204 -0
  81. package/src/agents/sre/playbooks/02-database-deadlock.md +241 -0
  82. package/src/agents/sre/playbooks/03-memory-leak.md +252 -0
  83. package/src/agents/sre/playbooks/04-slow-api-response.md +269 -0
  84. package/src/agents/sre/playbooks/05-ddos-attack.md +293 -0
  85. package/src/agents/sre/playbooks/06-disk-full.md +314 -0
  86. package/src/agents/sre/playbooks/07-service-down.md +333 -0
  87. package/src/agents/sre/playbooks/08-data-corruption.md +337 -0
  88. package/src/agents/sre/playbooks/09-cascade-failure.md +430 -0
  89. package/src/agents/sre/playbooks/10-rate-limit-exceeded.md +464 -0
  90. package/src/agents/sre/scripts/health-check.sh +230 -0
  91. package/src/agents/sre/scripts/log-analyzer.py +213 -0
  92. package/src/agents/sre/scripts/metrics-collector.sh +294 -0
  93. package/src/agents/sre/scripts/trace-analyzer.js +257 -0
  94. package/src/agents/sre/templates/incident-report.md +249 -0
  95. package/src/agents/sre/templates/mitigation-plan.md +375 -0
  96. package/src/agents/sre/templates/post-mortem.md +418 -0
  97. package/src/agents/sre/templates/runbook-template.md +412 -0
  98. package/src/agents/tech-lead/AGENT.md +263 -0
  99. package/src/commands/add-tasks.md +176 -0
  100. package/src/commands/close-increment.md +347 -0
  101. package/src/commands/create-increment.md +223 -0
  102. package/src/commands/create-project.md +528 -0
  103. package/src/commands/generate-docs.md +623 -0
  104. package/src/commands/list-increments.md +180 -0
  105. package/src/commands/review-docs.md +331 -0
  106. package/src/commands/start-increment.md +139 -0
  107. package/src/commands/sync-github.md +115 -0
  108. package/src/commands/validate-increment.md +800 -0
  109. package/src/hooks/README.md +252 -0
  110. package/src/hooks/docs-changed.sh +59 -0
  111. package/src/hooks/human-input-required.sh +55 -0
  112. package/src/hooks/post-task-completion.sh +57 -0
  113. package/src/hooks/pre-implementation.sh +47 -0
  114. package/src/skills/ado-sync/README.md +449 -0
  115. package/src/skills/ado-sync/SKILL.md +245 -0
  116. package/src/skills/ado-sync/test-cases/test-1.yaml +9 -0
  117. package/src/skills/ado-sync/test-cases/test-2.yaml +8 -0
  118. package/src/skills/ado-sync/test-cases/test-3.yaml +9 -0
  119. package/src/skills/bmad-method-expert/SKILL.md +628 -0
  120. package/src/skills/bmad-method-expert/scripts/analyze-project.js +318 -0
  121. package/src/skills/bmad-method-expert/scripts/check-setup.js +208 -0
  122. package/src/skills/bmad-method-expert/scripts/generate-template.js +1149 -0
  123. package/src/skills/bmad-method-expert/scripts/validate-documents.js +340 -0
  124. package/src/skills/bmad-method-expert/test-cases/test-1-placeholder.yaml +12 -0
  125. package/src/skills/bmad-method-expert/test-cases/test-2-placeholder.yaml +12 -0
  126. package/src/skills/bmad-method-expert/test-cases/test-3-placeholder.yaml +12 -0
  127. package/src/skills/brownfield-analyzer/SKILL.md +523 -0
  128. package/src/skills/brownfield-analyzer/test-cases/test-1-basic-analysis.yaml +48 -0
  129. package/src/skills/brownfield-analyzer/test-cases/test-2-placeholder.yaml +12 -0
  130. package/src/skills/brownfield-analyzer/test-cases/test-3-placeholder.yaml +12 -0
  131. package/src/skills/brownfield-onboarder/SKILL.md +625 -0
  132. package/src/skills/brownfield-onboarder/test-cases/test-1-placeholder.yaml +12 -0
  133. package/src/skills/brownfield-onboarder/test-cases/test-2-placeholder.yaml +12 -0
  134. package/src/skills/brownfield-onboarder/test-cases/test-3-placeholder.yaml +12 -0
  135. package/src/skills/calendar-system/test-cases/test-1-placeholder.yaml +12 -0
  136. package/src/skills/calendar-system/test-cases/test-2-placeholder.yaml +12 -0
  137. package/src/skills/calendar-system/test-cases/test-3-placeholder.yaml +12 -0
  138. package/src/skills/context-loader/SKILL.md +734 -0
  139. package/src/skills/context-loader/test-cases/test-1-basic-loading.yaml +39 -0
  140. package/src/skills/context-loader/test-cases/test-2-token-budget-exceeded.yaml +44 -0
  141. package/src/skills/context-loader/test-cases/test-3-section-anchors.yaml +45 -0
  142. package/src/skills/context-optimizer/SKILL.md +618 -0
  143. package/src/skills/context-optimizer/test-cases/test-1-bug-fix-narrow.yaml +97 -0
  144. package/src/skills/context-optimizer/test-cases/test-2-feature-focused.yaml +109 -0
  145. package/src/skills/context-optimizer/test-cases/test-3-architecture-broad.yaml +98 -0
  146. package/src/skills/cost-optimizer/SKILL.md +190 -0
  147. package/src/skills/cost-optimizer/test-cases/test-1-basic-comparison.yaml +75 -0
  148. package/src/skills/cost-optimizer/test-cases/test-2-budget-constraint.yaml +52 -0
  149. package/src/skills/cost-optimizer/test-cases/test-3-scale-requirement.yaml +63 -0
  150. package/src/skills/cost-optimizer/test-results/README.md +46 -0
  151. package/src/skills/design-system-architect/SKILL.md +107 -0
  152. package/src/skills/design-system-architect/test-cases/test-1-token-structure.yaml +23 -0
  153. package/src/skills/design-system-architect/test-cases/test-2-component-hierarchy.yaml +24 -0
  154. package/src/skills/design-system-architect/test-cases/test-3-accessibility-checklist.yaml +23 -0
  155. package/src/skills/diagrams-architect/SKILL.md +763 -0
  156. package/src/skills/diagrams-generator/SKILL.md +25 -0
  157. package/src/skills/diagrams-generator/test-cases/test-1.yaml +9 -0
  158. package/src/skills/diagrams-generator/test-cases/test-2.yaml +9 -0
  159. package/src/skills/diagrams-generator/test-cases/test-3.yaml +8 -0
  160. package/src/skills/docs-updater/README.md +48 -0
  161. package/src/skills/docs-updater/test-cases/test-1-placeholder.yaml +12 -0
  162. package/src/skills/docs-updater/test-cases/test-2-placeholder.yaml +12 -0
  163. package/src/skills/docs-updater/test-cases/test-3-placeholder.yaml +12 -0
  164. package/src/skills/dotnet-backend/SKILL.md +250 -0
  165. package/src/skills/e2e-playwright/README.md +506 -0
  166. package/src/skills/e2e-playwright/SKILL.md +457 -0
  167. package/src/skills/e2e-playwright/execute.js +373 -0
  168. package/src/skills/e2e-playwright/lib/utils.js +514 -0
  169. package/src/skills/e2e-playwright/package.json +33 -0
  170. package/src/skills/e2e-playwright/test-cases/TC-001-basic-navigation.yaml +54 -0
  171. package/src/skills/e2e-playwright/test-cases/TC-002-form-interaction.yaml +64 -0
  172. package/src/skills/e2e-playwright/test-cases/TC-003-specweave-integration.yaml +74 -0
  173. package/src/skills/e2e-playwright/test-cases/TC-004-accessibility-check.yaml +98 -0
  174. package/src/skills/figma-designer/SKILL.md +149 -0
  175. package/src/skills/figma-implementer/SKILL.md +148 -0
  176. package/src/skills/figma-mcp-connector/SKILL.md +136 -0
  177. package/src/skills/figma-mcp-connector/test-cases/test-1-read-file-desktop.yaml +22 -0
  178. package/src/skills/figma-mcp-connector/test-cases/test-2-read-file-framelink.yaml +21 -0
  179. package/src/skills/figma-mcp-connector/test-cases/test-3-error-handling.yaml +18 -0
  180. package/src/skills/figma-to-code/SKILL.md +128 -0
  181. package/src/skills/figma-to-code/test-cases/test-1-token-generation.yaml +29 -0
  182. package/src/skills/figma-to-code/test-cases/test-2-component-generation.yaml +27 -0
  183. package/src/skills/figma-to-code/test-cases/test-3-typescript-generation.yaml +28 -0
  184. package/src/skills/frontend/SKILL.md +177 -0
  185. package/src/skills/github-sync/SKILL.md +252 -0
  186. package/src/skills/github-sync/test-cases/test-1-placeholder.yaml +12 -0
  187. package/src/skills/github-sync/test-cases/test-2-placeholder.yaml +12 -0
  188. package/src/skills/github-sync/test-cases/test-3-placeholder.yaml +12 -0
  189. package/src/skills/hetzner-provisioner/README.md +308 -0
  190. package/src/skills/hetzner-provisioner/SKILL.md +251 -0
  191. package/src/skills/hetzner-provisioner/test-cases/test-1-basic-provision.yaml +71 -0
  192. package/src/skills/hetzner-provisioner/test-cases/test-2-postgres-provision.yaml +85 -0
  193. package/src/skills/hetzner-provisioner/test-cases/test-3-ssl-config.yaml +126 -0
  194. package/src/skills/hetzner-provisioner/test-results/README.md +259 -0
  195. package/src/skills/increment-planner/SKILL.md +889 -0
  196. package/src/skills/increment-planner/scripts/feature-utils.js +250 -0
  197. package/src/skills/increment-planner/test-cases/test-1-basic-feature.yaml +27 -0
  198. package/src/skills/increment-planner/test-cases/test-2-complex-feature.yaml +30 -0
  199. package/src/skills/increment-planner/test-cases/test-3-auto-numbering.yaml +24 -0
  200. package/src/skills/increment-quality-judge/SKILL.md +566 -0
  201. package/src/skills/increment-quality-judge/test-cases/test-1-good-spec.yaml +95 -0
  202. package/src/skills/increment-quality-judge/test-cases/test-2-poor-spec.yaml +108 -0
  203. package/src/skills/increment-quality-judge/test-cases/test-3-export-suggestions.yaml +87 -0
  204. package/src/skills/jira-sync/README.md +328 -0
  205. package/src/skills/jira-sync/SKILL.md +209 -0
  206. package/src/skills/jira-sync/test-cases/test-1.yaml +9 -0
  207. package/src/skills/jira-sync/test-cases/test-2.yaml +9 -0
  208. package/src/skills/jira-sync/test-cases/test-3.yaml +10 -0
  209. package/src/skills/nextjs/SKILL.md +176 -0
  210. package/src/skills/nodejs-backend/SKILL.md +181 -0
  211. package/src/skills/notification-system/test-cases/test-1-placeholder.yaml +12 -0
  212. package/src/skills/notification-system/test-cases/test-2-placeholder.yaml +12 -0
  213. package/src/skills/notification-system/test-cases/test-3-placeholder.yaml +12 -0
  214. package/src/skills/python-backend/SKILL.md +226 -0
  215. package/src/skills/role-orchestrator/README.md +197 -0
  216. package/src/skills/role-orchestrator/SKILL.md +1184 -0
  217. package/src/skills/role-orchestrator/test-cases/test-1-simple-product.yaml +98 -0
  218. package/src/skills/role-orchestrator/test-cases/test-2-quality-gate-failure.yaml +73 -0
  219. package/src/skills/role-orchestrator/test-cases/test-3-security-workflow.yaml +121 -0
  220. package/src/skills/role-orchestrator/test-cases/test-4-parallel-execution.yaml +145 -0
  221. package/src/skills/role-orchestrator/test-cases/test-5-feedback-loops.yaml +149 -0
  222. package/src/skills/skill-creator/LICENSE.txt +202 -0
  223. package/src/skills/skill-creator/SKILL.md +209 -0
  224. package/src/skills/skill-creator/scripts/init_skill.py +303 -0
  225. package/src/skills/skill-creator/scripts/package_skill.py +110 -0
  226. package/src/skills/skill-creator/scripts/quick_validate.py +65 -0
  227. package/src/skills/skill-creator/test-cases/test-1-placeholder.yaml +12 -0
  228. package/src/skills/skill-creator/test-cases/test-2-placeholder.yaml +12 -0
  229. package/src/skills/skill-creator/test-cases/test-3-placeholder.yaml +12 -0
  230. package/src/skills/skill-router/SKILL.md +497 -0
  231. package/src/skills/skill-router/test-cases/test-1-basic-routing.yaml +33 -0
  232. package/src/skills/skill-router/test-cases/test-2-ambiguous-request.yaml +42 -0
  233. package/src/skills/skill-router/test-cases/test-3-nested-orchestration.yaml +50 -0
  234. package/src/skills/spec-driven-brainstorming/README.md +264 -0
  235. package/src/skills/spec-driven-brainstorming/SKILL.md +439 -0
  236. package/src/skills/spec-driven-brainstorming/test-cases/TC-001-simple-idea-to-design.yaml +148 -0
  237. package/src/skills/spec-driven-brainstorming/test-cases/TC-002-complex-ultrathink-design.yaml +190 -0
  238. package/src/skills/spec-driven-brainstorming/test-cases/TC-003-unclear-requirements-socratic.yaml +233 -0
  239. package/src/skills/spec-driven-debugging/README.md +479 -0
  240. package/src/skills/spec-driven-debugging/SKILL.md +652 -0
  241. package/src/skills/spec-driven-debugging/test-cases/TC-001-simple-auth-bug.yaml +212 -0
  242. package/src/skills/spec-driven-debugging/test-cases/TC-002-race-condition-ultrathink.yaml +461 -0
  243. package/src/skills/spec-driven-debugging/test-cases/TC-003-brownfield-missing-spec.yaml +366 -0
  244. package/src/skills/spec-kit-expert/SKILL.md +1012 -0
  245. package/src/skills/spec-kit-expert/test-cases/test-1-placeholder.yaml +12 -0
  246. package/src/skills/spec-kit-expert/test-cases/test-2-placeholder.yaml +12 -0
  247. package/src/skills/spec-kit-expert/test-cases/test-3-placeholder.yaml +12 -0
  248. package/src/skills/specweave-ado-mapper/SKILL.md +501 -0
  249. package/src/skills/specweave-detector/SKILL.md +420 -0
  250. package/src/skills/specweave-detector/test-cases/test-1-basic-detection.yaml +37 -0
  251. package/src/skills/specweave-detector/test-cases/test-2-missing-config.yaml +37 -0
  252. package/src/skills/specweave-detector/test-cases/test-3-non-specweave-project.yaml +34 -0
  253. package/src/skills/specweave-jira-mapper/SKILL.md +500 -0
  254. package/src/skills/stripe-integrator/test-cases/test-1-placeholder.yaml +12 -0
  255. package/src/skills/stripe-integrator/test-cases/test-2-placeholder.yaml +12 -0
  256. package/src/skills/stripe-integrator/test-cases/test-3-placeholder.yaml +12 -0
  257. package/src/skills/task-builder/README.md +90 -0
  258. package/src/skills/task-builder/test-cases/test-1-placeholder.yaml +12 -0
  259. package/src/skills/task-builder/test-cases/test-2-placeholder.yaml +12 -0
  260. package/src/skills/task-builder/test-cases/test-3-placeholder.yaml +12 -0
  261. package/src/templates/.env.example +144 -0
  262. package/src/templates/.gitignore.template +81 -0
  263. package/src/templates/CLAUDE.md.template +383 -0
  264. package/src/templates/README.md.template +240 -0
  265. package/src/templates/config.yaml +333 -0
  266. package/src/templates/docs/README.md +124 -0
  267. package/src/templates/docs/adr-template.md +118 -0
  268. package/src/templates/docs/hld-template.md +220 -0
  269. package/src/templates/docs/lld-template.md +580 -0
  270. package/src/templates/docs/prd-template.md +132 -0
  271. package/src/templates/docs/rfc-template.md +229 -0
  272. package/src/templates/docs/runbook-template.md +298 -0
  273. package/src/templates/environments/minimal/.env.production +16 -0
  274. package/src/templates/environments/minimal/README.md +54 -0
  275. package/src/templates/environments/minimal/deploy-production.yml +52 -0
  276. package/src/templates/environments/progressive/.env.qa +28 -0
  277. package/src/templates/environments/progressive/README.md +129 -0
  278. package/src/templates/environments/progressive/deploy-production.yml +93 -0
  279. package/src/templates/environments/progressive/deploy-qa.yml +62 -0
  280. package/src/templates/environments/progressive/deploy-staging.yml +67 -0
  281. package/src/templates/environments/standard/.env.development +20 -0
  282. package/src/templates/environments/standard/.env.production +30 -0
  283. package/src/templates/environments/standard/.env.staging +23 -0
  284. package/src/templates/environments/standard/README.md +97 -0
  285. package/src/templates/environments/standard/deploy-production.yml +68 -0
  286. package/src/templates/environments/standard/deploy-staging.yml +61 -0
  287. package/src/templates/environments/standard/docker-compose.yml +43 -0
  288. package/src/templates/increment-metadata-template.yaml +138 -0
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Feature Planning Utilities for SpecWeave
3
+ * Supports increment-planner skill with auto-numbering and name generation
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ /**
10
+ * Stop words to filter from feature descriptions
11
+ */
12
+ const STOP_WORDS = new Set([
13
+ 'a', 'an', 'the', 'and', 'or', 'but', 'for', 'with', 'to', 'from', 'in', 'on', 'at',
14
+ 'by', 'of', 'as', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
15
+ 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should',
16
+ 'can', 'may', 'might', 'must', 'i', 'you', 'we', 'they', 'it', 'this', 'that',
17
+ 'want', 'need', 'help', 'please', 'create', 'make', 'build'
18
+ ]);
19
+
20
+ /**
21
+ * Generate a short feature name from description
22
+ * @param {string} description - Feature description
23
+ * @returns {string} Short kebab-case name
24
+ */
25
+ function generateShortName(description) {
26
+ // Lowercase and remove special characters
27
+ let cleaned = description
28
+ .toLowerCase()
29
+ .replace(/[^a-z0-9\s-]/g, ' ')
30
+ .trim();
31
+
32
+ // Split into words
33
+ let words = cleaned.split(/\s+/);
34
+
35
+ // Filter stop words
36
+ let meaningful = words.filter(word =>
37
+ word.length > 2 && !STOP_WORDS.has(word)
38
+ );
39
+
40
+ // Take first 2-4 most meaningful words
41
+ let selected = meaningful.slice(0, Math.min(4, meaningful.length));
42
+
43
+ // Join with hyphens
44
+ let shortName = selected.join('-');
45
+
46
+ // Enforce max 50 characters
47
+ if (shortName.length > 50) {
48
+ shortName = shortName.substring(0, 47) + '...';
49
+ }
50
+
51
+ return shortName || 'new-feature';
52
+ }
53
+
54
+ /**
55
+ * Get the next available feature number
56
+ * @param {string} featuresDir - Path to features directory (default: '.specweave/increments')
57
+ * @returns {string} Next feature number (zero-padded to 4 digits: 0001-9999)
58
+ */
59
+ function getNextFeatureNumber(featuresDir = '.specweave/increments') {
60
+ let highest = 0;
61
+
62
+ if (fs.existsSync(featuresDir)) {
63
+ const entries = fs.readdirSync(featuresDir);
64
+
65
+ entries.forEach(entry => {
66
+ // Match BOTH 3-digit (legacy) and 4-digit formats to prevent conflicts
67
+ const match = entry.match(/^(\d{3,4})-/);
68
+ if (match) {
69
+ const num = parseInt(match[1], 10);
70
+ if (num > highest) {
71
+ highest = num;
72
+ }
73
+ }
74
+ });
75
+ }
76
+
77
+ const next = highest + 1;
78
+
79
+ // Always return 4-digit format
80
+ return String(next).padStart(4, '0');
81
+ }
82
+
83
+ /**
84
+ * Check if feature name already exists
85
+ * @param {string} shortName - Feature short name
86
+ * @param {string} featuresDir - Path to features directory
87
+ * @returns {boolean} True if exists
88
+ */
89
+ function featureExists(shortName, featuresDir = '.specweave/increments') {
90
+ if (!fs.existsSync(featuresDir)) {
91
+ return false;
92
+ }
93
+
94
+ const entries = fs.readdirSync(featuresDir);
95
+ return entries.some(entry => entry.endsWith(`-${shortName}`));
96
+ }
97
+
98
+ /**
99
+ * Check if increment number already exists (prevents duplicates like 0002, 0002)
100
+ * @param {string} incrementNumber - Increment number to check (e.g., '0001')
101
+ * @param {string} featuresDir - Path to features directory
102
+ * @returns {boolean} True if number already exists
103
+ */
104
+ function incrementNumberExists(incrementNumber, featuresDir = '.specweave/increments') {
105
+ if (!fs.existsSync(featuresDir)) {
106
+ return false;
107
+ }
108
+
109
+ const entries = fs.readdirSync(featuresDir);
110
+
111
+ // Normalize to 4-digit format for comparison
112
+ const normalizedNum = String(incrementNumber).padStart(4, '0');
113
+
114
+ return entries.some(entry => {
115
+ const match = entry.match(/^(\d{3,4})-/);
116
+ if (match) {
117
+ const entryNum = String(match[1]).padStart(4, '0');
118
+ return entryNum === normalizedNum;
119
+ }
120
+ return false;
121
+ });
122
+ }
123
+
124
+ /**
125
+ * Create feature directory structure
126
+ * @param {string} featureNumber - Feature number (e.g., '0001')
127
+ * @param {string} shortName - Feature short name
128
+ * @param {string} featuresDir - Path to features directory
129
+ * @returns {string} Full feature path
130
+ * @throws {Error} If increment number already exists
131
+ */
132
+ function createFeatureDirectory(featureNumber, shortName, featuresDir = '.specweave/increments') {
133
+ // Normalize to 4-digit format
134
+ const normalizedNumber = String(featureNumber).padStart(4, '0');
135
+
136
+ // Check for duplicate increment number
137
+ if (incrementNumberExists(normalizedNumber, featuresDir)) {
138
+ throw new Error(`Increment number ${normalizedNumber} already exists! Use getNextFeatureNumber() to get the next available number.`);
139
+ }
140
+
141
+ const featurePath = path.join(featuresDir, `${normalizedNumber}-${shortName}`);
142
+
143
+ if (!fs.existsSync(featuresDir)) {
144
+ fs.mkdirSync(featuresDir, { recursive: true });
145
+ }
146
+
147
+ if (!fs.existsSync(featurePath)) {
148
+ fs.mkdirSync(featurePath, { recursive: true });
149
+ }
150
+
151
+ return featurePath;
152
+ }
153
+
154
+ /**
155
+ * Extract priority from description
156
+ * @param {string} description - Feature description
157
+ * @returns {string} Priority level (P1, P2, or P3)
158
+ */
159
+ function extractPriority(description) {
160
+ const lower = description.toLowerCase();
161
+
162
+ // Check for explicit priority mentions
163
+ if (lower.includes('critical') || lower.includes('must have') || lower.includes('mvp')) {
164
+ return 'P1';
165
+ }
166
+
167
+ if (lower.includes('nice to have') || lower.includes('polish') || lower.includes('optional')) {
168
+ return 'P3';
169
+ }
170
+
171
+ // Default to P2 (important)
172
+ return 'P2';
173
+ }
174
+
175
+ /**
176
+ * Get current date in YYYY-MM-DD format
177
+ * @returns {string} Current date
178
+ */
179
+ function getCurrentDate() {
180
+ const now = new Date();
181
+ const year = now.getFullYear();
182
+ const month = String(now.getMonth() + 1).padStart(2, '0');
183
+ const day = String(now.getDate()).padStart(2, '0');
184
+ return `${year}-${month}-${day}`;
185
+ }
186
+
187
+ /**
188
+ * Parse feature description into structured data
189
+ * @param {string} description - Feature description
190
+ * @returns {object} Parsed feature data
191
+ */
192
+ function parseFeatureDescription(description) {
193
+ return {
194
+ description,
195
+ shortName: generateShortName(description),
196
+ priority: extractPriority(description),
197
+ createdDate: getCurrentDate()
198
+ };
199
+ }
200
+
201
+ module.exports = {
202
+ generateShortName,
203
+ getNextFeatureNumber,
204
+ featureExists,
205
+ incrementNumberExists,
206
+ createFeatureDirectory,
207
+ extractPriority,
208
+ getCurrentDate,
209
+ parseFeatureDescription,
210
+ STOP_WORDS
211
+ };
212
+
213
+ // CLI usage
214
+ if (require.main === module) {
215
+ const args = process.argv.slice(2);
216
+
217
+ if (args.length === 0) {
218
+ console.log('Usage:');
219
+ console.log(' node feature-utils.js shortname "feature description"');
220
+ console.log(' node feature-utils.js next [features-dir]');
221
+ console.log(' node feature-utils.js parse "feature description"');
222
+ process.exit(0);
223
+ }
224
+
225
+ const command = args[0];
226
+
227
+ switch (command) {
228
+ case 'shortname':
229
+ if (args[1]) {
230
+ console.log(generateShortName(args[1]));
231
+ }
232
+ break;
233
+
234
+ case 'next':
235
+ const dir = args[1] || '.specweave/increments';
236
+ console.log(getNextFeatureNumber(dir));
237
+ break;
238
+
239
+ case 'parse':
240
+ if (args[1]) {
241
+ const parsed = parseFeatureDescription(args[1]);
242
+ console.log(JSON.stringify(parsed, null, 2));
243
+ }
244
+ break;
245
+
246
+ default:
247
+ console.error(`Unknown command: ${command}`);
248
+ process.exit(1);
249
+ }
250
+ }
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: "Basic Feature Planning"
3
+ description: "Tests if increment-planner can create a basic feature from a simple description"
4
+ input:
5
+ prompt: "Plan a feature for user authentication with email and password"
6
+ files: []
7
+ expected_output:
8
+ type: "files_generated"
9
+ files:
10
+ - "features/001-user-authentication/spec.md"
11
+ - "features/001-user-authentication/plan.md"
12
+ - "features/001-user-authentication/tasks.md"
13
+ - "features/001-user-authentication/tests.md"
14
+ - "features/001-user-authentication/context-manifest.yaml"
15
+ contains:
16
+ - "User authentication"
17
+ - "P1"
18
+ - "Acceptance Criteria"
19
+ - "Test-First"
20
+ validation:
21
+ - "All files exist in correct directory"
22
+ - "spec.md is technology-agnostic"
23
+ - "plan.md contains technical decisions"
24
+ - "tasks.md has test-first sequencing"
25
+ - "tests.md covers P1 user stories"
26
+ - "context-manifest.yaml has token budget"
27
+ ---
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: "Complex Feature with Multiple User Stories"
3
+ description: "Tests feature planning for a complex feature with multiple priorities"
4
+ input:
5
+ prompt: "Plan a feature for Stripe payment integration including subscriptions, one-time payments, and webhooks"
6
+ files: []
7
+ expected_output:
8
+ type: "files_generated"
9
+ files:
10
+ - "features/002-stripe-payment-integration/spec.md"
11
+ - "features/002-stripe-payment-integration/plan.md"
12
+ - "features/002-stripe-payment-integration/tasks.md"
13
+ - "features/002-stripe-payment-integration/tests.md"
14
+ - "features/002-stripe-payment-integration/context-manifest.yaml"
15
+ contains:
16
+ - "US1"
17
+ - "US2"
18
+ - "US3"
19
+ - "P1"
20
+ - "P2"
21
+ - "Stripe"
22
+ - "subscriptions"
23
+ - "webhooks"
24
+ validation:
25
+ - "Multiple user stories with different priorities"
26
+ - "P1/P2/P3 prioritization present"
27
+ - "tasks.md organized by user story"
28
+ - "tests.md has integration tests"
29
+ - "context-manifest.yaml references payment specs"
30
+ ---
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: "Auto-Numbering Feature Test"
3
+ description: "Tests that features are correctly auto-numbered when previous features exist"
4
+ input:
5
+ prompt: "Plan a feature for email notifications"
6
+ files:
7
+ - "features/001-user-authentication/"
8
+ - "features/002-stripe-payment-integration/"
9
+ expected_output:
10
+ type: "files_generated"
11
+ files:
12
+ - "features/003-email-notifications/spec.md"
13
+ - "features/003-email-notifications/plan.md"
14
+ - "features/003-email-notifications/tasks.md"
15
+ - "features/003-email-notifications/tests.md"
16
+ - "features/003-email-notifications/context-manifest.yaml"
17
+ contains:
18
+ - "feature: 003-email-notifications"
19
+ - "003"
20
+ validation:
21
+ - "Feature number is 003 (incremented from 002)"
22
+ - "No conflicts with existing features"
23
+ - "features/README.md updated with new feature"
24
+ ---