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 +1 -1
- package/scripts/agileflow-configure.js +11 -11
- package/scripts/agileflow-statusline.sh +155 -9
- package/scripts/agileflow-welcome.js +83 -52
- package/scripts/auto-self-improve.js +63 -20
- package/scripts/check-update.js +1 -4
- package/scripts/get-env.js +15 -7
- package/scripts/lib/frontmatter-parser.js +4 -1
- package/scripts/obtain-context.js +59 -48
- package/scripts/ralph-loop.js +25 -13
- package/scripts/validate-expertise.sh +19 -15
- package/tools/cli/commands/list.js +3 -1
- package/tools/cli/commands/uninstall.js +4 -5
- package/tools/cli/commands/update.js +11 -3
- package/tools/cli/lib/content-injector.js +6 -1
package/package.json
CHANGED
|
@@ -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 =
|
|
588
|
-
|
|
589
|
-
|
|
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 (
|
|
1031
|
-
|
|
1032
|
-
|
|
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
|
-
|
|
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="$
|
|
213
|
+
CTX_COLOR="$CTX_RED" # Coral red - critical
|
|
144
214
|
elif [ "$PERCENT_USED" -ge 60 ]; then
|
|
145
|
-
CTX_COLOR="$
|
|
215
|
+
CTX_COLOR="$CTX_ORANGE" # Peach - high usage
|
|
146
216
|
elif [ "$PERCENT_USED" -ge 40 ]; then
|
|
147
|
-
CTX_COLOR="$
|
|
217
|
+
CTX_COLOR="$CTX_YELLOW" # Peach - moderate
|
|
148
218
|
else
|
|
149
|
-
CTX_COLOR="$
|
|
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
|
-
|
|
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(
|
|
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.
|
|
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.
|
|
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
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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(
|
|
647
|
-
lines.push(fullRow(` Run: npx agileflow update`,
|
|
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(
|
|
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(
|
|
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`,
|
|
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.
|
|
668
|
-
info.wipCount > 0 ? c.
|
|
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.
|
|
676
|
-
info.blockedCount > 0 ? c.
|
|
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.
|
|
684
|
-
info.readyCount > 0 ? c.
|
|
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
|
-
|
|
692
|
-
info.completedCount > 0 ?
|
|
720
|
+
completedColor,
|
|
721
|
+
info.completedCount > 0 ? completedColor : c.dim
|
|
693
722
|
)
|
|
694
723
|
);
|
|
695
724
|
|
|
696
725
|
lines.push(divider());
|
|
697
726
|
|
|
698
|
-
//
|
|
727
|
+
// System section (colorful labels like obtain-context)
|
|
699
728
|
if (archival.disabled) {
|
|
700
|
-
lines.push(row('Auto-archival', 'disabled', c.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
750
|
+
lines.push(row('Context preserve', cmdDisplay, c.lavender, c.mintGreen));
|
|
722
751
|
} else {
|
|
723
|
-
lines.push(row('Context preserve', '
|
|
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.
|
|
755
|
+
lines.push(row('Context preserve', 'script missing', c.peach, c.peach));
|
|
727
756
|
} else {
|
|
728
|
-
lines.push(row('Context preserve', 'not configured', c.
|
|
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.
|
|
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.
|
|
769
|
+
lines.push(row('Sessions', sessionStr, c.lavender, c.mintGreen));
|
|
741
770
|
}
|
|
742
771
|
}
|
|
743
772
|
|
|
744
|
-
// Agent expertise validation (
|
|
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.
|
|
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.
|
|
780
|
+
lines.push(row('Expertise', expertStr, c.peach, c.peach));
|
|
752
781
|
} else {
|
|
753
|
-
lines.push(row('Expertise', `ā ${expertise.total} valid`, c.
|
|
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 (
|
|
788
|
+
// Current story (colorful like obtain-context)
|
|
760
789
|
if (info.currentStory) {
|
|
761
790
|
lines.push(
|
|
762
791
|
row(
|
|
763
792
|
'Current',
|
|
764
|
-
`${c.
|
|
765
|
-
c.
|
|
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.
|
|
799
|
+
lines.push(row('Current', 'No active story', c.skyBlue, c.dim));
|
|
771
800
|
}
|
|
772
801
|
|
|
773
|
-
// Last commit
|
|
774
|
-
lines.push(row('Last commit', `${info.commit} ${info.lastCommit}`, c.
|
|
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(
|
|
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.
|
|
819
|
-
console.log(`${c.
|
|
820
|
-
console.log(`${c.
|
|
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
|
|