agileflow 2.30.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 (133) hide show
  1. package/package.json +61 -0
  2. package/src/core/agents/accessibility.md +445 -0
  3. package/src/core/agents/adr-writer.md +215 -0
  4. package/src/core/agents/analytics.md +523 -0
  5. package/src/core/agents/api.md +484 -0
  6. package/src/core/agents/ci.md +452 -0
  7. package/src/core/agents/compliance.md +401 -0
  8. package/src/core/agents/context7.md +164 -0
  9. package/src/core/agents/database.md +377 -0
  10. package/src/core/agents/datamigration.md +565 -0
  11. package/src/core/agents/design.md +400 -0
  12. package/src/core/agents/devops.md +576 -0
  13. package/src/core/agents/documentation.md +229 -0
  14. package/src/core/agents/epic-planner.md +277 -0
  15. package/src/core/agents/integrations.md +459 -0
  16. package/src/core/agents/mentor.md +375 -0
  17. package/src/core/agents/mobile.md +391 -0
  18. package/src/core/agents/monitoring.md +430 -0
  19. package/src/core/agents/performance.md +390 -0
  20. package/src/core/agents/product.md +311 -0
  21. package/src/core/agents/qa.md +647 -0
  22. package/src/core/agents/readme-updater.md +325 -0
  23. package/src/core/agents/refactor.md +432 -0
  24. package/src/core/agents/research.md +250 -0
  25. package/src/core/agents/security.md +379 -0
  26. package/src/core/agents/testing.md +397 -0
  27. package/src/core/agents/ui.md +999 -0
  28. package/src/core/commands/adr.md +32 -0
  29. package/src/core/commands/agent.md +23 -0
  30. package/src/core/commands/assign.md +34 -0
  31. package/src/core/commands/auto.md +364 -0
  32. package/src/core/commands/babysit.md +1357 -0
  33. package/src/core/commands/baseline.md +520 -0
  34. package/src/core/commands/blockers.md +343 -0
  35. package/src/core/commands/board.md +241 -0
  36. package/src/core/commands/changelog.md +321 -0
  37. package/src/core/commands/ci.md +36 -0
  38. package/src/core/commands/compress.md +270 -0
  39. package/src/core/commands/context.md +222 -0
  40. package/src/core/commands/debt.md +268 -0
  41. package/src/core/commands/deploy.md +544 -0
  42. package/src/core/commands/deps.md +560 -0
  43. package/src/core/commands/diagnose.md +227 -0
  44. package/src/core/commands/docs.md +166 -0
  45. package/src/core/commands/epic.md +40 -0
  46. package/src/core/commands/feedback.md +307 -0
  47. package/src/core/commands/handoff.md +33 -0
  48. package/src/core/commands/help.md +90 -0
  49. package/src/core/commands/impact.md +204 -0
  50. package/src/core/commands/metrics.md +530 -0
  51. package/src/core/commands/packages.md +369 -0
  52. package/src/core/commands/pr.md +35 -0
  53. package/src/core/commands/readme-sync.md +168 -0
  54. package/src/core/commands/research.md +30 -0
  55. package/src/core/commands/resume.md +475 -0
  56. package/src/core/commands/retro.md +538 -0
  57. package/src/core/commands/review.md +364 -0
  58. package/src/core/commands/session-init.md +532 -0
  59. package/src/core/commands/setup.md +708 -0
  60. package/src/core/commands/sprint.md +490 -0
  61. package/src/core/commands/status.md +38 -0
  62. package/src/core/commands/story-validate.md +242 -0
  63. package/src/core/commands/story.md +38 -0
  64. package/src/core/commands/template.md +458 -0
  65. package/src/core/commands/tests.md +359 -0
  66. package/src/core/commands/update.md +407 -0
  67. package/src/core/commands/velocity.md +369 -0
  68. package/src/core/commands/verify.md +283 -0
  69. package/src/core/skills/acceptance-criteria-generator/SKILL.md +46 -0
  70. package/src/core/skills/adr-template/SKILL.md +62 -0
  71. package/src/core/skills/agileflow-acceptance-criteria/SKILL.md +156 -0
  72. package/src/core/skills/agileflow-adr/SKILL.md +147 -0
  73. package/src/core/skills/agileflow-adr/examples/database-choice-example.md +122 -0
  74. package/src/core/skills/agileflow-adr/templates/adr-template.md +69 -0
  75. package/src/core/skills/agileflow-commit-messages/SKILL.md +130 -0
  76. package/src/core/skills/agileflow-commit-messages/reference/bad-examples.md +168 -0
  77. package/src/core/skills/agileflow-commit-messages/reference/good-examples.md +120 -0
  78. package/src/core/skills/agileflow-commit-messages/scripts/check-attribution.sh +15 -0
  79. package/src/core/skills/agileflow-epic-planner/SKILL.md +184 -0
  80. package/src/core/skills/agileflow-retro-facilitator/SKILL.md +281 -0
  81. package/src/core/skills/agileflow-sprint-planner/SKILL.md +212 -0
  82. package/src/core/skills/agileflow-story-writer/SKILL.md +163 -0
  83. package/src/core/skills/agileflow-story-writer/examples/good-story-example.md +63 -0
  84. package/src/core/skills/agileflow-story-writer/templates/story-template.md +44 -0
  85. package/src/core/skills/agileflow-tech-debt/SKILL.md +215 -0
  86. package/src/core/skills/api-documentation-generator/SKILL.md +65 -0
  87. package/src/core/skills/changelog-entry/SKILL.md +55 -0
  88. package/src/core/skills/commit-message-formatter/SKILL.md +50 -0
  89. package/src/core/skills/deployment-guide-generator/SKILL.md +84 -0
  90. package/src/core/skills/diagram-generator/SKILL.md +65 -0
  91. package/src/core/skills/error-handler-template/SKILL.md +78 -0
  92. package/src/core/skills/migration-checklist/SKILL.md +82 -0
  93. package/src/core/skills/pr-description/SKILL.md +65 -0
  94. package/src/core/skills/sql-schema-generator/SKILL.md +69 -0
  95. package/src/core/skills/story-skeleton/SKILL.md +34 -0
  96. package/src/core/skills/test-case-generator/SKILL.md +63 -0
  97. package/src/core/skills/type-definitions/SKILL.md +65 -0
  98. package/src/core/skills/validation-schema-generator/SKILL.md +64 -0
  99. package/src/core/templates/README-template.md +16 -0
  100. package/src/core/templates/adr-template.md +28 -0
  101. package/src/core/templates/agent-profile-template.md +51 -0
  102. package/src/core/templates/agileflow-metadata.json +41 -0
  103. package/src/core/templates/ci-workflow.yml +74 -0
  104. package/src/core/templates/claude-settings.advanced.example.json +71 -0
  105. package/src/core/templates/claude-settings.example.json +26 -0
  106. package/src/core/templates/comms-note-template.md +24 -0
  107. package/src/core/templates/environment.json +18 -0
  108. package/src/core/templates/epic-template.md +27 -0
  109. package/src/core/templates/init.sh +76 -0
  110. package/src/core/templates/research-template.md +44 -0
  111. package/src/core/templates/resume-session.sh +121 -0
  112. package/src/core/templates/session-state.json +20 -0
  113. package/src/core/templates/skill-template.md +75 -0
  114. package/src/core/templates/story-template.md +88 -0
  115. package/src/core/templates/validate-tokens.sh +88 -0
  116. package/src/core/templates/worktree-create.sh +111 -0
  117. package/src/core/templates/worktrees-guide.md +235 -0
  118. package/tools/agileflow-npx.js +40 -0
  119. package/tools/cli/agileflow-cli.js +70 -0
  120. package/tools/cli/commands/doctor.js +243 -0
  121. package/tools/cli/commands/install.js +82 -0
  122. package/tools/cli/commands/status.js +121 -0
  123. package/tools/cli/commands/uninstall.js +110 -0
  124. package/tools/cli/commands/update.js +99 -0
  125. package/tools/cli/installers/core/installer.js +296 -0
  126. package/tools/cli/installers/ide/_base-ide.js +133 -0
  127. package/tools/cli/installers/ide/claude-code.js +174 -0
  128. package/tools/cli/installers/ide/cursor.js +189 -0
  129. package/tools/cli/installers/ide/manager.js +197 -0
  130. package/tools/cli/installers/ide/windsurf.js +192 -0
  131. package/tools/cli/lib/ui.js +203 -0
  132. package/tools/cli/lib/version-checker.js +95 -0
  133. package/tools/postinstall.js +141 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * AgileFlow CLI - Install Command
3
+ *
4
+ * Installs AgileFlow to a project directory.
5
+ */
6
+
7
+ const chalk = require('chalk');
8
+ const path = require('node:path');
9
+ const { Installer } = require('../installers/core/installer');
10
+ const { IdeManager } = require('../installers/ide/manager');
11
+ const { promptInstall, success, error, info, displaySection } = require('../lib/ui');
12
+
13
+ const installer = new Installer();
14
+ const ideManager = new IdeManager();
15
+
16
+ module.exports = {
17
+ name: 'install',
18
+ description: 'Install AgileFlow to a project',
19
+ options: [
20
+ ['-d, --directory <path>', 'Installation directory (default: current directory)'],
21
+ ['-y, --yes', 'Skip prompts and use defaults'],
22
+ ],
23
+ action: async (options) => {
24
+ try {
25
+ let config;
26
+
27
+ if (options.yes) {
28
+ // Use defaults
29
+ config = {
30
+ directory: path.resolve(options.directory || '.'),
31
+ ides: ['claude-code'],
32
+ userName: 'Developer',
33
+ agileflowFolder: '.agileflow',
34
+ };
35
+ } else {
36
+ // Interactive prompts
37
+ config = await promptInstall();
38
+ }
39
+
40
+ displaySection('Installing AgileFlow', `Target: ${config.directory}`);
41
+
42
+ // Run core installation
43
+ const coreResult = await installer.install(config);
44
+
45
+ if (!coreResult.success) {
46
+ error('Core installation failed');
47
+ process.exit(1);
48
+ }
49
+
50
+ success(`Installed ${coreResult.counts.agents} agents`);
51
+ success(`Installed ${coreResult.counts.commands} commands`);
52
+ success(`Installed ${coreResult.counts.skills} skills`);
53
+
54
+ // Setup IDE configurations
55
+ displaySection('Configuring IDEs');
56
+
57
+ ideManager.setAgileflowFolder(config.agileflowFolder);
58
+
59
+ for (const ide of config.ides) {
60
+ await ideManager.setup(ide, config.directory, coreResult.path);
61
+ }
62
+
63
+ // Final summary
64
+ console.log(chalk.green('\n✨ Installation complete!\n'));
65
+
66
+ console.log(chalk.bold('Get started:'));
67
+ info('Open your IDE and use /agileflow:help');
68
+ info(`Run 'npx agileflow status' to check installation`);
69
+ info(`Run 'npx agileflow update' to get updates`);
70
+
71
+ console.log(chalk.dim(`\nInstalled to: ${coreResult.path}\n`));
72
+
73
+ process.exit(0);
74
+ } catch (err) {
75
+ console.error(chalk.red('\nInstallation failed:'), err.message);
76
+ if (process.env.DEBUG) {
77
+ console.error(err.stack);
78
+ }
79
+ process.exit(1);
80
+ }
81
+ },
82
+ };
@@ -0,0 +1,121 @@
1
+ /**
2
+ * AgileFlow CLI - Status Command
3
+ *
4
+ * Shows installation status for the current project.
5
+ */
6
+
7
+ const chalk = require('chalk');
8
+ const path = require('node:path');
9
+ const fs = require('fs-extra');
10
+ const ora = require('ora');
11
+ const { Installer } = require('../installers/core/installer');
12
+ const { displayLogo, displaySection, success, warning, info } = require('../lib/ui');
13
+ const { checkForUpdate } = require('../lib/version-checker');
14
+
15
+ const installer = new Installer();
16
+
17
+ module.exports = {
18
+ name: 'status',
19
+ description: 'Show AgileFlow installation status',
20
+ options: [
21
+ ['-d, --directory <path>', 'Project directory (default: current directory)'],
22
+ ],
23
+ action: async (options) => {
24
+ try {
25
+ const directory = path.resolve(options.directory || '.');
26
+
27
+ displayLogo();
28
+ displaySection('Installation Status');
29
+
30
+ const status = await installer.getStatus(directory);
31
+
32
+ if (!status.installed) {
33
+ warning('No AgileFlow installation found in this directory');
34
+ console.log(chalk.dim(`\nRun 'npx agileflow install' to set up AgileFlow\n`));
35
+ process.exit(0);
36
+ }
37
+
38
+ // Show installation info
39
+ console.log(chalk.bold('Location: '), status.path);
40
+ console.log(chalk.bold('Version: '), status.version);
41
+
42
+ // Count installed items
43
+ const counts = await installer.countInstalledItems(status.path);
44
+
45
+ console.log(chalk.bold('\nCore: '), chalk.green('✓ Installed'));
46
+ info(`${counts.agents} agents`);
47
+ info(`${counts.commands} commands`);
48
+ info(`${counts.skills} skills`);
49
+
50
+ // Show configured IDEs
51
+ if (status.ides && status.ides.length > 0) {
52
+ console.log(chalk.bold('\nConfigured IDEs:'));
53
+ for (const ide of status.ides) {
54
+ // Check if IDE config exists
55
+ const ideConfigPath = getIdeConfigPath(directory, ide);
56
+ const exists = await fs.pathExists(ideConfigPath);
57
+
58
+ if (exists) {
59
+ success(formatIdeName(ide));
60
+ } else {
61
+ warning(`${formatIdeName(ide)} (config missing)`);
62
+ }
63
+ }
64
+ }
65
+
66
+ // Check for updates
67
+ const spinner = ora('Checking for updates...').start();
68
+ const updateInfo = await checkForUpdate();
69
+ spinner.stop();
70
+
71
+ if (updateInfo.updateAvailable) {
72
+ console.log(chalk.bold('\nUpdate Available:'));
73
+ console.log(chalk.yellow(` ${updateInfo.current} → ${updateInfo.latest}`));
74
+ console.log(chalk.dim(` Run 'npx agileflow update' to update\n`));
75
+ } else if (updateInfo.error) {
76
+ console.log(chalk.dim(`\n${updateInfo.error}\n`));
77
+ } else {
78
+ console.log(chalk.green('\n✓ You are on the latest version\n'));
79
+ }
80
+
81
+ process.exit(0);
82
+ } catch (err) {
83
+ console.error(chalk.red('Error:'), err.message);
84
+ if (process.env.DEBUG) {
85
+ console.error(err.stack);
86
+ }
87
+ process.exit(1);
88
+ }
89
+ },
90
+ };
91
+
92
+ /**
93
+ * Get IDE config path
94
+ * @param {string} projectDir - Project directory
95
+ * @param {string} ide - IDE name
96
+ * @returns {string}
97
+ */
98
+ function getIdeConfigPath(projectDir, ide) {
99
+ const paths = {
100
+ 'claude-code': '.claude/commands/AgileFlow',
101
+ 'cursor': '.cursor/rules/agileflow',
102
+ 'windsurf': '.windsurf/workflows/agileflow',
103
+ };
104
+
105
+ return path.join(projectDir, paths[ide] || '');
106
+ }
107
+
108
+ /**
109
+ * Format IDE name for display
110
+ * @param {string} ide - IDE name
111
+ * @returns {string}
112
+ */
113
+ function formatIdeName(ide) {
114
+ const names = {
115
+ 'claude-code': 'Claude Code',
116
+ 'cursor': 'Cursor',
117
+ 'windsurf': 'Windsurf',
118
+ };
119
+
120
+ return names[ide] || ide;
121
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * AgileFlow CLI - Uninstall Command
3
+ *
4
+ * Removes AgileFlow from a project.
5
+ */
6
+
7
+ const chalk = require('chalk');
8
+ const path = require('node:path');
9
+ const fs = require('fs-extra');
10
+ const { Installer } = require('../installers/core/installer');
11
+ const { IdeManager } = require('../installers/ide/manager');
12
+ const { displayLogo, displaySection, success, warning, error, confirm } = require('../lib/ui');
13
+
14
+ const installer = new Installer();
15
+ const ideManager = new IdeManager();
16
+
17
+ module.exports = {
18
+ name: 'uninstall',
19
+ description: 'Remove AgileFlow from a project',
20
+ options: [
21
+ ['-d, --directory <path>', 'Project directory (default: current directory)'],
22
+ ['--force', 'Skip confirmation prompt'],
23
+ ],
24
+ action: async (options) => {
25
+ try {
26
+ const directory = path.resolve(options.directory || '.');
27
+
28
+ displayLogo();
29
+
30
+ // Check for existing installation
31
+ const status = await installer.getStatus(directory);
32
+
33
+ if (!status.installed) {
34
+ warning('No AgileFlow installation found');
35
+ process.exit(0);
36
+ }
37
+
38
+ displaySection('Uninstalling AgileFlow', `Location: ${status.path}`);
39
+
40
+ // Confirm uninstall
41
+ if (!options.force) {
42
+ const proceed = await confirm('Are you sure you want to uninstall AgileFlow?', false);
43
+ if (!proceed) {
44
+ console.log(chalk.dim('\nUninstall cancelled\n'));
45
+ process.exit(0);
46
+ }
47
+ }
48
+
49
+ console.log();
50
+
51
+ // Remove IDE configurations
52
+ if (status.ides && status.ides.length > 0) {
53
+ for (const ide of status.ides) {
54
+ const configPath = getIdeConfigPath(directory, ide);
55
+ if (await fs.pathExists(configPath)) {
56
+ await fs.remove(configPath);
57
+ success(`Removed ${formatIdeName(ide)} configuration`);
58
+ }
59
+ }
60
+ }
61
+
62
+ // Remove AgileFlow directory
63
+ if (await fs.pathExists(status.path)) {
64
+ await fs.remove(status.path);
65
+ success(`Removed ${path.basename(status.path)}/`);
66
+ }
67
+
68
+ console.log(chalk.green('\nAgileFlow has been uninstalled.\n'));
69
+
70
+ process.exit(0);
71
+ } catch (err) {
72
+ console.error(chalk.red('Uninstall failed:'), err.message);
73
+ if (process.env.DEBUG) {
74
+ console.error(err.stack);
75
+ }
76
+ process.exit(1);
77
+ }
78
+ },
79
+ };
80
+
81
+ /**
82
+ * Get IDE config path
83
+ * @param {string} projectDir - Project directory
84
+ * @param {string} ide - IDE name
85
+ * @returns {string}
86
+ */
87
+ function getIdeConfigPath(projectDir, ide) {
88
+ const paths = {
89
+ 'claude-code': '.claude/commands/AgileFlow',
90
+ 'cursor': '.cursor/rules/agileflow',
91
+ 'windsurf': '.windsurf/workflows/agileflow',
92
+ };
93
+
94
+ return path.join(projectDir, paths[ide] || '');
95
+ }
96
+
97
+ /**
98
+ * Format IDE name for display
99
+ * @param {string} ide - IDE name
100
+ * @returns {string}
101
+ */
102
+ function formatIdeName(ide) {
103
+ const names = {
104
+ 'claude-code': 'Claude Code',
105
+ 'cursor': 'Cursor',
106
+ 'windsurf': 'Windsurf',
107
+ };
108
+
109
+ return names[ide] || ide;
110
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * AgileFlow CLI - Update Command
3
+ *
4
+ * Updates an existing AgileFlow installation.
5
+ */
6
+
7
+ const chalk = require('chalk');
8
+ const path = require('node:path');
9
+ const { Installer } = require('../installers/core/installer');
10
+ const { IdeManager } = require('../installers/ide/manager');
11
+ const { displayLogo, displaySection, success, warning, error, info, confirm } = require('../lib/ui');
12
+
13
+ const installer = new Installer();
14
+ const ideManager = new IdeManager();
15
+
16
+ module.exports = {
17
+ name: 'update',
18
+ description: 'Update existing AgileFlow installation',
19
+ options: [
20
+ ['-d, --directory <path>', 'Project directory (default: current directory)'],
21
+ ['--force', 'Force update, overwriting modified files'],
22
+ ],
23
+ action: async (options) => {
24
+ try {
25
+ const directory = path.resolve(options.directory || '.');
26
+
27
+ displayLogo();
28
+
29
+ // Check for existing installation
30
+ const status = await installer.getStatus(directory);
31
+
32
+ if (!status.installed) {
33
+ warning('No AgileFlow installation found');
34
+ console.log(chalk.dim(`\nRun 'npx agileflow install' to set up AgileFlow\n`));
35
+ process.exit(1);
36
+ }
37
+
38
+ displaySection('Updating AgileFlow', `Current version: ${status.version}`);
39
+
40
+ // Get package version
41
+ const packageJson = require(path.join(__dirname, '..', '..', '..', 'package.json'));
42
+ const newVersion = packageJson.version;
43
+
44
+ console.log(chalk.bold('Current: '), status.version);
45
+ console.log(chalk.bold('Latest: '), newVersion);
46
+
47
+ if (status.version === newVersion && !options.force) {
48
+ success('Already on the latest version');
49
+ process.exit(0);
50
+ }
51
+
52
+ // Confirm update
53
+ if (!options.force) {
54
+ const proceed = await confirm(`Update to v${newVersion}?`);
55
+ if (!proceed) {
56
+ console.log(chalk.dim('\nUpdate cancelled\n'));
57
+ process.exit(0);
58
+ }
59
+ }
60
+
61
+ console.log();
62
+
63
+ // Re-run installation with existing config
64
+ const config = {
65
+ directory,
66
+ ides: status.ides || ['claude-code'],
67
+ userName: 'Developer', // Could read from existing config
68
+ agileflowFolder: path.basename(status.path),
69
+ };
70
+
71
+ // Run core installation
72
+ const coreResult = await installer.install(config);
73
+
74
+ if (!coreResult.success) {
75
+ error('Update failed');
76
+ process.exit(1);
77
+ }
78
+
79
+ success('Updated core content');
80
+
81
+ // Re-setup IDEs
82
+ ideManager.setAgileflowFolder(config.agileflowFolder);
83
+
84
+ for (const ide of config.ides) {
85
+ await ideManager.setup(ide, directory, status.path);
86
+ }
87
+
88
+ console.log(chalk.green(`\n✨ Update complete! (${status.version} → ${newVersion})\n`));
89
+
90
+ process.exit(0);
91
+ } catch (err) {
92
+ console.error(chalk.red('Update failed:'), err.message);
93
+ if (process.env.DEBUG) {
94
+ console.error(err.stack);
95
+ }
96
+ process.exit(1);
97
+ }
98
+ },
99
+ };
@@ -0,0 +1,296 @@
1
+ /**
2
+ * AgileFlow CLI - Core Installer
3
+ *
4
+ * Handles the main installation logic for AgileFlow.
5
+ */
6
+
7
+ const path = require('node:path');
8
+ const fs = require('fs-extra');
9
+ const chalk = require('chalk');
10
+ const ora = require('ora');
11
+ const yaml = require('js-yaml');
12
+
13
+ /**
14
+ * Get the source path for AgileFlow content
15
+ * @returns {string} Path to src directory
16
+ */
17
+ function getSourcePath() {
18
+ return path.join(__dirname, '..', '..', '..', '..', 'src');
19
+ }
20
+
21
+ /**
22
+ * Get the package root path
23
+ * @returns {string} Path to package root
24
+ */
25
+ function getPackageRoot() {
26
+ return path.join(__dirname, '..', '..', '..', '..');
27
+ }
28
+
29
+ /**
30
+ * Core Installer class
31
+ */
32
+ class Installer {
33
+ constructor() {
34
+ this.sourcePath = getSourcePath();
35
+ this.packageRoot = getPackageRoot();
36
+ }
37
+
38
+ /**
39
+ * Install AgileFlow to a project
40
+ * @param {Object} config - Installation configuration
41
+ * @returns {Promise<Object>} Installation result
42
+ */
43
+ async install(config) {
44
+ const { directory, ides, userName, agileflowFolder } = config;
45
+
46
+ const agileflowDir = path.join(directory, agileflowFolder);
47
+ const spinner = ora('Installing AgileFlow...').start();
48
+
49
+ try {
50
+ // Create AgileFlow directory
51
+ await fs.ensureDir(agileflowDir);
52
+ spinner.text = 'Creating directory structure...';
53
+
54
+ // Create _cfg directory for manifest
55
+ const cfgDir = path.join(agileflowDir, '_cfg');
56
+ await fs.ensureDir(cfgDir);
57
+
58
+ // Copy core content
59
+ spinner.text = 'Installing core content...';
60
+ const coreSourcePath = path.join(this.sourcePath, 'core');
61
+
62
+ if (await fs.pathExists(coreSourcePath)) {
63
+ await this.copyContent(coreSourcePath, agileflowDir, agileflowFolder);
64
+ } else {
65
+ // Fallback: copy from old structure (commands, agents, skills at root)
66
+ await this.copyLegacyContent(directory, agileflowDir, agileflowFolder);
67
+ }
68
+
69
+ // Create config.yaml
70
+ spinner.text = 'Creating configuration...';
71
+ await this.createConfig(agileflowDir, userName, agileflowFolder);
72
+
73
+ // Create manifest
74
+ spinner.text = 'Creating manifest...';
75
+ await this.createManifest(cfgDir, ides);
76
+
77
+ // Count installed items
78
+ const counts = await this.countInstalledItems(agileflowDir);
79
+
80
+ spinner.succeed('Core installation complete');
81
+
82
+ return {
83
+ success: true,
84
+ path: agileflowDir,
85
+ projectDir: directory,
86
+ counts,
87
+ };
88
+ } catch (error) {
89
+ spinner.fail('Installation failed');
90
+ throw error;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Copy content from source to destination with placeholder replacement
96
+ * @param {string} source - Source directory
97
+ * @param {string} dest - Destination directory
98
+ * @param {string} agileflowFolder - AgileFlow folder name
99
+ */
100
+ async copyContent(source, dest, agileflowFolder) {
101
+ const entries = await fs.readdir(source, { withFileTypes: true });
102
+
103
+ for (const entry of entries) {
104
+ const srcPath = path.join(source, entry.name);
105
+ const destPath = path.join(dest, entry.name);
106
+
107
+ if (entry.isDirectory()) {
108
+ await fs.ensureDir(destPath);
109
+ await this.copyContent(srcPath, destPath, agileflowFolder);
110
+ } else {
111
+ await this.copyFileWithReplacements(srcPath, destPath, agileflowFolder);
112
+ }
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Copy legacy content structure (from root commands/agents/skills)
118
+ * @param {string} projectDir - Project directory
119
+ * @param {string} agileflowDir - AgileFlow installation directory
120
+ * @param {string} agileflowFolder - AgileFlow folder name
121
+ */
122
+ async copyLegacyContent(projectDir, agileflowDir, agileflowFolder) {
123
+ const packageRoot = this.packageRoot;
124
+
125
+ // Copy commands
126
+ const commandsSource = path.join(packageRoot, 'commands');
127
+ const commandsDest = path.join(agileflowDir, 'commands');
128
+ if (await fs.pathExists(commandsSource)) {
129
+ await fs.ensureDir(commandsDest);
130
+ await this.copyContent(commandsSource, commandsDest, agileflowFolder);
131
+ }
132
+
133
+ // Copy agents
134
+ const agentsSource = path.join(packageRoot, 'agents');
135
+ const agentsDest = path.join(agileflowDir, 'agents');
136
+ if (await fs.pathExists(agentsSource)) {
137
+ await fs.ensureDir(agentsDest);
138
+ await this.copyContent(agentsSource, agentsDest, agileflowFolder);
139
+ }
140
+
141
+ // Copy skills
142
+ const skillsSource = path.join(packageRoot, 'skills');
143
+ const skillsDest = path.join(agileflowDir, 'skills');
144
+ if (await fs.pathExists(skillsSource)) {
145
+ await fs.ensureDir(skillsDest);
146
+ await this.copyContent(skillsSource, skillsDest, agileflowFolder);
147
+ }
148
+
149
+ // Copy templates
150
+ const templatesSource = path.join(packageRoot, 'templates');
151
+ const templatesDest = path.join(agileflowDir, 'templates');
152
+ if (await fs.pathExists(templatesSource)) {
153
+ await fs.ensureDir(templatesDest);
154
+ await this.copyContent(templatesSource, templatesDest, agileflowFolder);
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Copy a file with placeholder replacements
160
+ * @param {string} source - Source file path
161
+ * @param {string} dest - Destination file path
162
+ * @param {string} agileflowFolder - AgileFlow folder name
163
+ */
164
+ async copyFileWithReplacements(source, dest, agileflowFolder) {
165
+ const textExtensions = ['.md', '.yaml', '.yml', '.txt', '.json'];
166
+ const ext = path.extname(source).toLowerCase();
167
+
168
+ if (textExtensions.includes(ext)) {
169
+ let content = await fs.readFile(source, 'utf8');
170
+
171
+ // Replace placeholders
172
+ content = content.replace(/\{agileflow_folder\}/g, agileflowFolder);
173
+ content = content.replace(/\{project-root\}/g, '{project-root}'); // Keep as-is for runtime
174
+
175
+ await fs.writeFile(dest, content, 'utf8');
176
+ } else {
177
+ await fs.copy(source, dest);
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Create configuration file
183
+ * @param {string} agileflowDir - AgileFlow directory
184
+ * @param {string} userName - User name
185
+ * @param {string} agileflowFolder - AgileFlow folder name
186
+ */
187
+ async createConfig(agileflowDir, userName, agileflowFolder) {
188
+ const config = {
189
+ version: require(path.join(this.packageRoot, 'package.json')).version,
190
+ user_name: userName,
191
+ agileflow_folder: agileflowFolder,
192
+ communication_language: 'English',
193
+ created_at: new Date().toISOString(),
194
+ };
195
+
196
+ const configPath = path.join(agileflowDir, 'config.yaml');
197
+ await fs.writeFile(configPath, yaml.dump(config), 'utf8');
198
+ }
199
+
200
+ /**
201
+ * Create manifest file
202
+ * @param {string} cfgDir - Config directory
203
+ * @param {string[]} ides - Selected IDEs
204
+ */
205
+ async createManifest(cfgDir, ides) {
206
+ const packageJson = require(path.join(this.packageRoot, 'package.json'));
207
+
208
+ const manifest = {
209
+ version: packageJson.version,
210
+ installed_at: new Date().toISOString(),
211
+ updated_at: new Date().toISOString(),
212
+ ides: ides,
213
+ modules: ['core'],
214
+ };
215
+
216
+ const manifestPath = path.join(cfgDir, 'manifest.yaml');
217
+ await fs.writeFile(manifestPath, yaml.dump(manifest), 'utf8');
218
+ }
219
+
220
+ /**
221
+ * Count installed items
222
+ * @param {string} agileflowDir - AgileFlow directory
223
+ * @returns {Promise<Object>} Counts
224
+ */
225
+ async countInstalledItems(agileflowDir) {
226
+ const counts = {
227
+ agents: 0,
228
+ commands: 0,
229
+ skills: 0,
230
+ };
231
+
232
+ // Count agents
233
+ const agentsDir = path.join(agileflowDir, 'agents');
234
+ if (await fs.pathExists(agentsDir)) {
235
+ const files = await fs.readdir(agentsDir);
236
+ counts.agents = files.filter((f) => f.endsWith('.md')).length;
237
+ }
238
+
239
+ // Count commands
240
+ const commandsDir = path.join(agileflowDir, 'commands');
241
+ if (await fs.pathExists(commandsDir)) {
242
+ const files = await fs.readdir(commandsDir);
243
+ counts.commands = files.filter((f) => f.endsWith('.md')).length;
244
+ }
245
+
246
+ // Count skills
247
+ const skillsDir = path.join(agileflowDir, 'skills');
248
+ if (await fs.pathExists(skillsDir)) {
249
+ const entries = await fs.readdir(skillsDir, { withFileTypes: true });
250
+ counts.skills = entries.filter((e) => e.isDirectory()).length;
251
+ }
252
+
253
+ return counts;
254
+ }
255
+
256
+ /**
257
+ * Get installation status
258
+ * @param {string} directory - Project directory
259
+ * @returns {Promise<Object>} Installation status
260
+ */
261
+ async getStatus(directory) {
262
+ const status = {
263
+ installed: false,
264
+ path: null,
265
+ version: null,
266
+ ides: [],
267
+ modules: [],
268
+ };
269
+
270
+ // Look for AgileFlow installation
271
+ const possibleFolders = ['.agileflow', 'agileflow', '.aflow'];
272
+
273
+ for (const folder of possibleFolders) {
274
+ const agileflowDir = path.join(directory, folder);
275
+ const manifestPath = path.join(agileflowDir, '_cfg', 'manifest.yaml');
276
+
277
+ if (await fs.pathExists(manifestPath)) {
278
+ status.installed = true;
279
+ status.path = agileflowDir;
280
+
281
+ const manifestContent = await fs.readFile(manifestPath, 'utf8');
282
+ const manifest = yaml.load(manifestContent);
283
+
284
+ status.version = manifest.version;
285
+ status.ides = manifest.ides || [];
286
+ status.modules = manifest.modules || [];
287
+
288
+ break;
289
+ }
290
+ }
291
+
292
+ return status;
293
+ }
294
+ }
295
+
296
+ module.exports = { Installer, getSourcePath, getPackageRoot };