agileflow 2.71.0 → 2.73.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.71.0",
3
+ "version": "2.73.0",
4
4
  "description": "AI-driven agile development system for Claude Code, Cursor, Windsurf, and more",
5
5
  "keywords": [
6
6
  "agile",
@@ -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
@@ -93,19 +93,19 @@ const PROFILES = {
93
93
  full: {
94
94
  description: 'All features enabled',
95
95
  enable: ['sessionstart', 'precompact', 'archival', 'statusline'],
96
- archivalDays: 7,
96
+ archivalDays: 30,
97
97
  },
98
98
  basic: {
99
99
  description: 'Essential hooks + archival (SessionStart + PreCompact + Archival)',
100
100
  enable: ['sessionstart', 'precompact', 'archival'],
101
101
  disable: ['statusline'],
102
- archivalDays: 7,
102
+ archivalDays: 30,
103
103
  },
104
104
  minimal: {
105
105
  description: 'SessionStart + archival only',
106
106
  enable: ['sessionstart', 'archival'],
107
107
  disable: ['precompact', 'statusline'],
108
- archivalDays: 7,
108
+ archivalDays: 30,
109
109
  },
110
110
  none: {
111
111
  description: 'Disable all AgileFlow features',
@@ -155,22 +155,16 @@ const writeJSON = (filePath, data) => {
155
155
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
156
156
  };
157
157
 
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;
158
+ // Scripts are located in .agileflow/scripts/ (installed by AgileFlow)
159
+ const SCRIPTS_DIR = path.join(process.cwd(), '.agileflow', 'scripts');
160
+
161
+ const scriptExists = scriptName => {
162
+ const scriptPath = path.join(SCRIPTS_DIR, scriptName);
163
+ return fs.existsSync(scriptPath);
164
+ };
165
+
166
+ const getScriptPath = scriptName => {
167
+ return `.agileflow/scripts/${scriptName}`;
174
168
  };
175
169
 
176
170
  // ============================================================================
@@ -184,12 +178,14 @@ function detectConfig() {
184
178
  settingsValid: true,
185
179
  settingsIssues: [],
186
180
  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: [] },
181
+ sessionstart: { enabled: false, valid: true, issues: [], version: null, outdated: false },
182
+ precompact: { enabled: false, valid: true, issues: [], version: null, outdated: false },
183
+ archival: { enabled: false, threshold: null, version: null, outdated: false },
184
+ statusline: { enabled: false, valid: true, issues: [], version: null, outdated: false },
191
185
  },
192
186
  metadata: { exists: false, version: null },
187
+ currentVersion: VERSION,
188
+ hasOutdated: false,
193
189
  };
194
190
 
195
191
  // Git
@@ -280,6 +276,20 @@ function detectConfig() {
280
276
  status.features.archival.enabled = true;
281
277
  status.features.archival.threshold = meta.archival.threshold_days;
282
278
  }
279
+
280
+ // Read feature versions from metadata and check if outdated
281
+ if (meta.features) {
282
+ Object.entries(meta.features).forEach(([feature, data]) => {
283
+ if (status.features[feature] && data.version) {
284
+ status.features[feature].version = data.version;
285
+ // Check if feature version differs from current VERSION
286
+ if (data.version !== VERSION && status.features[feature].enabled) {
287
+ status.features[feature].outdated = true;
288
+ status.hasOutdated = true;
289
+ }
290
+ }
291
+ });
292
+ }
283
293
  }
284
294
  }
285
295
 
@@ -317,6 +327,10 @@ function printStatus(status) {
317
327
  statusIcon = '⚠️';
318
328
  statusText = 'INVALID FORMAT';
319
329
  color = c.yellow;
330
+ } else if (f.enabled && f.outdated) {
331
+ statusIcon = '🔄';
332
+ statusText = `outdated (v${f.version} → v${status.currentVersion})`;
333
+ color = c.yellow;
320
334
  }
321
335
 
322
336
  log(` ${statusIcon} ${label}: ${statusText}`, color);
@@ -348,7 +362,11 @@ function printStatus(status) {
348
362
  log('\n⚠️ Format issues detected! Run with --migrate to fix.', c.yellow);
349
363
  }
350
364
 
351
- return hasIssues;
365
+ if (status.hasOutdated) {
366
+ log('\n🔄 Outdated scripts detected! Run with --upgrade to update.', c.yellow);
367
+ }
368
+
369
+ return { hasIssues, hasOutdated: status.hasOutdated };
352
370
  }
353
371
 
354
372
  // ============================================================================
@@ -454,6 +472,34 @@ function migrateSettings() {
454
472
  return migrated;
455
473
  }
456
474
 
475
+ // ============================================================================
476
+ // UPGRADE FEATURES
477
+ // ============================================================================
478
+
479
+ function upgradeFeatures(status) {
480
+ header('🔄 Upgrading Outdated Features...');
481
+
482
+ let upgraded = 0;
483
+
484
+ Object.entries(status.features).forEach(([feature, data]) => {
485
+ if (data.enabled && data.outdated) {
486
+ log(`\nUpgrading ${feature}...`, c.cyan);
487
+ // Re-enable the feature to deploy latest scripts
488
+ if (enableFeature(feature, { archivalDays: data.threshold || 30, isUpgrade: true })) {
489
+ upgraded++;
490
+ }
491
+ }
492
+ });
493
+
494
+ if (upgraded === 0) {
495
+ info('No features needed upgrading');
496
+ } else {
497
+ success(`Upgraded ${upgraded} feature(s) to v${VERSION}`);
498
+ }
499
+
500
+ return upgraded > 0;
501
+ }
502
+
457
503
  // ============================================================================
458
504
  // ENABLE/DISABLE FEATURES
459
505
  // ============================================================================
@@ -466,7 +512,6 @@ function enableFeature(feature, options = {}) {
466
512
  }
467
513
 
468
514
  ensureDir('.claude');
469
- ensureDir('scripts');
470
515
 
471
516
  const settings = readJSON('.claude/settings.json') || {};
472
517
  settings.hooks = settings.hooks || {};
@@ -474,25 +519,13 @@ function enableFeature(feature, options = {}) {
474
519
 
475
520
  // Handle hook-based features
476
521
  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}`);
522
+ const scriptPath = getScriptPath(config.script);
523
+
524
+ // Verify script exists
525
+ if (!scriptExists(config.script)) {
526
+ error(`Script not found: ${scriptPath}`);
527
+ info('Run "npx agileflow update" to reinstall scripts');
528
+ return false;
496
529
  }
497
530
 
498
531
  // Configure hook
@@ -504,18 +537,18 @@ function enableFeature(feature, options = {}) {
504
537
  hooks: [{ type: 'command', command }],
505
538
  },
506
539
  ];
507
- success(`${config.hook} hook enabled`);
540
+ success(`${config.hook} hook enabled (${config.script})`);
508
541
  }
509
542
 
510
543
  // Handle archival
511
544
  if (feature === 'archival') {
512
- const days = options.archivalDays || 7;
513
- const scriptPath = 'scripts/archive-completed-stories.sh';
545
+ const days = options.archivalDays || 30;
546
+ const scriptPath = getScriptPath('archive-completed-stories.sh');
514
547
 
515
- if (!copyTemplate('archive-completed-stories.sh', scriptPath)) {
516
- warn('Archival script template not found');
517
- } else {
518
- success('Deployed archive-completed-stories.sh');
548
+ if (!scriptExists('archive-completed-stories.sh')) {
549
+ error(`Script not found: ${scriptPath}`);
550
+ info('Run "npx agileflow update" to reinstall scripts');
551
+ return false;
519
552
  }
520
553
 
521
554
  // Add to SessionStart hook
@@ -526,7 +559,7 @@ function enableFeature(feature, options = {}) {
526
559
  if (!hasArchival) {
527
560
  settings.hooks.SessionStart[0].hooks.push({
528
561
  type: 'command',
529
- command: 'bash scripts/archive-completed-stories.sh --quiet',
562
+ command: `bash ${scriptPath} --quiet`,
530
563
  });
531
564
  }
532
565
  }
@@ -538,28 +571,17 @@ function enableFeature(feature, options = {}) {
538
571
 
539
572
  // Handle statusLine
540
573
  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');
574
+ const scriptPath = getScriptPath('agileflow-statusline.sh');
575
+
576
+ if (!scriptExists('agileflow-statusline.sh')) {
577
+ error(`Script not found: ${scriptPath}`);
578
+ info('Run "npx agileflow update" to reinstall scripts');
579
+ return false;
558
580
  }
559
581
 
560
582
  settings.statusLine = {
561
583
  type: 'command',
562
- command: 'bash scripts/agileflow-statusline.sh',
584
+ command: `bash ${scriptPath}`,
563
585
  padding: 0,
564
586
  };
565
587
  success('Status line enabled');
@@ -855,7 +877,7 @@ function printHelp() {
855
877
  ${c.bold}AgileFlow Configure${c.reset} - Manage AgileFlow features
856
878
 
857
879
  ${c.cyan}Usage:${c.reset}
858
- node scripts/agileflow-configure.js [options]
880
+ node .agileflow/scripts/agileflow-configure.js [options]
859
881
 
860
882
  ${c.cyan}Profiles:${c.reset}
861
883
  --profile=full All features (hooks, archival, statusline)
@@ -877,37 +899,41 @@ ${c.cyan}Statusline Components:${c.reset}
877
899
  Components: agileflow, model, story, epic, wip, context, cost, git
878
900
 
879
901
  ${c.cyan}Settings:${c.reset}
880
- --archival-days=N Set archival threshold (default: 7)
902
+ --archival-days=N Set archival threshold (default: 30)
881
903
 
882
904
  ${c.cyan}Maintenance:${c.reset}
883
905
  --migrate Fix old/invalid formats
906
+ --upgrade Re-deploy all enabled features with latest scripts
884
907
  --validate Check for issues (same as --detect)
885
908
  --detect Show current configuration
886
909
 
887
910
  ${c.cyan}Examples:${c.reset}
888
911
  # Quick setup with all features
889
- node scripts/agileflow-configure.js --profile=full
912
+ node .agileflow/scripts/agileflow-configure.js --profile=full
890
913
 
891
914
  # Enable specific features
892
- node scripts/agileflow-configure.js --enable=sessionstart,precompact,archival
915
+ node .agileflow/scripts/agileflow-configure.js --enable=sessionstart,precompact,archival
893
916
 
894
917
  # Disable a feature
895
- node scripts/agileflow-configure.js --disable=statusline
918
+ node .agileflow/scripts/agileflow-configure.js --disable=statusline
896
919
 
897
920
  # Show only agileflow branding and context in statusline
898
- node scripts/agileflow-configure.js --hide=model,story,epic,wip,cost,git
921
+ node .agileflow/scripts/agileflow-configure.js --hide=model,story,epic,wip,cost,git
899
922
 
900
923
  # Re-enable git branch in statusline
901
- node scripts/agileflow-configure.js --show=git
924
+ node .agileflow/scripts/agileflow-configure.js --show=git
902
925
 
903
926
  # List component status
904
- node scripts/agileflow-configure.js --components
927
+ node .agileflow/scripts/agileflow-configure.js --components
905
928
 
906
929
  # Fix format issues
907
- node scripts/agileflow-configure.js --migrate
930
+ node .agileflow/scripts/agileflow-configure.js --migrate
908
931
 
909
932
  # Check current status
910
- node scripts/agileflow-configure.js --detect
933
+ node .agileflow/scripts/agileflow-configure.js --detect
934
+
935
+ # Upgrade outdated scripts to latest version
936
+ node .agileflow/scripts/agileflow-configure.js --upgrade
911
937
  `);
912
938
  }
913
939
 
@@ -924,9 +950,10 @@ function main() {
924
950
  let disable = [];
925
951
  let show = [];
926
952
  let hide = [];
927
- let archivalDays = 7;
953
+ let archivalDays = 30;
928
954
  let migrate = false;
929
955
  let detect = false;
956
+ let upgrade = false;
930
957
  let components = false;
931
958
  let help = false;
932
959
 
@@ -952,9 +979,10 @@ function main() {
952
979
  .split('=')[1]
953
980
  .split(',')
954
981
  .map(s => s.trim().toLowerCase());
955
- else if (arg.startsWith('--archival-days=')) archivalDays = parseInt(arg.split('=')[1]) || 7;
982
+ else if (arg.startsWith('--archival-days=')) archivalDays = parseInt(arg.split('=')[1]) || 30;
956
983
  else if (arg === '--migrate') migrate = true;
957
984
  else if (arg === '--detect' || arg === '--validate') detect = true;
985
+ else if (arg === '--upgrade') upgrade = true;
958
986
  else if (arg === '--components') components = true;
959
987
  else if (arg === '--help' || arg === '-h') help = true;
960
988
  });
@@ -979,10 +1007,16 @@ function main() {
979
1007
 
980
1008
  // Always detect first
981
1009
  const status = detectConfig();
982
- const hasIssues = printStatus(status);
1010
+ const { hasIssues, hasOutdated } = printStatus(status);
983
1011
 
984
1012
  // Detect only mode
985
- if (detect && !migrate && !profile && enable.length === 0 && disable.length === 0) {
1013
+ if (detect && !migrate && !upgrade && !profile && enable.length === 0 && disable.length === 0) {
1014
+ return;
1015
+ }
1016
+
1017
+ // Upgrade mode
1018
+ if (upgrade) {
1019
+ upgradeFeatures(status);
986
1020
  return;
987
1021
  }
988
1022
 
@@ -36,9 +36,9 @@ ROLE: Auto-Archival Configurator
36
36
  "header": "Threshold",
37
37
  "multiSelect": false,
38
38
  "options": [
39
- {"label": "7 days (Recommended)", "description": "Archive after 1 week"},
39
+ {"label": "30 days (Recommended)", "description": "Archive after 1 month"},
40
40
  {"label": "14 days", "description": "Archive after 2 weeks"},
41
- {"label": "30 days", "description": "Archive after 1 month"}
41
+ {"label": "7 days", "description": "Archive after 1 week"}
42
42
  ]
43
43
  }]</parameter>
44
44
  </invoke>
@@ -71,20 +71,20 @@ Use AskUserQuestion tool to get user preference:
71
71
  "multiSelect": false,
72
72
  "options": [
73
73
  {
74
- "label": "3 days",
75
- "description": "Very aggressive - keeps status.json very small (best for large teams)"
74
+ "label": "30 days (Recommended)",
75
+ "description": "Monthly archival - default, keeps recent context visible"
76
76
  },
77
77
  {
78
- "label": "7 days",
79
- "description": "Weekly archival - recommended for fast-moving teams"
78
+ "label": "14 days",
79
+ "description": "Bi-weekly archival - good balance for fast-moving projects"
80
80
  },
81
81
  {
82
- "label": "14 days",
83
- "description": "Bi-weekly archival - good balance for most projects"
82
+ "label": "7 days",
83
+ "description": "Weekly archival - for large teams with many stories"
84
84
  },
85
85
  {
86
- "label": "30 days",
87
- "description": "Monthly archival - default, keeps recent context visible"
86
+ "label": "3 days",
87
+ "description": "Very aggressive - keeps status.json very small"
88
88
  }
89
89
  ]
90
90
  }]</parameter>
@@ -1,38 +1,43 @@
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]
3
+ argument-hint: [--profile=full|basic|minimal|none] [--enable/--disable=features] [--migrate] [--upgrade]
4
4
  ---
5
5
 
6
6
  <!-- COMPACT_SUMMARY_START -->
7
7
 
8
8
  ## Compact Summary
9
9
 
10
- Configuration management with **profiles**, **enable/disable**, and **format migration**.
10
+ Configuration management with **profiles**, **enable/disable**, **format migration**, and **upgrade detection**.
11
11
 
12
12
  ### Workflow (MUST FOLLOW)
13
13
 
14
14
  1. **Run detection**: `node .agileflow/scripts/agileflow-configure.js --detect`
15
15
  2. **If ⚠️ INVALID FORMAT shown**: Ask user to fix with `--migrate` BEFORE anything else
16
- 3. **Present options**: Profiles, enable/disable, or check status
16
+ 3. **If 🔄 OUTDATED shown**: Ask user to upgrade with `--upgrade`
17
+ 4. **Present options**: Profiles, enable/disable, or check status
17
18
 
18
19
  ### Quick Commands
19
20
 
20
21
  ```bash
21
- node .agileflow/scripts/agileflow-configure.js --detect # Check status
22
- node .agileflow/scripts/agileflow-configure.js --migrate # Fix format issues
23
- node .agileflow/scripts/agileflow-configure.js --profile=full # Enable all
24
- node .agileflow/scripts/agileflow-configure.js --profile=none # Disable all
25
- node .agileflow/scripts/agileflow-configure.js --enable=stop # Enable specific
26
- node .agileflow/scripts/agileflow-configure.js --disable=archival # Disable specific
22
+ node .agileflow/scripts/agileflow-configure.js --detect # Check status
23
+ node .agileflow/scripts/agileflow-configure.js --migrate # Fix format issues
24
+ node .agileflow/scripts/agileflow-configure.js --upgrade # Update outdated scripts
25
+ node .agileflow/scripts/agileflow-configure.js --profile=full # Enable all
26
+ node .agileflow/scripts/agileflow-configure.js --profile=none # Disable all
27
+ node .agileflow/scripts/agileflow-configure.js --enable=sessionstart # Enable specific
28
+ node .agileflow/scripts/agileflow-configure.js --disable=archival # Disable specific
27
29
  ```
28
30
 
31
+ **Note:** All scripts are located in `.agileflow/scripts/` - no files in project root `scripts/`.
32
+
29
33
  ### Features
30
34
 
31
- `sessionstart`, `precompact`, `stop`, `archival`, `statusline`, `autoupdate`
35
+ `sessionstart`, `precompact`, `archival`, `statusline`, `autoupdate`
32
36
 
33
37
  ### Critical Rules
34
38
 
35
39
  - **Check for format issues FIRST** - offer to fix before other options
40
+ - **Check for outdated scripts** - offer to upgrade if versions differ
36
41
  - **Backup created** on migrate: `.claude/settings.json.backup`
37
42
  - **Restart required** - always show red banner after changes
38
43
 
@@ -54,10 +59,9 @@ node .agileflow/scripts/agileflow-configure.js --detect
54
59
 
55
60
  **CRITICAL**: Check the output for format issues (⚠️ INVALID FORMAT).
56
61
 
57
- ## STEP 2: If Format Issues Detected Offer Migration FIRST
58
-
59
- If you see `⚠️ INVALID FORMAT` in the detection output, **immediately ask user about fixing**:
62
+ ## STEP 2: Handle Issues (Migration or Upgrade)
60
63
 
64
+ ### If ⚠️ INVALID FORMAT detected → Offer Migration
61
65
  ```xml
62
66
  <invoke name="AskUserQuestion">
63
67
  <parameter name="questions">[{
@@ -77,6 +81,26 @@ If user says yes:
77
81
  node .agileflow/scripts/agileflow-configure.js --migrate
78
82
  ```
79
83
 
84
+ ### If 🔄 OUTDATED detected → Offer Upgrade
85
+ ```xml
86
+ <invoke name="AskUserQuestion">
87
+ <parameter name="questions">[{
88
+ "question": "Outdated scripts detected! Your features were configured with an older AgileFlow version. Update them?",
89
+ "header": "Upgrade",
90
+ "multiSelect": false,
91
+ "options": [
92
+ {"label": "Yes, upgrade scripts (Recommended)", "description": "Re-deploy all enabled features with latest scripts."},
93
+ {"label": "No, keep current versions", "description": "Continue with older scripts (may miss bug fixes)."}
94
+ ]
95
+ }]</parameter>
96
+ </invoke>
97
+ ```
98
+
99
+ If user says yes:
100
+ ```bash
101
+ node .agileflow/scripts/agileflow-configure.js --upgrade
102
+ ```
103
+
80
104
  ## STEP 3: Configuration Options
81
105
 
82
106
  After fixing issues (or if no issues), present main options:
@@ -120,13 +144,13 @@ node .agileflow/scripts/agileflow-configure.js --profile=none
120
144
 
121
145
  ```bash
122
146
  # Enable features
123
- node .agileflow/scripts/agileflow-configure.js --enable=sessionstart,precompact,stop
147
+ node .agileflow/scripts/agileflow-configure.js --enable=sessionstart,precompact
124
148
 
125
149
  # Disable features
126
150
  node .agileflow/scripts/agileflow-configure.js --disable=statusline
127
151
 
128
152
  # Both at once
129
- node .agileflow/scripts/agileflow-configure.js --enable=stop --disable=archival
153
+ node .agileflow/scripts/agileflow-configure.js --enable=statusline --disable=archival
130
154
 
131
155
  # With custom archival days
132
156
  node .agileflow/scripts/agileflow-configure.js --enable=archival --archival-days=14
@@ -134,12 +158,12 @@ node .agileflow/scripts/agileflow-configure.js --enable=archival --archival-days
134
158
 
135
159
  ## Profile Details
136
160
 
137
- | Profile | SessionStart | PreCompact | Stop | Archival | StatusLine |
138
- |---------|-------------|------------|------|----------|------------|
139
- | `full` | ✅ | ✅ | ✅ | ✅ 7 days | ✅ |
140
- | `basic` | ✅ | ✅ | ❌ | 7 days | ❌ |
141
- | `minimal` | ✅ | ❌ | ❌ | 7 days | ❌ |
142
- | `none` | ❌ | ❌ | ❌ | ❌ | ❌ |
161
+ | Profile | SessionStart | PreCompact | Archival | StatusLine |
162
+ |---------|-------------|------------|----------|------------|
163
+ | `full` | ✅ | ✅ | ✅ 30 days | ✅ |
164
+ | `basic` | ✅ | ✅ | ✅ 30 days | ❌ |
165
+ | `minimal` | ✅ | ❌ | ✅ 30 days | ❌ |
166
+ | `none` | ❌ | ❌ | ❌ | ❌ |
143
167
 
144
168
  ## Interactive Mode (via /configure command)
145
169
 
@@ -176,7 +200,6 @@ Based on selection, run appropriate command.
176
200
  "options": [
177
201
  {"label": "SessionStart Hook", "description": "Welcome display with project status"},
178
202
  {"label": "PreCompact Hook", "description": "Context preservation on compact"},
179
- {"label": "Stop Hook", "description": "Warns about uncommitted git changes"},
180
203
  {"label": "Archival", "description": "Auto-archive old completed stories"},
181
204
  {"label": "Status Line", "description": "Custom status bar"},
182
205
  {"label": "Auto-Update", "description": "Automatically update AgileFlow on session start"}
@@ -188,7 +211,6 @@ Based on selection, run appropriate command.
188
211
  Map selections:
189
212
  - "SessionStart Hook" → `sessionstart`
190
213
  - "PreCompact Hook" → `precompact`
191
- - "Stop Hook" → `stop`
192
214
  - "Archival" → `archival`
193
215
  - "Status Line" → `statusline`
194
216
  - "Auto-Update" → `autoupdate`
@@ -243,18 +265,17 @@ The script updates `docs/00-meta/agileflow-metadata.json`:
243
265
 
244
266
  ```json
245
267
  {
246
- "version": "2.41.0",
247
- "updated": "2025-12-22T...",
268
+ "version": "2.71.0",
269
+ "updated": "2025-12-29T...",
248
270
  "archival": {
249
271
  "enabled": true,
250
272
  "threshold_days": 7
251
273
  },
252
274
  "features": {
253
- "sessionstart": {"enabled": true, "version": "2.41.0", "at": "..."},
254
- "precompact": {"enabled": true, "version": "2.41.0", "at": "..."},
255
- "stop": {"enabled": true, "version": "2.41.0", "at": "..."},
256
- "archival": {"enabled": true, "version": "2.41.0", "at": "..."},
257
- "statusline": {"enabled": true, "version": "2.41.0", "at": "..."}
275
+ "sessionstart": {"enabled": true, "version": "2.71.0", "at": "..."},
276
+ "precompact": {"enabled": true, "version": "2.71.0", "at": "..."},
277
+ "archival": {"enabled": true, "version": "2.71.0", "at": "..."},
278
+ "statusline": {"enabled": true, "version": "2.71.0", "at": "..."}
258
279
  }
259
280
  }
260
281
  ```
@@ -296,10 +317,9 @@ After configuration:
296
317
  Enabled:
297
318
  ✅ sessionstart
298
319
  ✅ precompact
299
- stop
320
+ archival
300
321
 
301
322
  Disabled:
302
- ❌ archival
303
323
  ❌ statusline
304
324
 
305
325
  ═══════════════════════════════════════════════════════
@@ -307,3 +327,19 @@ Disabled:
307
327
  Quit completely, wait 5 seconds, restart
308
328
  ═══════════════════════════════════════════════════════
309
329
  ```
330
+
331
+ After upgrade:
332
+
333
+ ```
334
+ 🔄 Upgrading Outdated Features...
335
+
336
+ Upgrading sessionstart...
337
+ ✅ Deployed agileflow-welcome.js
338
+ ✅ SessionStart hook enabled
339
+
340
+ Upgrading precompact...
341
+ ✅ Deployed precompact-context.sh
342
+ ✅ PreCompact hook enabled
343
+
344
+ ✅ Upgraded 2 feature(s) to v2.71.0
345
+ ```
@@ -46,11 +46,11 @@ class Installer {
46
46
 
47
47
  /**
48
48
  * Clean up existing content directories before installing.
49
- * Removes agents/, commands/, skills/, templates/ but preserves _cfg/ and config.yaml.
49
+ * Removes agents/, commands/, skills/, scripts/, templates/ but preserves _cfg/ and config.yaml.
50
50
  * @param {string} agileflowDir - AgileFlow installation directory
51
51
  */
52
52
  async cleanup(agileflowDir) {
53
- const dirsToRemove = ['agents', 'commands', 'skills', 'templates'];
53
+ const dirsToRemove = ['agents', 'commands', 'skills', 'scripts', 'templates'];
54
54
 
55
55
  for (const dir of dirsToRemove) {
56
56
  const dirPath = path.join(agileflowDir, dir);
@@ -243,14 +243,6 @@ class Installer {
243
243
  await fs.ensureDir(skillsDest);
244
244
  await this.copyContent(skillsSource, skillsDest, agileflowFolder, policy);
245
245
  }
246
-
247
- // Copy templates
248
- const templatesSource = path.join(packageRoot, 'templates');
249
- const templatesDest = path.join(agileflowDir, 'templates');
250
- if (await fs.pathExists(templatesSource)) {
251
- await fs.ensureDir(templatesDest);
252
- await this.copyContent(templatesSource, templatesDest, agileflowFolder, policy);
253
- }
254
246
  }
255
247
 
256
248
  /**
@@ -430,7 +422,7 @@ class Installer {
430
422
  const backupRoot = path.join(cfgDir, 'backups', timestamp);
431
423
  await fs.ensureDir(backupRoot);
432
424
 
433
- const candidates = ['agents', 'commands', 'skills', 'templates', 'config.yaml'];
425
+ const candidates = ['agents', 'commands', 'skills', 'scripts', 'templates', 'config.yaml'];
434
426
  for (const name of candidates) {
435
427
  const srcPath = path.join(agileflowDir, name);
436
428
  if (await fs.pathExists(srcPath)) {