agileflow 2.73.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agileflow",
3
- "version": "2.73.0",
3
+ "version": "2.74.0",
4
4
  "description": "AI-driven agile development system for Claude Code, Cursor, Windsurf, and more",
5
5
  "keywords": [
6
6
  "agile",
@@ -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',
@@ -811,6 +839,240 @@ function listStatuslineComponents() {
811
839
  log(`Components: ${STATUSLINE_COMPONENTS.join(', ')}`, c.dim);
812
840
  }
813
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
+
814
1076
  // ============================================================================
815
1077
  // PROFILES
816
1078
  // ============================================================================
@@ -907,6 +1169,12 @@ ${c.cyan}Maintenance:${c.reset}
907
1169
  --validate Check for issues (same as --detect)
908
1170
  --detect Show current configuration
909
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
+
910
1178
  ${c.cyan}Examples:${c.reset}
911
1179
  # Quick setup with all features
912
1180
  node .agileflow/scripts/agileflow-configure.js --profile=full
@@ -934,6 +1202,18 @@ ${c.cyan}Examples:${c.reset}
934
1202
 
935
1203
  # Upgrade outdated scripts to latest version
936
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
937
1217
  `);
938
1218
  }
939
1219
 
@@ -956,6 +1236,10 @@ function main() {
956
1236
  let upgrade = false;
957
1237
  let components = false;
958
1238
  let help = false;
1239
+ let repair = false;
1240
+ let repairFeature = null;
1241
+ let showVersion = false;
1242
+ let listScriptsMode = false;
959
1243
 
960
1244
  args.forEach(arg => {
961
1245
  if (arg.startsWith('--profile=')) profile = arg.split('=')[1];
@@ -985,6 +1269,13 @@ function main() {
985
1269
  else if (arg === '--upgrade') upgrade = true;
986
1270
  else if (arg === '--components') components = true;
987
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;
988
1279
  });
989
1280
 
990
1281
  if (help) {
@@ -992,6 +1283,30 @@ function main() {
992
1283
  return;
993
1284
  }
994
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
+
995
1310
  // Components list mode
996
1311
  if (components && show.length === 0 && hide.length === 0) {
997
1312
  listStatuslineComponents();
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Configure advanced AgileFlow features (git, hooks, archival, CI, status line)
3
- argument-hint: [--profile=full|basic|minimal|none] [--enable/--disable=features] [--migrate] [--upgrade]
3
+ argument-hint: [--profile=full|basic|minimal|none] [--enable/--disable=features] [--migrate] [--upgrade] [--repair] [--version] [--list-scripts]
4
4
  ---
5
5
 
6
6
  <!-- COMPACT_SUMMARY_START -->
@@ -26,6 +26,10 @@ node .agileflow/scripts/agileflow-configure.js --profile=full # Enable all
26
26
  node .agileflow/scripts/agileflow-configure.js --profile=none # Disable all
27
27
  node .agileflow/scripts/agileflow-configure.js --enable=sessionstart # Enable specific
28
28
  node .agileflow/scripts/agileflow-configure.js --disable=archival # Disable specific
29
+ node .agileflow/scripts/agileflow-configure.js --list-scripts # Show all scripts status
30
+ node .agileflow/scripts/agileflow-configure.js --version # Version info
31
+ node .agileflow/scripts/agileflow-configure.js --repair # Fix missing scripts
32
+ node .agileflow/scripts/agileflow-configure.js --repair=statusline # Fix specific feature
29
33
  ```
30
34
 
31
35
  **Note:** All scripts are located in `.agileflow/scripts/` - no files in project root `scripts/`.
@@ -343,3 +347,86 @@ Upgrading precompact...
343
347
 
344
348
  āœ… Upgraded 2 feature(s) to v2.71.0
345
349
  ```
350
+
351
+ ## Repair & Diagnostics
352
+
353
+ When scripts are accidentally deleted or corrupted, use these commands:
354
+
355
+ ### List Scripts Status
356
+
357
+ ```bash
358
+ node .agileflow/scripts/agileflow-configure.js --list-scripts
359
+ ```
360
+
361
+ Shows all scripts with their status (present/missing/modified):
362
+
363
+ ```
364
+ šŸ“‹ Installed Scripts
365
+ āœ… agileflow-welcome.js: present
366
+ āœ… precompact-context.sh: present
367
+ āŒ agileflow-statusline.sh: MISSING
368
+ └─ Feature: statusline
369
+ āš ļø obtain-context.js: modified (local changes)
370
+
371
+ Summary: 15 present, 1 modified, 1 missing
372
+
373
+ šŸ’” Run with --repair to restore missing scripts
374
+ ```
375
+
376
+ ### Show Version Info
377
+
378
+ ```bash
379
+ node .agileflow/scripts/agileflow-configure.js --version
380
+ ```
381
+
382
+ Shows installed vs latest versions:
383
+
384
+ ```
385
+ šŸ“Š Version Information
386
+ Installed: v2.71.0
387
+ CLI: v2.73.0
388
+ Latest: v2.73.0
389
+
390
+ šŸ”„ Update available! Run: npx agileflow update
391
+
392
+ Feature Versions:
393
+ āœ… sessionstart: v2.73.0
394
+ šŸ”„ precompact: v2.68.0 → v2.73.0
395
+ āœ… archival: v2.73.0
396
+ āŒ statusline: disabled
397
+ ```
398
+
399
+ ### Repair Missing Scripts
400
+
401
+ ```bash
402
+ # Repair all missing scripts
403
+ node .agileflow/scripts/agileflow-configure.js --repair
404
+
405
+ # Repair scripts for a specific feature only
406
+ node .agileflow/scripts/agileflow-configure.js --repair=statusline
407
+ ```
408
+
409
+ Output:
410
+
411
+ ```
412
+ šŸ”§ Repairing Scripts...
413
+ āœ… Restored agileflow-statusline.sh
414
+
415
+ Repaired: 1, Errors: 0, Skipped: 18
416
+
417
+ ═══════════════════════════════════════════════════════
418
+ šŸ”“ RESTART CLAUDE CODE NOW!
419
+ Quit completely, wait 5 seconds, restart
420
+ ═══════════════════════════════════════════════════════
421
+ ```
422
+
423
+ ### When to Use Each Command
424
+
425
+ | Scenario | Command |
426
+ |----------|---------|
427
+ | Accidentally deleted a script | `--repair` |
428
+ | Want to see what's installed | `--list-scripts` |
429
+ | Check if update is available | `--version` |
430
+ | Scripts outdated (feature version differs) | `--upgrade` |
431
+ | Settings format broken | `--migrate` |
432
+ | Major corruption/reinstall needed | `npx agileflow update --force`