specsmd 0.1.34 → 0.1.35
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 +116 -18
- package/package.json +1 -1
package/lib/dashboard/tui/app.js
CHANGED
|
@@ -1397,6 +1397,81 @@ function openFileWithDefaultApp(filePath) {
|
|
|
1397
1397
|
};
|
|
1398
1398
|
}
|
|
1399
1399
|
|
|
1400
|
+
function buildQuickHelpText(view, options = {}) {
|
|
1401
|
+
const {
|
|
1402
|
+
previewOpen = false,
|
|
1403
|
+
availableFlowCount = 1
|
|
1404
|
+
} = options;
|
|
1405
|
+
|
|
1406
|
+
const parts = ['1/2/3 views', 'g/G sections'];
|
|
1407
|
+
|
|
1408
|
+
if (view === 'runs') {
|
|
1409
|
+
if (previewOpen) {
|
|
1410
|
+
parts.push('tab pane', '↑/↓ nav/scroll', 'v close');
|
|
1411
|
+
} else {
|
|
1412
|
+
parts.push('↑/↓ navigate', 'enter expand', 'v preview');
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
if (availableFlowCount > 1) {
|
|
1417
|
+
parts.push('[/] flow');
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
parts.push('r refresh', '? shortcuts', 'q quit');
|
|
1421
|
+
return parts.join(' | ');
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
function buildHelpOverlayLines(options = {}) {
|
|
1425
|
+
const {
|
|
1426
|
+
view = 'runs',
|
|
1427
|
+
previewOpen = false,
|
|
1428
|
+
paneFocus = 'main',
|
|
1429
|
+
availableFlowCount = 1,
|
|
1430
|
+
showErrorSection = false
|
|
1431
|
+
} = options;
|
|
1432
|
+
|
|
1433
|
+
const lines = [
|
|
1434
|
+
{ text: 'Global', color: 'cyan', bold: true },
|
|
1435
|
+
'q or Ctrl+C quit',
|
|
1436
|
+
'r refresh snapshot',
|
|
1437
|
+
'1 runs | 2 overview | 3 health',
|
|
1438
|
+
'g next section | G previous section',
|
|
1439
|
+
'h/? toggle this shortcuts overlay',
|
|
1440
|
+
'esc close overlays (help/preview/fullscreen)',
|
|
1441
|
+
{ text: '', color: undefined, bold: false },
|
|
1442
|
+
{ text: 'Runs View', color: 'yellow', bold: true },
|
|
1443
|
+
'a current | f files | p pending',
|
|
1444
|
+
'up/down or j/k move selection',
|
|
1445
|
+
'enter expand/collapse pending/completed groups',
|
|
1446
|
+
'v preview selected file',
|
|
1447
|
+
'v twice quickly opens fullscreen preview overlay',
|
|
1448
|
+
'tab switch focus between main and preview panes',
|
|
1449
|
+
'o open selected file in system default app'
|
|
1450
|
+
];
|
|
1451
|
+
|
|
1452
|
+
if (previewOpen) {
|
|
1453
|
+
lines.push(`preview is open (focus: ${paneFocus})`);
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
if (availableFlowCount > 1) {
|
|
1457
|
+
lines.push('[/] (and m) switch flow');
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
lines.push(
|
|
1461
|
+
{ text: '', color: undefined, bold: false },
|
|
1462
|
+
{ text: 'Overview View', color: 'green', bold: true },
|
|
1463
|
+
'i intents | c completed | s standards | p project',
|
|
1464
|
+
'when Intents is focused: n next | x completed | left/right toggle filter',
|
|
1465
|
+
{ text: '', color: undefined, bold: false },
|
|
1466
|
+
{ text: 'Health View', color: 'magenta', bold: true },
|
|
1467
|
+
`t stats | w warnings${showErrorSection ? ' | e errors' : ''}`,
|
|
1468
|
+
{ text: '', color: undefined, bold: false },
|
|
1469
|
+
{ text: `Current view: ${String(view || 'runs').toUpperCase()}`, color: 'gray', bold: false }
|
|
1470
|
+
);
|
|
1471
|
+
|
|
1472
|
+
return lines;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1400
1475
|
function colorizeMarkdownLine(line, inCodeBlock) {
|
|
1401
1476
|
const text = String(line ?? '');
|
|
1402
1477
|
|
|
@@ -1823,6 +1898,15 @@ function createDashboardApp(deps) {
|
|
|
1823
1898
|
return;
|
|
1824
1899
|
}
|
|
1825
1900
|
|
|
1901
|
+
if (key.escape && ui.showHelp) {
|
|
1902
|
+
setUi((previous) => ({ ...previous, showHelp: false }));
|
|
1903
|
+
return;
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
if (ui.showHelp) {
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1826
1910
|
if (input === '1') {
|
|
1827
1911
|
setUi((previous) => ({ ...previous, view: 'runs' }));
|
|
1828
1912
|
setPaneFocus('main');
|
|
@@ -2240,16 +2324,16 @@ function createDashboardApp(deps) {
|
|
|
2240
2324
|
const rows = Number.isFinite(terminalSize.rows) ? terminalSize.rows : (process.stdout.rows || 40);
|
|
2241
2325
|
|
|
2242
2326
|
const fullWidth = Math.max(40, cols - 1);
|
|
2243
|
-
const
|
|
2327
|
+
const showFooterHelpLine = rows >= 10;
|
|
2244
2328
|
const showErrorPanel = Boolean(error) && rows >= 18;
|
|
2245
2329
|
const showErrorInline = Boolean(error) && !showErrorPanel;
|
|
2246
2330
|
const densePanels = rows <= 28 || cols <= 120;
|
|
2247
2331
|
|
|
2248
|
-
const reservedRows = 2 + (
|
|
2332
|
+
const reservedRows = 2 + (showFooterHelpLine ? 1 : 0) + (showErrorPanel ? 5 : 0) + (showErrorInline ? 1 : 0);
|
|
2249
2333
|
const contentRowsBudget = Math.max(4, rows - reservedRows);
|
|
2250
2334
|
const ultraCompact = rows <= 14;
|
|
2251
2335
|
const panelTitles = getPanelTitles(activeFlow, snapshot);
|
|
2252
|
-
const splitPreviewLayout = ui.view === 'runs' && previewOpen && !overlayPreviewOpen && cols >= 110 && rows >= 16;
|
|
2336
|
+
const splitPreviewLayout = ui.view === 'runs' && previewOpen && !overlayPreviewOpen && !ui.showHelp && cols >= 110 && rows >= 16;
|
|
2253
2337
|
const mainPaneWidth = splitPreviewLayout
|
|
2254
2338
|
? Math.max(34, Math.floor((fullWidth - 1) * 0.52))
|
|
2255
2339
|
: fullWidth;
|
|
@@ -2280,8 +2364,30 @@ function createDashboardApp(deps) {
|
|
|
2280
2364
|
})
|
|
2281
2365
|
: [];
|
|
2282
2366
|
|
|
2367
|
+
const shortcutsOverlayLines = buildHelpOverlayLines({
|
|
2368
|
+
view: ui.view,
|
|
2369
|
+
previewOpen,
|
|
2370
|
+
paneFocus,
|
|
2371
|
+
availableFlowCount: availableFlowIds.length,
|
|
2372
|
+
showErrorSection: showErrorPanel
|
|
2373
|
+
});
|
|
2374
|
+
const quickHelpText = buildQuickHelpText(ui.view, {
|
|
2375
|
+
previewOpen,
|
|
2376
|
+
paneFocus,
|
|
2377
|
+
availableFlowCount: availableFlowIds.length
|
|
2378
|
+
});
|
|
2379
|
+
|
|
2283
2380
|
let panelCandidates;
|
|
2284
|
-
if (ui.
|
|
2381
|
+
if (ui.showHelp) {
|
|
2382
|
+
panelCandidates = [
|
|
2383
|
+
{
|
|
2384
|
+
key: 'shortcuts-overlay',
|
|
2385
|
+
title: 'Keyboard Shortcuts',
|
|
2386
|
+
lines: shortcutsOverlayLines,
|
|
2387
|
+
borderColor: 'cyan'
|
|
2388
|
+
}
|
|
2389
|
+
];
|
|
2390
|
+
} else if (ui.view === 'runs' && previewOpen && overlayPreviewOpen) {
|
|
2285
2391
|
panelCandidates = [
|
|
2286
2392
|
{
|
|
2287
2393
|
key: 'preview-overlay',
|
|
@@ -2382,16 +2488,6 @@ function createDashboardApp(deps) {
|
|
|
2382
2488
|
}
|
|
2383
2489
|
|
|
2384
2490
|
const panels = allocateSingleColumnPanels(panelCandidates, contentRowsBudget);
|
|
2385
|
-
const flowSwitchHint = availableFlowIds.length > 1 ? ' | [ or ] switch flow' : '';
|
|
2386
|
-
const sectionHint = ui.view === 'runs'
|
|
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');
|
|
2389
|
-
const previewHint = ui.view === 'runs'
|
|
2390
|
-
? (previewOpen
|
|
2391
|
-
? ` | tab ${paneFocus === 'preview' ? 'main' : 'preview'} | ↑/↓ ${paneFocus === 'preview' ? 'scroll' : 'navigate'} | v close | vv fullscreen`
|
|
2392
|
-
: ' | ↑/↓ navigate | enter expand | v preview | vv fullscreen | o open')
|
|
2393
|
-
: '';
|
|
2394
|
-
const helpText = `q quit | r refresh | h/? help | 1 runs | 2 overview | 3 health | g/G section${sectionHint}${previewHint}${flowSwitchHint}`;
|
|
2395
2491
|
|
|
2396
2492
|
const renderPanel = (panel, index, width, isFocused) => React.createElement(SectionPanel, {
|
|
2397
2493
|
key: panel.key,
|
|
@@ -2455,9 +2551,11 @@ function createDashboardApp(deps) {
|
|
|
2455
2551
|
panel,
|
|
2456
2552
|
index,
|
|
2457
2553
|
fullWidth,
|
|
2458
|
-
|
|
2554
|
+
ui.showHelp
|
|
2555
|
+
? true
|
|
2556
|
+
: ((panel.key === 'preview' || panel.key === 'preview-overlay')
|
|
2459
2557
|
? paneFocus === 'preview'
|
|
2460
|
-
: (paneFocus === 'main' && panel.key === focusedSection)
|
|
2558
|
+
: (paneFocus === 'main' && panel.key === focusedSection))
|
|
2461
2559
|
));
|
|
2462
2560
|
}
|
|
2463
2561
|
|
|
@@ -2486,8 +2584,8 @@ function createDashboardApp(deps) {
|
|
|
2486
2584
|
statusLine !== ''
|
|
2487
2585
|
? React.createElement(Text, { color: 'yellow' }, truncate(statusLine, fullWidth))
|
|
2488
2586
|
: null,
|
|
2489
|
-
|
|
2490
|
-
? React.createElement(Text, { color: 'gray' }, truncate(
|
|
2587
|
+
showFooterHelpLine
|
|
2588
|
+
? React.createElement(Text, { color: 'gray' }, truncate(quickHelpText, fullWidth))
|
|
2491
2589
|
: null
|
|
2492
2590
|
);
|
|
2493
2591
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specsmd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
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": {
|