agileflow 2.94.1 → 2.95.1

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +3 -3
  3. package/lib/colors.generated.js +117 -0
  4. package/lib/colors.js +59 -109
  5. package/lib/generator-factory.js +333 -0
  6. package/lib/path-utils.js +49 -0
  7. package/lib/session-registry.js +25 -15
  8. package/lib/smart-json-file.js +40 -32
  9. package/lib/state-machine.js +286 -0
  10. package/package.json +1 -1
  11. package/scripts/agileflow-configure.js +7 -6
  12. package/scripts/archive-completed-stories.sh +86 -11
  13. package/scripts/babysit-context-restore.js +89 -0
  14. package/scripts/claude-tmux.sh +111 -5
  15. package/scripts/damage-control/bash-tool-damage-control.js +11 -247
  16. package/scripts/damage-control/edit-tool-damage-control.js +9 -249
  17. package/scripts/damage-control/write-tool-damage-control.js +9 -244
  18. package/scripts/generate-colors.js +314 -0
  19. package/scripts/lib/colors.generated.sh +82 -0
  20. package/scripts/lib/colors.sh +10 -70
  21. package/scripts/lib/configure-features.js +401 -0
  22. package/scripts/lib/context-loader.js +181 -52
  23. package/scripts/precompact-context.sh +54 -17
  24. package/scripts/session-coordinator.sh +2 -2
  25. package/scripts/session-manager.js +653 -10
  26. package/src/core/commands/audit.md +93 -0
  27. package/src/core/commands/auto.md +73 -0
  28. package/src/core/commands/babysit.md +169 -13
  29. package/src/core/commands/baseline.md +73 -0
  30. package/src/core/commands/batch.md +64 -0
  31. package/src/core/commands/blockers.md +60 -0
  32. package/src/core/commands/board.md +66 -0
  33. package/src/core/commands/choose.md +77 -0
  34. package/src/core/commands/ci.md +77 -0
  35. package/src/core/commands/compress.md +27 -1
  36. package/src/core/commands/configure.md +126 -10
  37. package/src/core/commands/council.md +74 -0
  38. package/src/core/commands/debt.md +72 -0
  39. package/src/core/commands/deploy.md +73 -0
  40. package/src/core/commands/deps.md +68 -0
  41. package/src/core/commands/docs.md +60 -0
  42. package/src/core/commands/feedback.md +68 -0
  43. package/src/core/commands/ideate.md +74 -0
  44. package/src/core/commands/impact.md +74 -0
  45. package/src/core/commands/install.md +529 -0
  46. package/src/core/commands/maintain.md +558 -0
  47. package/src/core/commands/metrics.md +75 -0
  48. package/src/core/commands/multi-expert.md +74 -0
  49. package/src/core/commands/packages.md +69 -0
  50. package/src/core/commands/readme-sync.md +64 -0
  51. package/src/core/commands/research/analyze.md +285 -121
  52. package/src/core/commands/research/import.md +281 -109
  53. package/src/core/commands/retro.md +76 -0
  54. package/src/core/commands/review.md +72 -0
  55. package/src/core/commands/rlm.md +83 -0
  56. package/src/core/commands/rpi.md +90 -0
  57. package/src/core/commands/session/cleanup.md +214 -12
  58. package/src/core/commands/session/end.md +155 -17
  59. package/src/core/commands/sprint.md +72 -0
  60. package/src/core/commands/story-validate.md +68 -0
  61. package/src/core/commands/template.md +69 -0
  62. package/src/core/commands/tests.md +83 -0
  63. package/src/core/commands/update.md +59 -0
  64. package/src/core/commands/validate-expertise.md +76 -0
  65. package/src/core/commands/velocity.md +74 -0
  66. package/src/core/commands/verify.md +91 -0
  67. package/src/core/commands/whats-new.md +69 -0
  68. package/src/core/commands/workflow.md +88 -0
  69. package/src/core/templates/command-documentation.md +187 -0
  70. package/tools/cli/commands/session.js +1171 -0
  71. package/tools/cli/commands/setup.js +2 -81
  72. package/tools/cli/installers/core/installer.js +0 -5
  73. package/tools/cli/installers/ide/claude-code.js +6 -0
  74. package/tools/cli/lib/config-manager.js +42 -5
@@ -31,6 +31,7 @@
31
31
  const fs = require('fs');
32
32
  const path = require('path');
33
33
  const { createTypedError, getErrorCodeFromError, ErrorCodes } = require('./error-codes');
34
+ const { success, failure, failureFromError } = require('./result-schema');
34
35
 
35
36
  // Debug logging
36
37
  const DEBUG = process.env.AGILEFLOW_DEBUG === '1';
@@ -54,7 +55,7 @@ const SECURE_FILE_MODE = 0o600;
54
55
  function checkFilePermissions(mode) {
55
56
  // Skip permission checks on Windows (different permission model)
56
57
  if (process.platform === 'win32') {
57
- return { ok: true };
58
+ return success(undefined);
58
59
  }
59
60
 
60
61
  // Extract permission bits (last 9 bits)
@@ -106,7 +107,7 @@ function checkFilePermissions(mode) {
106
107
  };
107
108
  }
108
109
 
109
- return { ok: true };
110
+ return success(undefined);
110
111
  }
111
112
 
112
113
  /**
@@ -117,13 +118,13 @@ function checkFilePermissions(mode) {
117
118
  function setSecurePermissions(filePath) {
118
119
  // Skip on Windows
119
120
  if (process.platform === 'win32') {
120
- return { ok: true };
121
+ return success(undefined);
121
122
  }
122
123
 
123
124
  try {
124
125
  fs.chmodSync(filePath, SECURE_FILE_MODE);
125
126
  debugLog('setSecurePermissions', { filePath, mode: SECURE_FILE_MODE.toString(8) });
126
- return { ok: true };
127
+ return success(undefined);
127
128
  } catch (err) {
128
129
  const error = createTypedError(
129
130
  `Failed to set secure permissions on ${filePath}: ${err.message}`,
@@ -133,7 +134,7 @@ function setSecurePermissions(filePath) {
133
134
  context: { filePath, mode: SECURE_FILE_MODE },
134
135
  }
135
136
  );
136
- return { ok: false, error };
137
+ return failureFromError(error);
137
138
  }
138
139
  }
139
140
 
@@ -221,12 +222,12 @@ class SmartJsonFile {
221
222
  if (!fs.existsSync(this.filePath)) {
222
223
  if (this.defaultValue !== undefined) {
223
224
  debugLog('read', { status: 'using default value' });
224
- return { ok: true, data: this.defaultValue };
225
+ return success(this.defaultValue);
225
226
  }
226
227
  const error = createTypedError(`File not found: ${this.filePath}`, 'ENOENT', {
227
228
  context: { filePath: this.filePath },
228
229
  });
229
- return { ok: false, error };
230
+ return failureFromError(error);
230
231
  }
231
232
 
232
233
  // Read file
@@ -257,7 +258,7 @@ class SmartJsonFile {
257
258
  'EPARSE',
258
259
  { cause: parseError, context: { filePath: this.filePath } }
259
260
  );
260
- return { ok: false, error };
261
+ return failureFromError(error);
261
262
  }
262
263
 
263
264
  // Validate schema if provided
@@ -270,12 +271,12 @@ class SmartJsonFile {
270
271
  'ESCHEMA',
271
272
  { cause: schemaError, context: { filePath: this.filePath } }
272
273
  );
273
- return { ok: false, error };
274
+ return failureFromError(error);
274
275
  }
275
276
  }
276
277
 
277
278
  debugLog('read', { status: 'success' });
278
- return { ok: true, data };
279
+ return success(data);
279
280
  } catch (err) {
280
281
  lastError = err;
281
282
  debugLog('read', { status: 'error', error: err.message, attempt });
@@ -288,7 +289,7 @@ class SmartJsonFile {
288
289
  cause: err,
289
290
  context: { filePath: this.filePath },
290
291
  });
291
- return { ok: false, error };
292
+ return failureFromError(error);
292
293
  }
293
294
 
294
295
  // Wait before retrying
@@ -308,7 +309,7 @@ class SmartJsonFile {
308
309
  'EUNKNOWN',
309
310
  { cause: lastError, context: { filePath: this.filePath, attempts: this.retries + 1 } }
310
311
  );
311
- return { ok: false, error };
312
+ return failureFromError(error);
312
313
  }
313
314
 
314
315
  /**
@@ -330,7 +331,7 @@ class SmartJsonFile {
330
331
  'ESCHEMA',
331
332
  { cause: schemaError, context: { filePath: this.filePath } }
332
333
  );
333
- return { ok: false, error };
334
+ return failureFromError(error);
334
335
  }
335
336
  }
336
337
 
@@ -368,7 +369,7 @@ class SmartJsonFile {
368
369
 
369
370
  debugLog('write', { status: 'success' });
370
371
 
371
- return { ok: true };
372
+ return success(undefined);
372
373
  } catch (err) {
373
374
  lastError = err;
374
375
  debugLog('write', { status: 'error', error: err.message, attempt });
@@ -394,7 +395,7 @@ class SmartJsonFile {
394
395
  errorCode.code,
395
396
  { cause: err, context: { filePath: this.filePath } }
396
397
  );
397
- return { ok: false, error };
398
+ return failureFromError(error);
398
399
  }
399
400
 
400
401
  // Wait before retrying
@@ -414,7 +415,7 @@ class SmartJsonFile {
414
415
  'EUNKNOWN',
415
416
  { cause: lastError, context: { filePath: this.filePath, attempts: this.retries + 1 } }
416
417
  );
417
- return { ok: false, error };
418
+ return failureFromError(error);
418
419
  }
419
420
 
420
421
  /**
@@ -447,7 +448,7 @@ class SmartJsonFile {
447
448
  cause: modifyError,
448
449
  context: { filePath: this.filePath },
449
450
  });
450
- return { ok: false, error };
451
+ return failureFromError(error);
451
452
  }
452
453
 
453
454
  // Write modified data
@@ -456,7 +457,7 @@ class SmartJsonFile {
456
457
  return writeResult;
457
458
  }
458
459
 
459
- return { ok: true, data: newData };
460
+ return success(newData);
460
461
  }
461
462
 
462
463
  /**
@@ -474,12 +475,12 @@ class SmartJsonFile {
474
475
  async delete() {
475
476
  try {
476
477
  if (!fs.existsSync(this.filePath)) {
477
- return { ok: true }; // Already doesn't exist
478
+ return success(undefined); // Already doesn't exist
478
479
  }
479
480
 
480
481
  fs.unlinkSync(this.filePath);
481
482
  debugLog('delete', { filePath: this.filePath, status: 'success' });
482
- return { ok: true };
483
+ return success(undefined);
483
484
  } catch (err) {
484
485
  const errorCode = getErrorCodeFromError(err);
485
486
  const error = createTypedError(
@@ -487,7 +488,7 @@ class SmartJsonFile {
487
488
  errorCode.code,
488
489
  { cause: err, context: { filePath: this.filePath } }
489
490
  );
490
- return { ok: false, error };
491
+ return failureFromError(error);
491
492
  }
492
493
  }
493
494
 
@@ -499,12 +500,12 @@ class SmartJsonFile {
499
500
  try {
500
501
  if (!fs.existsSync(this.filePath)) {
501
502
  if (this.defaultValue !== undefined) {
502
- return { ok: true, data: this.defaultValue };
503
+ return success(this.defaultValue);
503
504
  }
504
505
  const error = createTypedError(`File not found: ${this.filePath}`, 'ENOENT', {
505
506
  context: { filePath: this.filePath },
506
507
  });
507
- return { ok: false, error };
508
+ return failureFromError(error);
508
509
  }
509
510
 
510
511
  const content = fs.readFileSync(this.filePath, 'utf8');
@@ -514,7 +515,7 @@ class SmartJsonFile {
514
515
  this.schema(data);
515
516
  }
516
517
 
517
- return { ok: true, data };
518
+ return success(data);
518
519
  } catch (err) {
519
520
  const errorCode = getErrorCodeFromError(err);
520
521
  const error = createTypedError(
@@ -522,7 +523,7 @@ class SmartJsonFile {
522
523
  errorCode.code,
523
524
  { cause: err, context: { filePath: this.filePath } }
524
525
  );
525
- return { ok: false, error };
526
+ return failureFromError(error);
526
527
  }
527
528
  }
528
529
 
@@ -559,7 +560,7 @@ class SmartJsonFile {
559
560
  }
560
561
  }
561
562
 
562
- return { ok: true };
563
+ return success(undefined);
563
564
  } catch (err) {
564
565
  // Clean up temp file
565
566
  try {
@@ -576,7 +577,7 @@ class SmartJsonFile {
576
577
  errorCode.code,
577
578
  { cause: err, context: { filePath: this.filePath } }
578
579
  );
579
- return { ok: false, error };
580
+ return failureFromError(error);
580
581
  }
581
582
  }
582
583
  }
@@ -594,7 +595,7 @@ const DEFAULT_TEMP_MAX_AGE_MS = 24 * 60 * 60 * 1000;
594
595
  * @param {Object} [options={}] - Cleanup options
595
596
  * @param {number} [options.maxAgeMs=86400000] - Max age in ms (default: 24 hours)
596
597
  * @param {boolean} [options.dryRun=false] - Don't delete, just report
597
- * @returns {{ok: boolean, cleaned: string[], errors: string[]}}
598
+ * @returns {Result<{cleaned: string[], errors: string[]}>}
598
599
  */
599
600
  function cleanupTempFiles(directory, options = {}) {
600
601
  const { maxAgeMs = DEFAULT_TEMP_MAX_AGE_MS, dryRun = false } = options;
@@ -604,7 +605,7 @@ function cleanupTempFiles(directory, options = {}) {
604
605
 
605
606
  try {
606
607
  if (!fs.existsSync(directory)) {
607
- return { ok: true, cleaned, errors };
608
+ return success({ cleaned, errors });
608
609
  }
609
610
 
610
611
  const now = Date.now();
@@ -646,10 +647,17 @@ function cleanupTempFiles(directory, options = {}) {
646
647
  }
647
648
  }
648
649
 
649
- return { ok: errors.length === 0, cleaned, errors };
650
+ if (errors.length > 0) {
651
+ return failure('EUNKNOWN', 'Some temp files could not be cleaned', {
652
+ context: { cleaned, errors },
653
+ });
654
+ }
655
+ return success({ cleaned, errors });
650
656
  } catch (err) {
651
657
  errors.push(`Directory read error: ${err.message}`);
652
- return { ok: false, cleaned, errors };
658
+ return failure('EUNKNOWN', `Directory read error: ${err.message}`, {
659
+ context: { cleaned, errors },
660
+ });
653
661
  }
654
662
  }
655
663
 
@@ -658,7 +666,7 @@ function cleanupTempFiles(directory, options = {}) {
658
666
  *
659
667
  * @param {string} filePath - Path to the JSON file
660
668
  * @param {Object} [options={}] - Cleanup options
661
- * @returns {{ok: boolean, cleaned: string[], errors: string[]}}
669
+ * @returns {Result<{cleaned: string[], errors: string[]}>}
662
670
  */
663
671
  function cleanupTempFilesFor(filePath, options = {}) {
664
672
  const directory = path.dirname(filePath);
@@ -0,0 +1,286 @@
1
+ /**
2
+ * state-machine.js - Generic State Machine Base Class
3
+ *
4
+ * Provides a reusable state machine pattern for:
5
+ * - Story status transitions (ready → in_progress → completed)
6
+ * - Session thread type transitions (base → parallel → fusion)
7
+ *
8
+ * Features:
9
+ * - Configurable states and transitions
10
+ * - Transition validation with clear error messages
11
+ * - Audit trail support
12
+ * - Force mode for admin overrides
13
+ *
14
+ * Usage:
15
+ * const { StateMachine } = require('./state-machine');
16
+ *
17
+ * const storyMachine = new StateMachine({
18
+ * states: ['ready', 'in_progress', 'completed'],
19
+ * transitions: {
20
+ * ready: ['in_progress'],
21
+ * in_progress: ['completed', 'ready'],
22
+ * completed: [],
23
+ * },
24
+ * initial: 'ready',
25
+ * });
26
+ *
27
+ * const result = storyMachine.transition('ready', 'in_progress');
28
+ * // { success: true, from: 'ready', to: 'in_progress' }
29
+ */
30
+
31
+ /**
32
+ * Generic State Machine
33
+ */
34
+ class StateMachine {
35
+ /**
36
+ * @param {Object} config - State machine configuration
37
+ * @param {string[]} config.states - Valid state values
38
+ * @param {Object<string, string[]>} config.transitions - Map of state -> allowed next states
39
+ * @param {string} [config.initial] - Initial state (first in states array if not specified)
40
+ * @param {string} [config.name='state'] - Name for error messages (e.g., 'status', 'thread_type')
41
+ */
42
+ constructor(config) {
43
+ if (!config.states || !Array.isArray(config.states) || config.states.length === 0) {
44
+ throw new Error('StateMachine requires non-empty states array');
45
+ }
46
+ if (!config.transitions || typeof config.transitions !== 'object') {
47
+ throw new Error('StateMachine requires transitions object');
48
+ }
49
+
50
+ this.states = config.states;
51
+ this.transitions = config.transitions;
52
+ this.initial = config.initial || config.states[0];
53
+ this.name = config.name || 'state';
54
+
55
+ // Validate that all transition targets are valid states
56
+ for (const [from, targets] of Object.entries(this.transitions)) {
57
+ if (!this.states.includes(from)) {
58
+ throw new Error(`Invalid transition source state: ${from}`);
59
+ }
60
+ for (const to of targets) {
61
+ if (!this.states.includes(to)) {
62
+ throw new Error(`Invalid transition target state: ${to} (from ${from})`);
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Check if a state is valid
70
+ * @param {string} state - State to check
71
+ * @returns {boolean}
72
+ */
73
+ isValidState(state) {
74
+ return this.states.includes(state);
75
+ }
76
+
77
+ /**
78
+ * Check if a transition is valid
79
+ * @param {string} from - Current state
80
+ * @param {string} to - Target state
81
+ * @returns {boolean}
82
+ */
83
+ isValidTransition(from, to) {
84
+ // Same state is always valid (no-op)
85
+ if (from === to) {
86
+ return true;
87
+ }
88
+
89
+ // Check if from state has defined transitions
90
+ const allowed = this.transitions[from];
91
+ if (!allowed) {
92
+ return false;
93
+ }
94
+
95
+ return allowed.includes(to);
96
+ }
97
+
98
+ /**
99
+ * Get valid transitions from a state
100
+ * @param {string} from - Current state
101
+ * @returns {string[]}
102
+ */
103
+ getValidTransitions(from) {
104
+ return this.transitions[from] || [];
105
+ }
106
+
107
+ /**
108
+ * Validate and perform a transition
109
+ * @param {string} from - Current state
110
+ * @param {string} to - Target state
111
+ * @param {Object} [options={}] - Transition options
112
+ * @param {boolean} [options.force=false] - Force transition even if invalid
113
+ * @returns {{success: boolean, from: string, to: string, error?: string, forced?: boolean}}
114
+ */
115
+ transition(from, to, options = {}) {
116
+ const { force = false } = options;
117
+
118
+ // Validate target state
119
+ if (!this.isValidState(to)) {
120
+ return {
121
+ success: false,
122
+ from,
123
+ to,
124
+ error: `Invalid ${this.name}: "${to}". Valid values: ${this.states.join(', ')}`,
125
+ };
126
+ }
127
+
128
+ // Validate source state
129
+ if (!this.isValidState(from)) {
130
+ return {
131
+ success: false,
132
+ from,
133
+ to,
134
+ error: `Invalid source ${this.name}: "${from}". Valid values: ${this.states.join(', ')}`,
135
+ };
136
+ }
137
+
138
+ // Same state is a no-op
139
+ if (from === to) {
140
+ return {
141
+ success: true,
142
+ from,
143
+ to,
144
+ noop: true,
145
+ };
146
+ }
147
+
148
+ // Check transition validity
149
+ if (!force && !this.isValidTransition(from, to)) {
150
+ const validTargets = this.getValidTransitions(from);
151
+ return {
152
+ success: false,
153
+ from,
154
+ to,
155
+ error: `Invalid transition: ${from} → ${to}. Valid transitions from "${from}": ${validTargets.join(', ') || 'none'}`,
156
+ };
157
+ }
158
+
159
+ return {
160
+ success: true,
161
+ from,
162
+ to,
163
+ forced: force && !this.isValidTransition(from, to),
164
+ };
165
+ }
166
+
167
+ /**
168
+ * Get the initial state
169
+ * @returns {string}
170
+ */
171
+ getInitialState() {
172
+ return this.initial;
173
+ }
174
+
175
+ /**
176
+ * Get all valid states
177
+ * @returns {string[]}
178
+ */
179
+ getStates() {
180
+ return [...this.states];
181
+ }
182
+
183
+ /**
184
+ * Get all transitions as a map
185
+ * @returns {Object<string, string[]>}
186
+ */
187
+ getTransitionsMap() {
188
+ return { ...this.transitions };
189
+ }
190
+
191
+ /**
192
+ * Generate a Mermaid state diagram
193
+ * @returns {string}
194
+ */
195
+ toMermaidDiagram() {
196
+ const lines = ['stateDiagram-v2'];
197
+
198
+ // Add initial state arrow
199
+ lines.push(` [*] --> ${this.initial}`);
200
+
201
+ // Add transitions
202
+ for (const [from, targets] of Object.entries(this.transitions)) {
203
+ for (const to of targets) {
204
+ lines.push(` ${from} --> ${to}`);
205
+ }
206
+ // Mark terminal states
207
+ if (targets.length === 0) {
208
+ lines.push(` ${from} --> [*]`);
209
+ }
210
+ }
211
+
212
+ return lines.join('\n');
213
+ }
214
+ }
215
+
216
+ // ============================================================================
217
+ // Pre-configured State Machines
218
+ // ============================================================================
219
+
220
+ /**
221
+ * Story status state machine
222
+ *
223
+ * States: ready, in_progress, in_review, blocked, completed, archived
224
+ *
225
+ * Transitions:
226
+ * - ready → in_progress, blocked
227
+ * - in_progress → in_review, blocked, ready
228
+ * - in_review → completed, in_progress, blocked
229
+ * - blocked → ready, in_progress, in_review
230
+ * - completed → archived, in_progress (reopened)
231
+ * - archived → (terminal)
232
+ */
233
+ const storyStatusMachine = new StateMachine({
234
+ name: 'status',
235
+ states: ['ready', 'in_progress', 'in_review', 'blocked', 'completed', 'archived'],
236
+ transitions: {
237
+ ready: ['in_progress', 'blocked'],
238
+ in_progress: ['in_review', 'blocked', 'ready'],
239
+ in_review: ['completed', 'in_progress', 'blocked'],
240
+ blocked: ['ready', 'in_progress', 'in_review'],
241
+ completed: ['archived', 'in_progress'],
242
+ archived: [], // Terminal state
243
+ },
244
+ initial: 'ready',
245
+ });
246
+
247
+ /**
248
+ * Session thread type state machine
249
+ *
250
+ * States: base, parallel, chained, fusion, big, long
251
+ *
252
+ * Thread Type Semantics:
253
+ * - base: Main session in project root (default)
254
+ * - parallel: Independent worktree session
255
+ * - chained: Sequential dependency on another session
256
+ * - fusion: Merged work from multiple sessions
257
+ * - big: Large task spanning multiple sessions
258
+ * - long: Extended session with context preservation
259
+ *
260
+ * Transitions:
261
+ * - base → parallel (spawn worktree)
262
+ * - parallel → base (merge to main), fusion (merge multiple), chained (add dependency)
263
+ * - chained → parallel (remove dependency), fusion (complete chain)
264
+ * - fusion → base (merge to main)
265
+ * - big → parallel (split), fusion (consolidate)
266
+ * - long → base (complete), parallel (split)
267
+ */
268
+ const sessionThreadMachine = new StateMachine({
269
+ name: 'thread_type',
270
+ states: ['base', 'parallel', 'chained', 'fusion', 'big', 'long'],
271
+ transitions: {
272
+ base: ['parallel', 'big', 'long'],
273
+ parallel: ['base', 'fusion', 'chained'],
274
+ chained: ['parallel', 'fusion'],
275
+ fusion: ['base'],
276
+ big: ['parallel', 'fusion'],
277
+ long: ['base', 'parallel'],
278
+ },
279
+ initial: 'base',
280
+ });
281
+
282
+ module.exports = {
283
+ StateMachine,
284
+ storyStatusMachine,
285
+ sessionThreadMachine,
286
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agileflow",
3
- "version": "2.94.1",
3
+ "version": "2.95.1",
4
4
  "description": "AI-driven agile development system for Claude Code, Cursor, Windsurf, and more",
5
5
  "keywords": [
6
6
  "agile",
@@ -23,7 +23,7 @@
23
23
  * --detect Show current status
24
24
  * --help Show help
25
25
  *
26
- * Features: sessionstart, precompact, ralphloop, selfimprove, archival, statusline, autoupdate, damagecontrol, askuserquestion, tmuxautospawn
26
+ * Features: sessionstart, precompact, ralphloop, selfimprove, archival, statusline, autoupdate, damagecontrol, askuserquestion, tmuxautospawn, shellaliases, claudemdreinforcement
27
27
  */
28
28
 
29
29
  const fs = require('fs');
@@ -121,16 +121,17 @@ ${c.cyan}Usage:${c.reset}
121
121
  node .agileflow/scripts/agileflow-configure.js [options]
122
122
 
123
123
  ${c.cyan}Profiles:${c.reset}
124
- --profile=full All features (hooks, Stop hooks, archival, statusline)
125
- --profile=basic SessionStart + PreCompact + archival (no Stop hooks)
126
- --profile=minimal SessionStart + archival only
127
- --profile=none Disable all AgileFlow features
124
+ --profile=full All features (hooks, Stop hooks, archival, statusline)
125
+ --profile=basic SessionStart + PreCompact + archival (no Stop hooks)
126
+ --profile=minimal SessionStart + archival only
127
+ --profile=experimental ⚠️ All features + FULL FILE injection during compact (CONTEXT HEAVY)
128
+ --profile=none Disable all AgileFlow features
128
129
 
129
130
  ${c.cyan}Feature Control:${c.reset}
130
131
  --enable=<list> Enable features (comma-separated)
131
132
  --disable=<list> Disable features (comma-separated)
132
133
 
133
- Features: sessionstart, precompact, ralphloop, selfimprove, archival, statusline, damagecontrol, askuserquestion, tmuxautospawn
134
+ Features: sessionstart, precompact, ralphloop, selfimprove, archival, statusline, damagecontrol, askuserquestion, tmuxautospawn, shellaliases, claudemdreinforcement
134
135
 
135
136
  ${c.cyan}Statusline Components:${c.reset}
136
137
  --show=<list> Show statusline components (comma-separated)