specsmd 0.1.27 → 0.1.28

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.
@@ -114,18 +114,33 @@ function formatTime(value) {
114
114
  return date.toLocaleTimeString();
115
115
  }
116
116
 
117
- function buildShortStats(snapshot) {
117
+ function buildShortStats(snapshot, flow) {
118
118
  if (!snapshot?.initialized) {
119
+ if (flow === 'aidlc') {
120
+ return 'init: waiting for memory-bank scan';
121
+ }
122
+ if (flow === 'simple') {
123
+ return 'init: waiting for specs scan';
124
+ }
119
125
  return 'init: waiting for state.yaml';
120
126
  }
121
127
 
122
- const stats = snapshot.stats;
123
- return `runs ${stats.activeRunsCount}/${stats.completedRuns} | intents ${stats.completedIntents}/${stats.totalIntents} | work ${stats.completedWorkItems}/${stats.totalWorkItems}`;
128
+ const stats = snapshot?.stats || {};
129
+
130
+ if (flow === 'aidlc') {
131
+ return `bolts ${stats.activeBoltsCount || 0}/${stats.completedBolts || 0} | intents ${stats.completedIntents || 0}/${stats.totalIntents || 0} | stories ${stats.completedStories || 0}/${stats.totalStories || 0}`;
132
+ }
133
+
134
+ if (flow === 'simple') {
135
+ return `specs ${stats.completedSpecs || 0}/${stats.totalSpecs || 0} | tasks ${stats.completedTasks || 0}/${stats.totalTasks || 0} | active ${stats.activeSpecsCount || 0}`;
136
+ }
137
+
138
+ return `runs ${stats.activeRunsCount || 0}/${stats.completedRuns || 0} | intents ${stats.completedIntents || 0}/${stats.totalIntents || 0} | work ${stats.completedWorkItems || 0}/${stats.totalWorkItems || 0}`;
124
139
  }
125
140
 
126
141
  function buildHeaderLine(snapshot, flow, watchEnabled, watchStatus, lastRefreshAt, view, runFilter, width) {
127
- const projectName = snapshot?.project?.name || 'Unnamed FIRE project';
128
- const shortStats = buildShortStats(snapshot);
142
+ const projectName = snapshot?.project?.name || 'Unnamed project';
143
+ const shortStats = buildShortStats(snapshot, flow);
129
144
 
130
145
  const line = `${flow.toUpperCase()} | ${projectName} | ${shortStats} | watch:${watchEnabled ? watchStatus : 'off'} | ${view}/${runFilter} | ${formatTime(lastRefreshAt)}`;
131
146
 
@@ -192,7 +207,7 @@ function buildPhaseTrack(currentPhase) {
192
207
  return labels.map((label, index) => (index === currentIndex ? `[${label}]` : ` ${label} `)).join(' - ');
193
208
  }
194
209
 
195
- function buildCurrentRunLines(snapshot, width) {
210
+ function buildFireCurrentRunLines(snapshot, width) {
196
211
  const run = getCurrentRun(snapshot);
197
212
  if (!run) {
198
213
  return [truncate('No active run', width)];
@@ -218,7 +233,7 @@ function buildCurrentRunLines(snapshot, width) {
218
233
  return lines.map((line) => truncate(line, width));
219
234
  }
220
235
 
221
- function buildRunFilesLines(snapshot, width, icons) {
236
+ function buildFireRunFilesLines(snapshot, width, icons) {
222
237
  const run = getCurrentRun(snapshot);
223
238
  if (!run) {
224
239
  return [truncate('No run files (no active run)', width)];
@@ -232,7 +247,7 @@ function buildRunFilesLines(snapshot, width, icons) {
232
247
  return files.map((file) => truncate(`${icons.runFile} ${file}`, width));
233
248
  }
234
249
 
235
- function buildPendingLines(snapshot, runFilter, width) {
250
+ function buildFirePendingLines(snapshot, runFilter, width) {
236
251
  if (runFilter === 'completed') {
237
252
  return [truncate('Hidden by run filter: completed', width)];
238
253
  }
@@ -248,7 +263,7 @@ function buildPendingLines(snapshot, runFilter, width) {
248
263
  });
249
264
  }
250
265
 
251
- function buildCompletedLines(snapshot, runFilter, width) {
266
+ function buildFireCompletedLines(snapshot, runFilter, width) {
252
267
  if (runFilter === 'active') {
253
268
  return [truncate('Hidden by run filter: active', width)];
254
269
  }
@@ -265,7 +280,7 @@ function buildCompletedLines(snapshot, runFilter, width) {
265
280
  });
266
281
  }
267
282
 
268
- function buildStatsLines(snapshot, width) {
283
+ function buildFireStatsLines(snapshot, width) {
269
284
  if (!snapshot?.initialized) {
270
285
  return [truncate('Waiting for .specs-fire/state.yaml initialization.', width)];
271
286
  }
@@ -287,7 +302,7 @@ function buildWarningsLines(snapshot, width) {
287
302
  return warnings.map((warning) => truncate(warning, width));
288
303
  }
289
304
 
290
- function buildOverviewProjectLines(snapshot, width) {
305
+ function buildFireOverviewProjectLines(snapshot, width) {
291
306
  if (!snapshot?.initialized) {
292
307
  return [
293
308
  truncate('FIRE folder detected, but state.yaml is missing.', width),
@@ -305,7 +320,7 @@ function buildOverviewProjectLines(snapshot, width) {
305
320
  ].map((line) => truncate(line, width));
306
321
  }
307
322
 
308
- function buildOverviewIntentLines(snapshot, width) {
323
+ function buildFireOverviewIntentLines(snapshot, width) {
309
324
  const intents = snapshot?.intents || [];
310
325
  if (intents.length === 0) {
311
326
  return [truncate('No intents found', width)];
@@ -318,7 +333,7 @@ function buildOverviewIntentLines(snapshot, width) {
318
333
  });
319
334
  }
320
335
 
321
- function buildOverviewStandardsLines(snapshot, width) {
336
+ function buildFireOverviewStandardsLines(snapshot, width) {
322
337
  const expected = ['constitution', 'tech-stack', 'coding-standards', 'testing-standards', 'system-architecture'];
323
338
  const actual = new Set((snapshot?.standards || []).map((item) => item.type));
324
339
 
@@ -328,6 +343,435 @@ function buildOverviewStandardsLines(snapshot, width) {
328
343
  });
329
344
  }
330
345
 
346
+ function getEffectiveFlow(flow, snapshot) {
347
+ const explicitFlow = typeof flow === 'string' && flow !== '' ? flow : null;
348
+ const snapshotFlow = typeof snapshot?.flow === 'string' && snapshot.flow !== '' ? snapshot.flow : null;
349
+ return (snapshotFlow || explicitFlow || 'fire').toLowerCase();
350
+ }
351
+
352
+ function getCurrentBolt(snapshot) {
353
+ const activeBolts = Array.isArray(snapshot?.activeBolts) ? [...snapshot.activeBolts] : [];
354
+ if (activeBolts.length === 0) {
355
+ return null;
356
+ }
357
+
358
+ activeBolts.sort((a, b) => {
359
+ const aTime = a?.startedAt ? Date.parse(a.startedAt) : 0;
360
+ const bTime = b?.startedAt ? Date.parse(b.startedAt) : 0;
361
+ if (bTime !== aTime) {
362
+ return bTime - aTime;
363
+ }
364
+ return String(a?.id || '').localeCompare(String(b?.id || ''));
365
+ });
366
+
367
+ return activeBolts[0] || null;
368
+ }
369
+
370
+ function buildAidlcStageTrack(bolt) {
371
+ const stages = Array.isArray(bolt?.stages) ? bolt.stages : [];
372
+ if (stages.length === 0) {
373
+ return 'n/a';
374
+ }
375
+
376
+ return stages.map((stage) => {
377
+ const label = String(stage?.name || '?').charAt(0).toUpperCase();
378
+ if (stage?.status === 'completed') {
379
+ return `[${label}]`;
380
+ }
381
+ if (stage?.status === 'in_progress') {
382
+ return `<${label}>`;
383
+ }
384
+ return ` ${label} `;
385
+ }).join('-');
386
+ }
387
+
388
+ function buildAidlcCurrentRunLines(snapshot, width) {
389
+ const bolt = getCurrentBolt(snapshot);
390
+ if (!bolt) {
391
+ return [truncate('No active bolt', width)];
392
+ }
393
+
394
+ const stages = Array.isArray(bolt.stages) ? bolt.stages : [];
395
+ const completedStages = stages.filter((stage) => stage.status === 'completed').length;
396
+ const phaseTrack = buildAidlcStageTrack(bolt);
397
+ const location = `${bolt.intent || 'unknown-intent'} / ${bolt.unit || 'unknown-unit'}`;
398
+
399
+ const lines = [
400
+ `${bolt.id} [${bolt.type}] ${completedStages}/${stages.length} stages done`,
401
+ `scope: ${location}`,
402
+ `stage: ${bolt.currentStage || 'n/a'} | status: ${bolt.status}`,
403
+ `phase: ${phaseTrack}`
404
+ ];
405
+
406
+ return lines.map((line) => truncate(line, width));
407
+ }
408
+
409
+ function buildAidlcRunFilesLines(snapshot, width, icons) {
410
+ const bolt = getCurrentBolt(snapshot);
411
+ if (!bolt) {
412
+ return [truncate('No bolt files (no active bolt)', width)];
413
+ }
414
+
415
+ const files = Array.isArray(bolt.files) ? bolt.files : [];
416
+ if (files.length === 0) {
417
+ return [truncate('No markdown files found in active bolt', width)];
418
+ }
419
+
420
+ return files.map((file) => truncate(`${icons.runFile} ${file}`, width));
421
+ }
422
+
423
+ function buildAidlcPendingLines(snapshot, runFilter, width) {
424
+ if (runFilter === 'completed') {
425
+ return [truncate('Hidden by run filter: completed', width)];
426
+ }
427
+
428
+ const pendingBolts = Array.isArray(snapshot?.pendingBolts) ? snapshot.pendingBolts : [];
429
+ if (pendingBolts.length === 0) {
430
+ return [truncate('No queued bolts', width)];
431
+ }
432
+
433
+ return pendingBolts.map((bolt) => {
434
+ const deps = Array.isArray(bolt.blockedBy) && bolt.blockedBy.length > 0
435
+ ? ` blocked_by:${bolt.blockedBy.join(',')}`
436
+ : '';
437
+ const location = `${bolt.intent || 'unknown'}/${bolt.unit || 'unknown'}`;
438
+ return truncate(`${bolt.id} (${bolt.status}) in ${location}${deps}`, width);
439
+ });
440
+ }
441
+
442
+ function buildAidlcCompletedLines(snapshot, runFilter, width) {
443
+ if (runFilter === 'active') {
444
+ return [truncate('Hidden by run filter: active', width)];
445
+ }
446
+
447
+ const completedBolts = Array.isArray(snapshot?.completedBolts) ? snapshot.completedBolts : [];
448
+ if (completedBolts.length === 0) {
449
+ return [truncate('No completed bolts yet', width)];
450
+ }
451
+
452
+ return completedBolts.map((bolt) =>
453
+ truncate(`${bolt.id} [${bolt.type}] done at ${bolt.completedAt || 'unknown'}`, width)
454
+ );
455
+ }
456
+
457
+ function buildAidlcStatsLines(snapshot, width) {
458
+ const stats = snapshot?.stats || {};
459
+
460
+ return [
461
+ `intents: ${stats.completedIntents || 0}/${stats.totalIntents || 0} done | in_progress: ${stats.inProgressIntents || 0} | blocked: ${stats.blockedIntents || 0}`,
462
+ `stories: ${stats.completedStories || 0}/${stats.totalStories || 0} done | in_progress: ${stats.inProgressStories || 0} | pending: ${stats.pendingStories || 0} | blocked: ${stats.blockedStories || 0}`,
463
+ `bolts: ${stats.activeBoltsCount || 0} active | ${stats.queuedBolts || 0} queued | ${stats.blockedBolts || 0} blocked | ${stats.completedBolts || 0} done`
464
+ ].map((line) => truncate(line, width));
465
+ }
466
+
467
+ function buildAidlcOverviewProjectLines(snapshot, width) {
468
+ const project = snapshot?.project || {};
469
+ const stats = snapshot?.stats || {};
470
+
471
+ return [
472
+ `project: ${project.name || 'unknown'} | project_type: ${project.projectType || 'unknown'}`,
473
+ `memory-bank: intents ${stats.totalIntents || 0} | units ${stats.totalUnits || 0} | stories ${stats.totalStories || 0}`,
474
+ `progress: ${stats.progressPercent || 0}% stories complete | standards: ${(snapshot?.standards || []).length}`
475
+ ].map((line) => truncate(line, width));
476
+ }
477
+
478
+ function buildAidlcOverviewIntentLines(snapshot, width) {
479
+ const intents = Array.isArray(snapshot?.intents) ? snapshot.intents : [];
480
+ if (intents.length === 0) {
481
+ return [truncate('No intents found', width)];
482
+ }
483
+
484
+ return intents.map((intent) => {
485
+ return truncate(
486
+ `${intent.id}: ${intent.status} (${intent.completedStories || 0}/${intent.storyCount || 0} stories, ${intent.completedUnits || 0}/${intent.unitCount || 0} units)`,
487
+ width
488
+ );
489
+ });
490
+ }
491
+
492
+ function buildAidlcOverviewStandardsLines(snapshot, width) {
493
+ const standards = Array.isArray(snapshot?.standards) ? snapshot.standards : [];
494
+ if (standards.length === 0) {
495
+ return [truncate('No standards found under memory-bank/standards', width)];
496
+ }
497
+
498
+ return standards.map((standard) =>
499
+ truncate(`[x] ${standard.name || standard.type || 'unknown'}.md`, width)
500
+ );
501
+ }
502
+
503
+ function getCurrentSpec(snapshot) {
504
+ const specs = Array.isArray(snapshot?.activeSpecs) ? snapshot.activeSpecs : [];
505
+ if (specs.length === 0) {
506
+ return null;
507
+ }
508
+ return specs[0] || null;
509
+ }
510
+
511
+ function simplePhaseIndex(state) {
512
+ if (state === 'requirements_pending') {
513
+ return 0;
514
+ }
515
+ if (state === 'design_pending') {
516
+ return 1;
517
+ }
518
+ return 2;
519
+ }
520
+
521
+ function buildSimplePhaseTrack(spec) {
522
+ if (spec?.state === 'completed') {
523
+ return '[R] - [D] - [T]';
524
+ }
525
+
526
+ const labels = ['R', 'D', 'T'];
527
+ const current = simplePhaseIndex(spec?.state);
528
+ return labels.map((label, index) => (index === current ? `[${label}]` : ` ${label} `)).join(' - ');
529
+ }
530
+
531
+ function buildSimpleCurrentRunLines(snapshot, width) {
532
+ const spec = getCurrentSpec(snapshot);
533
+ if (!spec) {
534
+ return [truncate('No active spec', width)];
535
+ }
536
+
537
+ const files = [
538
+ spec.hasRequirements ? 'req' : '-',
539
+ spec.hasDesign ? 'design' : '-',
540
+ spec.hasTasks ? 'tasks' : '-'
541
+ ].join('/');
542
+
543
+ const lines = [
544
+ `${spec.name} [${spec.state}] ${spec.tasksCompleted}/${spec.tasksTotal} tasks done`,
545
+ `phase: ${spec.phase}`,
546
+ `files: ${files}`,
547
+ `track: ${buildSimplePhaseTrack(spec)}`
548
+ ];
549
+
550
+ return lines.map((line) => truncate(line, width));
551
+ }
552
+
553
+ function buildSimpleRunFilesLines(snapshot, width, icons) {
554
+ const spec = getCurrentSpec(snapshot);
555
+ if (!spec) {
556
+ return [truncate('No spec files (no active spec)', width)];
557
+ }
558
+
559
+ const files = [];
560
+ if (spec.hasRequirements) files.push('requirements.md');
561
+ if (spec.hasDesign) files.push('design.md');
562
+ if (spec.hasTasks) files.push('tasks.md');
563
+
564
+ if (files.length === 0) {
565
+ return [truncate('No files found in active spec folder', width)];
566
+ }
567
+
568
+ return files.map((file) => truncate(`${icons.runFile} ${file}`, width));
569
+ }
570
+
571
+ function buildSimplePendingLines(snapshot, runFilter, width) {
572
+ if (runFilter === 'completed') {
573
+ return [truncate('Hidden by run filter: completed', width)];
574
+ }
575
+
576
+ const pendingSpecs = Array.isArray(snapshot?.pendingSpecs) ? snapshot.pendingSpecs : [];
577
+ if (pendingSpecs.length === 0) {
578
+ return [truncate('No pending specs', width)];
579
+ }
580
+
581
+ return pendingSpecs.map((spec) =>
582
+ truncate(`${spec.name} (${spec.state}) ${spec.tasksCompleted}/${spec.tasksTotal} tasks`, width)
583
+ );
584
+ }
585
+
586
+ function buildSimpleCompletedLines(snapshot, runFilter, width) {
587
+ if (runFilter === 'active') {
588
+ return [truncate('Hidden by run filter: active', width)];
589
+ }
590
+
591
+ const completedSpecs = Array.isArray(snapshot?.completedSpecs) ? snapshot.completedSpecs : [];
592
+ if (completedSpecs.length === 0) {
593
+ return [truncate('No completed specs yet', width)];
594
+ }
595
+
596
+ return completedSpecs.map((spec) =>
597
+ truncate(`${spec.name} done at ${spec.updatedAt || 'unknown'} (${spec.tasksCompleted}/${spec.tasksTotal})`, width)
598
+ );
599
+ }
600
+
601
+ function buildSimpleStatsLines(snapshot, width) {
602
+ const stats = snapshot?.stats || {};
603
+
604
+ return [
605
+ `specs: ${stats.completedSpecs || 0}/${stats.totalSpecs || 0} complete | in_progress: ${stats.inProgressSpecs || 0} | pending: ${stats.pendingSpecs || 0}`,
606
+ `pipeline: ready ${stats.readySpecs || 0} | design_pending ${stats.designPendingSpecs || 0} | tasks_pending ${stats.tasksPendingSpecs || 0}`,
607
+ `tasks: ${stats.completedTasks || 0}/${stats.totalTasks || 0} complete | pending: ${stats.pendingTasks || 0} | optional: ${stats.optionalTasks || 0}`
608
+ ].map((line) => truncate(line, width));
609
+ }
610
+
611
+ function buildSimpleOverviewProjectLines(snapshot, width) {
612
+ const project = snapshot?.project || {};
613
+ const stats = snapshot?.stats || {};
614
+
615
+ return [
616
+ `project: ${project.name || 'unknown'} | simple flow`,
617
+ `specs: ${stats.totalSpecs || 0} total | active: ${stats.activeSpecsCount || 0} | completed: ${stats.completedSpecs || 0}`,
618
+ `tasks: ${stats.completedTasks || 0}/${stats.totalTasks || 0} complete (${stats.progressPercent || 0}%)`
619
+ ].map((line) => truncate(line, width));
620
+ }
621
+
622
+ function buildSimpleOverviewIntentLines(snapshot, width) {
623
+ const specs = Array.isArray(snapshot?.specs) ? snapshot.specs : [];
624
+ if (specs.length === 0) {
625
+ return [truncate('No specs found', width)];
626
+ }
627
+
628
+ return specs.map((spec) =>
629
+ truncate(`${spec.name}: ${spec.state} (${spec.tasksCompleted}/${spec.tasksTotal} tasks)`, width)
630
+ );
631
+ }
632
+
633
+ function buildSimpleOverviewStandardsLines(snapshot, width) {
634
+ const specs = Array.isArray(snapshot?.specs) ? snapshot.specs : [];
635
+ if (specs.length === 0) {
636
+ return [truncate('No spec artifacts found', width)];
637
+ }
638
+
639
+ const reqCount = specs.filter((spec) => spec.hasRequirements).length;
640
+ const designCount = specs.filter((spec) => spec.hasDesign).length;
641
+ const tasksCount = specs.filter((spec) => spec.hasTasks).length;
642
+ const total = specs.length;
643
+
644
+ return [
645
+ `[x] requirements.md coverage ${reqCount}/${total}`,
646
+ `[x] design.md coverage ${designCount}/${total}`,
647
+ `[x] tasks.md coverage ${tasksCount}/${total}`
648
+ ].map((line) => truncate(line, width));
649
+ }
650
+
651
+ function buildCurrentRunLines(snapshot, width, flow) {
652
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
653
+ if (effectiveFlow === 'aidlc') {
654
+ return buildAidlcCurrentRunLines(snapshot, width);
655
+ }
656
+ if (effectiveFlow === 'simple') {
657
+ return buildSimpleCurrentRunLines(snapshot, width);
658
+ }
659
+ return buildFireCurrentRunLines(snapshot, width);
660
+ }
661
+
662
+ function buildRunFilesLines(snapshot, width, icons, flow) {
663
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
664
+ if (effectiveFlow === 'aidlc') {
665
+ return buildAidlcRunFilesLines(snapshot, width, icons);
666
+ }
667
+ if (effectiveFlow === 'simple') {
668
+ return buildSimpleRunFilesLines(snapshot, width, icons);
669
+ }
670
+ return buildFireRunFilesLines(snapshot, width, icons);
671
+ }
672
+
673
+ function buildPendingLines(snapshot, runFilter, width, flow) {
674
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
675
+ if (effectiveFlow === 'aidlc') {
676
+ return buildAidlcPendingLines(snapshot, runFilter, width);
677
+ }
678
+ if (effectiveFlow === 'simple') {
679
+ return buildSimplePendingLines(snapshot, runFilter, width);
680
+ }
681
+ return buildFirePendingLines(snapshot, runFilter, width);
682
+ }
683
+
684
+ function buildCompletedLines(snapshot, runFilter, width, flow) {
685
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
686
+ if (effectiveFlow === 'aidlc') {
687
+ return buildAidlcCompletedLines(snapshot, runFilter, width);
688
+ }
689
+ if (effectiveFlow === 'simple') {
690
+ return buildSimpleCompletedLines(snapshot, runFilter, width);
691
+ }
692
+ return buildFireCompletedLines(snapshot, runFilter, width);
693
+ }
694
+
695
+ function buildStatsLines(snapshot, width, flow) {
696
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
697
+ if (!snapshot?.initialized) {
698
+ if (effectiveFlow === 'aidlc') {
699
+ return [truncate('Waiting for memory-bank initialization.', width)];
700
+ }
701
+ if (effectiveFlow === 'simple') {
702
+ return [truncate('Waiting for specs/ initialization.', width)];
703
+ }
704
+ return [truncate('Waiting for .specs-fire/state.yaml initialization.', width)];
705
+ }
706
+
707
+ if (effectiveFlow === 'aidlc') {
708
+ return buildAidlcStatsLines(snapshot, width);
709
+ }
710
+ if (effectiveFlow === 'simple') {
711
+ return buildSimpleStatsLines(snapshot, width);
712
+ }
713
+ return buildFireStatsLines(snapshot, width);
714
+ }
715
+
716
+ function buildOverviewProjectLines(snapshot, width, flow) {
717
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
718
+ if (effectiveFlow === 'aidlc') {
719
+ return buildAidlcOverviewProjectLines(snapshot, width);
720
+ }
721
+ if (effectiveFlow === 'simple') {
722
+ return buildSimpleOverviewProjectLines(snapshot, width);
723
+ }
724
+ return buildFireOverviewProjectLines(snapshot, width);
725
+ }
726
+
727
+ function buildOverviewIntentLines(snapshot, width, flow) {
728
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
729
+ if (effectiveFlow === 'aidlc') {
730
+ return buildAidlcOverviewIntentLines(snapshot, width);
731
+ }
732
+ if (effectiveFlow === 'simple') {
733
+ return buildSimpleOverviewIntentLines(snapshot, width);
734
+ }
735
+ return buildFireOverviewIntentLines(snapshot, width);
736
+ }
737
+
738
+ function buildOverviewStandardsLines(snapshot, width, flow) {
739
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
740
+ if (effectiveFlow === 'aidlc') {
741
+ return buildAidlcOverviewStandardsLines(snapshot, width);
742
+ }
743
+ if (effectiveFlow === 'simple') {
744
+ return buildSimpleOverviewStandardsLines(snapshot, width);
745
+ }
746
+ return buildFireOverviewStandardsLines(snapshot, width);
747
+ }
748
+
749
+ function getPanelTitles(flow, snapshot) {
750
+ const effectiveFlow = getEffectiveFlow(flow, snapshot);
751
+ if (effectiveFlow === 'aidlc') {
752
+ return {
753
+ current: 'Current Bolt',
754
+ files: 'Bolt Files',
755
+ pending: 'Queued Bolts',
756
+ completed: 'Recent Completed Bolts'
757
+ };
758
+ }
759
+ if (effectiveFlow === 'simple') {
760
+ return {
761
+ current: 'Current Spec',
762
+ files: 'Spec Files',
763
+ pending: 'Pending Specs',
764
+ completed: 'Recent Completed Specs'
765
+ };
766
+ }
767
+ return {
768
+ current: 'Current Run',
769
+ files: 'Run Files',
770
+ pending: 'Pending Queue',
771
+ completed: 'Recent Completed Runs'
772
+ };
773
+ }
774
+
331
775
  function allocateSingleColumnPanels(candidates, rowsBudget) {
332
776
  const filtered = (candidates || []).filter(Boolean);
333
777
  if (filtered.length === 0) {
@@ -634,6 +1078,7 @@ function createDashboardApp(deps) {
634
1078
  const reservedRows = 2 + (showHelpLine ? 1 : 0) + (showErrorPanel ? 5 : 0) + (showErrorInline ? 1 : 0);
635
1079
  const contentRowsBudget = Math.max(4, rows - reservedRows);
636
1080
  const ultraCompact = rows <= 14;
1081
+ const panelTitles = getPanelTitles(flow, snapshot);
637
1082
 
638
1083
  let panelCandidates;
639
1084
  if (ui.view === 'overview') {
@@ -641,19 +1086,19 @@ function createDashboardApp(deps) {
641
1086
  {
642
1087
  key: 'project',
643
1088
  title: 'Project + Workspace',
644
- lines: buildOverviewProjectLines(snapshot, compactWidth),
1089
+ lines: buildOverviewProjectLines(snapshot, compactWidth, flow),
645
1090
  borderColor: 'green'
646
1091
  },
647
1092
  {
648
1093
  key: 'intent-status',
649
1094
  title: 'Intent Status',
650
- lines: buildOverviewIntentLines(snapshot, compactWidth),
1095
+ lines: buildOverviewIntentLines(snapshot, compactWidth, flow),
651
1096
  borderColor: 'yellow'
652
1097
  },
653
1098
  {
654
1099
  key: 'standards',
655
1100
  title: 'Standards',
656
- lines: buildOverviewStandardsLines(snapshot, compactWidth),
1101
+ lines: buildOverviewStandardsLines(snapshot, compactWidth, flow),
657
1102
  borderColor: 'blue'
658
1103
  }
659
1104
  ];
@@ -662,7 +1107,7 @@ function createDashboardApp(deps) {
662
1107
  {
663
1108
  key: 'stats',
664
1109
  title: 'Stats',
665
- lines: buildStatsLines(snapshot, compactWidth),
1110
+ lines: buildStatsLines(snapshot, compactWidth, flow),
666
1111
  borderColor: 'magenta'
667
1112
  },
668
1113
  {
@@ -685,26 +1130,26 @@ function createDashboardApp(deps) {
685
1130
  panelCandidates = [
686
1131
  {
687
1132
  key: 'current-run',
688
- title: 'Current Run',
689
- lines: buildCurrentRunLines(snapshot, compactWidth),
1133
+ title: panelTitles.current,
1134
+ lines: buildCurrentRunLines(snapshot, compactWidth, flow),
690
1135
  borderColor: 'green'
691
1136
  },
692
1137
  {
693
1138
  key: 'run-files',
694
- title: 'Run Files',
695
- lines: buildRunFilesLines(snapshot, compactWidth, icons),
1139
+ title: panelTitles.files,
1140
+ lines: buildRunFilesLines(snapshot, compactWidth, icons, flow),
696
1141
  borderColor: 'yellow'
697
1142
  },
698
1143
  {
699
1144
  key: 'pending',
700
- title: 'Pending Queue',
701
- lines: buildPendingLines(snapshot, ui.runFilter, compactWidth),
1145
+ title: panelTitles.pending,
1146
+ lines: buildPendingLines(snapshot, ui.runFilter, compactWidth, flow),
702
1147
  borderColor: 'yellow'
703
1148
  },
704
1149
  {
705
1150
  key: 'completed',
706
- title: 'Recent Completed Runs',
707
- lines: buildCompletedLines(snapshot, ui.runFilter, compactWidth),
1151
+ title: panelTitles.completed,
1152
+ lines: buildCompletedLines(snapshot, ui.runFilter, compactWidth, flow),
708
1153
  borderColor: 'blue'
709
1154
  }
710
1155
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specsmd",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
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": {