agileflow 2.51.0 → 2.56.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.
Files changed (90) hide show
  1. package/README.md +80 -460
  2. package/package.json +18 -3
  3. package/scripts/agileflow-configure.js +134 -63
  4. package/scripts/agileflow-welcome.js +161 -31
  5. package/scripts/generators/agent-registry.js +45 -57
  6. package/scripts/generators/command-registry.js +48 -32
  7. package/scripts/generators/index.js +2 -6
  8. package/scripts/generators/inject-babysit.js +9 -2
  9. package/scripts/generators/inject-help.js +3 -1
  10. package/scripts/generators/inject-readme.js +7 -3
  11. package/scripts/generators/skill-registry.js +60 -33
  12. package/scripts/get-env.js +13 -12
  13. package/scripts/lib/frontmatter-parser.js +82 -0
  14. package/scripts/obtain-context.js +79 -26
  15. package/scripts/session-coordinator.sh +232 -0
  16. package/scripts/session-manager.js +512 -0
  17. package/src/core/agents/orchestrator.md +275 -0
  18. package/src/core/commands/adr.md +38 -16
  19. package/src/core/commands/agent.md +39 -22
  20. package/src/core/commands/assign.md +17 -0
  21. package/src/core/commands/auto.md +60 -46
  22. package/src/core/commands/babysit.md +302 -637
  23. package/src/core/commands/baseline.md +20 -0
  24. package/src/core/commands/blockers.md +33 -48
  25. package/src/core/commands/board.md +19 -0
  26. package/src/core/commands/changelog.md +20 -0
  27. package/src/core/commands/ci.md +17 -0
  28. package/src/core/commands/context.md +43 -40
  29. package/src/core/commands/debt.md +76 -45
  30. package/src/core/commands/deploy.md +20 -0
  31. package/src/core/commands/deps.md +40 -46
  32. package/src/core/commands/diagnose.md +24 -18
  33. package/src/core/commands/docs.md +18 -0
  34. package/src/core/commands/epic.md +31 -0
  35. package/src/core/commands/feedback.md +33 -21
  36. package/src/core/commands/handoff.md +29 -0
  37. package/src/core/commands/help.md +16 -7
  38. package/src/core/commands/impact.md +31 -61
  39. package/src/core/commands/metrics.md +17 -35
  40. package/src/core/commands/packages.md +21 -0
  41. package/src/core/commands/pr.md +15 -0
  42. package/src/core/commands/readme-sync.md +42 -9
  43. package/src/core/commands/research.md +58 -11
  44. package/src/core/commands/retro.md +42 -50
  45. package/src/core/commands/review.md +22 -27
  46. package/src/core/commands/session/end.md +53 -297
  47. package/src/core/commands/session/history.md +38 -257
  48. package/src/core/commands/session/init.md +44 -446
  49. package/src/core/commands/session/new.md +152 -0
  50. package/src/core/commands/session/resume.md +51 -447
  51. package/src/core/commands/session/status.md +32 -244
  52. package/src/core/commands/sprint.md +33 -0
  53. package/src/core/commands/status.md +18 -0
  54. package/src/core/commands/story-validate.md +32 -0
  55. package/src/core/commands/story.md +21 -6
  56. package/src/core/commands/template.md +18 -0
  57. package/src/core/commands/tests.md +22 -0
  58. package/src/core/commands/update.md +72 -58
  59. package/src/core/commands/validate-expertise.md +25 -37
  60. package/src/core/commands/velocity.md +33 -74
  61. package/src/core/commands/verify.md +16 -0
  62. package/src/core/experts/documentation/expertise.yaml +16 -2
  63. package/src/core/skills/agileflow-retro-facilitator/SKILL.md +57 -219
  64. package/src/core/skills/agileflow-retro-facilitator/cookbook/4ls.md +86 -0
  65. package/src/core/skills/agileflow-retro-facilitator/cookbook/glad-sad-mad.md +79 -0
  66. package/src/core/skills/agileflow-retro-facilitator/cookbook/start-stop-continue.md +142 -0
  67. package/src/core/skills/agileflow-retro-facilitator/prompts/action-items.md +83 -0
  68. package/src/core/skills/writing-skills/SKILL.md +352 -0
  69. package/src/core/skills/writing-skills/testing-skills-with-subagents.md +232 -0
  70. package/tools/cli/agileflow-cli.js +4 -2
  71. package/tools/cli/commands/config.js +20 -13
  72. package/tools/cli/commands/doctor.js +25 -9
  73. package/tools/cli/commands/list.js +10 -6
  74. package/tools/cli/commands/setup.js +54 -3
  75. package/tools/cli/commands/status.js +6 -8
  76. package/tools/cli/commands/uninstall.js +5 -5
  77. package/tools/cli/commands/update.js +51 -7
  78. package/tools/cli/installers/core/installer.js +8 -4
  79. package/tools/cli/installers/ide/_base-ide.js +58 -1
  80. package/tools/cli/installers/ide/claude-code.js +3 -61
  81. package/tools/cli/installers/ide/codex.js +440 -0
  82. package/tools/cli/installers/ide/cursor.js +21 -51
  83. package/tools/cli/installers/ide/manager.js +2 -6
  84. package/tools/cli/installers/ide/windsurf.js +20 -50
  85. package/tools/cli/lib/content-injector.js +26 -49
  86. package/tools/cli/lib/docs-setup.js +3 -2
  87. package/tools/cli/lib/npm-utils.js +39 -12
  88. package/tools/cli/lib/ui.js +31 -10
  89. package/tools/cli/lib/version-checker.js +3 -3
  90. package/tools/postinstall.js +2 -3
@@ -2,14 +2,24 @@
2
2
  * AgileFlow CLI - Update Command
3
3
  *
4
4
  * Updates an existing AgileFlow installation.
5
+ * Includes self-update capability to always use the latest CLI.
5
6
  */
6
7
 
7
8
  const chalk = require('chalk');
8
9
  const path = require('node:path');
10
+ const { spawnSync } = require('node:child_process');
9
11
  const semver = require('semver');
10
12
  const { Installer } = require('../installers/core/installer');
11
13
  const { IdeManager } = require('../installers/ide/manager');
12
- const { displayLogo, displaySection, success, warning, error, info, confirm } = require('../lib/ui');
14
+ const {
15
+ displayLogo,
16
+ displaySection,
17
+ success,
18
+ warning,
19
+ error,
20
+ info,
21
+ confirm,
22
+ } = require('../lib/ui');
13
23
  const { createDocsStructure, getDocsFolderName } = require('../lib/docs-setup');
14
24
  const { getLatestVersion } = require('../lib/npm-utils');
15
25
 
@@ -22,8 +32,10 @@ module.exports = {
22
32
  options: [
23
33
  ['-d, --directory <path>', 'Project directory (default: current directory)'],
24
34
  ['--force', 'Force reinstall (skip prompts; overwrites local changes)'],
35
+ ['--no-self-update', 'Skip automatic CLI self-update check'],
36
+ ['--self-updated', 'Internal flag: indicates CLI was already self-updated'],
25
37
  ],
26
- action: async (options) => {
38
+ action: async options => {
27
39
  try {
28
40
  const directory = path.resolve(options.directory || '.');
29
41
 
@@ -60,14 +72,44 @@ module.exports = {
60
72
  console.log(chalk.bold('Latest (npm):'), npmLatestVersion);
61
73
  }
62
74
 
63
- // Check if CLI itself is outdated
64
- if (npmLatestVersion && semver.lt(localCliVersion, npmLatestVersion)) {
75
+ // Self-update: if CLI is outdated and we haven't already self-updated, re-run with latest
76
+ const shouldSelfUpdate = options.selfUpdate !== false && !options.selfUpdated;
77
+ if (npmLatestVersion && semver.lt(localCliVersion, npmLatestVersion) && shouldSelfUpdate) {
78
+ console.log();
79
+ info(`Updating CLI from v${localCliVersion} to v${npmLatestVersion}...`);
80
+ console.log(chalk.dim(' Fetching latest version from npm...\n'));
81
+
82
+ // Build the command with all current options forwarded
83
+ const args = ['agileflow@latest', 'update', '--self-updated'];
84
+ if (options.directory) args.push('-d', options.directory);
85
+ if (options.force) args.push('--force');
86
+
87
+ const result = spawnSync('npx', args, {
88
+ stdio: 'inherit',
89
+ cwd: process.cwd(),
90
+ shell: process.platform === 'win32',
91
+ });
92
+
93
+ // Exit with the same code as the spawned process
94
+ process.exit(result.status ?? 0);
95
+ }
96
+
97
+ // If we self-updated, show confirmation
98
+ if (options.selfUpdated) {
99
+ success(`CLI updated to v${localCliVersion}`);
100
+ console.log();
101
+ }
102
+
103
+ // Check if CLI itself is still outdated (only if self-update was disabled)
104
+ if (npmLatestVersion && semver.lt(localCliVersion, npmLatestVersion) && !shouldSelfUpdate) {
65
105
  console.log();
66
106
  warning('Your CLI is outdated!');
67
107
  console.log(chalk.dim(` To update your installation, run:\n`));
68
108
  console.log(chalk.cyan(` npx agileflow@latest update\n`));
69
109
 
70
- const useOutdated = options.force ? true : await confirm('Continue with outdated CLI anyway?');
110
+ const useOutdated = options.force
111
+ ? true
112
+ : await confirm('Continue with outdated CLI anyway?');
71
113
  if (!useOutdated) {
72
114
  console.log(chalk.dim('\nUpdate cancelled\n'));
73
115
  process.exit(0);
@@ -137,12 +179,14 @@ module.exports = {
137
179
 
138
180
  // Create/update docs structure (idempotent - only creates missing files)
139
181
  displaySection('Updating Documentation Structure', `Folder: ${config.docsFolder}/`);
140
- const docsResult = await createDocsStructure(directory, config.docsFolder, { updateGitignore: false });
182
+ const docsResult = await createDocsStructure(directory, config.docsFolder, {
183
+ updateGitignore: false,
184
+ });
141
185
 
142
186
  if (!docsResult.success) {
143
187
  warning('Failed to update docs structure');
144
188
  if (docsResult.errors.length > 0) {
145
- docsResult.errors.forEach((err) => error(` ${err}`));
189
+ docsResult.errors.forEach(err => error(` ${err}`));
146
190
  }
147
191
  }
148
192
 
@@ -161,7 +161,11 @@ class Installer {
161
161
 
162
162
  // Create manifest
163
163
  spinner.text = 'Creating manifest...';
164
- await this.createManifest(cfgDir, { ides, userName, agileflowFolder, docsFolder }, { force: effectiveForce });
164
+ await this.createManifest(
165
+ cfgDir,
166
+ { ides, userName, agileflowFolder, docsFolder },
167
+ { force: effectiveForce }
168
+ );
165
169
 
166
170
  // Persist file index (used for safe future updates)
167
171
  spinner.text = 'Writing file index...';
@@ -578,21 +582,21 @@ class Installer {
578
582
  const agentsDir = path.join(agileflowDir, 'agents');
579
583
  if (await fs.pathExists(agentsDir)) {
580
584
  const files = await fs.readdir(agentsDir);
581
- counts.agents = files.filter((f) => f.endsWith('.md')).length;
585
+ counts.agents = files.filter(f => f.endsWith('.md')).length;
582
586
  }
583
587
 
584
588
  // Count commands
585
589
  const commandsDir = path.join(agileflowDir, 'commands');
586
590
  if (await fs.pathExists(commandsDir)) {
587
591
  const files = await fs.readdir(commandsDir);
588
- counts.commands = files.filter((f) => f.endsWith('.md')).length;
592
+ counts.commands = files.filter(f => f.endsWith('.md')).length;
589
593
  }
590
594
 
591
595
  // Count skills
592
596
  const skillsDir = path.join(agileflowDir, 'skills');
593
597
  if (await fs.pathExists(skillsDir)) {
594
598
  const entries = await fs.readdir(skillsDir, { withFileTypes: true });
595
- counts.skills = entries.filter((e) => e.isDirectory()).length;
599
+ counts.skills = entries.filter(e => e.isDirectory()).length;
596
600
  }
597
601
 
598
602
  return counts;
@@ -96,7 +96,9 @@ class BaseIdeSetup {
96
96
  const agileflowPath = path.join(projectDir, this.configDir, 'commands', folderName);
97
97
  if (await fs.pathExists(agileflowPath)) {
98
98
  await fs.remove(agileflowPath);
99
- console.log(chalk.dim(` Removed old ${folderName} configuration from ${this.displayName}`));
99
+ console.log(
100
+ chalk.dim(` Removed old ${folderName} configuration from ${this.displayName}`)
101
+ );
100
102
  }
101
103
  }
102
104
  }
@@ -177,6 +179,61 @@ class BaseIdeSetup {
177
179
 
178
180
  return results;
179
181
  }
182
+
183
+ /**
184
+ * Recursively install markdown files from source to target directory
185
+ * Handles content injection and docs reference replacement.
186
+ * @param {string} sourceDir - Source directory path
187
+ * @param {string} targetDir - Target directory path
188
+ * @param {string} agileflowDir - AgileFlow installation directory (for dynamic content)
189
+ * @param {boolean} injectDynamic - Whether to inject dynamic content (only for top-level commands)
190
+ * @returns {Promise<{commands: number, subdirs: number}>} Count of installed items
191
+ */
192
+ async installCommandsRecursive(sourceDir, targetDir, agileflowDir, injectDynamic = false) {
193
+ let commandCount = 0;
194
+ let subdirCount = 0;
195
+
196
+ if (!(await this.exists(sourceDir))) {
197
+ return { commands: 0, subdirs: 0 };
198
+ }
199
+
200
+ await this.ensureDir(targetDir);
201
+
202
+ const entries = await fs.readdir(sourceDir, { withFileTypes: true });
203
+
204
+ for (const entry of entries) {
205
+ const sourcePath = path.join(sourceDir, entry.name);
206
+ const targetPath = path.join(targetDir, entry.name);
207
+
208
+ if (entry.isFile() && entry.name.endsWith('.md')) {
209
+ // Read and process .md file
210
+ let content = await this.readFile(sourcePath);
211
+
212
+ // Inject dynamic content if enabled (for top-level commands)
213
+ if (injectDynamic) {
214
+ content = this.injectDynamicContent(content, agileflowDir);
215
+ }
216
+
217
+ // Replace docs/ references with custom folder name
218
+ content = this.replaceDocsReferences(content);
219
+
220
+ await this.writeFile(targetPath, content);
221
+ commandCount++;
222
+ } else if (entry.isDirectory()) {
223
+ // Recursively process subdirectory
224
+ const subResult = await this.installCommandsRecursive(
225
+ sourcePath,
226
+ targetPath,
227
+ agileflowDir,
228
+ false // Don't inject dynamic content in subdirectories
229
+ );
230
+ commandCount += subResult.commands;
231
+ subdirCount += 1 + subResult.subdirs;
232
+ }
233
+ }
234
+
235
+ return { commands: commandCount, subdirs: subdirCount };
236
+ }
180
237
  }
181
238
 
182
239
  module.exports = { BaseIdeSetup };
@@ -19,60 +19,6 @@ class ClaudeCodeSetup extends BaseIdeSetup {
19
19
  this.commandsDir = 'commands';
20
20
  }
21
21
 
22
- /**
23
- * Recursively install commands from a source directory
24
- * @param {string} sourceDir - Source directory path
25
- * @param {string} targetDir - Target directory path
26
- * @param {string} agileflowDir - AgileFlow installation directory (for dynamic content)
27
- * @param {boolean} injectDynamic - Whether to inject dynamic content (only for top-level commands)
28
- * @returns {Promise<{commands: number, subdirs: number}>} Count of installed items
29
- */
30
- async installCommandsRecursive(sourceDir, targetDir, agileflowDir, injectDynamic = false) {
31
- let commandCount = 0;
32
- let subdirCount = 0;
33
-
34
- if (!(await this.exists(sourceDir))) {
35
- return { commands: 0, subdirs: 0 };
36
- }
37
-
38
- await this.ensureDir(targetDir);
39
-
40
- const entries = await fs.readdir(sourceDir, { withFileTypes: true });
41
-
42
- for (const entry of entries) {
43
- const sourcePath = path.join(sourceDir, entry.name);
44
- const targetPath = path.join(targetDir, entry.name);
45
-
46
- if (entry.isFile() && entry.name.endsWith('.md')) {
47
- // Read and process .md file
48
- let content = await this.readFile(sourcePath);
49
-
50
- // Inject dynamic content if enabled (for top-level commands)
51
- if (injectDynamic) {
52
- content = this.injectDynamicContent(content, agileflowDir);
53
- }
54
-
55
- // Replace docs/ references with custom folder name
56
- content = this.replaceDocsReferences(content);
57
-
58
- await this.writeFile(targetPath, content);
59
- commandCount++;
60
- } else if (entry.isDirectory()) {
61
- // Recursively process subdirectory
62
- const subResult = await this.installCommandsRecursive(
63
- sourcePath,
64
- targetPath,
65
- agileflowDir,
66
- false // Don't inject dynamic content in subdirectories
67
- );
68
- commandCount += subResult.commands;
69
- subdirCount += 1 + subResult.subdirs;
70
- }
71
- }
72
-
73
- return { commands: commandCount, subdirs: subdirCount };
74
- }
75
-
76
22
  /**
77
23
  * Setup Claude Code IDE configuration
78
24
  * @param {string} projectDir - Project directory
@@ -114,12 +60,7 @@ class ClaudeCodeSetup extends BaseIdeSetup {
114
60
  // ALSO install agents as spawnable subagents (.claude/agents/agileflow/)
115
61
  // This allows Task tool to spawn them with subagent_type: "agileflow-ui"
116
62
  const spawnableAgentsDir = path.join(claudeDir, 'agents', 'agileflow');
117
- await this.installCommandsRecursive(
118
- agentsSource,
119
- spawnableAgentsDir,
120
- agileflowDir,
121
- false
122
- );
63
+ await this.installCommandsRecursive(agentsSource, spawnableAgentsDir, agileflowDir, false);
123
64
  console.log(chalk.dim(` - Spawnable agents: .claude/agents/agileflow/`));
124
65
 
125
66
  // Install skills (.claude/skills/)
@@ -140,7 +81,8 @@ class ClaudeCodeSetup extends BaseIdeSetup {
140
81
  }
141
82
 
142
83
  const totalCommands = commandResult.commands + agentResult.commands;
143
- const totalSubdirs = commandResult.subdirs + (agentResult.commands > 0 ? 1 : 0) + agentResult.subdirs;
84
+ const totalSubdirs =
85
+ commandResult.subdirs + (agentResult.commands > 0 ? 1 : 0) + agentResult.subdirs;
144
86
 
145
87
  console.log(chalk.green(` ✓ ${this.displayName} configured:`));
146
88
  console.log(chalk.dim(` - ${totalCommands} commands installed`));