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.
- package/README.md +80 -460
- package/package.json +18 -3
- package/scripts/agileflow-configure.js +134 -63
- package/scripts/agileflow-welcome.js +161 -31
- package/scripts/generators/agent-registry.js +45 -57
- package/scripts/generators/command-registry.js +48 -32
- package/scripts/generators/index.js +2 -6
- package/scripts/generators/inject-babysit.js +9 -2
- package/scripts/generators/inject-help.js +3 -1
- package/scripts/generators/inject-readme.js +7 -3
- package/scripts/generators/skill-registry.js +60 -33
- package/scripts/get-env.js +13 -12
- package/scripts/lib/frontmatter-parser.js +82 -0
- package/scripts/obtain-context.js +79 -26
- package/scripts/session-coordinator.sh +232 -0
- package/scripts/session-manager.js +512 -0
- package/src/core/agents/orchestrator.md +275 -0
- package/src/core/commands/adr.md +38 -16
- package/src/core/commands/agent.md +39 -22
- package/src/core/commands/assign.md +17 -0
- package/src/core/commands/auto.md +60 -46
- package/src/core/commands/babysit.md +302 -637
- package/src/core/commands/baseline.md +20 -0
- package/src/core/commands/blockers.md +33 -48
- package/src/core/commands/board.md +19 -0
- package/src/core/commands/changelog.md +20 -0
- package/src/core/commands/ci.md +17 -0
- package/src/core/commands/context.md +43 -40
- package/src/core/commands/debt.md +76 -45
- package/src/core/commands/deploy.md +20 -0
- package/src/core/commands/deps.md +40 -46
- package/src/core/commands/diagnose.md +24 -18
- package/src/core/commands/docs.md +18 -0
- package/src/core/commands/epic.md +31 -0
- package/src/core/commands/feedback.md +33 -21
- package/src/core/commands/handoff.md +29 -0
- package/src/core/commands/help.md +16 -7
- package/src/core/commands/impact.md +31 -61
- package/src/core/commands/metrics.md +17 -35
- package/src/core/commands/packages.md +21 -0
- package/src/core/commands/pr.md +15 -0
- package/src/core/commands/readme-sync.md +42 -9
- package/src/core/commands/research.md +58 -11
- package/src/core/commands/retro.md +42 -50
- package/src/core/commands/review.md +22 -27
- package/src/core/commands/session/end.md +53 -297
- package/src/core/commands/session/history.md +38 -257
- package/src/core/commands/session/init.md +44 -446
- package/src/core/commands/session/new.md +152 -0
- package/src/core/commands/session/resume.md +51 -447
- package/src/core/commands/session/status.md +32 -244
- package/src/core/commands/sprint.md +33 -0
- package/src/core/commands/status.md +18 -0
- package/src/core/commands/story-validate.md +32 -0
- package/src/core/commands/story.md +21 -6
- package/src/core/commands/template.md +18 -0
- package/src/core/commands/tests.md +22 -0
- package/src/core/commands/update.md +72 -58
- package/src/core/commands/validate-expertise.md +25 -37
- package/src/core/commands/velocity.md +33 -74
- package/src/core/commands/verify.md +16 -0
- package/src/core/experts/documentation/expertise.yaml +16 -2
- package/src/core/skills/agileflow-retro-facilitator/SKILL.md +57 -219
- package/src/core/skills/agileflow-retro-facilitator/cookbook/4ls.md +86 -0
- package/src/core/skills/agileflow-retro-facilitator/cookbook/glad-sad-mad.md +79 -0
- package/src/core/skills/agileflow-retro-facilitator/cookbook/start-stop-continue.md +142 -0
- package/src/core/skills/agileflow-retro-facilitator/prompts/action-items.md +83 -0
- package/src/core/skills/writing-skills/SKILL.md +352 -0
- package/src/core/skills/writing-skills/testing-skills-with-subagents.md +232 -0
- package/tools/cli/agileflow-cli.js +4 -2
- package/tools/cli/commands/config.js +20 -13
- package/tools/cli/commands/doctor.js +25 -9
- package/tools/cli/commands/list.js +10 -6
- package/tools/cli/commands/setup.js +54 -3
- package/tools/cli/commands/status.js +6 -8
- package/tools/cli/commands/uninstall.js +5 -5
- package/tools/cli/commands/update.js +51 -7
- package/tools/cli/installers/core/installer.js +8 -4
- package/tools/cli/installers/ide/_base-ide.js +58 -1
- package/tools/cli/installers/ide/claude-code.js +3 -61
- package/tools/cli/installers/ide/codex.js +440 -0
- package/tools/cli/installers/ide/cursor.js +21 -51
- package/tools/cli/installers/ide/manager.js +2 -6
- package/tools/cli/installers/ide/windsurf.js +20 -50
- package/tools/cli/lib/content-injector.js +26 -49
- package/tools/cli/lib/docs-setup.js +3 -2
- package/tools/cli/lib/npm-utils.js +39 -12
- package/tools/cli/lib/ui.js +31 -10
- package/tools/cli/lib/version-checker.js +3 -3
- 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 {
|
|
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
|
|
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
|
-
//
|
|
64
|
-
|
|
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
|
|
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, {
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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`));
|