speckit-assistant 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 (180) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +71 -0
  3. package/.next/app-path-routes-manifest.json +10 -0
  4. package/.next/build-manifest.json +33 -0
  5. package/.next/cache/.previewinfo +1 -0
  6. package/.next/cache/.rscinfo +1 -0
  7. package/.next/cache/webpack/client-production/0.pack +0 -0
  8. package/.next/cache/webpack/client-production/1.pack +0 -0
  9. package/.next/cache/webpack/client-production/10.pack +0 -0
  10. package/.next/cache/webpack/client-production/11.pack +0 -0
  11. package/.next/cache/webpack/client-production/12.pack +0 -0
  12. package/.next/cache/webpack/client-production/13.pack +0 -0
  13. package/.next/cache/webpack/client-production/14.pack +0 -0
  14. package/.next/cache/webpack/client-production/15.pack +0 -0
  15. package/.next/cache/webpack/client-production/16.pack +0 -0
  16. package/.next/cache/webpack/client-production/17.pack +0 -0
  17. package/.next/cache/webpack/client-production/18.pack +0 -0
  18. package/.next/cache/webpack/client-production/19.pack +0 -0
  19. package/.next/cache/webpack/client-production/2.pack +0 -0
  20. package/.next/cache/webpack/client-production/20.pack +0 -0
  21. package/.next/cache/webpack/client-production/21.pack +0 -0
  22. package/.next/cache/webpack/client-production/22.pack +0 -0
  23. package/.next/cache/webpack/client-production/3.pack +0 -0
  24. package/.next/cache/webpack/client-production/4.pack +0 -0
  25. package/.next/cache/webpack/client-production/5.pack +0 -0
  26. package/.next/cache/webpack/client-production/6.pack +0 -0
  27. package/.next/cache/webpack/client-production/7.pack +0 -0
  28. package/.next/cache/webpack/client-production/8.pack +0 -0
  29. package/.next/cache/webpack/client-production/9.pack +0 -0
  30. package/.next/cache/webpack/client-production/index.pack +0 -0
  31. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  32. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  33. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  34. package/.next/cache/webpack/server-production/0.pack +0 -0
  35. package/.next/cache/webpack/server-production/1.pack +0 -0
  36. package/.next/cache/webpack/server-production/10.pack +0 -0
  37. package/.next/cache/webpack/server-production/11.pack +0 -0
  38. package/.next/cache/webpack/server-production/12.pack +0 -0
  39. package/.next/cache/webpack/server-production/13.pack +0 -0
  40. package/.next/cache/webpack/server-production/14.pack +0 -0
  41. package/.next/cache/webpack/server-production/15.pack +0 -0
  42. package/.next/cache/webpack/server-production/16.pack +0 -0
  43. package/.next/cache/webpack/server-production/17.pack +0 -0
  44. package/.next/cache/webpack/server-production/18.pack +0 -0
  45. package/.next/cache/webpack/server-production/19.pack +0 -0
  46. package/.next/cache/webpack/server-production/2.pack +0 -0
  47. package/.next/cache/webpack/server-production/20.pack +0 -0
  48. package/.next/cache/webpack/server-production/3.pack +0 -0
  49. package/.next/cache/webpack/server-production/4.pack +0 -0
  50. package/.next/cache/webpack/server-production/5.pack +0 -0
  51. package/.next/cache/webpack/server-production/6.pack +0 -0
  52. package/.next/cache/webpack/server-production/7.pack +0 -0
  53. package/.next/cache/webpack/server-production/8.pack +0 -0
  54. package/.next/cache/webpack/server-production/9.pack +0 -0
  55. package/.next/cache/webpack/server-production/index.pack +0 -0
  56. package/.next/cache/webpack/server-production/index.pack.old +0 -0
  57. package/.next/diagnostics/build-diagnostics.json +6 -0
  58. package/.next/diagnostics/framework.json +1 -0
  59. package/.next/export-marker.json +6 -0
  60. package/.next/images-manifest.json +58 -0
  61. package/.next/next-minimal-server.js.nft.json +1 -0
  62. package/.next/next-server.js.nft.json +1 -0
  63. package/.next/package.json +1 -0
  64. package/.next/prerender-manifest.json +61 -0
  65. package/.next/react-loadable-manifest.json +1 -0
  66. package/.next/required-server-files.json +320 -0
  67. package/.next/routes-manifest.json +53 -0
  68. package/.next/server/app/_not-found/page.js +2 -0
  69. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  70. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  71. package/.next/server/app/_not-found.html +1 -0
  72. package/.next/server/app/_not-found.meta +8 -0
  73. package/.next/server/app/_not-found.rsc +15 -0
  74. package/.next/server/app/api/feature/route.js +1 -0
  75. package/.next/server/app/api/feature/route.js.nft.json +1 -0
  76. package/.next/server/app/api/feature/route_client-reference-manifest.js +1 -0
  77. package/.next/server/app/api/file/route.js +1 -0
  78. package/.next/server/app/api/file/route.js.nft.json +1 -0
  79. package/.next/server/app/api/file/route_client-reference-manifest.js +1 -0
  80. package/.next/server/app/api/phase/route.js +4 -0
  81. package/.next/server/app/api/phase/route.js.nft.json +1 -0
  82. package/.next/server/app/api/phase/route_client-reference-manifest.js +1 -0
  83. package/.next/server/app/api/state/route.js +1 -0
  84. package/.next/server/app/api/state/route.js.nft.json +1 -0
  85. package/.next/server/app/api/state/route_client-reference-manifest.js +1 -0
  86. package/.next/server/app/api/state/watch/route.js +4 -0
  87. package/.next/server/app/api/state/watch/route.js.nft.json +1 -0
  88. package/.next/server/app/api/state/watch/route_client-reference-manifest.js +1 -0
  89. package/.next/server/app/api/task/route.js +1 -0
  90. package/.next/server/app/api/task/route.js.nft.json +1 -0
  91. package/.next/server/app/api/task/route_client-reference-manifest.js +1 -0
  92. package/.next/server/app/index.html +1 -0
  93. package/.next/server/app/index.meta +7 -0
  94. package/.next/server/app/index.rsc +20 -0
  95. package/.next/server/app/page.js +14 -0
  96. package/.next/server/app/page.js.nft.json +1 -0
  97. package/.next/server/app/page_client-reference-manifest.js +1 -0
  98. package/.next/server/app-paths-manifest.json +10 -0
  99. package/.next/server/chunks/355.js +22 -0
  100. package/.next/server/chunks/6.js +9 -0
  101. package/.next/server/chunks/607.js +6 -0
  102. package/.next/server/chunks/643.js +1 -0
  103. package/.next/server/chunks/897.js +9 -0
  104. package/.next/server/functions-config-manifest.json +4 -0
  105. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  106. package/.next/server/middleware-build-manifest.js +1 -0
  107. package/.next/server/middleware-manifest.json +6 -0
  108. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  109. package/.next/server/next-font-manifest.js +1 -0
  110. package/.next/server/next-font-manifest.json +1 -0
  111. package/.next/server/pages/404.html +1 -0
  112. package/.next/server/pages/500.html +1 -0
  113. package/.next/server/pages/_app.js +1 -0
  114. package/.next/server/pages/_app.js.nft.json +1 -0
  115. package/.next/server/pages/_document.js +1 -0
  116. package/.next/server/pages/_document.js.nft.json +1 -0
  117. package/.next/server/pages/_error.js +19 -0
  118. package/.next/server/pages/_error.js.nft.json +1 -0
  119. package/.next/server/pages-manifest.json +6 -0
  120. package/.next/server/server-reference-manifest.js +1 -0
  121. package/.next/server/server-reference-manifest.json +1 -0
  122. package/.next/server/webpack-runtime.js +1 -0
  123. package/.next/static/chunks/590-a6568595ecd2a994.js +1 -0
  124. package/.next/static/chunks/8381d2c4-9707dccab70b742b.js +1 -0
  125. package/.next/static/chunks/920-f9bfc1b0d0402c3e.js +1 -0
  126. package/.next/static/chunks/acfafb44-8249079a6627ac92.js +1 -0
  127. package/.next/static/chunks/app/_not-found/page-be798b363e27e8c5.js +1 -0
  128. package/.next/static/chunks/app/api/feature/route-bb3c1a82e892ab58.js +1 -0
  129. package/.next/static/chunks/app/api/file/route-bb3c1a82e892ab58.js +1 -0
  130. package/.next/static/chunks/app/api/phase/route-bb3c1a82e892ab58.js +1 -0
  131. package/.next/static/chunks/app/api/state/route-bb3c1a82e892ab58.js +1 -0
  132. package/.next/static/chunks/app/api/state/watch/route-bb3c1a82e892ab58.js +1 -0
  133. package/.next/static/chunks/app/api/task/route-bb3c1a82e892ab58.js +1 -0
  134. package/.next/static/chunks/app/layout-3226c76a5f7f74bc.js +1 -0
  135. package/.next/static/chunks/app/page-8a5248f7704cde29.js +1 -0
  136. package/.next/static/chunks/framework-20dd4f6054cc5446.js +1 -0
  137. package/.next/static/chunks/main-91029f76ac1b7110.js +1 -0
  138. package/.next/static/chunks/main-app-b9ad56d6b1dfa941.js +1 -0
  139. package/.next/static/chunks/pages/_app-aa33dc41c3472021.js +1 -0
  140. package/.next/static/chunks/pages/_error-78b0b3b591df0e73.js +1 -0
  141. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  142. package/.next/static/chunks/webpack-c460f8e58a9e9eff.js +1 -0
  143. package/.next/static/css/008a05b0ad6b854a.css +31 -0
  144. package/.next/static/css/6fd2e11db3a59771.css +3 -0
  145. package/.next/static/fWuQ3yoHovA7Cre6u89W7/_buildManifest.js +1 -0
  146. package/.next/static/fWuQ3yoHovA7Cre6u89W7/_ssgManifest.js +1 -0
  147. package/.next/trace +3 -0
  148. package/.next/types/app/api/feature/route.ts +347 -0
  149. package/.next/types/app/api/file/route.ts +347 -0
  150. package/.next/types/app/api/phase/route.ts +347 -0
  151. package/.next/types/app/api/state/route.ts +347 -0
  152. package/.next/types/app/api/state/watch/route.ts +347 -0
  153. package/.next/types/app/api/task/route.ts +347 -0
  154. package/.next/types/app/layout.ts +84 -0
  155. package/.next/types/app/page.ts +84 -0
  156. package/.next/types/cache-life.d.ts +141 -0
  157. package/.next/types/package.json +1 -0
  158. package/.next/types/routes.d.ts +78 -0
  159. package/.next/types/validator.ts +124 -0
  160. package/LICENSE +21 -0
  161. package/README.md +284 -0
  162. package/bin/adapters/di.js +9 -0
  163. package/bin/adapters/primary/api/utils.js +57 -0
  164. package/bin/adapters/secondary/agent/ProcessAgentRunner.js +161 -0
  165. package/bin/adapters/secondary/fs/FSWorkspaceRepository.js +283 -0
  166. package/bin/app/api/feature/route.js +35 -0
  167. package/bin/app/api/file/route.js +36 -0
  168. package/bin/app/api/phase/route.js +55 -0
  169. package/bin/app/api/state/route.js +28 -0
  170. package/bin/app/api/state/watch/route.js +92 -0
  171. package/bin/app/api/task/route.js +20 -0
  172. package/bin/bin/cli.js +317 -0
  173. package/bin/cli.js +85 -0
  174. package/bin/domain/models/types.js +2 -0
  175. package/bin/domain/ports/in/WorkflowUseCases.js +2 -0
  176. package/bin/domain/ports/out/AgentRunnerPort.js +2 -0
  177. package/bin/domain/ports/out/WorkspaceRepositoryPort.js +2 -0
  178. package/bin/domain/services/WorkflowService.js +174 -0
  179. package/next.config.ts +13 -0
  180. package/package.json +53 -0
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkflowService = void 0;
4
+ const FEATURE_PHASES = [
5
+ 'specification',
6
+ 'clarification',
7
+ 'planning',
8
+ 'checklist',
9
+ 'analyze',
10
+ 'tasks',
11
+ 'taskstoissues',
12
+ 'implementation'
13
+ ];
14
+ class WorkflowService {
15
+ workspaceRepo;
16
+ agentRunner;
17
+ constructor(workspaceRepo, agentRunner) {
18
+ this.workspaceRepo = workspaceRepo;
19
+ this.agentRunner = agentRunner;
20
+ }
21
+ async getWorkflowState(workspacePath) {
22
+ const state = await this.workspaceRepo.getWorkflowState(workspacePath);
23
+ return state;
24
+ }
25
+ async createFeature(workspacePath, name) {
26
+ const state = await this.workspaceRepo.createFeature(workspacePath, name);
27
+ state.activeFeatureName = name;
28
+ await this.workspaceRepo.saveWorkflowState(workspacePath, state);
29
+ return state;
30
+ }
31
+ async deleteFeature(workspacePath, name) {
32
+ const state = await this.workspaceRepo.deleteFeature(workspacePath, name);
33
+ return state;
34
+ }
35
+ async setActiveFeature(workspacePath, name) {
36
+ const state = await this.workspaceRepo.getWorkflowState(workspacePath);
37
+ if (state.features.some(f => f.name === name)) {
38
+ state.activeFeatureName = name;
39
+ await this.workspaceRepo.saveWorkflowState(workspacePath, state);
40
+ }
41
+ return state;
42
+ }
43
+ async runPhase(workspacePath, phase, featureName, agentConfig, userPrompt, onData) {
44
+ const state = await this.workspaceRepo.getWorkflowState(workspacePath);
45
+ const targetFeature = featureName || state.activeFeatureName;
46
+ // Set status to running
47
+ this.setPhaseStatus(state, phase, targetFeature, 'running');
48
+ await this.workspaceRepo.saveWorkflowState(workspacePath, state);
49
+ try {
50
+ const exitCode = await this.agentRunner.runPhase(workspacePath, phase, targetFeature, agentConfig, userPrompt, onData);
51
+ // Re-read state in case files changed on disk during run
52
+ const freshState = await this.workspaceRepo.getWorkflowState(workspacePath);
53
+ if (exitCode === 0) {
54
+ this.setPhaseStatus(freshState, phase, targetFeature, 'awaiting_review');
55
+ }
56
+ else {
57
+ this.setPhaseStatus(freshState, phase, targetFeature, 'idle');
58
+ }
59
+ // Check if tasks are completed to auto-complete implementation
60
+ if (phase === 'implementation') {
61
+ await this.checkImplementationAutoReview(workspacePath, freshState, targetFeature);
62
+ }
63
+ await this.workspaceRepo.saveWorkflowState(workspacePath, freshState);
64
+ return freshState;
65
+ }
66
+ catch (err) {
67
+ const freshState = await this.workspaceRepo.getWorkflowState(workspacePath);
68
+ this.setPhaseStatus(freshState, phase, targetFeature, 'idle');
69
+ await this.workspaceRepo.saveWorkflowState(workspacePath, freshState);
70
+ throw err;
71
+ }
72
+ }
73
+ async approvePhase(workspacePath, phase, featureName) {
74
+ const state = await this.workspaceRepo.getWorkflowState(workspacePath);
75
+ const targetFeature = featureName || state.activeFeatureName;
76
+ const ps = this.findPhase(state, phase, targetFeature);
77
+ if (ps) {
78
+ ps.status = 'approved';
79
+ ps.stale = false;
80
+ }
81
+ await this.workspaceRepo.saveWorkflowState(workspacePath, state);
82
+ return state;
83
+ }
84
+ async discardPhase(workspacePath, phase, featureName) {
85
+ const state = await this.workspaceRepo.getWorkflowState(workspacePath);
86
+ const targetFeature = featureName || state.activeFeatureName;
87
+ const ps = this.findPhase(state, phase, targetFeature);
88
+ if (ps) {
89
+ ps.status = 'idle';
90
+ ps.content = null;
91
+ ps.stale = false;
92
+ }
93
+ this.markDownstreamStale(state, phase, targetFeature);
94
+ await this.workspaceRepo.saveWorkflowState(workspacePath, state);
95
+ return state;
96
+ }
97
+ async toggleTask(workspacePath, featureName, lineIndex, checked) {
98
+ const freshState = await this.workspaceRepo.toggleTask(workspacePath, featureName, lineIndex, checked);
99
+ await this.checkImplementationAutoReview(workspacePath, freshState, featureName);
100
+ await this.workspaceRepo.saveWorkflowState(workspacePath, freshState);
101
+ return freshState;
102
+ }
103
+ async readFile(workspacePath, filePath) {
104
+ return this.workspaceRepo.readFile(workspacePath, filePath);
105
+ }
106
+ async writeFile(workspacePath, filePath, content) {
107
+ await this.workspaceRepo.writeFile(workspacePath, filePath, content);
108
+ // Determine which phase/feature this file belongs to and update status to awaiting_review if not approved
109
+ const state = await this.workspaceRepo.getWorkflowState(workspacePath);
110
+ await this.workspaceRepo.saveWorkflowState(workspacePath, state);
111
+ return state;
112
+ }
113
+ // Helper methods
114
+ findPhase(state, phase, featureName) {
115
+ if (phase === 'constitution') {
116
+ return state.constitutionPhase;
117
+ }
118
+ const feature = state.features.find(f => f.name === featureName);
119
+ if (!feature)
120
+ return null;
121
+ return feature.phases.find(p => p.phase === phase) || null;
122
+ }
123
+ setPhaseStatus(state, phase, featureName, status) {
124
+ const ps = this.findPhase(state, phase, featureName);
125
+ if (ps) {
126
+ ps.status = status;
127
+ }
128
+ }
129
+ markDownstreamStale(state, discarded, featureName) {
130
+ if (discarded === 'constitution') {
131
+ for (const feature of state.features) {
132
+ for (const p of feature.phases) {
133
+ if (p.status === 'approved')
134
+ p.stale = true;
135
+ }
136
+ }
137
+ return;
138
+ }
139
+ const feature = state.features.find(f => f.name === featureName);
140
+ if (!feature)
141
+ return;
142
+ const idx = FEATURE_PHASES.indexOf(discarded);
143
+ if (idx === -1)
144
+ return;
145
+ for (let i = idx + 1; i < FEATURE_PHASES.length; i++) {
146
+ const later = feature.phases.find(p => p.phase === FEATURE_PHASES[i]);
147
+ if (later && later.status === 'approved') {
148
+ later.stale = true;
149
+ }
150
+ }
151
+ }
152
+ async checkImplementationAutoReview(workspacePath, state, featureName) {
153
+ const feature = state.features.find(f => f.name === featureName);
154
+ if (!feature)
155
+ return;
156
+ const tasksPhase = feature.phases.find(p => p.phase === 'tasks');
157
+ const implPhase = feature.phases.find(p => p.phase === 'implementation');
158
+ if (!tasksPhase?.filePath || !implPhase)
159
+ return;
160
+ try {
161
+ const content = await this.workspaceRepo.readFile(workspacePath, tasksPhase.filePath);
162
+ const checkboxes = [...content.matchAll(/^\s*(?:[-*]|\d+\.)\s+\[( |x|X)\]/gm)];
163
+ if (checkboxes.length > 0 && checkboxes.every(c => c[1].toLowerCase() === 'x')) {
164
+ if (implPhase.status === 'running' || implPhase.status === 'idle') {
165
+ implPhase.status = 'awaiting_review';
166
+ }
167
+ }
168
+ }
169
+ catch {
170
+ // ignore
171
+ }
172
+ }
173
+ }
174
+ exports.WorkflowService = WorkflowService;
package/next.config.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ reactStrictMode: true,
5
+ eslint: {
6
+ ignoreDuringBuilds: true,
7
+ },
8
+ typescript: {
9
+ ignoreBuildErrors: true,
10
+ }
11
+ };
12
+
13
+ export default nextConfig;
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "speckit-assistant",
3
+ "version": "0.1.0",
4
+ "description": "Visual orchestrator for Spec-Driven Development (SDD) — Next.js, ReactFlow and Hexagonal Architecture",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "speckit-assistant": "./bin/bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "dev": "next dev",
11
+ "build": "next build && tsc -p tsconfig.bin.json",
12
+ "start": "next start",
13
+ "test": "vitest run",
14
+ "prepublishOnly": "pnpm run build"
15
+ },
16
+ "files": [
17
+ "bin",
18
+ ".next",
19
+ "next.config.ts"
20
+ ],
21
+ "keywords": [
22
+ "sdd",
23
+ "speckit",
24
+ "nextjs",
25
+ "reactflow",
26
+ "hexagonal-architecture"
27
+ ],
28
+ "author": "",
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "@xyflow/react": "^12.3.5",
32
+ "chokidar": "^5.0.0",
33
+ "class-variance-authority": "^0.7.1",
34
+ "clsx": "^2.1.1",
35
+ "lucide-react": "^0.468.0",
36
+ "next": "^15.1.0",
37
+ "open": "^10.1.0",
38
+ "react": "^19.0.0",
39
+ "react-dom": "^19.0.0",
40
+ "tailwind-merge": "^2.5.5"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^20.17.9",
44
+ "@types/react": "^19.0.1",
45
+ "@types/react-dom": "^19.0.2",
46
+ "@vitest/coverage-v8": "^2.1.9",
47
+ "autoprefixer": "^10.4.20",
48
+ "postcss": "^8.4.49",
49
+ "tailwindcss": "^3.4.16",
50
+ "typescript": "^5.7.2",
51
+ "vitest": "^2.1.8"
52
+ }
53
+ }