agileflow 2.76.0 → 2.78.0

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.
Files changed (124) hide show
  1. package/README.md +3 -3
  2. package/package.json +6 -1
  3. package/scripts/agileflow-configure.js +185 -13
  4. package/scripts/agileflow-statusline.sh +266 -27
  5. package/scripts/agileflow-welcome.js +160 -52
  6. package/scripts/auto-self-improve.js +63 -20
  7. package/scripts/check-update.js +1 -4
  8. package/scripts/damage-control-bash.js +232 -0
  9. package/scripts/damage-control-edit.js +243 -0
  10. package/scripts/damage-control-write.js +243 -0
  11. package/scripts/get-env.js +15 -7
  12. package/scripts/lib/frontmatter-parser.js +4 -1
  13. package/scripts/obtain-context.js +59 -48
  14. package/scripts/ralph-loop.js +25 -13
  15. package/scripts/validate-expertise.sh +19 -15
  16. package/src/core/agents/accessibility.md +124 -53
  17. package/src/core/agents/adr-writer.md +192 -52
  18. package/src/core/agents/analytics.md +139 -60
  19. package/src/core/agents/api.md +173 -63
  20. package/src/core/agents/ci.md +139 -57
  21. package/src/core/agents/compliance.md +159 -68
  22. package/src/core/agents/configuration/damage-control.md +356 -0
  23. package/src/core/agents/database.md +162 -61
  24. package/src/core/agents/datamigration.md +179 -66
  25. package/src/core/agents/design.md +179 -57
  26. package/src/core/agents/devops.md +160 -3
  27. package/src/core/agents/documentation.md +204 -60
  28. package/src/core/agents/epic-planner.md +147 -55
  29. package/src/core/agents/integrations.md +197 -69
  30. package/src/core/agents/mentor.md +158 -57
  31. package/src/core/agents/mobile.md +159 -67
  32. package/src/core/agents/monitoring.md +154 -65
  33. package/src/core/agents/multi-expert.md +115 -43
  34. package/src/core/agents/orchestrator.md +77 -24
  35. package/src/core/agents/performance.md +130 -75
  36. package/src/core/agents/product.md +151 -55
  37. package/src/core/agents/qa.md +162 -74
  38. package/src/core/agents/readme-updater.md +178 -76
  39. package/src/core/agents/refactor.md +148 -95
  40. package/src/core/agents/research.md +143 -72
  41. package/src/core/agents/security.md +154 -65
  42. package/src/core/agents/testing.md +176 -97
  43. package/src/core/agents/ui.md +170 -79
  44. package/src/core/commands/adr/list.md +171 -0
  45. package/src/core/commands/adr/update.md +235 -0
  46. package/src/core/commands/adr/view.md +252 -0
  47. package/src/core/commands/adr.md +207 -50
  48. package/src/core/commands/agent.md +16 -0
  49. package/src/core/commands/assign.md +148 -44
  50. package/src/core/commands/auto.md +18 -1
  51. package/src/core/commands/babysit.md +361 -36
  52. package/src/core/commands/baseline.md +14 -0
  53. package/src/core/commands/blockers.md +170 -51
  54. package/src/core/commands/board.md +144 -66
  55. package/src/core/commands/changelog.md +15 -0
  56. package/src/core/commands/ci.md +179 -69
  57. package/src/core/commands/compress.md +18 -0
  58. package/src/core/commands/configure.md +16 -0
  59. package/src/core/commands/context/export.md +193 -4
  60. package/src/core/commands/context/full.md +191 -18
  61. package/src/core/commands/context/note.md +248 -4
  62. package/src/core/commands/debt.md +17 -0
  63. package/src/core/commands/deploy.md +208 -65
  64. package/src/core/commands/deps.md +15 -0
  65. package/src/core/commands/diagnose.md +16 -0
  66. package/src/core/commands/docs.md +196 -64
  67. package/src/core/commands/epic/list.md +170 -0
  68. package/src/core/commands/epic/view.md +242 -0
  69. package/src/core/commands/epic.md +192 -69
  70. package/src/core/commands/feedback.md +191 -71
  71. package/src/core/commands/handoff.md +162 -48
  72. package/src/core/commands/help.md +9 -0
  73. package/src/core/commands/ideate.md +446 -0
  74. package/src/core/commands/impact.md +16 -0
  75. package/src/core/commands/metrics.md +141 -37
  76. package/src/core/commands/multi-expert.md +77 -0
  77. package/src/core/commands/packages.md +16 -0
  78. package/src/core/commands/pr.md +161 -67
  79. package/src/core/commands/readme-sync.md +16 -0
  80. package/src/core/commands/research/analyze.md +568 -0
  81. package/src/core/commands/research/ask.md +345 -20
  82. package/src/core/commands/research/import.md +562 -19
  83. package/src/core/commands/research/list.md +173 -5
  84. package/src/core/commands/research/view.md +181 -8
  85. package/src/core/commands/retro.md +135 -48
  86. package/src/core/commands/review.md +219 -47
  87. package/src/core/commands/session/end.md +209 -0
  88. package/src/core/commands/session/history.md +210 -0
  89. package/src/core/commands/session/init.md +116 -0
  90. package/src/core/commands/session/new.md +296 -0
  91. package/src/core/commands/session/resume.md +166 -0
  92. package/src/core/commands/session/status.md +166 -0
  93. package/src/core/commands/skill/create.md +115 -17
  94. package/src/core/commands/skill/delete.md +117 -0
  95. package/src/core/commands/skill/edit.md +104 -0
  96. package/src/core/commands/skill/list.md +128 -0
  97. package/src/core/commands/skill/test.md +135 -0
  98. package/src/core/commands/skill/upgrade.md +542 -0
  99. package/src/core/commands/sprint.md +17 -1
  100. package/src/core/commands/status.md +133 -21
  101. package/src/core/commands/story/list.md +176 -0
  102. package/src/core/commands/story/view.md +265 -0
  103. package/src/core/commands/story-validate.md +101 -1
  104. package/src/core/commands/story.md +204 -51
  105. package/src/core/commands/template.md +16 -1
  106. package/src/core/commands/tests.md +226 -64
  107. package/src/core/commands/update.md +17 -1
  108. package/src/core/commands/validate-expertise.md +16 -0
  109. package/src/core/commands/velocity.md +140 -36
  110. package/src/core/commands/verify.md +14 -0
  111. package/src/core/commands/whats-new.md +30 -0
  112. package/src/core/skills/_learnings/README.md +91 -0
  113. package/src/core/skills/_learnings/_template.yaml +106 -0
  114. package/src/core/skills/_learnings/commit.yaml +69 -0
  115. package/src/core/templates/damage-control-patterns.yaml +234 -0
  116. package/src/core/templates/skill-template.md +53 -11
  117. package/tools/cli/commands/list.js +3 -1
  118. package/tools/cli/commands/start.js +180 -0
  119. package/tools/cli/commands/uninstall.js +4 -5
  120. package/tools/cli/commands/update.js +11 -3
  121. package/tools/cli/lib/content-injector.js +6 -1
  122. package/tools/cli/tui/Dashboard.js +66 -0
  123. package/tools/cli/tui/StoryList.js +69 -0
  124. package/tools/cli/tui/index.js +16 -0
@@ -32,6 +32,7 @@ const c = {
32
32
  bold: '\x1b[1m',
33
33
  dim: '\x1b[2m',
34
34
 
35
+ // Standard ANSI colors
35
36
  red: '\x1b[31m',
36
37
  green: '\x1b[32m',
37
38
  yellow: '\x1b[33m',
@@ -44,6 +45,22 @@ const c = {
44
45
  brightYellow: '\x1b[93m',
45
46
  brightCyan: '\x1b[96m',
46
47
 
48
+ // Vibrant 256-color palette (modern, sleek look)
49
+ mintGreen: '\x1b[38;5;158m', // Healthy/success states
50
+ peach: '\x1b[38;5;215m', // Warning states
51
+ coral: '\x1b[38;5;203m', // Critical/error states
52
+ lightGreen: '\x1b[38;5;194m', // Session healthy
53
+ lightYellow: '\x1b[38;5;228m', // Session warning
54
+ lightPink: '\x1b[38;5;210m', // Session critical
55
+ skyBlue: '\x1b[38;5;117m', // Directories/paths
56
+ lavender: '\x1b[38;5;147m', // Model info, story IDs
57
+ softGold: '\x1b[38;5;222m', // Cost/money
58
+ teal: '\x1b[38;5;80m', // Ready/pending states
59
+ slate: '\x1b[38;5;103m', // Secondary info
60
+ rose: '\x1b[38;5;211m', // Blocked/critical accent
61
+ amber: '\x1b[38;5;214m', // WIP/in-progress accent
62
+ powder: '\x1b[38;5;153m', // Labels/headers
63
+
47
64
  // Brand color (#e8683a)
48
65
  brand: '\x1b[38;2;232;104;58m',
49
66
  };
@@ -105,7 +122,9 @@ function getProjectInfo(rootDir) {
105
122
  } catch (e) {
106
123
  // Fallback: check .agileflow/package.json
107
124
  try {
108
- const pkg = JSON.parse(fs.readFileSync(path.join(rootDir, '.agileflow/package.json'), 'utf8'));
125
+ const pkg = JSON.parse(
126
+ fs.readFileSync(path.join(rootDir, '.agileflow/package.json'), 'utf8')
127
+ );
109
128
  info.version = pkg.version || info.version;
110
129
  } catch (e2) {}
111
130
  }
@@ -327,6 +346,67 @@ function checkPreCompact(rootDir) {
327
346
  return result;
328
347
  }
329
348
 
349
+ function checkDamageControl(rootDir) {
350
+ const result = { configured: false, level: null, patternCount: 0, scriptsOk: true };
351
+
352
+ try {
353
+ // Check if PreToolUse hooks are configured in settings
354
+ const settingsPath = path.join(rootDir, '.claude/settings.json');
355
+ if (fs.existsSync(settingsPath)) {
356
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
357
+ if (settings.hooks?.PreToolUse && Array.isArray(settings.hooks.PreToolUse)) {
358
+ // Check for damage-control hooks
359
+ const hasDamageControlHooks = settings.hooks.PreToolUse.some(
360
+ h => h.hooks?.some(hk => hk.command?.includes('damage-control'))
361
+ );
362
+ if (hasDamageControlHooks) {
363
+ result.configured = true;
364
+
365
+ // Count how many hooks are present (should be 3: Bash, Edit, Write)
366
+ const dcHooks = settings.hooks.PreToolUse.filter(h =>
367
+ h.hooks?.some(hk => hk.command?.includes('damage-control'))
368
+ );
369
+ result.hooksCount = dcHooks.length;
370
+
371
+ // Check if all required scripts exist
372
+ const scriptsDir = path.join(rootDir, '.agileflow', 'scripts');
373
+ const requiredScripts = [
374
+ 'damage-control-bash.js',
375
+ 'damage-control-edit.js',
376
+ 'damage-control-write.js',
377
+ ];
378
+ for (const script of requiredScripts) {
379
+ if (!fs.existsSync(path.join(scriptsDir, script))) {
380
+ result.scriptsOk = false;
381
+ break;
382
+ }
383
+ }
384
+ }
385
+ }
386
+ }
387
+
388
+ // Get protection level and pattern count from metadata
389
+ const metadataPath = path.join(rootDir, 'docs/00-meta/agileflow-metadata.json');
390
+ if (fs.existsSync(metadataPath)) {
391
+ const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
392
+ if (metadata.features?.damagecontrol) {
393
+ result.level = metadata.features.damagecontrol.protectionLevel || 'standard';
394
+ }
395
+ }
396
+
397
+ // Count patterns in config file
398
+ const patternsPath = path.join(rootDir, '.agileflow', 'config', 'damage-control-patterns.yaml');
399
+ if (fs.existsSync(patternsPath)) {
400
+ const content = fs.readFileSync(patternsPath, 'utf8');
401
+ // Count pattern entries (lines starting with " - pattern:")
402
+ const patternMatches = content.match(/^\s*-\s*pattern:/gm);
403
+ result.patternCount = patternMatches ? patternMatches.length : 0;
404
+ }
405
+ } catch (e) {}
406
+
407
+ return result;
408
+ }
409
+
330
410
  // Compare semantic versions: returns -1 if a < b, 0 if equal, 1 if a > b
331
411
  function compareVersions(a, b) {
332
412
  if (!a || !b) return 0;
@@ -420,7 +500,7 @@ function getChangelogEntries(version) {
420
500
  // Run auto-update if enabled
421
501
  async function runAutoUpdate(rootDir) {
422
502
  try {
423
- console.log(`${c.cyan}Updating AgileFlow...${c.reset}`);
503
+ console.log(`${c.skyBlue}Updating AgileFlow...${c.reset}`);
424
504
  execSync('npx agileflow update', {
425
505
  cwd: rootDir,
426
506
  encoding: 'utf8',
@@ -428,7 +508,7 @@ async function runAutoUpdate(rootDir) {
428
508
  });
429
509
  return true;
430
510
  } catch (e) {
431
- console.log(`${c.yellow}Auto-update failed. Run manually: npx agileflow update${c.reset}`);
511
+ console.log(`${c.peach}Auto-update failed. Run manually: npx agileflow update${c.reset}`);
432
512
  return false;
433
513
  }
434
514
  }
@@ -449,7 +529,8 @@ function validateExpertise(rootDir) {
449
529
  const MAX_LINES = 200;
450
530
 
451
531
  try {
452
- const domains = fs.readdirSync(expertsDir, { withFileTypes: true })
532
+ const domains = fs
533
+ .readdirSync(expertsDir, { withFileTypes: true })
453
534
  .filter(d => d.isDirectory() && d.name !== 'templates')
454
535
  .map(d => d.name);
455
536
 
@@ -584,7 +665,16 @@ function truncate(str, maxLen, suffix = '..') {
584
665
  return str.substring(0, cutIndex) + suffix;
585
666
  }
586
667
 
587
- function formatTable(info, archival, session, precompact, parallelSessions, updateInfo = {}, expertise = {}) {
668
+ function formatTable(
669
+ info,
670
+ archival,
671
+ session,
672
+ precompact,
673
+ parallelSessions,
674
+ updateInfo = {},
675
+ expertise = {},
676
+ damageControl = {}
677
+ ) {
588
678
  const W = 58; // inner width
589
679
  const R = W - 24; // right column width (34 chars)
590
680
  const lines = [];
@@ -605,21 +695,21 @@ function formatTable(info, archival, session, precompact, parallelSessions, upda
605
695
 
606
696
  const divider = () =>
607
697
  `${c.dim}${box.lT}${box.h.repeat(22)}${box.cross}${box.h.repeat(W - 22)}${box.rT}${c.reset}`;
608
- const fullDivider = () =>
609
- `${c.dim}${box.lT}${box.h.repeat(W)}${box.rT}${c.reset}`;
698
+ const fullDivider = () => `${c.dim}${box.lT}${box.h.repeat(W)}${box.rT}${c.reset}`;
610
699
  const topBorder = `${c.dim}${box.tl}${box.h.repeat(22)}${box.tT}${box.h.repeat(W - 22)}${box.tr}${c.reset}`;
611
700
  const bottomBorder = `${c.dim}${box.bl}${box.h.repeat(22)}${box.bT}${box.h.repeat(W - 22)}${box.br}${c.reset}`;
612
701
 
613
702
  // Header with version and optional update indicator
703
+ // Use vibrant colors for branch
614
704
  const branchColor =
615
- info.branch === 'main' ? c.green : info.branch.startsWith('fix') ? c.red : c.cyan;
705
+ info.branch === 'main' ? c.mintGreen : info.branch.startsWith('fix') ? c.coral : c.skyBlue;
616
706
 
617
- // Build version string with update status
707
+ // Build version string with update status (vibrant colors)
618
708
  let versionStr = `v${info.version}`;
619
709
  if (updateInfo.justUpdated && updateInfo.previousVersion) {
620
- versionStr = `v${info.version} ${c.green}✓${c.reset}${c.dim} (was v${updateInfo.previousVersion})`;
710
+ versionStr = `v${info.version} ${c.mintGreen}✓${c.reset}${c.slate} (was v${updateInfo.previousVersion})`;
621
711
  } else if (updateInfo.available && updateInfo.latest) {
622
- versionStr = `v${info.version} ${c.yellow}↑${updateInfo.latest}${c.reset}`;
712
+ versionStr = `v${info.version} ${c.amber}↑${updateInfo.latest}${c.reset}`;
623
713
  }
624
714
 
625
715
  // Calculate remaining space for branch
@@ -640,138 +730,153 @@ function formatTable(info, archival, session, precompact, parallelSessions, upda
640
730
  lines.push(topBorder);
641
731
  lines.push(headerLine);
642
732
 
643
- // Show update available notification
733
+ // Show update available notification (using vibrant colors)
644
734
  if (updateInfo.available && updateInfo.latest && !updateInfo.justUpdated) {
645
735
  lines.push(fullDivider());
646
- lines.push(fullRow(`↑ Update available: v${updateInfo.latest}`, c.yellow));
647
- lines.push(fullRow(` Run: npx agileflow update`, c.dim));
736
+ lines.push(fullRow(`${c.amber}↑${c.reset} Update available: ${c.softGold}v${updateInfo.latest}${c.reset}`, ''));
737
+ lines.push(fullRow(` Run: ${c.skyBlue}npx agileflow update${c.reset}`, ''));
648
738
  }
649
739
 
650
740
  // Show "just updated" changelog
651
741
  if (updateInfo.justUpdated && updateInfo.changelog && updateInfo.changelog.length > 0) {
652
742
  lines.push(fullDivider());
653
- lines.push(fullRow(`What's new in v${info.version}:`, c.green));
743
+ lines.push(fullRow(`${c.mintGreen}✨${c.reset} What's new in ${c.softGold}v${info.version}${c.reset}:`, ''));
654
744
  for (const entry of updateInfo.changelog.slice(0, 2)) {
655
- lines.push(fullRow(`• ${truncate(entry, W - 4)}`, c.dim));
745
+ lines.push(fullRow(` ${c.teal}•${c.reset} ${truncate(entry, W - 6)}`, ''));
656
746
  }
657
- lines.push(fullRow(`Run /agileflow:whats-new for full changelog`, c.dim));
747
+ lines.push(fullRow(` Run ${c.skyBlue}/agileflow:whats-new${c.reset} for full changelog`, ''));
658
748
  }
659
749
 
660
750
  lines.push(divider());
661
751
 
662
- // Stories section
752
+ // Stories section (always colorful labels like obtain-context)
663
753
  lines.push(
664
754
  row(
665
755
  'In Progress',
666
756
  info.wipCount > 0 ? `${info.wipCount}` : '0',
667
- c.dim,
668
- info.wipCount > 0 ? c.yellow : c.dim
757
+ c.peach,
758
+ info.wipCount > 0 ? c.peach : c.dim
669
759
  )
670
760
  );
671
761
  lines.push(
672
762
  row(
673
763
  'Blocked',
674
764
  info.blockedCount > 0 ? `${info.blockedCount}` : '0',
675
- c.dim,
676
- info.blockedCount > 0 ? c.red : c.dim
765
+ c.coral,
766
+ info.blockedCount > 0 ? c.coral : c.dim
677
767
  )
678
768
  );
679
769
  lines.push(
680
770
  row(
681
771
  'Ready',
682
772
  info.readyCount > 0 ? `${info.readyCount}` : '0',
683
- c.dim,
684
- info.readyCount > 0 ? c.cyan : c.dim
773
+ c.skyBlue,
774
+ info.readyCount > 0 ? c.skyBlue : c.dim
685
775
  )
686
776
  );
777
+ const completedColor = `${c.bold}${c.mintGreen}`;
687
778
  lines.push(
688
779
  row(
689
780
  'Completed',
690
781
  info.completedCount > 0 ? `${info.completedCount}` : '0',
691
- c.dim,
692
- info.completedCount > 0 ? c.green : c.dim
782
+ completedColor,
783
+ info.completedCount > 0 ? completedColor : c.dim
693
784
  )
694
785
  );
695
786
 
696
787
  lines.push(divider());
697
788
 
698
- // Archival section
789
+ // System section (colorful labels like obtain-context)
699
790
  if (archival.disabled) {
700
- lines.push(row('Auto-archival', 'disabled', c.dim, c.dim));
791
+ lines.push(row('Auto-archival', 'disabled', c.lavender, c.slate));
701
792
  } else {
702
793
  const archivalStatus =
703
794
  archival.archived > 0 ? `archived ${archival.archived} stories` : `nothing to archive`;
704
795
  lines.push(
705
- row('Auto-archival', archivalStatus, c.dim, archival.archived > 0 ? c.green : c.dim)
796
+ row('Auto-archival', archivalStatus, c.lavender, archival.archived > 0 ? c.mintGreen : c.dim)
706
797
  );
707
798
  }
708
799
 
709
800
  // Session cleanup
710
801
  const sessionStatus = session.cleared > 0 ? `cleared ${session.cleared} command(s)` : `clean`;
711
- lines.push(row('Session state', sessionStatus, c.dim, session.cleared > 0 ? c.green : c.dim));
802
+ lines.push(row('Session state', sessionStatus, c.lavender, session.cleared > 0 ? c.mintGreen : c.dim));
712
803
 
713
804
  // PreCompact status with version check
714
805
  if (precompact.configured && precompact.scriptExists) {
715
806
  if (precompact.outdated) {
716
807
  const verStr = precompact.version ? ` (v${precompact.version})` : '';
717
- lines.push(row('Context preserve', `outdated${verStr}`, c.dim, c.yellow));
808
+ lines.push(row('Context preserve', `outdated${verStr}`, c.peach, c.peach));
718
809
  } else if (session.commandNames && session.commandNames.length > 0) {
719
810
  // Show the preserved command names
720
811
  const cmdDisplay = session.commandNames.map(n => `/agileflow:${n}`).join(', ');
721
- lines.push(row('Context preserve', cmdDisplay, c.dim, c.green));
812
+ lines.push(row('Context preserve', cmdDisplay, c.lavender, c.mintGreen));
722
813
  } else {
723
- lines.push(row('Context preserve', 'nothing to compact', c.dim, c.dim));
814
+ lines.push(row('Context preserve', 'ready', c.lavender, c.dim));
724
815
  }
725
816
  } else if (precompact.configured) {
726
- lines.push(row('Context preserve', 'script missing', c.dim, c.yellow));
817
+ lines.push(row('Context preserve', 'script missing', c.peach, c.peach));
727
818
  } else {
728
- lines.push(row('Context preserve', 'not configured', c.dim, c.dim));
819
+ lines.push(row('Context preserve', 'not configured', c.slate, c.slate));
729
820
  }
730
821
 
731
822
  // Parallel sessions status
732
823
  if (parallelSessions && parallelSessions.available) {
733
824
  if (parallelSessions.otherActive > 0) {
734
825
  const sessionStr = `⚠️ ${parallelSessions.otherActive} other active`;
735
- lines.push(row('Sessions', sessionStr, c.dim, c.yellow));
826
+ lines.push(row('Sessions', sessionStr, c.peach, c.peach));
736
827
  } else {
737
828
  const sessionStr = parallelSessions.currentId
738
829
  ? `✓ Session ${parallelSessions.currentId} (only)`
739
830
  : '✓ Only session';
740
- lines.push(row('Sessions', sessionStr, c.dim, c.green));
831
+ lines.push(row('Sessions', sessionStr, c.lavender, c.mintGreen));
741
832
  }
742
833
  }
743
834
 
744
- // Agent expertise validation (only show if issues exist)
835
+ // Agent expertise validation (always show with color)
745
836
  if (expertise && expertise.total > 0) {
746
837
  if (expertise.failed > 0) {
747
838
  const expertStr = `❌ ${expertise.failed} failed, ${expertise.warnings} warnings`;
748
- lines.push(row('Expertise', expertStr, c.dim, c.red));
839
+ lines.push(row('Expertise', expertStr, c.coral, c.coral));
749
840
  } else if (expertise.warnings > 0) {
750
841
  const expertStr = `⚠️ ${expertise.warnings} warnings (${expertise.passed} ok)`;
751
- lines.push(row('Expertise', expertStr, c.dim, c.yellow));
842
+ lines.push(row('Expertise', expertStr, c.peach, c.peach));
843
+ } else {
844
+ lines.push(row('Expertise', `✓ ${expertise.total} valid`, c.lavender, c.mintGreen));
845
+ }
846
+ }
847
+
848
+ // Damage control status (PreToolUse hooks for dangerous command protection)
849
+ if (damageControl && damageControl.configured) {
850
+ if (!damageControl.scriptsOk) {
851
+ lines.push(row('Damage control', '⚠️ scripts missing', c.coral, c.coral));
752
852
  } else {
753
- lines.push(row('Expertise', `✓ ${expertise.total} valid`, c.dim, c.green));
853
+ const levelStr = damageControl.level || 'standard';
854
+ const patternStr = damageControl.patternCount > 0 ? `${damageControl.patternCount} patterns` : '';
855
+ const dcStatus = `🛡️ ${levelStr}${patternStr ? ` (${patternStr})` : ''}`;
856
+ lines.push(row('Damage control', dcStatus, c.lavender, c.mintGreen));
754
857
  }
858
+ } else {
859
+ lines.push(row('Damage control', 'not configured', c.slate, c.slate));
755
860
  }
756
861
 
757
862
  lines.push(divider());
758
863
 
759
- // Current story (if any) - row() auto-truncates
864
+ // Current story (colorful like obtain-context)
760
865
  if (info.currentStory) {
761
866
  lines.push(
762
867
  row(
763
868
  'Current',
764
- `${c.blue}${info.currentStory.id}${c.reset}: ${info.currentStory.title}`,
765
- c.dim,
869
+ `${c.lightYellow}${info.currentStory.id}${c.reset}: ${info.currentStory.title}`,
870
+ c.skyBlue,
766
871
  ''
767
872
  )
768
873
  );
769
874
  } else {
770
- lines.push(row('Current', 'No active story', c.dim, c.dim));
875
+ lines.push(row('Current', 'No active story', c.skyBlue, c.dim));
771
876
  }
772
877
 
773
- // Last commit - row() auto-truncates
774
- lines.push(row('Last commit', `${info.commit} ${info.lastCommit}`, c.dim, c.dim));
878
+ // Last commit (colorful like obtain-context)
879
+ lines.push(row('Last commit', `${c.peach}${info.commit}${c.reset} ${info.lastCommit}`, c.lavender, ''));
775
880
 
776
881
  lines.push(bottomBorder);
777
882
 
@@ -787,6 +892,7 @@ async function main() {
787
892
  const precompact = checkPreCompact(rootDir);
788
893
  const parallelSessions = checkParallelSessions(rootDir);
789
894
  const expertise = validateExpertise(rootDir);
895
+ const damageControl = checkDamageControl(rootDir);
790
896
 
791
897
  // Check for updates (async, cached)
792
898
  let updateInfo = {};
@@ -810,14 +916,16 @@ async function main() {
810
916
  // Update check failed - continue without it
811
917
  }
812
918
 
813
- console.log(formatTable(info, archival, session, precompact, parallelSessions, updateInfo, expertise));
919
+ console.log(
920
+ formatTable(info, archival, session, precompact, parallelSessions, updateInfo, expertise, damageControl)
921
+ );
814
922
 
815
- // Show warning and tip if other sessions are active
923
+ // Show warning and tip if other sessions are active (vibrant colors)
816
924
  if (parallelSessions.otherActive > 0) {
817
925
  console.log('');
818
- console.log(`${c.yellow}⚠️ Other Claude session(s) active in this repo.${c.reset}`);
819
- console.log(`${c.dim} Run /agileflow:session:status to see all sessions.${c.reset}`);
820
- console.log(`${c.dim} Run /agileflow:session:new to create isolated workspace.${c.reset}`);
926
+ console.log(`${c.amber}⚠️ Other Claude session(s) active in this repo.${c.reset}`);
927
+ console.log(`${c.slate} Run ${c.skyBlue}/agileflow:session:status${c.reset}${c.slate} to see all sessions.${c.reset}`);
928
+ console.log(`${c.slate} Run ${c.skyBlue}/agileflow:session:new${c.reset}${c.slate} to create isolated workspace.${c.reset}`);
821
929
  }
822
930
  }
823
931
 
@@ -36,24 +36,44 @@ const c = {
36
36
 
37
37
  // Agents that have expertise files
38
38
  const AGENTS_WITH_EXPERTISE = [
39
- 'accessibility', 'adr-writer', 'analytics', 'api', 'ci', 'compliance',
40
- 'database', 'datamigration', 'design', 'devops', 'documentation',
41
- 'epic-planner', 'integrations', 'mentor', 'mobile', 'monitoring',
42
- 'performance', 'product', 'qa', 'readme-updater', 'refactor',
43
- 'research', 'security', 'testing', 'ui'
39
+ 'accessibility',
40
+ 'adr-writer',
41
+ 'analytics',
42
+ 'api',
43
+ 'ci',
44
+ 'compliance',
45
+ 'database',
46
+ 'datamigration',
47
+ 'design',
48
+ 'devops',
49
+ 'documentation',
50
+ 'epic-planner',
51
+ 'integrations',
52
+ 'mentor',
53
+ 'mobile',
54
+ 'monitoring',
55
+ 'performance',
56
+ 'product',
57
+ 'qa',
58
+ 'readme-updater',
59
+ 'refactor',
60
+ 'research',
61
+ 'security',
62
+ 'testing',
63
+ 'ui',
44
64
  ];
45
65
 
46
66
  // File patterns that suggest domain expertise
47
67
  const DOMAIN_PATTERNS = {
48
- 'database': [/schema/, /migration/, /\.sql$/, /prisma/, /drizzle/, /sequelize/],
49
- 'api': [/\/api\//, /controller/, /route/, /endpoint/, /graphql/],
50
- 'ui': [/component/, /\.tsx$/, /\.jsx$/, /styles/, /\.css$/, /\.scss$/],
51
- 'testing': [/\.test\./, /\.spec\./, /__tests__/, /jest/, /vitest/],
52
- 'security': [/auth/, /password/, /token/, /jwt/, /oauth/, /permission/],
53
- 'ci': [/\.github\/workflows/, /\.gitlab-ci/, /dockerfile/i, /docker-compose/],
54
- 'documentation': [/\.md$/, /readme/i, /docs\//, /jsdoc/],
55
- 'performance': [/cache/, /optimize/, /performance/, /benchmark/],
56
- 'devops': [/deploy/, /kubernetes/, /k8s/, /terraform/, /ansible/],
68
+ database: [/schema/, /migration/, /\.sql$/, /prisma/, /drizzle/, /sequelize/],
69
+ api: [/\/api\//, /controller/, /route/, /endpoint/, /graphql/],
70
+ ui: [/component/, /\.tsx$/, /\.jsx$/, /styles/, /\.css$/, /\.scss$/],
71
+ testing: [/\.test\./, /\.spec\./, /__tests__/, /jest/, /vitest/],
72
+ security: [/auth/, /password/, /token/, /jwt/, /oauth/, /permission/],
73
+ ci: [/\.github\/workflows/, /\.gitlab-ci/, /dockerfile/i, /docker-compose/],
74
+ documentation: [/\.md$/, /readme/i, /docs\//, /jsdoc/],
75
+ performance: [/cache/, /optimize/, /performance/, /benchmark/],
76
+ devops: [/deploy/, /kubernetes/, /k8s/, /terraform/, /ansible/],
57
77
  };
58
78
 
59
79
  // Find project root
@@ -83,19 +103,28 @@ function getGitDiff(rootDir) {
83
103
  const diffFiles = execSync('git diff --name-only HEAD 2>/dev/null || git diff --name-only', {
84
104
  cwd: rootDir,
85
105
  encoding: 'utf8',
86
- }).trim().split('\n').filter(Boolean);
106
+ })
107
+ .trim()
108
+ .split('\n')
109
+ .filter(Boolean);
87
110
 
88
111
  // Get staged files
89
112
  const stagedFiles = execSync('git diff --cached --name-only 2>/dev/null', {
90
113
  cwd: rootDir,
91
114
  encoding: 'utf8',
92
- }).trim().split('\n').filter(Boolean);
115
+ })
116
+ .trim()
117
+ .split('\n')
118
+ .filter(Boolean);
93
119
 
94
120
  // Get untracked files
95
121
  const untrackedFiles = execSync('git ls-files --others --exclude-standard 2>/dev/null', {
96
122
  cwd: rootDir,
97
123
  encoding: 'utf8',
98
- }).trim().split('\n').filter(Boolean);
124
+ })
125
+ .trim()
126
+ .split('\n')
127
+ .filter(Boolean);
99
128
 
100
129
  // Combine all
101
130
  const allFiles = [...new Set([...diffFiles, ...stagedFiles, ...untrackedFiles])];
@@ -186,7 +215,16 @@ function getExpertisePath(rootDir, agent) {
186
215
  if (fs.existsSync(installedPath)) return installedPath;
187
216
 
188
217
  // Try source location
189
- const sourcePath = path.join(rootDir, 'packages', 'cli', 'src', 'core', 'experts', agent, 'expertise.yaml');
218
+ const sourcePath = path.join(
219
+ rootDir,
220
+ 'packages',
221
+ 'cli',
222
+ 'src',
223
+ 'core',
224
+ 'experts',
225
+ agent,
226
+ 'expertise.yaml'
227
+ );
190
228
  if (fs.existsSync(sourcePath)) return sourcePath;
191
229
 
192
230
  return null;
@@ -219,7 +257,10 @@ function appendLearning(expertisePath, learning) {
219
257
  // Format learning as YAML
220
258
  function formatLearning(summary, files, detectedDomain) {
221
259
  const date = new Date().toISOString().split('T')[0];
222
- const topFiles = files.slice(0, 5).map(f => ` - ${f}`).join('\n');
260
+ const topFiles = files
261
+ .slice(0, 5)
262
+ .map(f => ` - ${f}`)
263
+ .join('\n');
223
264
 
224
265
  return ` - date: "${date}"
225
266
  auto_generated: true
@@ -281,7 +322,9 @@ function main() {
281
322
  console.log('');
282
323
  console.log(`${c.green}✓ Auto-learned:${c.reset} ${c.dim}${activeAgent}${c.reset}`);
283
324
  console.log(`${c.dim} ${summary}${c.reset}`);
284
- console.log(`${c.dim} → Updated ${path.basename(path.dirname(expertisePath))}/expertise.yaml${c.reset}`);
325
+ console.log(
326
+ `${c.dim} → Updated ${path.basename(path.dirname(expertisePath))}/expertise.yaml${c.reset}`
327
+ );
285
328
  console.log('');
286
329
  }
287
330
  }
@@ -232,10 +232,7 @@ async function checkForUpdates(options = {}) {
232
232
  }
233
233
 
234
234
  // Check if we just updated (lastSeenVersion < installed)
235
- if (
236
- config.lastSeenVersion &&
237
- compareVersions(config.lastSeenVersion, installedVersion) < 0
238
- ) {
235
+ if (config.lastSeenVersion && compareVersions(config.lastSeenVersion, installedVersion) < 0) {
239
236
  result.justUpdated = true;
240
237
  result.previousVersion = config.lastSeenVersion;
241
238
  }