agileflow 2.72.0 → 2.74.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.
@@ -11,7 +11,7 @@
11
11
  * - RECONFIGURE: Change settings (archival days, etc.)
12
12
  *
13
13
  * Usage:
14
- * node scripts/agileflow-configure.js [options]
14
+ * node .agileflow/scripts/agileflow-configure.js [options]
15
15
  *
16
16
  * Options:
17
17
  * --profile=full|basic|minimal|none Apply a preset
@@ -77,6 +77,34 @@ const FEATURES = {
77
77
  autoupdate: { metadataOnly: true }, // Stored in metadata.updates.autoUpdate
78
78
  };
79
79
 
80
+ // Complete registry of all scripts that may need repair
81
+ const ALL_SCRIPTS = {
82
+ // Core feature scripts (linked to FEATURES)
83
+ 'agileflow-welcome.js': { feature: 'sessionstart', required: true },
84
+ 'precompact-context.sh': { feature: 'precompact', required: true },
85
+ 'archive-completed-stories.sh': { feature: 'archival', required: true },
86
+ 'agileflow-statusline.sh': { feature: 'statusline', required: true },
87
+
88
+ // Support scripts (used by commands/agents)
89
+ 'obtain-context.js': { usedBy: ['/babysit', '/mentor', '/sprint'] },
90
+ 'session-manager.js': { usedBy: ['/session:new', '/session:resume'] },
91
+ 'check-update.js': { usedBy: ['SessionStart hook'] },
92
+ 'get-env.js': { usedBy: ['SessionStart hook'] },
93
+ 'clear-active-command.js': { usedBy: ['session commands'] },
94
+
95
+ // Utility scripts
96
+ 'compress-status.sh': { usedBy: ['/compress'] },
97
+ 'validate-expertise.sh': { usedBy: ['/validate-expertise'] },
98
+ 'expertise-metrics.sh': { usedBy: ['agent experts'] },
99
+ 'session-coordinator.sh': { usedBy: ['session management'] },
100
+ 'validate-tokens.sh': { usedBy: ['token validation'] },
101
+ 'worktree-create.sh': { usedBy: ['/session:new'] },
102
+ 'resume-session.sh': { usedBy: ['/session:resume'] },
103
+ 'init.sh': { usedBy: ['/session:init'] },
104
+ 'agileflow-configure.js': { usedBy: ['/configure'] },
105
+ 'generate-all.sh': { usedBy: ['content generation'] },
106
+ };
107
+
80
108
  // Statusline component names
81
109
  const STATUSLINE_COMPONENTS = [
82
110
  'agileflow',
@@ -93,19 +121,19 @@ const PROFILES = {
93
121
  full: {
94
122
  description: 'All features enabled',
95
123
  enable: ['sessionstart', 'precompact', 'archival', 'statusline'],
96
- archivalDays: 7,
124
+ archivalDays: 30,
97
125
  },
98
126
  basic: {
99
127
  description: 'Essential hooks + archival (SessionStart + PreCompact + Archival)',
100
128
  enable: ['sessionstart', 'precompact', 'archival'],
101
129
  disable: ['statusline'],
102
- archivalDays: 7,
130
+ archivalDays: 30,
103
131
  },
104
132
  minimal: {
105
133
  description: 'SessionStart + archival only',
106
134
  enable: ['sessionstart', 'archival'],
107
135
  disable: ['precompact', 'statusline'],
108
- archivalDays: 7,
136
+ archivalDays: 30,
109
137
  },
110
138
  none: {
111
139
  description: 'Disable all AgileFlow features',
@@ -155,22 +183,16 @@ const writeJSON = (filePath, data) => {
155
183
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
156
184
  };
157
185
 
158
- const copyTemplate = (templateName, destPath) => {
159
- const sources = [
160
- path.join(process.cwd(), '.agileflow', 'templates', templateName),
161
- path.join(__dirname, templateName),
162
- path.join(__dirname, '..', 'templates', templateName),
163
- ];
164
- for (const src of sources) {
165
- if (fs.existsSync(src)) {
166
- fs.copyFileSync(src, destPath);
167
- try {
168
- fs.chmodSync(destPath, '755');
169
- } catch {}
170
- return true;
171
- }
172
- }
173
- return false;
186
+ // Scripts are located in .agileflow/scripts/ (installed by AgileFlow)
187
+ const SCRIPTS_DIR = path.join(process.cwd(), '.agileflow', 'scripts');
188
+
189
+ const scriptExists = scriptName => {
190
+ const scriptPath = path.join(SCRIPTS_DIR, scriptName);
191
+ return fs.existsSync(scriptPath);
192
+ };
193
+
194
+ const getScriptPath = scriptName => {
195
+ return `.agileflow/scripts/${scriptName}`;
174
196
  };
175
197
 
176
198
  // ============================================================================
@@ -184,12 +206,14 @@ function detectConfig() {
184
206
  settingsValid: true,
185
207
  settingsIssues: [],
186
208
  features: {
187
- sessionstart: { enabled: false, valid: true, issues: [] },
188
- precompact: { enabled: false, valid: true, issues: [] },
189
- archival: { enabled: false, threshold: null },
190
- statusline: { enabled: false, valid: true, issues: [] },
209
+ sessionstart: { enabled: false, valid: true, issues: [], version: null, outdated: false },
210
+ precompact: { enabled: false, valid: true, issues: [], version: null, outdated: false },
211
+ archival: { enabled: false, threshold: null, version: null, outdated: false },
212
+ statusline: { enabled: false, valid: true, issues: [], version: null, outdated: false },
191
213
  },
192
214
  metadata: { exists: false, version: null },
215
+ currentVersion: VERSION,
216
+ hasOutdated: false,
193
217
  };
194
218
 
195
219
  // Git
@@ -280,6 +304,20 @@ function detectConfig() {
280
304
  status.features.archival.enabled = true;
281
305
  status.features.archival.threshold = meta.archival.threshold_days;
282
306
  }
307
+
308
+ // Read feature versions from metadata and check if outdated
309
+ if (meta.features) {
310
+ Object.entries(meta.features).forEach(([feature, data]) => {
311
+ if (status.features[feature] && data.version) {
312
+ status.features[feature].version = data.version;
313
+ // Check if feature version differs from current VERSION
314
+ if (data.version !== VERSION && status.features[feature].enabled) {
315
+ status.features[feature].outdated = true;
316
+ status.hasOutdated = true;
317
+ }
318
+ }
319
+ });
320
+ }
283
321
  }
284
322
  }
285
323
 
@@ -317,6 +355,10 @@ function printStatus(status) {
317
355
  statusIcon = '⚠️';
318
356
  statusText = 'INVALID FORMAT';
319
357
  color = c.yellow;
358
+ } else if (f.enabled && f.outdated) {
359
+ statusIcon = '🔄';
360
+ statusText = `outdated (v${f.version} → v${status.currentVersion})`;
361
+ color = c.yellow;
320
362
  }
321
363
 
322
364
  log(` ${statusIcon} ${label}: ${statusText}`, color);
@@ -348,7 +390,11 @@ function printStatus(status) {
348
390
  log('\n⚠️ Format issues detected! Run with --migrate to fix.', c.yellow);
349
391
  }
350
392
 
351
- return hasIssues;
393
+ if (status.hasOutdated) {
394
+ log('\n🔄 Outdated scripts detected! Run with --upgrade to update.', c.yellow);
395
+ }
396
+
397
+ return { hasIssues, hasOutdated: status.hasOutdated };
352
398
  }
353
399
 
354
400
  // ============================================================================
@@ -454,6 +500,34 @@ function migrateSettings() {
454
500
  return migrated;
455
501
  }
456
502
 
503
+ // ============================================================================
504
+ // UPGRADE FEATURES
505
+ // ============================================================================
506
+
507
+ function upgradeFeatures(status) {
508
+ header('🔄 Upgrading Outdated Features...');
509
+
510
+ let upgraded = 0;
511
+
512
+ Object.entries(status.features).forEach(([feature, data]) => {
513
+ if (data.enabled && data.outdated) {
514
+ log(`\nUpgrading ${feature}...`, c.cyan);
515
+ // Re-enable the feature to deploy latest scripts
516
+ if (enableFeature(feature, { archivalDays: data.threshold || 30, isUpgrade: true })) {
517
+ upgraded++;
518
+ }
519
+ }
520
+ });
521
+
522
+ if (upgraded === 0) {
523
+ info('No features needed upgrading');
524
+ } else {
525
+ success(`Upgraded ${upgraded} feature(s) to v${VERSION}`);
526
+ }
527
+
528
+ return upgraded > 0;
529
+ }
530
+
457
531
  // ============================================================================
458
532
  // ENABLE/DISABLE FEATURES
459
533
  // ============================================================================
@@ -466,7 +540,6 @@ function enableFeature(feature, options = {}) {
466
540
  }
467
541
 
468
542
  ensureDir('.claude');
469
- ensureDir('scripts');
470
543
 
471
544
  const settings = readJSON('.claude/settings.json') || {};
472
545
  settings.hooks = settings.hooks || {};
@@ -474,25 +547,13 @@ function enableFeature(feature, options = {}) {
474
547
 
475
548
  // Handle hook-based features
476
549
  if (config.hook) {
477
- const scriptPath = `scripts/${config.script}`;
478
-
479
- // Deploy script
480
- if (!copyTemplate(config.script, scriptPath)) {
481
- // Create minimal version
482
- if (feature === 'sessionstart') {
483
- fs.writeFileSync(
484
- scriptPath,
485
- `#!/usr/bin/env node\nconsole.log('AgileFlow v${VERSION} loaded');\n`
486
- );
487
- } else if (feature === 'precompact') {
488
- fs.writeFileSync(scriptPath, '#!/bin/bash\necho "PreCompact: preserving context"\n');
489
- }
490
- try {
491
- fs.chmodSync(scriptPath, '755');
492
- } catch {}
493
- warn(`Created minimal ${config.script}`);
494
- } else {
495
- success(`Deployed ${config.script}`);
550
+ const scriptPath = getScriptPath(config.script);
551
+
552
+ // Verify script exists
553
+ if (!scriptExists(config.script)) {
554
+ error(`Script not found: ${scriptPath}`);
555
+ info('Run "npx agileflow update" to reinstall scripts');
556
+ return false;
496
557
  }
497
558
 
498
559
  // Configure hook
@@ -504,18 +565,18 @@ function enableFeature(feature, options = {}) {
504
565
  hooks: [{ type: 'command', command }],
505
566
  },
506
567
  ];
507
- success(`${config.hook} hook enabled`);
568
+ success(`${config.hook} hook enabled (${config.script})`);
508
569
  }
509
570
 
510
571
  // Handle archival
511
572
  if (feature === 'archival') {
512
- const days = options.archivalDays || 7;
513
- const scriptPath = 'scripts/archive-completed-stories.sh';
573
+ const days = options.archivalDays || 30;
574
+ const scriptPath = getScriptPath('archive-completed-stories.sh');
514
575
 
515
- if (!copyTemplate('archive-completed-stories.sh', scriptPath)) {
516
- warn('Archival script template not found');
517
- } else {
518
- success('Deployed archive-completed-stories.sh');
576
+ if (!scriptExists('archive-completed-stories.sh')) {
577
+ error(`Script not found: ${scriptPath}`);
578
+ info('Run "npx agileflow update" to reinstall scripts');
579
+ return false;
519
580
  }
520
581
 
521
582
  // Add to SessionStart hook
@@ -526,7 +587,7 @@ function enableFeature(feature, options = {}) {
526
587
  if (!hasArchival) {
527
588
  settings.hooks.SessionStart[0].hooks.push({
528
589
  type: 'command',
529
- command: 'bash scripts/archive-completed-stories.sh --quiet',
590
+ command: `bash ${scriptPath} --quiet`,
530
591
  });
531
592
  }
532
593
  }
@@ -538,28 +599,17 @@ function enableFeature(feature, options = {}) {
538
599
 
539
600
  // Handle statusLine
540
601
  if (feature === 'statusline') {
541
- const scriptPath = 'scripts/agileflow-statusline.sh';
542
-
543
- if (!copyTemplate('agileflow-statusline.sh', scriptPath)) {
544
- fs.writeFileSync(
545
- scriptPath,
546
- `#!/bin/bash
547
- input=$(cat)
548
- MODEL=$(echo "$input" | jq -r '.model.display_name // "Claude"')
549
- echo "[$MODEL] AgileFlow"
550
- `
551
- );
552
- try {
553
- fs.chmodSync(scriptPath, '755');
554
- } catch {}
555
- warn('Created minimal statusline script');
556
- } else {
557
- success('Deployed agileflow-statusline.sh');
602
+ const scriptPath = getScriptPath('agileflow-statusline.sh');
603
+
604
+ if (!scriptExists('agileflow-statusline.sh')) {
605
+ error(`Script not found: ${scriptPath}`);
606
+ info('Run "npx agileflow update" to reinstall scripts');
607
+ return false;
558
608
  }
559
609
 
560
610
  settings.statusLine = {
561
611
  type: 'command',
562
- command: 'bash scripts/agileflow-statusline.sh',
612
+ command: `bash ${scriptPath}`,
563
613
  padding: 0,
564
614
  };
565
615
  success('Status line enabled');
@@ -789,6 +839,240 @@ function listStatuslineComponents() {
789
839
  log(`Components: ${STATUSLINE_COMPONENTS.join(', ')}`, c.dim);
790
840
  }
791
841
 
842
+ // ============================================================================
843
+ // REPAIR & DIAGNOSTICS
844
+ // ============================================================================
845
+
846
+ const crypto = require('crypto');
847
+
848
+ /**
849
+ * Calculate SHA256 hash of a file
850
+ */
851
+ function sha256(data) {
852
+ return crypto.createHash('sha256').update(data).digest('hex');
853
+ }
854
+
855
+ /**
856
+ * Get the source scripts directory (from npm package)
857
+ */
858
+ function getSourceScriptsDir() {
859
+ // When running from installed package, __dirname is .agileflow/scripts
860
+ // The source is the same directory since it was copied during install
861
+ // But for repair, we need the npm package source
862
+
863
+ // Try to find the npm package (when run via npx or global install)
864
+ const possiblePaths = [
865
+ path.join(__dirname, '..', '..', 'scripts'), // npm package structure
866
+ path.join(__dirname), // Same directory (for development)
867
+ ];
868
+
869
+ for (const p of possiblePaths) {
870
+ if (fs.existsSync(p) && fs.existsSync(path.join(p, 'agileflow-welcome.js'))) {
871
+ return p;
872
+ }
873
+ }
874
+
875
+ return null;
876
+ }
877
+
878
+ /**
879
+ * List all scripts with their status (present/missing/modified)
880
+ */
881
+ function listScripts() {
882
+ header('📋 Installed Scripts');
883
+
884
+ const scriptsDir = path.join(process.cwd(), '.agileflow', 'scripts');
885
+ const fileIndexPath = path.join(process.cwd(), '.agileflow', '_cfg', 'files.json');
886
+ const fileIndex = readJSON(fileIndexPath);
887
+
888
+ let missing = 0;
889
+ let modified = 0;
890
+ let present = 0;
891
+
892
+ Object.entries(ALL_SCRIPTS).forEach(([script, info]) => {
893
+ const scriptPath = path.join(scriptsDir, script);
894
+ const exists = fs.existsSync(scriptPath);
895
+
896
+ // Check if modified (compare to file index hash)
897
+ let isModified = false;
898
+ if (exists && fileIndex?.files?.[`scripts/${script}`]) {
899
+ try {
900
+ const currentHash = sha256(fs.readFileSync(scriptPath));
901
+ const indexHash = fileIndex.files[`scripts/${script}`].sha256;
902
+ isModified = currentHash !== indexHash;
903
+ } catch {}
904
+ }
905
+
906
+ // Print status
907
+ if (!exists) {
908
+ log(` ❌ ${script}: MISSING`, c.red);
909
+ if (info.usedBy) log(` └─ Used by: ${info.usedBy.join(', ')}`, c.dim);
910
+ if (info.feature) log(` └─ Feature: ${info.feature}`, c.dim);
911
+ missing++;
912
+ } else if (isModified) {
913
+ log(` ⚠️ ${script}: modified (local changes)`, c.yellow);
914
+ modified++;
915
+ } else {
916
+ log(` ✅ ${script}: present`, c.green);
917
+ present++;
918
+ }
919
+ });
920
+
921
+ // Summary
922
+ log('');
923
+ log(`Summary: ${present} present, ${modified} modified, ${missing} missing`, c.dim);
924
+
925
+ if (missing > 0) {
926
+ log('\n💡 Run with --repair to restore missing scripts', c.yellow);
927
+ }
928
+ }
929
+
930
+ /**
931
+ * Show version information
932
+ */
933
+ function showVersionInfo() {
934
+ header('📊 Version Information');
935
+
936
+ const meta = readJSON('docs/00-meta/agileflow-metadata.json') || {};
937
+ const manifest = readJSON('.agileflow/_cfg/manifest.yaml');
938
+
939
+ const installedVersion = meta.version || 'unknown';
940
+
941
+ log(`Installed: v${installedVersion}`);
942
+ log(`CLI: v${VERSION}`);
943
+
944
+ // Check npm for latest
945
+ let latestVersion = null;
946
+ try {
947
+ latestVersion = execSync('npm view agileflow version 2>/dev/null', { encoding: 'utf8' }).trim();
948
+ log(`Latest: v${latestVersion}`);
949
+
950
+ if (installedVersion !== 'unknown' && latestVersion && installedVersion !== latestVersion) {
951
+ const installed = installedVersion.split('.').map(Number);
952
+ const latest = latestVersion.split('.').map(Number);
953
+
954
+ if (latest[0] > installed[0] ||
955
+ (latest[0] === installed[0] && latest[1] > installed[1]) ||
956
+ (latest[0] === installed[0] && latest[1] === installed[1] && latest[2] > installed[2])) {
957
+ log('\n🔄 Update available! Run: npx agileflow update', c.yellow);
958
+ }
959
+ }
960
+ } catch {
961
+ log('Latest: (could not check npm)', c.dim);
962
+ }
963
+
964
+ // Show per-feature versions
965
+ if (meta.features && Object.keys(meta.features).length > 0) {
966
+ header('Feature Versions:');
967
+ Object.entries(meta.features).forEach(([feature, data]) => {
968
+ if (!data) return;
969
+ const featureVersion = data.version || 'unknown';
970
+ const enabled = data.enabled !== false;
971
+ const outdated = featureVersion !== VERSION && enabled;
972
+
973
+ let icon = '❌';
974
+ let color = c.dim;
975
+ let statusText = `v${featureVersion}`;
976
+
977
+ if (!enabled) {
978
+ statusText = 'disabled';
979
+ } else if (outdated) {
980
+ icon = '🔄';
981
+ color = c.yellow;
982
+ statusText = `v${featureVersion} → v${VERSION}`;
983
+ } else {
984
+ icon = '✅';
985
+ color = c.green;
986
+ }
987
+
988
+ log(` ${icon} ${feature}: ${statusText}`, color);
989
+ });
990
+ }
991
+
992
+ // Show installation metadata
993
+ if (meta.created || meta.updated) {
994
+ header('Installation:');
995
+ if (meta.created) log(` Created: ${new Date(meta.created).toLocaleDateString()}`, c.dim);
996
+ if (meta.updated) log(` Updated: ${new Date(meta.updated).toLocaleDateString()}`, c.dim);
997
+ }
998
+ }
999
+
1000
+ /**
1001
+ * Repair missing or corrupted scripts
1002
+ */
1003
+ function repairScripts(targetFeature = null) {
1004
+ header('🔧 Repairing Scripts...');
1005
+
1006
+ const scriptsDir = path.join(process.cwd(), '.agileflow', 'scripts');
1007
+ const sourceDir = getSourceScriptsDir();
1008
+
1009
+ if (!sourceDir) {
1010
+ warn('Could not find source scripts directory');
1011
+ info('Try running: npx agileflow@latest update');
1012
+ return false;
1013
+ }
1014
+
1015
+ let repaired = 0;
1016
+ let errors = 0;
1017
+ let skipped = 0;
1018
+
1019
+ // Determine which scripts to check
1020
+ const scriptsToCheck = targetFeature
1021
+ ? Object.entries(ALL_SCRIPTS).filter(([_, info]) => info.feature === targetFeature)
1022
+ : Object.entries(ALL_SCRIPTS);
1023
+
1024
+ if (scriptsToCheck.length === 0 && targetFeature) {
1025
+ error(`Unknown feature: ${targetFeature}`);
1026
+ log(`Available features: ${Object.keys(FEATURES).join(', ')}`, c.dim);
1027
+ return false;
1028
+ }
1029
+
1030
+ // Ensure scripts directory exists
1031
+ ensureDir(scriptsDir);
1032
+
1033
+ for (const [script, info] of scriptsToCheck) {
1034
+ const destPath = path.join(scriptsDir, script);
1035
+ const srcPath = path.join(sourceDir, script);
1036
+
1037
+ if (!fs.existsSync(destPath)) {
1038
+ // Script is missing - reinstall from source
1039
+ if (fs.existsSync(srcPath)) {
1040
+ try {
1041
+ fs.copyFileSync(srcPath, destPath);
1042
+ // Make executable
1043
+ try {
1044
+ fs.chmodSync(destPath, 0o755);
1045
+ } catch {}
1046
+ success(`Restored ${script}`);
1047
+ repaired++;
1048
+ } catch (err) {
1049
+ error(`Failed to restore ${script}: ${err.message}`);
1050
+ errors++;
1051
+ }
1052
+ } else {
1053
+ warn(`Source not found for ${script}`);
1054
+ errors++;
1055
+ }
1056
+ } else {
1057
+ skipped++;
1058
+ }
1059
+ }
1060
+
1061
+ // Summary
1062
+ log('');
1063
+ if (repaired === 0 && errors === 0) {
1064
+ info('All scripts present - nothing to repair');
1065
+ } else {
1066
+ log(`Repaired: ${repaired}, Errors: ${errors}, Skipped: ${skipped}`, c.dim);
1067
+ }
1068
+
1069
+ if (errors > 0) {
1070
+ log('\n💡 For comprehensive repair, run: npx agileflow update --force', c.yellow);
1071
+ }
1072
+
1073
+ return repaired > 0;
1074
+ }
1075
+
792
1076
  // ============================================================================
793
1077
  // PROFILES
794
1078
  // ============================================================================
@@ -855,7 +1139,7 @@ function printHelp() {
855
1139
  ${c.bold}AgileFlow Configure${c.reset} - Manage AgileFlow features
856
1140
 
857
1141
  ${c.cyan}Usage:${c.reset}
858
- node scripts/agileflow-configure.js [options]
1142
+ node .agileflow/scripts/agileflow-configure.js [options]
859
1143
 
860
1144
  ${c.cyan}Profiles:${c.reset}
861
1145
  --profile=full All features (hooks, archival, statusline)
@@ -877,37 +1161,59 @@ ${c.cyan}Statusline Components:${c.reset}
877
1161
  Components: agileflow, model, story, epic, wip, context, cost, git
878
1162
 
879
1163
  ${c.cyan}Settings:${c.reset}
880
- --archival-days=N Set archival threshold (default: 7)
1164
+ --archival-days=N Set archival threshold (default: 30)
881
1165
 
882
1166
  ${c.cyan}Maintenance:${c.reset}
883
1167
  --migrate Fix old/invalid formats
1168
+ --upgrade Re-deploy all enabled features with latest scripts
884
1169
  --validate Check for issues (same as --detect)
885
1170
  --detect Show current configuration
886
1171
 
1172
+ ${c.cyan}Repair & Diagnostics:${c.reset}
1173
+ --repair Check for and restore missing scripts
1174
+ --repair=<feature> Repair scripts for a specific feature (e.g., statusline)
1175
+ --version Show installed vs latest version info
1176
+ --list-scripts List all scripts with their status (missing/present/modified)
1177
+
887
1178
  ${c.cyan}Examples:${c.reset}
888
1179
  # Quick setup with all features
889
- node scripts/agileflow-configure.js --profile=full
1180
+ node .agileflow/scripts/agileflow-configure.js --profile=full
890
1181
 
891
1182
  # Enable specific features
892
- node scripts/agileflow-configure.js --enable=sessionstart,precompact,archival
1183
+ node .agileflow/scripts/agileflow-configure.js --enable=sessionstart,precompact,archival
893
1184
 
894
1185
  # Disable a feature
895
- node scripts/agileflow-configure.js --disable=statusline
1186
+ node .agileflow/scripts/agileflow-configure.js --disable=statusline
896
1187
 
897
1188
  # Show only agileflow branding and context in statusline
898
- node scripts/agileflow-configure.js --hide=model,story,epic,wip,cost,git
1189
+ node .agileflow/scripts/agileflow-configure.js --hide=model,story,epic,wip,cost,git
899
1190
 
900
1191
  # Re-enable git branch in statusline
901
- node scripts/agileflow-configure.js --show=git
1192
+ node .agileflow/scripts/agileflow-configure.js --show=git
902
1193
 
903
1194
  # List component status
904
- node scripts/agileflow-configure.js --components
1195
+ node .agileflow/scripts/agileflow-configure.js --components
905
1196
 
906
1197
  # Fix format issues
907
- node scripts/agileflow-configure.js --migrate
1198
+ node .agileflow/scripts/agileflow-configure.js --migrate
908
1199
 
909
1200
  # Check current status
910
- node scripts/agileflow-configure.js --detect
1201
+ node .agileflow/scripts/agileflow-configure.js --detect
1202
+
1203
+ # Upgrade outdated scripts to latest version
1204
+ node .agileflow/scripts/agileflow-configure.js --upgrade
1205
+
1206
+ # List all scripts with status
1207
+ node .agileflow/scripts/agileflow-configure.js --list-scripts
1208
+
1209
+ # Show version information
1210
+ node .agileflow/scripts/agileflow-configure.js --version
1211
+
1212
+ # Repair missing scripts
1213
+ node .agileflow/scripts/agileflow-configure.js --repair
1214
+
1215
+ # Repair scripts for a specific feature
1216
+ node .agileflow/scripts/agileflow-configure.js --repair=statusline
911
1217
  `);
912
1218
  }
913
1219
 
@@ -924,11 +1230,16 @@ function main() {
924
1230
  let disable = [];
925
1231
  let show = [];
926
1232
  let hide = [];
927
- let archivalDays = 7;
1233
+ let archivalDays = 30;
928
1234
  let migrate = false;
929
1235
  let detect = false;
1236
+ let upgrade = false;
930
1237
  let components = false;
931
1238
  let help = false;
1239
+ let repair = false;
1240
+ let repairFeature = null;
1241
+ let showVersion = false;
1242
+ let listScriptsMode = false;
932
1243
 
933
1244
  args.forEach(arg => {
934
1245
  if (arg.startsWith('--profile=')) profile = arg.split('=')[1];
@@ -952,11 +1263,19 @@ function main() {
952
1263
  .split('=')[1]
953
1264
  .split(',')
954
1265
  .map(s => s.trim().toLowerCase());
955
- else if (arg.startsWith('--archival-days=')) archivalDays = parseInt(arg.split('=')[1]) || 7;
1266
+ else if (arg.startsWith('--archival-days=')) archivalDays = parseInt(arg.split('=')[1]) || 30;
956
1267
  else if (arg === '--migrate') migrate = true;
957
1268
  else if (arg === '--detect' || arg === '--validate') detect = true;
1269
+ else if (arg === '--upgrade') upgrade = true;
958
1270
  else if (arg === '--components') components = true;
959
1271
  else if (arg === '--help' || arg === '-h') help = true;
1272
+ else if (arg === '--repair') repair = true;
1273
+ else if (arg.startsWith('--repair=')) {
1274
+ repair = true;
1275
+ repairFeature = arg.split('=')[1].trim().toLowerCase();
1276
+ }
1277
+ else if (arg === '--version' || arg === '-v') showVersion = true;
1278
+ else if (arg === '--list-scripts' || arg === '--scripts') listScriptsMode = true;
960
1279
  });
961
1280
 
962
1281
  if (help) {
@@ -964,6 +1283,30 @@ function main() {
964
1283
  return;
965
1284
  }
966
1285
 
1286
+ // List scripts mode (standalone, doesn't need detection)
1287
+ if (listScriptsMode) {
1288
+ listScripts();
1289
+ return;
1290
+ }
1291
+
1292
+ // Version info mode (standalone, doesn't need detection)
1293
+ if (showVersion) {
1294
+ showVersionInfo();
1295
+ return;
1296
+ }
1297
+
1298
+ // Repair mode (standalone, doesn't need detection)
1299
+ if (repair) {
1300
+ const needsRestart = repairScripts(repairFeature);
1301
+ if (needsRestart) {
1302
+ log('\n' + '═'.repeat(55), c.red);
1303
+ log('🔴 RESTART CLAUDE CODE NOW!', c.red + c.bold);
1304
+ log(' Quit completely, wait 5 seconds, restart', c.red);
1305
+ log('═'.repeat(55), c.red);
1306
+ }
1307
+ return;
1308
+ }
1309
+
967
1310
  // Components list mode
968
1311
  if (components && show.length === 0 && hide.length === 0) {
969
1312
  listStatuslineComponents();
@@ -979,10 +1322,16 @@ function main() {
979
1322
 
980
1323
  // Always detect first
981
1324
  const status = detectConfig();
982
- const hasIssues = printStatus(status);
1325
+ const { hasIssues, hasOutdated } = printStatus(status);
983
1326
 
984
1327
  // Detect only mode
985
- if (detect && !migrate && !profile && enable.length === 0 && disable.length === 0) {
1328
+ if (detect && !migrate && !upgrade && !profile && enable.length === 0 && disable.length === 0) {
1329
+ return;
1330
+ }
1331
+
1332
+ // Upgrade mode
1333
+ if (upgrade) {
1334
+ upgradeFeatures(status);
986
1335
  return;
987
1336
  }
988
1337