agileflow 2.76.0 → 2.77.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agileflow",
3
- "version": "2.76.0",
3
+ "version": "2.77.0",
4
4
  "description": "AI-driven agile development system for Claude Code, Cursor, Windsurf, and more",
5
5
  "keywords": [
6
6
  "agile",
@@ -584,9 +584,10 @@ function enableFeature(feature, options = {}) {
584
584
 
585
585
  // Stop hooks use error suppression to avoid blocking Claude
586
586
  const isStoHook = config.hook === 'Stop';
587
- const command = config.type === 'node'
588
- ? `node ${absoluteScriptPath}${isStoHook ? ' 2>/dev/null || true' : ''}`
589
- : `bash ${absoluteScriptPath}${isStoHook ? ' 2>/dev/null || true' : ''}`;
587
+ const command =
588
+ config.type === 'node'
589
+ ? `node ${absoluteScriptPath}${isStoHook ? ' 2>/dev/null || true' : ''}`
590
+ : `bash ${absoluteScriptPath}${isStoHook ? ' 2>/dev/null || true' : ''}`;
590
591
 
591
592
  if (isStoHook) {
592
593
  // Stop hooks stack - add to existing hooks instead of replacing
@@ -599,9 +600,7 @@ function enableFeature(feature, options = {}) {
599
600
  }
600
601
 
601
602
  // Check if this script is already added
602
- const hasHook = settings.hooks.Stop[0].hooks.some(h =>
603
- h.command?.includes(config.script)
604
- );
603
+ const hasHook = settings.hooks.Stop[0].hooks.some(h => h.command?.includes(config.script));
605
604
 
606
605
  if (!hasHook) {
607
606
  settings.hooks.Stop[0].hooks.push({ type: 'command', command });
@@ -1027,9 +1026,11 @@ function showVersionInfo() {
1027
1026
  const installed = installedVersion.split('.').map(Number);
1028
1027
  const latest = latestVersion.split('.').map(Number);
1029
1028
 
1030
- if (latest[0] > installed[0] ||
1031
- (latest[0] === installed[0] && latest[1] > installed[1]) ||
1032
- (latest[0] === installed[0] && latest[1] === installed[1] && latest[2] > installed[2])) {
1029
+ if (
1030
+ latest[0] > installed[0] ||
1031
+ (latest[0] === installed[0] && latest[1] > installed[1]) ||
1032
+ (latest[0] === installed[0] && latest[1] === installed[1] && latest[2] > installed[2])
1033
+ ) {
1033
1034
  log('\nšŸ”„ Update available! Run: npx agileflow update', c.yellow);
1034
1035
  }
1035
1036
  }
@@ -1351,8 +1352,7 @@ function main() {
1351
1352
  else if (arg.startsWith('--repair=')) {
1352
1353
  repair = true;
1353
1354
  repairFeature = arg.split('=')[1].trim().toLowerCase();
1354
- }
1355
- else if (arg === '--version' || arg === '-v') showVersion = true;
1355
+ } else if (arg === '--version' || arg === '-v') showVersion = true;
1356
1356
  else if (arg === '--list-scripts' || arg === '--scripts') listScriptsMode = true;
1357
1357
  });
1358
1358
 
@@ -29,7 +29,7 @@ MAGENTA="\033[35m"
29
29
  CYAN="\033[36m"
30
30
  WHITE="\033[37m"
31
31
 
32
- # Bright foreground colors
32
+ # Bright foreground colors (standard ANSI)
33
33
  BRIGHT_RED="\033[91m"
34
34
  BRIGHT_GREEN="\033[92m"
35
35
  BRIGHT_YELLOW="\033[93m"
@@ -37,9 +37,74 @@ BRIGHT_BLUE="\033[94m"
37
37
  BRIGHT_MAGENTA="\033[95m"
38
38
  BRIGHT_CYAN="\033[96m"
39
39
 
40
+ # 256-color palette (vibrant modern colors from cc-statusline)
41
+ # Use these for context/session indicators for better visibility
42
+ CTX_GREEN="\033[38;5;158m" # Mint green - healthy context
43
+ CTX_YELLOW="\033[38;5;215m" # Peach - moderate usage
44
+ CTX_ORANGE="\033[38;5;215m" # Peach/orange - high usage
45
+ CTX_RED="\033[38;5;203m" # Coral red - critical
46
+
47
+ SESSION_GREEN="\033[38;5;194m" # Light green - plenty of time
48
+ SESSION_YELLOW="\033[38;5;228m" # Light yellow - getting low
49
+ SESSION_RED="\033[38;5;210m" # Light pink/red - critical
50
+
40
51
  # Brand color (burnt orange #e8683a = RGB 232,104,58)
41
52
  BRAND="\033[38;2;232;104;58m"
42
53
 
54
+ # ============================================================================
55
+ # Helper Functions
56
+ # ============================================================================
57
+
58
+ # Progress bar with custom characters: ā–“ (filled) ā–‘ (empty)
59
+ # Usage: progress_bar <percent> <width>
60
+ # Example: progress_bar 75 10 → "ā–“ā–“ā–“ā–“ā–“ā–“ā–“ā–‘ā–‘ā–‘"
61
+ progress_bar() {
62
+ local pct="${1:-0}"
63
+ local width="${2:-10}"
64
+
65
+ # Validate and clamp percentage
66
+ [[ "$pct" =~ ^[0-9]+$ ]] || pct=0
67
+ ((pct < 0)) && pct=0
68
+ ((pct > 100)) && pct=100
69
+
70
+ local filled=$(( pct * width / 100 ))
71
+ local empty=$(( width - filled ))
72
+
73
+ # Build bar with custom characters
74
+ local bar=""
75
+ for ((i=0; i<filled; i++)); do bar+="ā–“"; done
76
+ for ((i=0; i<empty; i++)); do bar+="ā–‘"; done
77
+
78
+ echo "$bar"
79
+ }
80
+
81
+ # Convert ISO timestamp to epoch seconds (cross-platform)
82
+ to_epoch() {
83
+ local ts="$1"
84
+ # Try gdate first (macOS with coreutils)
85
+ if command -v gdate >/dev/null 2>&1; then
86
+ gdate -d "$ts" +%s 2>/dev/null && return
87
+ fi
88
+ # Try BSD date (macOS)
89
+ date -u -j -f "%Y-%m-%dT%H:%M:%S%z" "${ts/Z/+0000}" +%s 2>/dev/null && return
90
+ # Fallback to Python
91
+ python3 - "$ts" <<'PY' 2>/dev/null
92
+ import sys, datetime
93
+ s=sys.argv[1].replace('Z','+00:00')
94
+ print(int(datetime.datetime.fromisoformat(s).timestamp()))
95
+ PY
96
+ }
97
+
98
+ # Format epoch to HH:MM
99
+ fmt_time_hm() {
100
+ local epoch="$1"
101
+ if date -r 0 +%s >/dev/null 2>&1; then
102
+ date -r "$epoch" +"%H:%M"
103
+ else
104
+ date -d "@$epoch" +"%H:%M"
105
+ fi
106
+ }
107
+
43
108
  # ============================================================================
44
109
  # Read Component Configuration
45
110
  # ============================================================================
@@ -50,6 +115,8 @@ SHOW_STORY=true
50
115
  SHOW_EPIC=true
51
116
  SHOW_WIP=true
52
117
  SHOW_CONTEXT=true
118
+ SHOW_CONTEXT_BAR=true
119
+ SHOW_SESSION_TIME=true
53
120
  SHOW_COST=true
54
121
  SHOW_GIT=true
55
122
 
@@ -65,6 +132,8 @@ if [ -f "docs/00-meta/agileflow-metadata.json" ]; then
65
132
  SHOW_EPIC=$(echo "$COMPONENTS" | jq -r '.epic | if . == null then true else . end')
66
133
  SHOW_WIP=$(echo "$COMPONENTS" | jq -r '.wip | if . == null then true else . end')
67
134
  SHOW_CONTEXT=$(echo "$COMPONENTS" | jq -r '.context | if . == null then true else . end')
135
+ SHOW_CONTEXT_BAR=$(echo "$COMPONENTS" | jq -r '.context_bar | if . == null then true else . end')
136
+ SHOW_SESSION_TIME=$(echo "$COMPONENTS" | jq -r '.session_time | if . == null then true else . end')
68
137
  SHOW_COST=$(echo "$COMPONENTS" | jq -r '.cost | if . == null then true else . end')
69
138
  SHOW_GIT=$(echo "$COMPONENTS" | jq -r '.git | if . == null then true else . end')
70
139
  fi
@@ -132,24 +201,29 @@ CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size // 200
132
201
  USAGE=$(echo "$input" | jq '.context_window.current_usage // null')
133
202
 
134
203
  CTX_DISPLAY=""
135
- CTX_COLOR="$GREEN"
204
+ CTX_BAR_DISPLAY=""
205
+ CTX_COLOR="$CTX_GREEN"
136
206
  if [ "$USAGE" != "null" ]; then
137
207
  CURRENT_TOKENS=$(echo "$USAGE" | jq '.input_tokens + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0)')
138
208
  if [ "$CURRENT_TOKENS" != "null" ] && [ "$CURRENT_TOKENS" -gt 0 ] 2>/dev/null; then
139
209
  PERCENT_USED=$((CURRENT_TOKENS * 100 / CONTEXT_SIZE))
140
210
 
141
- # Color based on usage level
211
+ # Color based on usage level (using vibrant 256-color palette)
142
212
  if [ "$PERCENT_USED" -ge 80 ]; then
143
- CTX_COLOR="$BRIGHT_RED"
213
+ CTX_COLOR="$CTX_RED" # Coral red - critical
144
214
  elif [ "$PERCENT_USED" -ge 60 ]; then
145
- CTX_COLOR="$YELLOW"
215
+ CTX_COLOR="$CTX_ORANGE" # Peach - high usage
146
216
  elif [ "$PERCENT_USED" -ge 40 ]; then
147
- CTX_COLOR="$BRIGHT_YELLOW"
217
+ CTX_COLOR="$CTX_YELLOW" # Peach - moderate
148
218
  else
149
- CTX_COLOR="$GREEN"
219
+ CTX_COLOR="$CTX_GREEN" # Mint green - healthy
150
220
  fi
151
221
 
152
222
  CTX_DISPLAY="${CTX_COLOR}${PERCENT_USED}%${RESET}"
223
+
224
+ # Generate progress bar (8 chars wide for compactness)
225
+ CTX_BAR=$(progress_bar "$PERCENT_USED" 8)
226
+ CTX_BAR_DISPLAY="${DIM}[${RESET}${CTX_COLOR}${CTX_BAR}${RESET}${DIM}]${RESET}"
153
227
  fi
154
228
  fi
155
229
 
@@ -166,6 +240,67 @@ if [ "$TOTAL_COST" != "0" ] && [ "$TOTAL_COST" != "null" ]; then
166
240
  fi
167
241
  fi
168
242
 
243
+ # ============================================================================
244
+ # Session Time Remaining (via ccusage if available)
245
+ # ============================================================================
246
+ SESSION_DISPLAY=""
247
+ if [ "$SHOW_SESSION_TIME" = "true" ]; then
248
+ # Try to get session info from ccusage (fast cached check)
249
+ if command -v npx >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then
250
+ # Use timeout to prevent blocking - ccusage should be fast
251
+ BLOCKS_OUTPUT=$(timeout 3 npx ccusage@latest blocks --json 2>/dev/null || true)
252
+
253
+ if [ -n "$BLOCKS_OUTPUT" ]; then
254
+ ACTIVE_BLOCK=$(echo "$BLOCKS_OUTPUT" | jq -c '.blocks[] | select(.isActive == true)' 2>/dev/null | head -n1)
255
+
256
+ if [ -n "$ACTIVE_BLOCK" ]; then
257
+ # Get reset time
258
+ RESET_TIME_STR=$(echo "$ACTIVE_BLOCK" | jq -r '.usageLimitResetTime // .endTime // empty')
259
+ START_TIME_STR=$(echo "$ACTIVE_BLOCK" | jq -r '.startTime // empty')
260
+
261
+ if [ -n "$RESET_TIME_STR" ] && [ -n "$START_TIME_STR" ]; then
262
+ START_SEC=$(to_epoch "$START_TIME_STR")
263
+ END_SEC=$(to_epoch "$RESET_TIME_STR")
264
+ NOW_SEC=$(date +%s)
265
+
266
+ if [ -n "$START_SEC" ] && [ -n "$END_SEC" ] && [ "$START_SEC" -gt 0 ] && [ "$END_SEC" -gt 0 ]; then
267
+ TOTAL=$(( END_SEC - START_SEC ))
268
+ [ "$TOTAL" -lt 1 ] && TOTAL=1
269
+
270
+ ELAPSED=$(( NOW_SEC - START_SEC ))
271
+ [ "$ELAPSED" -lt 0 ] && ELAPSED=0
272
+ [ "$ELAPSED" -gt "$TOTAL" ] && ELAPSED=$TOTAL
273
+
274
+ SESSION_PCT=$(( ELAPSED * 100 / TOTAL ))
275
+ REMAINING=$(( END_SEC - NOW_SEC ))
276
+ [ "$REMAINING" -lt 0 ] && REMAINING=0
277
+
278
+ # Format remaining time
279
+ RH=$(( REMAINING / 3600 ))
280
+ RM=$(( (REMAINING % 3600) / 60 ))
281
+
282
+ # Color based on time remaining (using vibrant 256-color palette)
283
+ if [ "$RH" -eq 0 ] && [ "$RM" -lt 30 ]; then
284
+ SESSION_COLOR="$SESSION_RED" # Light pink - critical
285
+ elif [ "$RH" -eq 0 ]; then
286
+ SESSION_COLOR="$SESSION_YELLOW" # Light yellow - getting low
287
+ else
288
+ SESSION_COLOR="$SESSION_GREEN" # Light green - plenty of time
289
+ fi
290
+
291
+ # Build compact display: "ā±2h15m" or "ā±45m"
292
+ if [ "$RH" -gt 0 ]; then
293
+ SESSION_DISPLAY="${SESSION_COLOR}ā±${RH}h${RM}m${RESET}"
294
+ else
295
+ SESSION_DISPLAY="${SESSION_COLOR}ā±${RM}m${RESET}"
296
+ fi
297
+ fi
298
+ fi
299
+ fi
300
+ fi
301
+ fi
302
+ fi
303
+
169
304
  # ============================================================================
170
305
  # AgileFlow Status - Read from status.json
171
306
  # ============================================================================
@@ -334,10 +469,21 @@ if [ "$SHOW_WIP" = "true" ] && [ -n "$WIP_DISPLAY" ]; then
334
469
  OUTPUT="${OUTPUT}${WIP_DISPLAY}"
335
470
  fi
336
471
 
337
- # Add context usage (if enabled)
472
+ # Add context usage (if enabled) - percentage and/or bar
338
473
  if [ "$SHOW_CONTEXT" = "true" ] && [ -n "$CTX_DISPLAY" ]; then
339
474
  [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
340
- OUTPUT="${OUTPUT}${CTX_DISPLAY}"
475
+ if [ "$SHOW_CONTEXT_BAR" = "true" ] && [ -n "$CTX_BAR_DISPLAY" ]; then
476
+ # Show both percentage and bar: "45% [ā–“ā–“ā–“ā–“ā–‘ā–‘ā–‘ā–‘]"
477
+ OUTPUT="${OUTPUT}${CTX_DISPLAY} ${CTX_BAR_DISPLAY}"
478
+ else
479
+ OUTPUT="${OUTPUT}${CTX_DISPLAY}"
480
+ fi
481
+ fi
482
+
483
+ # Add session time remaining (if enabled and available)
484
+ if [ "$SHOW_SESSION_TIME" = "true" ] && [ -n "$SESSION_DISPLAY" ]; then
485
+ [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
486
+ OUTPUT="${OUTPUT}${SESSION_DISPLAY}"
341
487
  fi
342
488
 
343
489
  # Add cost (if enabled)
@@ -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
  }
@@ -420,7 +439,7 @@ function getChangelogEntries(version) {
420
439
  // Run auto-update if enabled
421
440
  async function runAutoUpdate(rootDir) {
422
441
  try {
423
- console.log(`${c.cyan}Updating AgileFlow...${c.reset}`);
442
+ console.log(`${c.skyBlue}Updating AgileFlow...${c.reset}`);
424
443
  execSync('npx agileflow update', {
425
444
  cwd: rootDir,
426
445
  encoding: 'utf8',
@@ -428,7 +447,7 @@ async function runAutoUpdate(rootDir) {
428
447
  });
429
448
  return true;
430
449
  } catch (e) {
431
- console.log(`${c.yellow}Auto-update failed. Run manually: npx agileflow update${c.reset}`);
450
+ console.log(`${c.peach}Auto-update failed. Run manually: npx agileflow update${c.reset}`);
432
451
  return false;
433
452
  }
434
453
  }
@@ -449,7 +468,8 @@ function validateExpertise(rootDir) {
449
468
  const MAX_LINES = 200;
450
469
 
451
470
  try {
452
- const domains = fs.readdirSync(expertsDir, { withFileTypes: true })
471
+ const domains = fs
472
+ .readdirSync(expertsDir, { withFileTypes: true })
453
473
  .filter(d => d.isDirectory() && d.name !== 'templates')
454
474
  .map(d => d.name);
455
475
 
@@ -584,7 +604,15 @@ function truncate(str, maxLen, suffix = '..') {
584
604
  return str.substring(0, cutIndex) + suffix;
585
605
  }
586
606
 
587
- function formatTable(info, archival, session, precompact, parallelSessions, updateInfo = {}, expertise = {}) {
607
+ function formatTable(
608
+ info,
609
+ archival,
610
+ session,
611
+ precompact,
612
+ parallelSessions,
613
+ updateInfo = {},
614
+ expertise = {}
615
+ ) {
588
616
  const W = 58; // inner width
589
617
  const R = W - 24; // right column width (34 chars)
590
618
  const lines = [];
@@ -605,21 +633,21 @@ function formatTable(info, archival, session, precompact, parallelSessions, upda
605
633
 
606
634
  const divider = () =>
607
635
  `${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}`;
636
+ const fullDivider = () => `${c.dim}${box.lT}${box.h.repeat(W)}${box.rT}${c.reset}`;
610
637
  const topBorder = `${c.dim}${box.tl}${box.h.repeat(22)}${box.tT}${box.h.repeat(W - 22)}${box.tr}${c.reset}`;
611
638
  const bottomBorder = `${c.dim}${box.bl}${box.h.repeat(22)}${box.bT}${box.h.repeat(W - 22)}${box.br}${c.reset}`;
612
639
 
613
640
  // Header with version and optional update indicator
641
+ // Use vibrant colors for branch
614
642
  const branchColor =
615
- info.branch === 'main' ? c.green : info.branch.startsWith('fix') ? c.red : c.cyan;
643
+ info.branch === 'main' ? c.mintGreen : info.branch.startsWith('fix') ? c.coral : c.skyBlue;
616
644
 
617
- // Build version string with update status
645
+ // Build version string with update status (vibrant colors)
618
646
  let versionStr = `v${info.version}`;
619
647
  if (updateInfo.justUpdated && updateInfo.previousVersion) {
620
- versionStr = `v${info.version} ${c.green}āœ“${c.reset}${c.dim} (was v${updateInfo.previousVersion})`;
648
+ versionStr = `v${info.version} ${c.mintGreen}āœ“${c.reset}${c.slate} (was v${updateInfo.previousVersion})`;
621
649
  } else if (updateInfo.available && updateInfo.latest) {
622
- versionStr = `v${info.version} ${c.yellow}↑${updateInfo.latest}${c.reset}`;
650
+ versionStr = `v${info.version} ${c.amber}↑${updateInfo.latest}${c.reset}`;
623
651
  }
624
652
 
625
653
  // Calculate remaining space for branch
@@ -640,138 +668,139 @@ function formatTable(info, archival, session, precompact, parallelSessions, upda
640
668
  lines.push(topBorder);
641
669
  lines.push(headerLine);
642
670
 
643
- // Show update available notification
671
+ // Show update available notification (using vibrant colors)
644
672
  if (updateInfo.available && updateInfo.latest && !updateInfo.justUpdated) {
645
673
  lines.push(fullDivider());
646
- lines.push(fullRow(`↑ Update available: v${updateInfo.latest}`, c.yellow));
647
- lines.push(fullRow(` Run: npx agileflow update`, c.dim));
674
+ lines.push(fullRow(`${c.amber}↑${c.reset} Update available: ${c.softGold}v${updateInfo.latest}${c.reset}`, ''));
675
+ lines.push(fullRow(` Run: ${c.skyBlue}npx agileflow update${c.reset}`, ''));
648
676
  }
649
677
 
650
678
  // Show "just updated" changelog
651
679
  if (updateInfo.justUpdated && updateInfo.changelog && updateInfo.changelog.length > 0) {
652
680
  lines.push(fullDivider());
653
- lines.push(fullRow(`What's new in v${info.version}:`, c.green));
681
+ lines.push(fullRow(`${c.mintGreen}✨${c.reset} What's new in ${c.softGold}v${info.version}${c.reset}:`, ''));
654
682
  for (const entry of updateInfo.changelog.slice(0, 2)) {
655
- lines.push(fullRow(`• ${truncate(entry, W - 4)}`, c.dim));
683
+ lines.push(fullRow(` ${c.teal}•${c.reset} ${truncate(entry, W - 6)}`, ''));
656
684
  }
657
- lines.push(fullRow(`Run /agileflow:whats-new for full changelog`, c.dim));
685
+ lines.push(fullRow(` Run ${c.skyBlue}/agileflow:whats-new${c.reset} for full changelog`, ''));
658
686
  }
659
687
 
660
688
  lines.push(divider());
661
689
 
662
- // Stories section
690
+ // Stories section (always colorful labels like obtain-context)
663
691
  lines.push(
664
692
  row(
665
693
  'In Progress',
666
694
  info.wipCount > 0 ? `${info.wipCount}` : '0',
667
- c.dim,
668
- info.wipCount > 0 ? c.yellow : c.dim
695
+ c.peach,
696
+ info.wipCount > 0 ? c.peach : c.dim
669
697
  )
670
698
  );
671
699
  lines.push(
672
700
  row(
673
701
  'Blocked',
674
702
  info.blockedCount > 0 ? `${info.blockedCount}` : '0',
675
- c.dim,
676
- info.blockedCount > 0 ? c.red : c.dim
703
+ c.coral,
704
+ info.blockedCount > 0 ? c.coral : c.dim
677
705
  )
678
706
  );
679
707
  lines.push(
680
708
  row(
681
709
  'Ready',
682
710
  info.readyCount > 0 ? `${info.readyCount}` : '0',
683
- c.dim,
684
- info.readyCount > 0 ? c.cyan : c.dim
711
+ c.skyBlue,
712
+ info.readyCount > 0 ? c.skyBlue : c.dim
685
713
  )
686
714
  );
715
+ const completedColor = `${c.bold}${c.mintGreen}`;
687
716
  lines.push(
688
717
  row(
689
718
  'Completed',
690
719
  info.completedCount > 0 ? `${info.completedCount}` : '0',
691
- c.dim,
692
- info.completedCount > 0 ? c.green : c.dim
720
+ completedColor,
721
+ info.completedCount > 0 ? completedColor : c.dim
693
722
  )
694
723
  );
695
724
 
696
725
  lines.push(divider());
697
726
 
698
- // Archival section
727
+ // System section (colorful labels like obtain-context)
699
728
  if (archival.disabled) {
700
- lines.push(row('Auto-archival', 'disabled', c.dim, c.dim));
729
+ lines.push(row('Auto-archival', 'disabled', c.lavender, c.slate));
701
730
  } else {
702
731
  const archivalStatus =
703
732
  archival.archived > 0 ? `archived ${archival.archived} stories` : `nothing to archive`;
704
733
  lines.push(
705
- row('Auto-archival', archivalStatus, c.dim, archival.archived > 0 ? c.green : c.dim)
734
+ row('Auto-archival', archivalStatus, c.lavender, archival.archived > 0 ? c.mintGreen : c.dim)
706
735
  );
707
736
  }
708
737
 
709
738
  // Session cleanup
710
739
  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));
740
+ lines.push(row('Session state', sessionStatus, c.lavender, session.cleared > 0 ? c.mintGreen : c.dim));
712
741
 
713
742
  // PreCompact status with version check
714
743
  if (precompact.configured && precompact.scriptExists) {
715
744
  if (precompact.outdated) {
716
745
  const verStr = precompact.version ? ` (v${precompact.version})` : '';
717
- lines.push(row('Context preserve', `outdated${verStr}`, c.dim, c.yellow));
746
+ lines.push(row('Context preserve', `outdated${verStr}`, c.peach, c.peach));
718
747
  } else if (session.commandNames && session.commandNames.length > 0) {
719
748
  // Show the preserved command names
720
749
  const cmdDisplay = session.commandNames.map(n => `/agileflow:${n}`).join(', ');
721
- lines.push(row('Context preserve', cmdDisplay, c.dim, c.green));
750
+ lines.push(row('Context preserve', cmdDisplay, c.lavender, c.mintGreen));
722
751
  } else {
723
- lines.push(row('Context preserve', 'nothing to compact', c.dim, c.dim));
752
+ lines.push(row('Context preserve', 'ready', c.lavender, c.dim));
724
753
  }
725
754
  } else if (precompact.configured) {
726
- lines.push(row('Context preserve', 'script missing', c.dim, c.yellow));
755
+ lines.push(row('Context preserve', 'script missing', c.peach, c.peach));
727
756
  } else {
728
- lines.push(row('Context preserve', 'not configured', c.dim, c.dim));
757
+ lines.push(row('Context preserve', 'not configured', c.slate, c.slate));
729
758
  }
730
759
 
731
760
  // Parallel sessions status
732
761
  if (parallelSessions && parallelSessions.available) {
733
762
  if (parallelSessions.otherActive > 0) {
734
763
  const sessionStr = `āš ļø ${parallelSessions.otherActive} other active`;
735
- lines.push(row('Sessions', sessionStr, c.dim, c.yellow));
764
+ lines.push(row('Sessions', sessionStr, c.peach, c.peach));
736
765
  } else {
737
766
  const sessionStr = parallelSessions.currentId
738
767
  ? `āœ“ Session ${parallelSessions.currentId} (only)`
739
768
  : 'āœ“ Only session';
740
- lines.push(row('Sessions', sessionStr, c.dim, c.green));
769
+ lines.push(row('Sessions', sessionStr, c.lavender, c.mintGreen));
741
770
  }
742
771
  }
743
772
 
744
- // Agent expertise validation (only show if issues exist)
773
+ // Agent expertise validation (always show with color)
745
774
  if (expertise && expertise.total > 0) {
746
775
  if (expertise.failed > 0) {
747
776
  const expertStr = `āŒ ${expertise.failed} failed, ${expertise.warnings} warnings`;
748
- lines.push(row('Expertise', expertStr, c.dim, c.red));
777
+ lines.push(row('Expertise', expertStr, c.coral, c.coral));
749
778
  } else if (expertise.warnings > 0) {
750
779
  const expertStr = `āš ļø ${expertise.warnings} warnings (${expertise.passed} ok)`;
751
- lines.push(row('Expertise', expertStr, c.dim, c.yellow));
780
+ lines.push(row('Expertise', expertStr, c.peach, c.peach));
752
781
  } else {
753
- lines.push(row('Expertise', `āœ“ ${expertise.total} valid`, c.dim, c.green));
782
+ lines.push(row('Expertise', `āœ“ ${expertise.total} valid`, c.lavender, c.mintGreen));
754
783
  }
755
784
  }
756
785
 
757
786
  lines.push(divider());
758
787
 
759
- // Current story (if any) - row() auto-truncates
788
+ // Current story (colorful like obtain-context)
760
789
  if (info.currentStory) {
761
790
  lines.push(
762
791
  row(
763
792
  'Current',
764
- `${c.blue}${info.currentStory.id}${c.reset}: ${info.currentStory.title}`,
765
- c.dim,
793
+ `${c.lightYellow}${info.currentStory.id}${c.reset}: ${info.currentStory.title}`,
794
+ c.skyBlue,
766
795
  ''
767
796
  )
768
797
  );
769
798
  } else {
770
- lines.push(row('Current', 'No active story', c.dim, c.dim));
799
+ lines.push(row('Current', 'No active story', c.skyBlue, c.dim));
771
800
  }
772
801
 
773
- // Last commit - row() auto-truncates
774
- lines.push(row('Last commit', `${info.commit} ${info.lastCommit}`, c.dim, c.dim));
802
+ // Last commit (colorful like obtain-context)
803
+ lines.push(row('Last commit', `${c.peach}${info.commit}${c.reset} ${info.lastCommit}`, c.lavender, ''));
775
804
 
776
805
  lines.push(bottomBorder);
777
806
 
@@ -810,14 +839,16 @@ async function main() {
810
839
  // Update check failed - continue without it
811
840
  }
812
841
 
813
- console.log(formatTable(info, archival, session, precompact, parallelSessions, updateInfo, expertise));
842
+ console.log(
843
+ formatTable(info, archival, session, precompact, parallelSessions, updateInfo, expertise)
844
+ );
814
845
 
815
- // Show warning and tip if other sessions are active
846
+ // Show warning and tip if other sessions are active (vibrant colors)
816
847
  if (parallelSessions.otherActive > 0) {
817
848
  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}`);
849
+ console.log(`${c.amber}āš ļø Other Claude session(s) active in this repo.${c.reset}`);
850
+ console.log(`${c.slate} Run ${c.skyBlue}/agileflow:session:status${c.reset}${c.slate} to see all sessions.${c.reset}`);
851
+ console.log(`${c.slate} Run ${c.skyBlue}/agileflow:session:new${c.reset}${c.slate} to create isolated workspace.${c.reset}`);
821
852
  }
822
853
  }
823
854