specsmd 0.1.69 → 0.1.71
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.
- package/lib/dashboard/aidlc/parser.js +22 -2
- package/lib/dashboard/fire/model.js +15 -1
- package/lib/dashboard/fire/parser.js +50 -8
- package/lib/dashboard/web/extension-adapter.js +51 -3
- package/lib/dashboard/web/public/app.js +111 -0
- package/lib/dashboard/web/public/styles.css +74 -0
- package/lib/dashboard/web/public/webview-bundle.js +144 -4
- package/package.json +1 -1
|
@@ -114,6 +114,25 @@ function normalizeTimestamp(value) {
|
|
|
114
114
|
return parsed.toISOString();
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
function compareByCreatedAtThenId(a, b) {
|
|
118
|
+
const aTime = a?.createdAt ? Date.parse(a.createdAt) : NaN;
|
|
119
|
+
const bTime = b?.createdAt ? Date.parse(b.createdAt) : NaN;
|
|
120
|
+
const aHasTime = !Number.isNaN(aTime);
|
|
121
|
+
const bHasTime = !Number.isNaN(bTime);
|
|
122
|
+
|
|
123
|
+
if (aHasTime && bHasTime && aTime !== bTime) {
|
|
124
|
+
return aTime - bTime;
|
|
125
|
+
}
|
|
126
|
+
if (aHasTime && !bHasTime) {
|
|
127
|
+
return -1;
|
|
128
|
+
}
|
|
129
|
+
if (!aHasTime && bHasTime) {
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return String(a?.id || '').localeCompare(String(b?.id || ''));
|
|
134
|
+
}
|
|
135
|
+
|
|
117
136
|
function parseIntentFolderName(folderName) {
|
|
118
137
|
const match = String(folderName).match(/^(\d{3})-(.+)$/);
|
|
119
138
|
if (!match) {
|
|
@@ -272,7 +291,8 @@ function parseIntent(intentPath, warnings) {
|
|
|
272
291
|
completedStories: storyStats.completed,
|
|
273
292
|
inProgressStories: storyStats.inProgress,
|
|
274
293
|
pendingStories: storyStats.pending,
|
|
275
|
-
blockedStories: storyStats.blocked
|
|
294
|
+
blockedStories: storyStats.blocked,
|
|
295
|
+
createdAt: normalizeTimestamp(requirementsFrontmatter.created)
|
|
276
296
|
};
|
|
277
297
|
}
|
|
278
298
|
|
|
@@ -486,7 +506,7 @@ function parseAidlcDashboard(workspacePath) {
|
|
|
486
506
|
const intents = intentFolders
|
|
487
507
|
.map((intentFolder) => parseIntent(path.join(intentsPath, intentFolder), warnings))
|
|
488
508
|
.filter(Boolean)
|
|
489
|
-
.sort(
|
|
509
|
+
.sort(compareByCreatedAtThenId);
|
|
490
510
|
|
|
491
511
|
if (intentFolders.length === 0) {
|
|
492
512
|
warnings.push('No intents found under memory-bank/intents.');
|
|
@@ -350,7 +350,8 @@ function buildPendingItems(intents) {
|
|
|
350
350
|
mode: item.mode,
|
|
351
351
|
complexity: item.complexity,
|
|
352
352
|
dependencies: item.dependencies || [],
|
|
353
|
-
filePath: item.filePath
|
|
353
|
+
filePath: item.filePath,
|
|
354
|
+
createdAt: item.createdAt
|
|
354
355
|
});
|
|
355
356
|
}
|
|
356
357
|
}
|
|
@@ -360,6 +361,19 @@ function buildPendingItems(intents) {
|
|
|
360
361
|
if (depDiff !== 0) {
|
|
361
362
|
return depDiff;
|
|
362
363
|
}
|
|
364
|
+
const aTime = a.createdAt ? Date.parse(a.createdAt) : NaN;
|
|
365
|
+
const bTime = b.createdAt ? Date.parse(b.createdAt) : NaN;
|
|
366
|
+
const aHasTime = !Number.isNaN(aTime);
|
|
367
|
+
const bHasTime = !Number.isNaN(bTime);
|
|
368
|
+
if (aHasTime && bHasTime && aTime !== bTime) {
|
|
369
|
+
return aTime - bTime;
|
|
370
|
+
}
|
|
371
|
+
if (aHasTime && !bHasTime) {
|
|
372
|
+
return -1;
|
|
373
|
+
}
|
|
374
|
+
if (!aHasTime && bHasTime) {
|
|
375
|
+
return 1;
|
|
376
|
+
}
|
|
363
377
|
return a.id.localeCompare(b.id);
|
|
364
378
|
});
|
|
365
379
|
|
|
@@ -12,7 +12,8 @@ const {
|
|
|
12
12
|
calculateStats,
|
|
13
13
|
parseDependencies,
|
|
14
14
|
buildPendingItems,
|
|
15
|
-
normalizeRunWorkItem
|
|
15
|
+
normalizeRunWorkItem,
|
|
16
|
+
normalizeTimestamp
|
|
16
17
|
} = require('./model');
|
|
17
18
|
|
|
18
19
|
const STANDARD_TYPES = [
|
|
@@ -80,6 +81,46 @@ function getFirstStringValue(record, keys) {
|
|
|
80
81
|
return undefined;
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
function compareByCreatedAtThenId(a, b) {
|
|
85
|
+
const aTime = a?.createdAt ? Date.parse(a.createdAt) : NaN;
|
|
86
|
+
const bTime = b?.createdAt ? Date.parse(b.createdAt) : NaN;
|
|
87
|
+
const aHasTime = !Number.isNaN(aTime);
|
|
88
|
+
const bHasTime = !Number.isNaN(bTime);
|
|
89
|
+
|
|
90
|
+
if (aHasTime && bHasTime && aTime !== bTime) {
|
|
91
|
+
return aTime - bTime;
|
|
92
|
+
}
|
|
93
|
+
if (aHasTime && !bHasTime) {
|
|
94
|
+
return -1;
|
|
95
|
+
}
|
|
96
|
+
if (!aHasTime && bHasTime) {
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return String(a?.id || '').localeCompare(String(b?.id || ''));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function compareRunDatesDesc(a, b) {
|
|
104
|
+
const aDate = a?.completedAt || a?.startedAt;
|
|
105
|
+
const bDate = b?.completedAt || b?.startedAt;
|
|
106
|
+
const aTime = aDate ? Date.parse(aDate) : NaN;
|
|
107
|
+
const bTime = bDate ? Date.parse(bDate) : NaN;
|
|
108
|
+
const aHasTime = !Number.isNaN(aTime);
|
|
109
|
+
const bHasTime = !Number.isNaN(bTime);
|
|
110
|
+
|
|
111
|
+
if (aHasTime && bHasTime && aTime !== bTime) {
|
|
112
|
+
return bTime - aTime;
|
|
113
|
+
}
|
|
114
|
+
if (aHasTime && !bHasTime) {
|
|
115
|
+
return -1;
|
|
116
|
+
}
|
|
117
|
+
if (!aHasTime && bHasTime) {
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return String(b?.id || '').localeCompare(String(a?.id || ''));
|
|
122
|
+
}
|
|
123
|
+
|
|
83
124
|
function parseRunLog(runLogPath) {
|
|
84
125
|
const content = readFileSafe(runLogPath);
|
|
85
126
|
if (!content) {
|
|
@@ -210,8 +251,8 @@ function scanWorkItems(intentPath, intentId, stateWorkItems, warnings) {
|
|
|
210
251
|
filePath,
|
|
211
252
|
description: typeof frontmatter.description === 'string' ? frontmatter.description : undefined,
|
|
212
253
|
dependencies,
|
|
213
|
-
createdAt:
|
|
214
|
-
completedAt:
|
|
254
|
+
createdAt: normalizeTimestamp(frontmatter.created),
|
|
255
|
+
completedAt: normalizeTimestamp(frontmatter.completed_at)
|
|
215
256
|
};
|
|
216
257
|
});
|
|
217
258
|
}
|
|
@@ -252,8 +293,8 @@ function scanIntents(rootPath, normalizedState, warnings) {
|
|
|
252
293
|
filePath: briefPath,
|
|
253
294
|
description: typeof frontmatter.description === 'string' ? frontmatter.description : undefined,
|
|
254
295
|
workItems,
|
|
255
|
-
createdAt:
|
|
256
|
-
completedAt:
|
|
296
|
+
createdAt: normalizeTimestamp(frontmatter.created),
|
|
297
|
+
completedAt: normalizeTimestamp(frontmatter.completed_at)
|
|
257
298
|
};
|
|
258
299
|
});
|
|
259
300
|
}
|
|
@@ -325,7 +366,8 @@ function buildActiveRuns(runs, normalizedState) {
|
|
|
325
366
|
|
|
326
367
|
return (normalizedState.runs?.active || [])
|
|
327
368
|
.map((active) => byId.get(active.id) || null)
|
|
328
|
-
.filter(Boolean)
|
|
369
|
+
.filter(Boolean)
|
|
370
|
+
.sort(compareRunDatesDesc);
|
|
329
371
|
}
|
|
330
372
|
|
|
331
373
|
function buildCompletedRuns(runs) {
|
|
@@ -430,8 +472,8 @@ function parseFireDashboard(workspacePath) {
|
|
|
430
472
|
|
|
431
473
|
const warnings = [];
|
|
432
474
|
const normalizedState = normalizeState(rawState);
|
|
433
|
-
const intents = scanIntents(rootPath, normalizedState, warnings);
|
|
434
|
-
const runs = scanRuns(rootPath, normalizedState);
|
|
475
|
+
const intents = scanIntents(rootPath, normalizedState, warnings).sort(compareByCreatedAtThenId);
|
|
476
|
+
const runs = scanRuns(rootPath, normalizedState).sort(compareRunDatesDesc);
|
|
435
477
|
const activeRuns = buildActiveRuns(runs, normalizedState);
|
|
436
478
|
const completedRuns = buildCompletedRuns(runs);
|
|
437
479
|
const standards = scanStandards(rootPath);
|
|
@@ -248,7 +248,8 @@ function buildSpecsData(snapshot) {
|
|
|
248
248
|
path: intent.path,
|
|
249
249
|
storiesComplete: units.reduce((sum, unit) => sum + unit.storiesComplete, 0),
|
|
250
250
|
storiesTotal: units.reduce((sum, unit) => sum + unit.storiesTotal, 0),
|
|
251
|
-
units
|
|
251
|
+
units,
|
|
252
|
+
createdAt: intent.createdAt
|
|
252
253
|
};
|
|
253
254
|
});
|
|
254
255
|
|
|
@@ -400,7 +401,8 @@ function buildFireViewData(snapshot) {
|
|
|
400
401
|
mode: normalizeFireMode(item.mode),
|
|
401
402
|
complexity: normalizeFireComplexity(item.complexity),
|
|
402
403
|
filePath: item.filePath,
|
|
403
|
-
dependencies: item.dependencies || []
|
|
404
|
+
dependencies: item.dependencies || [],
|
|
405
|
+
createdAt: item.createdAt
|
|
404
406
|
}));
|
|
405
407
|
|
|
406
408
|
const completedRuns = (snapshot.completedRuns || []).map((run) => ({
|
|
@@ -418,13 +420,15 @@ function buildFireViewData(snapshot) {
|
|
|
418
420
|
status: normalizeFireStatus(intent.status),
|
|
419
421
|
filePath: intent.filePath,
|
|
420
422
|
description: intent.description,
|
|
423
|
+
createdAt: intent.createdAt,
|
|
421
424
|
workItems: (intent.workItems || []).map((item) => ({
|
|
422
425
|
id: item.id,
|
|
423
426
|
title: item.title || item.id,
|
|
424
427
|
status: normalizeFireStatus(item.status),
|
|
425
428
|
mode: normalizeFireMode(item.mode),
|
|
426
429
|
complexity: normalizeFireComplexity(item.complexity),
|
|
427
|
-
filePath: item.filePath
|
|
430
|
+
filePath: item.filePath,
|
|
431
|
+
createdAt: item.createdAt
|
|
428
432
|
}))
|
|
429
433
|
}));
|
|
430
434
|
|
|
@@ -634,6 +638,50 @@ function getOverviewViewHtml(data) {
|
|
|
634
638
|
`).join('') : '<div class="empty-state"><div class="empty-state-text">No standards defined</div></div>'}
|
|
635
639
|
</div>
|
|
636
640
|
</div>
|
|
641
|
+
<div class="overview-resources-footer">
|
|
642
|
+
<div class="overview-fabriqa-card">
|
|
643
|
+
<div class="overview-fabriqa-brand">
|
|
644
|
+
<div class="overview-fabriqa-mark">FA</div>
|
|
645
|
+
<div>
|
|
646
|
+
<div class="overview-fabriqa-title">specs.md by Fabriqa.AI</div>
|
|
647
|
+
<div class="overview-fabriqa-subtitle">Spec-native agentic development environment</div>
|
|
648
|
+
</div>
|
|
649
|
+
</div>
|
|
650
|
+
<div class="overview-fabriqa-copy">
|
|
651
|
+
Use Fabriqa.AI with your existing AI subscription to design, run, and reuse agentic workflows around your specs. It is free to try.
|
|
652
|
+
</div>
|
|
653
|
+
<div class="overview-fabriqa-actions">
|
|
654
|
+
<div class="overview-fabriqa-link" data-url="https://fabriqa.ai">Explore Fabriqa.AI</div>
|
|
655
|
+
<div class="overview-fabriqa-link secondary" data-url="https://specs.md">Open specs.md</div>
|
|
656
|
+
</div>
|
|
657
|
+
</div>
|
|
658
|
+
<div class="overview-dashboard-tip">
|
|
659
|
+
<div>
|
|
660
|
+
<div class="overview-dashboard-title">Did you know?</div>
|
|
661
|
+
<div class="overview-dashboard-copy">
|
|
662
|
+
You can use the specsmd dashboard outside VS Code and VS Code variants. Run this from your project folder:
|
|
663
|
+
</div>
|
|
664
|
+
<code>npx specsmd@latest dashboard</code>
|
|
665
|
+
</div>
|
|
666
|
+
<div class="overview-fabriqa-link secondary" data-url="https://specs.md/getting-started/cli-dashboard">Dashboard docs</div>
|
|
667
|
+
</div>
|
|
668
|
+
<div class="overview-resources-title">Community</div>
|
|
669
|
+
<div class="overview-resources-links">
|
|
670
|
+
<div class="overview-resource-link" data-url="https://discord.specs.md" title="Discord">
|
|
671
|
+
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
672
|
+
<path fill="currentColor" d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/>
|
|
673
|
+
</svg>
|
|
674
|
+
</div>
|
|
675
|
+
<div class="overview-resource-link" data-url="https://x.com/specsmd" title="X (Twitter)">
|
|
676
|
+
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
677
|
+
<path fill="currentColor" d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
|
|
678
|
+
</svg>
|
|
679
|
+
</div>
|
|
680
|
+
</div>
|
|
681
|
+
<div class="overview-feedback-message">
|
|
682
|
+
We're new! Help us improve — <span class="overview-feedback-link" data-url="https://specs.md/feedback">share your feedback</span>
|
|
683
|
+
</div>
|
|
684
|
+
</div>
|
|
637
685
|
</div>`;
|
|
638
686
|
}
|
|
639
687
|
|
|
@@ -28,6 +28,103 @@
|
|
|
28
28
|
document.documentElement.style.colorScheme = theme;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
function copyText(text) {
|
|
32
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
33
|
+
return navigator.clipboard.writeText(text);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var textarea = document.createElement('textarea');
|
|
37
|
+
textarea.value = text;
|
|
38
|
+
textarea.setAttribute('readonly', 'readonly');
|
|
39
|
+
textarea.style.position = 'fixed';
|
|
40
|
+
textarea.style.opacity = '0';
|
|
41
|
+
document.body.appendChild(textarea);
|
|
42
|
+
textarea.select();
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
document.execCommand('copy');
|
|
46
|
+
return Promise.resolve();
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return Promise.reject(error);
|
|
49
|
+
} finally {
|
|
50
|
+
textarea.remove();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function closeCommandDialog() {
|
|
55
|
+
var existing = document.querySelector('.specsmd-command-dialog');
|
|
56
|
+
if (existing) {
|
|
57
|
+
existing.remove();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function showCommandDialog(command) {
|
|
62
|
+
closeCommandDialog();
|
|
63
|
+
|
|
64
|
+
var overlay = document.createElement('div');
|
|
65
|
+
overlay.className = 'specsmd-command-dialog';
|
|
66
|
+
overlay.setAttribute('role', 'dialog');
|
|
67
|
+
overlay.setAttribute('aria-modal', 'true');
|
|
68
|
+
overlay.setAttribute('aria-label', 'Start FIRE run command');
|
|
69
|
+
|
|
70
|
+
var panel = document.createElement('div');
|
|
71
|
+
panel.className = 'specsmd-command-dialog-panel';
|
|
72
|
+
|
|
73
|
+
var title = document.createElement('div');
|
|
74
|
+
title.className = 'specsmd-command-dialog-title';
|
|
75
|
+
title.textContent = 'Start FIRE run';
|
|
76
|
+
|
|
77
|
+
var description = document.createElement('div');
|
|
78
|
+
description.className = 'specsmd-command-dialog-description';
|
|
79
|
+
description.textContent = 'Run this command from your project folder.';
|
|
80
|
+
|
|
81
|
+
var commandBox = document.createElement('textarea');
|
|
82
|
+
commandBox.className = 'specsmd-command-dialog-command';
|
|
83
|
+
commandBox.value = command;
|
|
84
|
+
commandBox.readOnly = true;
|
|
85
|
+
commandBox.rows = 2;
|
|
86
|
+
|
|
87
|
+
var actions = document.createElement('div');
|
|
88
|
+
actions.className = 'specsmd-command-dialog-actions';
|
|
89
|
+
|
|
90
|
+
var copyButton = document.createElement('button');
|
|
91
|
+
copyButton.type = 'button';
|
|
92
|
+
copyButton.className = 'specsmd-command-dialog-copy';
|
|
93
|
+
copyButton.textContent = 'Copy Command';
|
|
94
|
+
|
|
95
|
+
var closeButton = document.createElement('button');
|
|
96
|
+
closeButton.type = 'button';
|
|
97
|
+
closeButton.className = 'specsmd-command-dialog-close';
|
|
98
|
+
closeButton.textContent = 'Close';
|
|
99
|
+
|
|
100
|
+
copyButton.addEventListener('click', function () {
|
|
101
|
+
copyText(command).then(function () {
|
|
102
|
+
copyButton.textContent = 'Copied';
|
|
103
|
+
}).catch(function () {
|
|
104
|
+
commandBox.focus();
|
|
105
|
+
commandBox.select();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
closeButton.addEventListener('click', closeCommandDialog);
|
|
110
|
+
overlay.addEventListener('click', function (event) {
|
|
111
|
+
if (event.target === overlay) {
|
|
112
|
+
closeCommandDialog();
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
actions.appendChild(copyButton);
|
|
117
|
+
actions.appendChild(closeButton);
|
|
118
|
+
panel.appendChild(title);
|
|
119
|
+
panel.appendChild(description);
|
|
120
|
+
panel.appendChild(commandBox);
|
|
121
|
+
panel.appendChild(actions);
|
|
122
|
+
overlay.appendChild(panel);
|
|
123
|
+
document.body.appendChild(overlay);
|
|
124
|
+
commandBox.focus();
|
|
125
|
+
commandBox.select();
|
|
126
|
+
}
|
|
127
|
+
|
|
31
128
|
document.documentElement.dataset.host = 'dashboard-web';
|
|
32
129
|
applyTheme(readTheme());
|
|
33
130
|
|
|
@@ -44,4 +141,18 @@
|
|
|
44
141
|
document.documentElement.dataset.loaded = 'true';
|
|
45
142
|
}
|
|
46
143
|
});
|
|
144
|
+
|
|
145
|
+
window.addEventListener('specsmd-dashboard-command', function (event) {
|
|
146
|
+
if (!event.detail || !event.detail.command) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
showCommandDialog(String(event.detail.command));
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
window.addEventListener('keydown', function (event) {
|
|
154
|
+
if (event.key === 'Escape') {
|
|
155
|
+
closeCommandDialog();
|
|
156
|
+
}
|
|
157
|
+
});
|
|
47
158
|
}());
|
|
@@ -64,3 +64,77 @@ specsmd-app {
|
|
|
64
64
|
width: 100vw;
|
|
65
65
|
height: 100vh;
|
|
66
66
|
}
|
|
67
|
+
|
|
68
|
+
.specsmd-command-dialog {
|
|
69
|
+
position: fixed;
|
|
70
|
+
inset: 0;
|
|
71
|
+
z-index: 1000;
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: center;
|
|
75
|
+
padding: 24px;
|
|
76
|
+
background: rgba(0, 0, 0, 0.45);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.specsmd-command-dialog-panel {
|
|
80
|
+
width: min(520px, 100%);
|
|
81
|
+
padding: 16px;
|
|
82
|
+
border: 1px solid var(--vscode-sideBarSectionHeader-border);
|
|
83
|
+
border-radius: 8px;
|
|
84
|
+
background: var(--vscode-sideBar-background);
|
|
85
|
+
color: var(--vscode-foreground);
|
|
86
|
+
box-shadow: 0 18px 56px rgba(0, 0, 0, 0.28);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.specsmd-command-dialog-title {
|
|
90
|
+
font-size: 15px;
|
|
91
|
+
font-weight: 700;
|
|
92
|
+
margin-bottom: 4px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.specsmd-command-dialog-description {
|
|
96
|
+
margin-bottom: 12px;
|
|
97
|
+
color: var(--vscode-descriptionForeground);
|
|
98
|
+
font-size: 12px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.specsmd-command-dialog-command {
|
|
102
|
+
box-sizing: border-box;
|
|
103
|
+
width: 100%;
|
|
104
|
+
min-height: 58px;
|
|
105
|
+
resize: vertical;
|
|
106
|
+
padding: 10px;
|
|
107
|
+
border: 1px solid var(--vscode-input-border);
|
|
108
|
+
border-radius: 6px;
|
|
109
|
+
background: var(--vscode-input-background);
|
|
110
|
+
color: var(--vscode-foreground);
|
|
111
|
+
font: 12px ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.specsmd-command-dialog-actions {
|
|
115
|
+
display: flex;
|
|
116
|
+
justify-content: flex-end;
|
|
117
|
+
gap: 8px;
|
|
118
|
+
margin-top: 12px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.specsmd-command-dialog-actions button {
|
|
122
|
+
min-width: 88px;
|
|
123
|
+
padding: 7px 10px;
|
|
124
|
+
border: 1px solid var(--vscode-input-border);
|
|
125
|
+
border-radius: 6px;
|
|
126
|
+
color: var(--vscode-foreground);
|
|
127
|
+
background: transparent;
|
|
128
|
+
font: inherit;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.specsmd-command-dialog-actions button:hover {
|
|
133
|
+
background: var(--vscode-list-hoverBackground);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.specsmd-command-dialog-copy {
|
|
137
|
+
border-color: var(--vscode-button-background) !important;
|
|
138
|
+
background: var(--vscode-button-background) !important;
|
|
139
|
+
color: var(--vscode-button-foreground) !important;
|
|
140
|
+
}
|
|
@@ -6644,6 +6644,15 @@
|
|
|
6644
6644
|
connectEvents();
|
|
6645
6645
|
return {
|
|
6646
6646
|
postMessage(message) {
|
|
6647
|
+
if (isStandaloneStartRunMessage(message)) {
|
|
6648
|
+
window.dispatchEvent(new CustomEvent("specsmd-dashboard-command", {
|
|
6649
|
+
detail: {
|
|
6650
|
+
command: buildFireStartRunCommand(message.workItemIds),
|
|
6651
|
+
workItemIds: message.workItemIds
|
|
6652
|
+
}
|
|
6653
|
+
}));
|
|
6654
|
+
return;
|
|
6655
|
+
}
|
|
6647
6656
|
fetch("/api/message", {
|
|
6648
6657
|
method: "POST",
|
|
6649
6658
|
headers: { "content-type": "application/json" },
|
|
@@ -6665,6 +6674,13 @@
|
|
|
6665
6674
|
}
|
|
6666
6675
|
};
|
|
6667
6676
|
}
|
|
6677
|
+
function isStandaloneStartRunMessage(message) {
|
|
6678
|
+
return typeof message === "object" && message !== null && message.type === "startRun" && Array.isArray(message.workItemIds);
|
|
6679
|
+
}
|
|
6680
|
+
function buildFireStartRunCommand(workItemIds) {
|
|
6681
|
+
const ids = workItemIds.map((id) => String(id).trim()).filter(Boolean);
|
|
6682
|
+
return ["/specsmd-fire-builder", ...ids].join(" ");
|
|
6683
|
+
}
|
|
6668
6684
|
var vscode = typeof acquireVsCodeApi === "function" ? acquireVsCodeApi() : createStandaloneApi();
|
|
6669
6685
|
|
|
6670
6686
|
// src/webview/components/app.ts
|
|
@@ -6888,7 +6904,7 @@
|
|
|
6888
6904
|
}
|
|
6889
6905
|
});
|
|
6890
6906
|
});
|
|
6891
|
-
overviewView.querySelectorAll(".overview-resource-link").forEach((link) => {
|
|
6907
|
+
overviewView.querySelectorAll(".overview-resource-link, .overview-fabriqa-link").forEach((link) => {
|
|
6892
6908
|
const htmlLink = link;
|
|
6893
6909
|
link.addEventListener("click", () => {
|
|
6894
6910
|
const url = htmlLink.dataset.url;
|
|
@@ -7105,6 +7121,15 @@
|
|
|
7105
7121
|
}
|
|
7106
7122
|
}
|
|
7107
7123
|
_handleFireFilterChange(e7) {
|
|
7124
|
+
if (this._fireData) {
|
|
7125
|
+
this._fireData = {
|
|
7126
|
+
...this._fireData,
|
|
7127
|
+
intentsData: {
|
|
7128
|
+
...this._fireData.intentsData,
|
|
7129
|
+
filter: e7.detail.filter
|
|
7130
|
+
}
|
|
7131
|
+
};
|
|
7132
|
+
}
|
|
7108
7133
|
vscode.postMessage({ type: "fireIntentsFilter", filter: e7.detail.filter });
|
|
7109
7134
|
}
|
|
7110
7135
|
_handleFireToggleExpand(e7) {
|
|
@@ -7200,18 +7225,22 @@
|
|
|
7200
7225
|
...BaseElement.baseStyles,
|
|
7201
7226
|
i`
|
|
7202
7227
|
:host {
|
|
7203
|
-
display:
|
|
7204
|
-
flex-direction: column;
|
|
7228
|
+
display: block;
|
|
7205
7229
|
height: 100vh;
|
|
7206
7230
|
overflow: hidden;
|
|
7231
|
+
position: relative;
|
|
7207
7232
|
background: var(--background);
|
|
7208
7233
|
}
|
|
7209
7234
|
|
|
7210
7235
|
.shell {
|
|
7211
7236
|
display: flex;
|
|
7212
7237
|
flex-direction: column;
|
|
7213
|
-
|
|
7238
|
+
position: absolute;
|
|
7239
|
+
inset: 0;
|
|
7240
|
+
width: 100%;
|
|
7241
|
+
height: 100%;
|
|
7214
7242
|
min-height: 0;
|
|
7243
|
+
overflow: hidden;
|
|
7215
7244
|
}
|
|
7216
7245
|
|
|
7217
7246
|
.shell-chrome {
|
|
@@ -7310,10 +7339,12 @@
|
|
|
7310
7339
|
flex-direction: column;
|
|
7311
7340
|
flex: 1;
|
|
7312
7341
|
min-height: 0;
|
|
7342
|
+
overflow: hidden;
|
|
7313
7343
|
}
|
|
7314
7344
|
|
|
7315
7345
|
.view-container {
|
|
7316
7346
|
flex: 1;
|
|
7347
|
+
min-height: 0;
|
|
7317
7348
|
overflow-y: auto;
|
|
7318
7349
|
display: none;
|
|
7319
7350
|
}
|
|
@@ -7321,6 +7352,7 @@
|
|
|
7321
7352
|
.view-container.active {
|
|
7322
7353
|
display: flex;
|
|
7323
7354
|
flex-direction: column;
|
|
7355
|
+
min-height: 0;
|
|
7324
7356
|
}
|
|
7325
7357
|
|
|
7326
7358
|
bolts-view {
|
|
@@ -7745,6 +7777,114 @@
|
|
|
7745
7777
|
border-top: 1px solid var(--border-color);
|
|
7746
7778
|
}
|
|
7747
7779
|
|
|
7780
|
+
.overview-fabriqa-card {
|
|
7781
|
+
margin-bottom: 14px;
|
|
7782
|
+
padding: 14px;
|
|
7783
|
+
border: 1px solid var(--border-color);
|
|
7784
|
+
border-radius: 8px;
|
|
7785
|
+
background: var(--editor-background);
|
|
7786
|
+
}
|
|
7787
|
+
|
|
7788
|
+
.overview-fabriqa-brand {
|
|
7789
|
+
display: flex;
|
|
7790
|
+
align-items: center;
|
|
7791
|
+
gap: 10px;
|
|
7792
|
+
margin-bottom: 10px;
|
|
7793
|
+
}
|
|
7794
|
+
|
|
7795
|
+
.overview-fabriqa-mark {
|
|
7796
|
+
width: 34px;
|
|
7797
|
+
height: 34px;
|
|
7798
|
+
border-radius: 8px;
|
|
7799
|
+
display: inline-flex;
|
|
7800
|
+
align-items: center;
|
|
7801
|
+
justify-content: center;
|
|
7802
|
+
background: var(--accent-primary);
|
|
7803
|
+
color: #ffffff;
|
|
7804
|
+
font-size: 12px;
|
|
7805
|
+
font-weight: 700;
|
|
7806
|
+
flex-shrink: 0;
|
|
7807
|
+
}
|
|
7808
|
+
|
|
7809
|
+
.overview-fabriqa-title {
|
|
7810
|
+
font-size: 13px;
|
|
7811
|
+
font-weight: 700;
|
|
7812
|
+
color: var(--foreground);
|
|
7813
|
+
line-height: 1.25;
|
|
7814
|
+
}
|
|
7815
|
+
|
|
7816
|
+
.overview-fabriqa-subtitle,
|
|
7817
|
+
.overview-fabriqa-copy,
|
|
7818
|
+
.overview-dashboard-copy {
|
|
7819
|
+
color: var(--description-foreground);
|
|
7820
|
+
font-size: 11px;
|
|
7821
|
+
line-height: 1.45;
|
|
7822
|
+
}
|
|
7823
|
+
|
|
7824
|
+
.overview-fabriqa-copy {
|
|
7825
|
+
margin-bottom: 12px;
|
|
7826
|
+
}
|
|
7827
|
+
|
|
7828
|
+
.overview-fabriqa-actions {
|
|
7829
|
+
display: flex;
|
|
7830
|
+
flex-wrap: wrap;
|
|
7831
|
+
gap: 8px;
|
|
7832
|
+
}
|
|
7833
|
+
|
|
7834
|
+
.overview-fabriqa-link {
|
|
7835
|
+
display: inline-flex;
|
|
7836
|
+
align-items: center;
|
|
7837
|
+
justify-content: center;
|
|
7838
|
+
min-height: 30px;
|
|
7839
|
+
padding: 0 10px;
|
|
7840
|
+
border-radius: 6px;
|
|
7841
|
+
background: var(--accent-primary);
|
|
7842
|
+
color: #ffffff;
|
|
7843
|
+
font-size: 11px;
|
|
7844
|
+
font-weight: 700;
|
|
7845
|
+
cursor: pointer;
|
|
7846
|
+
}
|
|
7847
|
+
|
|
7848
|
+
.overview-fabriqa-link.secondary {
|
|
7849
|
+
background: var(--vscode-input-background);
|
|
7850
|
+
color: var(--foreground);
|
|
7851
|
+
border: 1px solid var(--border-color);
|
|
7852
|
+
}
|
|
7853
|
+
|
|
7854
|
+
.overview-fabriqa-link:hover {
|
|
7855
|
+
opacity: 0.88;
|
|
7856
|
+
}
|
|
7857
|
+
|
|
7858
|
+
.overview-dashboard-tip {
|
|
7859
|
+
display: flex;
|
|
7860
|
+
align-items: flex-start;
|
|
7861
|
+
justify-content: space-between;
|
|
7862
|
+
gap: 12px;
|
|
7863
|
+
margin-bottom: 14px;
|
|
7864
|
+
padding: 12px;
|
|
7865
|
+
border: 1px solid var(--border-color);
|
|
7866
|
+
border-radius: 8px;
|
|
7867
|
+
background: var(--vscode-input-background);
|
|
7868
|
+
}
|
|
7869
|
+
|
|
7870
|
+
.overview-dashboard-title {
|
|
7871
|
+
margin-bottom: 4px;
|
|
7872
|
+
color: var(--foreground);
|
|
7873
|
+
font-size: 12px;
|
|
7874
|
+
font-weight: 700;
|
|
7875
|
+
}
|
|
7876
|
+
|
|
7877
|
+
.overview-dashboard-tip code {
|
|
7878
|
+
display: inline-block;
|
|
7879
|
+
margin-top: 8px;
|
|
7880
|
+
padding: 5px 7px;
|
|
7881
|
+
border-radius: 4px;
|
|
7882
|
+
background: var(--editor-background);
|
|
7883
|
+
color: var(--foreground);
|
|
7884
|
+
font-size: 10px;
|
|
7885
|
+
white-space: nowrap;
|
|
7886
|
+
}
|
|
7887
|
+
|
|
7748
7888
|
.overview-resources-title {
|
|
7749
7889
|
font-size: 9px;
|
|
7750
7890
|
font-weight: 600;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specsmd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.71",
|
|
4
4
|
"description": "Multi-agent orchestration system for AI-native software development. Delivers AI-DLC, Agile, and custom SDLC flows as markdown-based agent systems.",
|
|
5
5
|
"main": "lib/installer.js",
|
|
6
6
|
"bin": {
|