specsmd 0.0.0-dev.85 → 0.0.0-dev.87

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 (62) hide show
  1. package/README.md +15 -0
  2. package/bin/cli.js +15 -1
  3. package/flows/fire/agents/builder/agent.md +2 -2
  4. package/flows/fire/agents/builder/skills/code-review/SKILL.md +1 -1
  5. package/flows/fire/agents/builder/skills/run-execute/SKILL.md +16 -7
  6. package/flows/fire/agents/builder/skills/run-execute/scripts/complete-run.cjs +22 -3
  7. package/flows/fire/agents/builder/skills/run-execute/scripts/init-run.cjs +63 -20
  8. package/flows/fire/agents/builder/skills/run-execute/scripts/update-checkpoint.cjs +254 -0
  9. package/flows/fire/agents/builder/skills/run-execute/scripts/update-phase.cjs +17 -6
  10. package/flows/fire/agents/builder/skills/run-status/SKILL.md +1 -1
  11. package/flows/fire/agents/builder/skills/walkthrough-generate/SKILL.md +30 -27
  12. package/flows/fire/agents/orchestrator/agent.md +1 -1
  13. package/flows/fire/agents/orchestrator/skills/status/SKILL.md +2 -2
  14. package/flows/fire/memory-bank.yaml +4 -4
  15. package/flows/ideation/agents/orchestrator/agent.md +8 -7
  16. package/flows/ideation/agents/orchestrator/skills/flame/SKILL.md +1 -0
  17. package/flows/ideation/agents/orchestrator/skills/flame/references/evaluation-criteria.md +4 -0
  18. package/flows/ideation/agents/orchestrator/skills/flame/references/six-hats-method.md +12 -0
  19. package/flows/ideation/agents/orchestrator/skills/forge/SKILL.md +1 -0
  20. package/flows/ideation/agents/orchestrator/skills/forge/references/disney-method.md +8 -0
  21. package/flows/ideation/agents/orchestrator/skills/forge/references/pitch-framework.md +15 -0
  22. package/flows/ideation/agents/orchestrator/skills/spark/SKILL.md +1 -0
  23. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/analogy.md +7 -0
  24. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/first-principles.md +5 -0
  25. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/inversion.md +6 -0
  26. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/questorming.md +6 -0
  27. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/random-word.md +1 -0
  28. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/scamper.md +15 -0
  29. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/what-if.md +6 -0
  30. package/flows/ideation/shared/protocols/anti-bias.md +7 -4
  31. package/flows/ideation/shared/protocols/deep-thinking.md +7 -0
  32. package/flows/ideation/shared/protocols/diverge-converge.md +2 -0
  33. package/flows/ideation/shared/protocols/interaction-adaptation.md +7 -0
  34. package/lib/dashboard/aidlc/parser.js +581 -0
  35. package/lib/dashboard/fire/model.js +382 -0
  36. package/lib/dashboard/fire/parser.js +470 -0
  37. package/lib/dashboard/flow-detect.js +86 -0
  38. package/lib/dashboard/git/changes.js +362 -0
  39. package/lib/dashboard/git/worktrees.js +248 -0
  40. package/lib/dashboard/index.js +709 -0
  41. package/lib/dashboard/runtime/watch-runtime.js +122 -0
  42. package/lib/dashboard/simple/parser.js +293 -0
  43. package/lib/dashboard/tui/app.js +1675 -0
  44. package/lib/dashboard/tui/components/error-banner.js +35 -0
  45. package/lib/dashboard/tui/components/header.js +60 -0
  46. package/lib/dashboard/tui/components/help-footer.js +15 -0
  47. package/lib/dashboard/tui/components/stats-strip.js +35 -0
  48. package/lib/dashboard/tui/file-entries.js +383 -0
  49. package/lib/dashboard/tui/flow-builders.js +991 -0
  50. package/lib/dashboard/tui/git-builders.js +218 -0
  51. package/lib/dashboard/tui/helpers.js +236 -0
  52. package/lib/dashboard/tui/overlays.js +242 -0
  53. package/lib/dashboard/tui/preview.js +220 -0
  54. package/lib/dashboard/tui/renderer.js +76 -0
  55. package/lib/dashboard/tui/row-builders.js +797 -0
  56. package/lib/dashboard/tui/sections.js +45 -0
  57. package/lib/dashboard/tui/store.js +44 -0
  58. package/lib/dashboard/tui/views/overview-view.js +61 -0
  59. package/lib/dashboard/tui/views/runs-view.js +93 -0
  60. package/lib/dashboard/tui/worktree-builders.js +229 -0
  61. package/lib/installers/CodexInstaller.js +72 -1
  62. package/package.json +7 -3
@@ -0,0 +1,382 @@
1
+ function normalizeStatus(status) {
2
+ if (typeof status !== 'string') {
3
+ return undefined;
4
+ }
5
+
6
+ const normalized = status.toLowerCase().trim().replace(/[-\s]+/g, '_');
7
+ const map = {
8
+ pending: 'pending',
9
+ todo: 'pending',
10
+ in_progress: 'in_progress',
11
+ inprogress: 'in_progress',
12
+ active: 'in_progress',
13
+ completed: 'completed',
14
+ complete: 'completed',
15
+ done: 'completed',
16
+ blocked: 'blocked'
17
+ };
18
+
19
+ return map[normalized];
20
+ }
21
+
22
+ function normalizeMode(mode) {
23
+ if (typeof mode !== 'string') {
24
+ return undefined;
25
+ }
26
+
27
+ const normalized = mode.toLowerCase().trim();
28
+ if (normalized === 'autopilot' || normalized === 'confirm' || normalized === 'validate') {
29
+ return normalized;
30
+ }
31
+
32
+ return undefined;
33
+ }
34
+
35
+ function normalizeScope(scope) {
36
+ if (typeof scope !== 'string') {
37
+ return undefined;
38
+ }
39
+
40
+ const normalized = scope.toLowerCase().trim();
41
+ if (normalized === 'single' || normalized === 'batch' || normalized === 'wide') {
42
+ return normalized;
43
+ }
44
+
45
+ return undefined;
46
+ }
47
+
48
+ function normalizeComplexity(complexity) {
49
+ if (typeof complexity !== 'string') {
50
+ return undefined;
51
+ }
52
+
53
+ const normalized = complexity.toLowerCase().trim();
54
+ if (normalized === 'low' || normalized === 'medium' || normalized === 'high') {
55
+ return normalized;
56
+ }
57
+
58
+ return undefined;
59
+ }
60
+
61
+ function normalizeArray(value) {
62
+ return Array.isArray(value) ? value : [];
63
+ }
64
+
65
+ function normalizeTimestamp(value) {
66
+ if (value == null) {
67
+ return undefined;
68
+ }
69
+
70
+ if (value instanceof Date) {
71
+ return value.toISOString();
72
+ }
73
+
74
+ if (typeof value === 'string') {
75
+ return value.trim() === '' ? undefined : value;
76
+ }
77
+
78
+ return String(value);
79
+ }
80
+
81
+ function normalizeCheckpointState(value) {
82
+ if (typeof value !== 'string') {
83
+ return undefined;
84
+ }
85
+
86
+ const normalized = value.toLowerCase().trim().replace(/[\s-]+/g, '_');
87
+ return normalized === '' ? undefined : normalized;
88
+ }
89
+
90
+ function parseDependencies(raw) {
91
+ if (Array.isArray(raw)) {
92
+ return raw.filter((item) => typeof item === 'string' && item.trim() !== '');
93
+ }
94
+
95
+ if (typeof raw === 'string' && raw.trim() !== '') {
96
+ return [raw.trim()];
97
+ }
98
+
99
+ return [];
100
+ }
101
+
102
+ function normalizeRunWorkItem(raw, fallbackIntentId = '') {
103
+ if (typeof raw === 'string') {
104
+ return {
105
+ id: raw,
106
+ intentId: fallbackIntentId,
107
+ mode: 'confirm',
108
+ status: 'pending',
109
+ currentPhase: undefined,
110
+ checkpointState: undefined,
111
+ currentCheckpoint: undefined
112
+ };
113
+ }
114
+
115
+ if (!raw || typeof raw !== 'object') {
116
+ return {
117
+ id: '',
118
+ intentId: fallbackIntentId,
119
+ mode: 'confirm',
120
+ status: 'pending',
121
+ currentPhase: undefined,
122
+ checkpointState: undefined,
123
+ currentCheckpoint: undefined
124
+ };
125
+ }
126
+
127
+ const id = typeof raw.id === 'string' ? raw.id : '';
128
+ const intentId = typeof raw.intent === 'string'
129
+ ? raw.intent
130
+ : (typeof raw.intentId === 'string' ? raw.intentId : fallbackIntentId);
131
+
132
+ const status = normalizeStatus(raw.status) || 'pending';
133
+ const mode = normalizeMode(raw.mode) || 'confirm';
134
+ const currentPhase = typeof raw.current_phase === 'string'
135
+ ? raw.current_phase
136
+ : (typeof raw.currentPhase === 'string' ? raw.currentPhase : undefined);
137
+ const checkpointState = typeof raw.checkpoint_state === 'string'
138
+ ? raw.checkpoint_state
139
+ : (typeof raw.checkpointState === 'string'
140
+ ? raw.checkpointState
141
+ : (typeof raw.approval_state === 'string'
142
+ ? raw.approval_state
143
+ : (typeof raw.approvalState === 'string' ? raw.approvalState : undefined)));
144
+ const currentCheckpoint = typeof raw.current_checkpoint === 'string'
145
+ ? raw.current_checkpoint
146
+ : (typeof raw.currentCheckpoint === 'string'
147
+ ? raw.currentCheckpoint
148
+ : (typeof raw.checkpoint === 'string' ? raw.checkpoint : undefined));
149
+
150
+ return {
151
+ id,
152
+ intentId,
153
+ mode,
154
+ status,
155
+ currentPhase,
156
+ checkpointState,
157
+ currentCheckpoint
158
+ };
159
+ }
160
+
161
+ function normalizeState(rawState) {
162
+ const raw = rawState && typeof rawState === 'object' ? rawState : {};
163
+
164
+ const project = raw.project && typeof raw.project === 'object'
165
+ ? {
166
+ name: typeof raw.project.name === 'string' ? raw.project.name : 'Unknown',
167
+ description: typeof raw.project.description === 'string' ? raw.project.description : undefined,
168
+ created: normalizeTimestamp(raw.project.created) || new Date().toISOString(),
169
+ fireVersion: typeof raw.project.fire_version === 'string'
170
+ ? raw.project.fire_version
171
+ : (typeof raw.project.fireVersion === 'string'
172
+ ? raw.project.fireVersion
173
+ : '0.0.0')
174
+ }
175
+ : null;
176
+
177
+ const workspace = raw.workspace && typeof raw.workspace === 'object'
178
+ ? {
179
+ type: typeof raw.workspace.type === 'string' ? raw.workspace.type : 'greenfield',
180
+ structure: typeof raw.workspace.structure === 'string' ? raw.workspace.structure : 'monolith',
181
+ autonomyBias: typeof raw.workspace.autonomy_bias === 'string'
182
+ ? raw.workspace.autonomy_bias
183
+ : (typeof raw.workspace.autonomyBias === 'string' ? raw.workspace.autonomyBias : 'balanced'),
184
+ runScopePreference: normalizeScope(raw.workspace.run_scope_preference)
185
+ || normalizeScope(raw.workspace.runScopePreference)
186
+ || 'single',
187
+ scannedAt: normalizeTimestamp(raw.workspace.scanned_at)
188
+ || normalizeTimestamp(raw.workspace.scannedAt),
189
+ parts: normalizeArray(raw.workspace.parts)
190
+ }
191
+ : null;
192
+
193
+ const intents = normalizeArray(raw.intents).map((intent) => {
194
+ if (!intent || typeof intent !== 'object') {
195
+ return null;
196
+ }
197
+
198
+ const workItemsRaw = normalizeArray(intent.work_items).concat(normalizeArray(intent.workItems));
199
+
200
+ return {
201
+ id: typeof intent.id === 'string' ? intent.id : '',
202
+ title: typeof intent.title === 'string' ? intent.title : '',
203
+ status: normalizeStatus(intent.status),
204
+ workItems: workItemsRaw
205
+ .map((item) => {
206
+ if (!item || typeof item !== 'object') {
207
+ return null;
208
+ }
209
+
210
+ return {
211
+ id: typeof item.id === 'string' ? item.id : '',
212
+ status: normalizeStatus(item.status) || 'pending',
213
+ mode: normalizeMode(item.mode)
214
+ };
215
+ })
216
+ .filter(Boolean)
217
+ };
218
+ }).filter(Boolean);
219
+
220
+ const rawRuns = raw.runs && typeof raw.runs === 'object' ? raw.runs : {};
221
+
222
+ const activeRuns = normalizeArray(rawRuns.active).map((run) => {
223
+ if (!run || typeof run !== 'object') {
224
+ return null;
225
+ }
226
+
227
+ const workItemsRaw = normalizeArray(run.work_items).concat(normalizeArray(run.workItems));
228
+
229
+ return {
230
+ id: typeof run.id === 'string' ? run.id : '',
231
+ scope: normalizeScope(run.scope) || 'single',
232
+ workItems: workItemsRaw.map((item) => normalizeRunWorkItem(item)).filter((item) => item.id !== ''),
233
+ currentItem: typeof run.current_item === 'string'
234
+ ? run.current_item
235
+ : (typeof run.currentItem === 'string' ? run.currentItem : ''),
236
+ started: normalizeTimestamp(run.started) || '',
237
+ checkpointState: normalizeCheckpointState(
238
+ run.checkpoint_state
239
+ || run.checkpointState
240
+ || run.approval_state
241
+ || run.approvalState
242
+ ),
243
+ currentCheckpoint: typeof run.current_checkpoint === 'string'
244
+ ? run.current_checkpoint
245
+ : (typeof run.currentCheckpoint === 'string'
246
+ ? run.currentCheckpoint
247
+ : (typeof run.checkpoint === 'string' ? run.checkpoint : undefined))
248
+ };
249
+ }).filter(Boolean);
250
+
251
+ const completedRuns = normalizeArray(rawRuns.completed).map((run) => {
252
+ if (!run || typeof run !== 'object') {
253
+ return null;
254
+ }
255
+
256
+ const fallbackIntentId = typeof run.intent === 'string' ? run.intent : '';
257
+ const workItemsRaw = normalizeArray(run.work_items).concat(normalizeArray(run.workItems));
258
+
259
+ return {
260
+ id: typeof run.id === 'string' ? run.id : '',
261
+ workItems: workItemsRaw.map((item) => normalizeRunWorkItem(item, fallbackIntentId)).filter((item) => item.id !== ''),
262
+ checkpointState: normalizeCheckpointState(
263
+ run.checkpoint_state
264
+ || run.checkpointState
265
+ || run.approval_state
266
+ || run.approvalState
267
+ ),
268
+ currentCheckpoint: typeof run.current_checkpoint === 'string'
269
+ ? run.current_checkpoint
270
+ : (typeof run.currentCheckpoint === 'string'
271
+ ? run.currentCheckpoint
272
+ : (typeof run.checkpoint === 'string' ? run.checkpoint : undefined)),
273
+ completed: normalizeTimestamp(run.completed) || ''
274
+ };
275
+ }).filter(Boolean);
276
+
277
+ return {
278
+ project,
279
+ workspace,
280
+ intents,
281
+ runs: {
282
+ active: activeRuns,
283
+ completed: completedRuns
284
+ }
285
+ };
286
+ }
287
+
288
+ function deriveIntentStatus(stateStatus, workItems) {
289
+ const normalizedState = normalizeStatus(stateStatus);
290
+ if (normalizedState) {
291
+ return normalizedState;
292
+ }
293
+
294
+ if (!Array.isArray(workItems) || workItems.length === 0) {
295
+ return 'pending';
296
+ }
297
+
298
+ if (workItems.every((item) => item.status === 'completed')) {
299
+ return 'completed';
300
+ }
301
+
302
+ if (workItems.some((item) => item.status === 'in_progress')) {
303
+ return 'in_progress';
304
+ }
305
+
306
+ if (workItems.some((item) => item.status === 'blocked')) {
307
+ return 'blocked';
308
+ }
309
+
310
+ return 'pending';
311
+ }
312
+
313
+ function calculateStats(intents, runs, activeRuns) {
314
+ const safeIntents = Array.isArray(intents) ? intents : [];
315
+ const safeRuns = Array.isArray(runs) ? runs : [];
316
+ const safeActiveRuns = Array.isArray(activeRuns) ? activeRuns : [];
317
+ const workItems = safeIntents.flatMap((intent) => intent.workItems || []);
318
+
319
+ return {
320
+ totalIntents: safeIntents.length,
321
+ completedIntents: safeIntents.filter((intent) => intent.status === 'completed').length,
322
+ inProgressIntents: safeIntents.filter((intent) => intent.status === 'in_progress').length,
323
+ pendingIntents: safeIntents.filter((intent) => intent.status === 'pending').length,
324
+ blockedIntents: safeIntents.filter((intent) => intent.status === 'blocked').length,
325
+ totalWorkItems: workItems.length,
326
+ completedWorkItems: workItems.filter((item) => item.status === 'completed').length,
327
+ inProgressWorkItems: workItems.filter((item) => item.status === 'in_progress').length,
328
+ pendingWorkItems: workItems.filter((item) => item.status === 'pending').length,
329
+ blockedWorkItems: workItems.filter((item) => item.status === 'blocked').length,
330
+ totalRuns: safeRuns.length,
331
+ completedRuns: safeRuns.filter((run) => run.completedAt != null).length,
332
+ activeRunsCount: safeActiveRuns.length
333
+ };
334
+ }
335
+
336
+ function buildPendingItems(intents) {
337
+ const pendingItems = [];
338
+
339
+ for (const intent of intents || []) {
340
+ for (const item of intent.workItems || []) {
341
+ if (item.status !== 'pending') {
342
+ continue;
343
+ }
344
+
345
+ pendingItems.push({
346
+ id: item.id,
347
+ title: item.title,
348
+ intentId: intent.id,
349
+ intentTitle: intent.title,
350
+ mode: item.mode,
351
+ complexity: item.complexity,
352
+ dependencies: item.dependencies || [],
353
+ filePath: item.filePath
354
+ });
355
+ }
356
+ }
357
+
358
+ pendingItems.sort((a, b) => {
359
+ const depDiff = (a.dependencies?.length || 0) - (b.dependencies?.length || 0);
360
+ if (depDiff !== 0) {
361
+ return depDiff;
362
+ }
363
+ return a.id.localeCompare(b.id);
364
+ });
365
+
366
+ return pendingItems;
367
+ }
368
+
369
+ module.exports = {
370
+ normalizeStatus,
371
+ normalizeMode,
372
+ normalizeScope,
373
+ normalizeComplexity,
374
+ normalizeArray,
375
+ normalizeTimestamp,
376
+ parseDependencies,
377
+ normalizeRunWorkItem,
378
+ normalizeState,
379
+ deriveIntentStatus,
380
+ calculateStats,
381
+ buildPendingItems
382
+ };