specsmd 0.1.33 → 0.1.34
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/tui/app.js +101 -36
- package/package.json +1 -1
package/lib/dashboard/tui/app.js
CHANGED
|
@@ -689,15 +689,70 @@ function buildOverviewProjectLines(snapshot, width, flow) {
|
|
|
689
689
|
return buildFireOverviewProjectLines(snapshot, width);
|
|
690
690
|
}
|
|
691
691
|
|
|
692
|
-
function
|
|
692
|
+
function listOverviewIntentEntries(snapshot, flow) {
|
|
693
693
|
const effectiveFlow = getEffectiveFlow(flow, snapshot);
|
|
694
694
|
if (effectiveFlow === 'aidlc') {
|
|
695
|
-
|
|
695
|
+
const intents = Array.isArray(snapshot?.intents) ? snapshot.intents : [];
|
|
696
|
+
return intents.map((intent) => ({
|
|
697
|
+
id: intent?.id || 'unknown',
|
|
698
|
+
status: intent?.status || 'pending',
|
|
699
|
+
line: `${intent?.id || 'unknown'}: ${intent?.status || 'pending'} (${intent?.completedStories || 0}/${intent?.storyCount || 0} stories, ${intent?.completedUnits || 0}/${intent?.unitCount || 0} units)`
|
|
700
|
+
}));
|
|
696
701
|
}
|
|
697
702
|
if (effectiveFlow === 'simple') {
|
|
698
|
-
|
|
703
|
+
const specs = Array.isArray(snapshot?.specs) ? snapshot.specs : [];
|
|
704
|
+
return specs.map((spec) => ({
|
|
705
|
+
id: spec?.name || 'unknown',
|
|
706
|
+
status: spec?.state || 'pending',
|
|
707
|
+
line: `${spec?.name || 'unknown'}: ${spec?.state || 'pending'} (${spec?.tasksCompleted || 0}/${spec?.tasksTotal || 0} tasks)`
|
|
708
|
+
}));
|
|
699
709
|
}
|
|
700
|
-
|
|
710
|
+
const intents = Array.isArray(snapshot?.intents) ? snapshot.intents : [];
|
|
711
|
+
return intents.map((intent) => {
|
|
712
|
+
const workItems = Array.isArray(intent?.workItems) ? intent.workItems : [];
|
|
713
|
+
const done = workItems.filter((item) => item.status === 'completed').length;
|
|
714
|
+
return {
|
|
715
|
+
id: intent?.id || 'unknown',
|
|
716
|
+
status: intent?.status || 'pending',
|
|
717
|
+
line: `${intent?.id || 'unknown'}: ${intent?.status || 'pending'} (${done}/${workItems.length} work items)`
|
|
718
|
+
};
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
function buildOverviewIntentLines(snapshot, width, flow, filter = 'next') {
|
|
723
|
+
const entries = listOverviewIntentEntries(snapshot, flow);
|
|
724
|
+
const normalizedFilter = filter === 'completed' ? 'completed' : 'next';
|
|
725
|
+
const isNextFilter = normalizedFilter === 'next';
|
|
726
|
+
const nextLabel = isNextFilter ? '[NEXT]' : ' next ';
|
|
727
|
+
const completedLabel = !isNextFilter ? '[COMPLETED]' : ' completed ';
|
|
728
|
+
|
|
729
|
+
const filtered = entries.filter((entry) => {
|
|
730
|
+
if (normalizedFilter === 'completed') {
|
|
731
|
+
return entry.status === 'completed';
|
|
732
|
+
}
|
|
733
|
+
return entry.status !== 'completed';
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
const lines = [{
|
|
737
|
+
text: truncate(`filter ${nextLabel} | ${completedLabel} (←/→ or n/x)`, width),
|
|
738
|
+
color: 'cyan',
|
|
739
|
+
bold: true
|
|
740
|
+
}];
|
|
741
|
+
|
|
742
|
+
if (filtered.length === 0) {
|
|
743
|
+
lines.push({
|
|
744
|
+
text: truncate(
|
|
745
|
+
normalizedFilter === 'completed' ? 'No completed intents yet' : 'No upcoming intents',
|
|
746
|
+
width
|
|
747
|
+
),
|
|
748
|
+
color: 'gray',
|
|
749
|
+
bold: false
|
|
750
|
+
});
|
|
751
|
+
return lines;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
lines.push(...filtered.map((entry) => truncate(entry.line, width)));
|
|
755
|
+
return lines;
|
|
701
756
|
}
|
|
702
757
|
|
|
703
758
|
function buildOverviewStandardsLines(snapshot, width, flow) {
|
|
@@ -739,12 +794,12 @@ function getPanelTitles(flow, snapshot) {
|
|
|
739
794
|
|
|
740
795
|
function getSectionOrderForView(view) {
|
|
741
796
|
if (view === 'overview') {
|
|
742
|
-
return ['
|
|
797
|
+
return ['intent-status', 'completed-runs', 'standards', 'project'];
|
|
743
798
|
}
|
|
744
799
|
if (view === 'health') {
|
|
745
800
|
return ['stats', 'warnings', 'error-details'];
|
|
746
801
|
}
|
|
747
|
-
return ['current-run', 'run-files', 'pending'
|
|
802
|
+
return ['current-run', 'run-files', 'pending'];
|
|
748
803
|
}
|
|
749
804
|
|
|
750
805
|
function cycleSection(view, currentSectionKey, direction = 1, availableSections = null) {
|
|
@@ -1638,6 +1693,7 @@ function createDashboardApp(deps) {
|
|
|
1638
1693
|
});
|
|
1639
1694
|
const [expandedGroups, setExpandedGroups] = useState({});
|
|
1640
1695
|
const [previewTarget, setPreviewTarget] = useState(null);
|
|
1696
|
+
const [overviewIntentFilter, setOverviewIntentFilter] = useState('next');
|
|
1641
1697
|
const [previewOpen, setPreviewOpen] = useState(false);
|
|
1642
1698
|
const [paneFocus, setPaneFocus] = useState('main');
|
|
1643
1699
|
const [overlayPreviewOpen, setOverlayPreviewOpen] = useState(false);
|
|
@@ -1807,6 +1863,7 @@ function createDashboardApp(deps) {
|
|
|
1807
1863
|
overview: 'project',
|
|
1808
1864
|
health: 'stats'
|
|
1809
1865
|
});
|
|
1866
|
+
setOverviewIntentFilter('next');
|
|
1810
1867
|
setExpandedGroups({});
|
|
1811
1868
|
setPreviewTarget(null);
|
|
1812
1869
|
setPreviewOpen(false);
|
|
@@ -1838,6 +1895,7 @@ function createDashboardApp(deps) {
|
|
|
1838
1895
|
overview: 'project',
|
|
1839
1896
|
health: 'stats'
|
|
1840
1897
|
});
|
|
1898
|
+
setOverviewIntentFilter('next');
|
|
1841
1899
|
setExpandedGroups({});
|
|
1842
1900
|
setPreviewTarget(null);
|
|
1843
1901
|
setPreviewOpen(false);
|
|
@@ -1857,7 +1915,22 @@ function createDashboardApp(deps) {
|
|
|
1857
1915
|
return;
|
|
1858
1916
|
}
|
|
1859
1917
|
|
|
1860
|
-
if (
|
|
1918
|
+
if (ui.view === 'overview' && activeSection === 'intent-status') {
|
|
1919
|
+
if (input === 'n') {
|
|
1920
|
+
setOverviewIntentFilter('next');
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
if (input === 'x') {
|
|
1924
|
+
setOverviewIntentFilter('completed');
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
if (key.rightArrow || key.leftArrow) {
|
|
1928
|
+
setOverviewIntentFilter((previous) => (previous === 'completed' ? 'next' : 'completed'));
|
|
1929
|
+
return;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
if (input === 'g' || key.rightArrow) {
|
|
1861
1934
|
setSectionFocus((previous) => ({
|
|
1862
1935
|
...previous,
|
|
1863
1936
|
[ui.view]: cycleSection(ui.view, activeSection, 1, availableSections)
|
|
@@ -1866,7 +1939,7 @@ function createDashboardApp(deps) {
|
|
|
1866
1939
|
return;
|
|
1867
1940
|
}
|
|
1868
1941
|
|
|
1869
|
-
if (
|
|
1942
|
+
if (input === 'G' || key.leftArrow) {
|
|
1870
1943
|
setSectionFocus((previous) => ({
|
|
1871
1944
|
...previous,
|
|
1872
1945
|
[ui.view]: cycleSection(ui.view, activeSection, -1, availableSections)
|
|
@@ -1891,11 +1964,6 @@ function createDashboardApp(deps) {
|
|
|
1891
1964
|
setPaneFocus('main');
|
|
1892
1965
|
return;
|
|
1893
1966
|
}
|
|
1894
|
-
if (input === 'c') {
|
|
1895
|
-
setSectionFocus((previous) => ({ ...previous, runs: 'completed' }));
|
|
1896
|
-
setPaneFocus('main');
|
|
1897
|
-
return;
|
|
1898
|
-
}
|
|
1899
1967
|
} else if (ui.view === 'overview') {
|
|
1900
1968
|
if (input === 'p') {
|
|
1901
1969
|
setSectionFocus((previous) => ({ ...previous, overview: 'project' }));
|
|
@@ -1909,6 +1977,10 @@ function createDashboardApp(deps) {
|
|
|
1909
1977
|
setSectionFocus((previous) => ({ ...previous, overview: 'standards' }));
|
|
1910
1978
|
return;
|
|
1911
1979
|
}
|
|
1980
|
+
if (input === 'c') {
|
|
1981
|
+
setSectionFocus((previous) => ({ ...previous, overview: 'completed-runs' }));
|
|
1982
|
+
return;
|
|
1983
|
+
}
|
|
1912
1984
|
} else if (ui.view === 'health') {
|
|
1913
1985
|
if (input === 't') {
|
|
1914
1986
|
setSectionFocus((previous) => ({ ...previous, health: 'stats' }));
|
|
@@ -2201,13 +2273,6 @@ function createDashboardApp(deps) {
|
|
|
2201
2273
|
mainCompactWidth,
|
|
2202
2274
|
ui.view === 'runs' && focusedSection === 'pending' && paneFocus === 'main'
|
|
2203
2275
|
);
|
|
2204
|
-
const completedLines = buildInteractiveRowsLines(
|
|
2205
|
-
completedRows,
|
|
2206
|
-
selectionBySection.completed || 0,
|
|
2207
|
-
icons,
|
|
2208
|
-
mainCompactWidth,
|
|
2209
|
-
ui.view === 'runs' && focusedSection === 'completed' && paneFocus === 'main'
|
|
2210
|
-
);
|
|
2211
2276
|
const effectivePreviewTarget = previewTarget || selectedFocusedFile;
|
|
2212
2277
|
const previewLines = previewOpen
|
|
2213
2278
|
? buildPreviewLines(effectivePreviewTarget, previewCompactWidth, previewScroll, {
|
|
@@ -2227,23 +2292,29 @@ function createDashboardApp(deps) {
|
|
|
2227
2292
|
];
|
|
2228
2293
|
} else if (ui.view === 'overview') {
|
|
2229
2294
|
panelCandidates = [
|
|
2230
|
-
{
|
|
2231
|
-
key: 'project',
|
|
2232
|
-
title: 'Project + Workspace',
|
|
2233
|
-
lines: buildOverviewProjectLines(snapshot, mainCompactWidth, activeFlow),
|
|
2234
|
-
borderColor: 'green'
|
|
2235
|
-
},
|
|
2236
2295
|
{
|
|
2237
2296
|
key: 'intent-status',
|
|
2238
|
-
title: '
|
|
2239
|
-
lines: buildOverviewIntentLines(snapshot, mainCompactWidth, activeFlow),
|
|
2297
|
+
title: 'Intents',
|
|
2298
|
+
lines: buildOverviewIntentLines(snapshot, mainCompactWidth, activeFlow, overviewIntentFilter),
|
|
2240
2299
|
borderColor: 'yellow'
|
|
2241
2300
|
},
|
|
2301
|
+
{
|
|
2302
|
+
key: 'completed-runs',
|
|
2303
|
+
title: panelTitles.completed,
|
|
2304
|
+
lines: buildCompletedLines(snapshot, mainCompactWidth, activeFlow),
|
|
2305
|
+
borderColor: 'blue'
|
|
2306
|
+
},
|
|
2242
2307
|
{
|
|
2243
2308
|
key: 'standards',
|
|
2244
2309
|
title: 'Standards',
|
|
2245
2310
|
lines: buildOverviewStandardsLines(snapshot, mainCompactWidth, activeFlow),
|
|
2246
2311
|
borderColor: 'blue'
|
|
2312
|
+
},
|
|
2313
|
+
{
|
|
2314
|
+
key: 'project',
|
|
2315
|
+
title: 'Project + Workspace',
|
|
2316
|
+
lines: buildOverviewProjectLines(snapshot, mainCompactWidth, activeFlow),
|
|
2317
|
+
borderColor: 'green'
|
|
2247
2318
|
}
|
|
2248
2319
|
];
|
|
2249
2320
|
} else if (ui.view === 'health') {
|
|
@@ -2298,12 +2369,6 @@ function createDashboardApp(deps) {
|
|
|
2298
2369
|
title: panelTitles.pending,
|
|
2299
2370
|
lines: pendingLines,
|
|
2300
2371
|
borderColor: 'yellow'
|
|
2301
|
-
},
|
|
2302
|
-
{
|
|
2303
|
-
key: 'completed',
|
|
2304
|
-
title: panelTitles.completed,
|
|
2305
|
-
lines: completedLines,
|
|
2306
|
-
borderColor: 'blue'
|
|
2307
2372
|
}
|
|
2308
2373
|
];
|
|
2309
2374
|
}
|
|
@@ -2319,8 +2384,8 @@ function createDashboardApp(deps) {
|
|
|
2319
2384
|
const panels = allocateSingleColumnPanels(panelCandidates, contentRowsBudget);
|
|
2320
2385
|
const flowSwitchHint = availableFlowIds.length > 1 ? ' | [ or ] switch flow' : '';
|
|
2321
2386
|
const sectionHint = ui.view === 'runs'
|
|
2322
|
-
? ' | a active | f files | p pending
|
|
2323
|
-
: (ui.view === 'overview' ? ' |
|
|
2387
|
+
? ' | a active | f files | p pending'
|
|
2388
|
+
: (ui.view === 'overview' ? ' | i intents | c completed | s standards | p project | n/x intent filter' : ' | t stats | w warnings | e errors');
|
|
2324
2389
|
const previewHint = ui.view === 'runs'
|
|
2325
2390
|
? (previewOpen
|
|
2326
2391
|
? ` | tab ${paneFocus === 'preview' ? 'main' : 'preview'} | ↑/↓ ${paneFocus === 'preview' ? 'scroll' : 'navigate'} | v close | vv fullscreen`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specsmd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
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": {
|