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.
@@ -689,15 +689,70 @@ function buildOverviewProjectLines(snapshot, width, flow) {
689
689
  return buildFireOverviewProjectLines(snapshot, width);
690
690
  }
691
691
 
692
- function buildOverviewIntentLines(snapshot, width, flow) {
692
+ function listOverviewIntentEntries(snapshot, flow) {
693
693
  const effectiveFlow = getEffectiveFlow(flow, snapshot);
694
694
  if (effectiveFlow === 'aidlc') {
695
- return buildAidlcOverviewIntentLines(snapshot, width);
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
- return buildSimpleOverviewIntentLines(snapshot, width);
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
- return buildFireOverviewIntentLines(snapshot, width);
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 ['project', 'intent-status', 'standards'];
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', 'completed'];
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 (key.rightArrow || input === 'g') {
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 (key.leftArrow || input === 'G') {
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: 'Intent Status',
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 | c done'
2323
- : (ui.view === 'overview' ? ' | p project | i intents | s standards' : ' | t stats | w warnings | e errors');
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.33",
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": {