agileflow 3.3.0 → 3.4.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 (210) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +6 -6
  3. package/lib/skill-loader.js +0 -1
  4. package/package.json +1 -1
  5. package/scripts/agileflow-statusline.sh +81 -0
  6. package/scripts/agileflow-welcome.js +79 -0
  7. package/scripts/claude-tmux.sh +90 -23
  8. package/scripts/claude-watchdog.sh +225 -0
  9. package/scripts/generators/agent-registry.js +14 -1
  10. package/scripts/generators/inject-babysit.js +22 -9
  11. package/scripts/generators/inject-help.js +19 -9
  12. package/scripts/lib/ac-test-matcher.js +452 -0
  13. package/scripts/lib/audit-cleanup.js +250 -0
  14. package/scripts/lib/audit-registry.js +304 -0
  15. package/scripts/lib/configure-features.js +35 -0
  16. package/scripts/lib/feature-catalog.js +3 -3
  17. package/scripts/lib/gate-enforcer.js +295 -0
  18. package/scripts/lib/model-profiles.js +118 -0
  19. package/scripts/lib/quality-gates.js +163 -0
  20. package/scripts/lib/signal-detectors.js +44 -1
  21. package/scripts/lib/skill-catalog.js +557 -0
  22. package/scripts/lib/skill-recommender.js +311 -0
  23. package/scripts/lib/status-writer.js +255 -0
  24. package/scripts/lib/story-claiming.js +128 -45
  25. package/scripts/lib/task-sync.js +32 -38
  26. package/scripts/lib/tdd-phase-manager.js +455 -0
  27. package/scripts/lib/team-events.js +34 -3
  28. package/scripts/lib/tmux-audit-monitor.js +611 -0
  29. package/scripts/lib/tmux-group-colors.js +113 -0
  30. package/scripts/lib/tool-registry.yaml +241 -0
  31. package/scripts/lib/tool-shed.js +441 -0
  32. package/scripts/messaging-bridge.js +209 -1
  33. package/scripts/native-team-observer.js +219 -0
  34. package/scripts/obtain-context.js +14 -0
  35. package/scripts/ralph-loop.js +30 -5
  36. package/scripts/smart-detect.js +21 -0
  37. package/scripts/spawn-audit-sessions.js +877 -0
  38. package/scripts/team-manager.js +56 -16
  39. package/scripts/tmux-close-windows.sh +180 -0
  40. package/src/core/agents/a11y-analyzer-aria.md +155 -0
  41. package/src/core/agents/a11y-analyzer-forms.md +162 -0
  42. package/src/core/agents/a11y-analyzer-keyboard.md +175 -0
  43. package/src/core/agents/a11y-analyzer-semantic.md +153 -0
  44. package/src/core/agents/a11y-analyzer-visual.md +158 -0
  45. package/src/core/agents/a11y-consensus.md +248 -0
  46. package/src/core/agents/ads-audit-budget.md +181 -0
  47. package/src/core/agents/ads-audit-compliance.md +169 -0
  48. package/src/core/agents/ads-audit-creative.md +164 -0
  49. package/src/core/agents/ads-audit-google.md +226 -0
  50. package/src/core/agents/ads-audit-meta.md +183 -0
  51. package/src/core/agents/ads-audit-tracking.md +197 -0
  52. package/src/core/agents/ads-consensus.md +396 -0
  53. package/src/core/agents/ads-generate.md +145 -0
  54. package/src/core/agents/ads-performance-tracker.md +197 -0
  55. package/src/core/agents/api-quality-analyzer-conventions.md +148 -0
  56. package/src/core/agents/api-quality-analyzer-docs.md +176 -0
  57. package/src/core/agents/api-quality-analyzer-errors.md +183 -0
  58. package/src/core/agents/api-quality-analyzer-pagination.md +171 -0
  59. package/src/core/agents/api-quality-analyzer-versioning.md +143 -0
  60. package/src/core/agents/api-quality-consensus.md +214 -0
  61. package/src/core/agents/arch-analyzer-circular.md +148 -0
  62. package/src/core/agents/arch-analyzer-complexity.md +171 -0
  63. package/src/core/agents/arch-analyzer-coupling.md +146 -0
  64. package/src/core/agents/arch-analyzer-layering.md +151 -0
  65. package/src/core/agents/arch-analyzer-patterns.md +162 -0
  66. package/src/core/agents/arch-consensus.md +227 -0
  67. package/src/core/agents/brainstorm-analyzer-features.md +169 -0
  68. package/src/core/agents/brainstorm-analyzer-growth.md +161 -0
  69. package/src/core/agents/brainstorm-analyzer-integration.md +172 -0
  70. package/src/core/agents/brainstorm-analyzer-market.md +147 -0
  71. package/src/core/agents/brainstorm-analyzer-ux.md +167 -0
  72. package/src/core/agents/brainstorm-consensus.md +237 -0
  73. package/src/core/agents/completeness-consensus.md +5 -5
  74. package/src/core/agents/perf-consensus.md +2 -2
  75. package/src/core/agents/security-consensus.md +2 -2
  76. package/src/core/agents/seo-analyzer-content.md +167 -0
  77. package/src/core/agents/seo-analyzer-images.md +187 -0
  78. package/src/core/agents/seo-analyzer-performance.md +206 -0
  79. package/src/core/agents/seo-analyzer-schema.md +176 -0
  80. package/src/core/agents/seo-analyzer-sitemap.md +172 -0
  81. package/src/core/agents/seo-analyzer-technical.md +144 -0
  82. package/src/core/agents/seo-consensus.md +289 -0
  83. package/src/core/agents/test-consensus.md +2 -2
  84. package/src/core/commands/adr.md +1 -0
  85. package/src/core/commands/ads/audit.md +375 -0
  86. package/src/core/commands/ads/budget.md +97 -0
  87. package/src/core/commands/ads/competitor.md +112 -0
  88. package/src/core/commands/ads/creative.md +85 -0
  89. package/src/core/commands/ads/generate.md +238 -0
  90. package/src/core/commands/ads/google.md +112 -0
  91. package/src/core/commands/ads/health.md +327 -0
  92. package/src/core/commands/ads/landing.md +119 -0
  93. package/src/core/commands/ads/linkedin.md +112 -0
  94. package/src/core/commands/ads/meta.md +91 -0
  95. package/src/core/commands/ads/microsoft.md +115 -0
  96. package/src/core/commands/ads/plan.md +321 -0
  97. package/src/core/commands/ads/test-plan.md +317 -0
  98. package/src/core/commands/ads/tiktok.md +129 -0
  99. package/src/core/commands/ads/track.md +288 -0
  100. package/src/core/commands/ads/youtube.md +124 -0
  101. package/src/core/commands/ads.md +140 -0
  102. package/src/core/commands/assign.md +1 -0
  103. package/src/core/commands/audit.md +43 -6
  104. package/src/core/commands/babysit.md +315 -1266
  105. package/src/core/commands/baseline.md +1 -0
  106. package/src/core/commands/blockers.md +1 -0
  107. package/src/core/commands/board.md +1 -0
  108. package/src/core/commands/changelog.md +1 -0
  109. package/src/core/commands/choose.md +1 -0
  110. package/src/core/commands/ci.md +1 -0
  111. package/src/core/commands/code/accessibility.md +347 -0
  112. package/src/core/commands/code/api.md +297 -0
  113. package/src/core/commands/code/architecture.md +297 -0
  114. package/src/core/commands/{audit → code}/completeness.md +72 -25
  115. package/src/core/commands/{audit → code}/legal.md +63 -16
  116. package/src/core/commands/{audit → code}/logic.md +64 -16
  117. package/src/core/commands/{audit → code}/performance.md +67 -20
  118. package/src/core/commands/{audit → code}/security.md +69 -19
  119. package/src/core/commands/{audit → code}/test.md +67 -20
  120. package/src/core/commands/configure.md +1 -0
  121. package/src/core/commands/council.md +1 -0
  122. package/src/core/commands/deploy.md +1 -0
  123. package/src/core/commands/diagnose.md +1 -0
  124. package/src/core/commands/docs.md +1 -0
  125. package/src/core/commands/epic/edit.md +213 -0
  126. package/src/core/commands/epic.md +1 -0
  127. package/src/core/commands/export.md +238 -0
  128. package/src/core/commands/help.md +16 -1
  129. package/src/core/commands/{discovery → ideate}/brief.md +12 -12
  130. package/src/core/commands/{discovery/new.md → ideate/discover.md} +20 -16
  131. package/src/core/commands/ideate/features.md +496 -0
  132. package/src/core/commands/ideate/new.md +158 -124
  133. package/src/core/commands/impact.md +1 -0
  134. package/src/core/commands/learn/explain.md +118 -0
  135. package/src/core/commands/learn/glossary.md +135 -0
  136. package/src/core/commands/learn/patterns.md +138 -0
  137. package/src/core/commands/learn/tour.md +126 -0
  138. package/src/core/commands/migrate/codemods.md +151 -0
  139. package/src/core/commands/migrate/plan.md +131 -0
  140. package/src/core/commands/migrate/scan.md +114 -0
  141. package/src/core/commands/migrate/validate.md +119 -0
  142. package/src/core/commands/multi-expert.md +1 -0
  143. package/src/core/commands/pr.md +1 -0
  144. package/src/core/commands/review.md +1 -0
  145. package/src/core/commands/seo/audit.md +373 -0
  146. package/src/core/commands/seo/competitor.md +174 -0
  147. package/src/core/commands/seo/content.md +107 -0
  148. package/src/core/commands/seo/geo.md +229 -0
  149. package/src/core/commands/seo/hreflang.md +140 -0
  150. package/src/core/commands/seo/images.md +96 -0
  151. package/src/core/commands/seo/page.md +198 -0
  152. package/src/core/commands/seo/plan.md +163 -0
  153. package/src/core/commands/seo/programmatic.md +131 -0
  154. package/src/core/commands/seo/references/cwv-thresholds.md +64 -0
  155. package/src/core/commands/seo/references/eeat-framework.md +110 -0
  156. package/src/core/commands/seo/references/quality-gates.md +91 -0
  157. package/src/core/commands/seo/references/schema-types.md +102 -0
  158. package/src/core/commands/seo/schema.md +183 -0
  159. package/src/core/commands/seo/sitemap.md +97 -0
  160. package/src/core/commands/seo/technical.md +100 -0
  161. package/src/core/commands/seo.md +107 -0
  162. package/src/core/commands/skill/list.md +68 -212
  163. package/src/core/commands/skill/recommend.md +216 -0
  164. package/src/core/commands/sprint.md +1 -0
  165. package/src/core/commands/status/undo.md +191 -0
  166. package/src/core/commands/status.md +1 -0
  167. package/src/core/commands/story/edit.md +204 -0
  168. package/src/core/commands/story/view.md +29 -7
  169. package/src/core/commands/story-validate.md +1 -0
  170. package/src/core/commands/story.md +1 -0
  171. package/src/core/commands/tdd-next.md +238 -0
  172. package/src/core/commands/tdd.md +211 -0
  173. package/src/core/commands/team/start.md +10 -6
  174. package/src/core/commands/tests.md +1 -0
  175. package/src/core/commands/verify.md +27 -1
  176. package/src/core/commands/workflow.md +2 -0
  177. package/src/core/experts/_core-expertise.yaml +105 -0
  178. package/src/core/experts/analytics/expertise.yaml +5 -99
  179. package/src/core/experts/codebase-query/expertise.yaml +3 -72
  180. package/src/core/experts/compliance/expertise.yaml +6 -72
  181. package/src/core/experts/database/expertise.yaml +9 -52
  182. package/src/core/experts/documentation/expertise.yaml +7 -140
  183. package/src/core/experts/integrations/expertise.yaml +7 -127
  184. package/src/core/experts/mentor/expertise.yaml +8 -35
  185. package/src/core/experts/monitoring/expertise.yaml +7 -49
  186. package/src/core/experts/performance/expertise.yaml +1 -26
  187. package/src/core/experts/security/expertise.yaml +9 -34
  188. package/src/core/experts/ui/expertise.yaml +6 -36
  189. package/src/core/knowledge/ads/ad-audit-checklist-scoring.md +424 -0
  190. package/src/core/knowledge/ads/ad-optimization-logic.md +590 -0
  191. package/src/core/knowledge/ads/ad-technical-specifications.md +385 -0
  192. package/src/core/knowledge/ads/definitive-advertising-reference-2026.md +506 -0
  193. package/src/core/knowledge/ads/paid-advertising-research-2026.md +445 -0
  194. package/src/core/teams/backend.json +41 -0
  195. package/src/core/teams/frontend.json +41 -0
  196. package/src/core/teams/qa.json +41 -0
  197. package/src/core/teams/solo.json +35 -0
  198. package/src/core/templates/agileflow-metadata.json +20 -1
  199. package/tools/cli/commands/setup.js +85 -3
  200. package/tools/cli/commands/update.js +42 -0
  201. package/tools/cli/installers/ide/_base-ide.js +42 -5
  202. package/tools/cli/installers/ide/claude-code.js +71 -3
  203. package/tools/cli/lib/content-injector.js +160 -12
  204. package/tools/cli/lib/docs-setup.js +1 -1
  205. package/src/core/commands/skill/create.md +0 -698
  206. package/src/core/commands/skill/delete.md +0 -316
  207. package/src/core/commands/skill/edit.md +0 -359
  208. package/src/core/commands/skill/test.md +0 -394
  209. package/src/core/commands/skill/upgrade.md +0 -552
  210. package/src/core/templates/skill-template.md +0 -117
@@ -71,7 +71,8 @@
71
71
  "wip": true,
72
72
  "context": true,
73
73
  "cost": true,
74
- "git": true
74
+ "git": true,
75
+ "ultradeep": true
75
76
  }
76
77
  },
77
78
  "mcp": {
@@ -127,5 +128,23 @@
127
128
  "security": {
128
129
  "mcpJsonGitignored": false,
129
130
  "envGitignored": false
131
+ },
132
+ "models": {
133
+ "default_audit_model": null,
134
+ "description": "Override via MODEL=haiku|sonnet|opus in audit command arguments. null = use agent defaults."
135
+ },
136
+ "ci_feedback_loops": {
137
+ "enabled": true,
138
+ "max_rounds": 3,
139
+ "description": "Auto-retry agent work when CI/tests fail, up to max_rounds before escalating to human"
140
+ },
141
+ "ultradeep": {
142
+ "tab_naming": "prefix:name",
143
+ "custom_colors": null,
144
+ "auto_attach": true,
145
+ "completion_timeout_minutes": 30,
146
+ "max_sessions_per_audit": 20,
147
+ "stagger_seconds": 3,
148
+ "max_concurrent": 0
130
149
  }
131
150
  }
@@ -89,7 +89,14 @@ module.exports = {
89
89
  config = await promptInstall();
90
90
  }
91
91
 
92
- displaySection('Setting Up AgileFlow', `Target: ${config.directory}`);
92
+ const totalSteps = 5;
93
+ let currentStep = 0;
94
+ const step = label => {
95
+ currentStep++;
96
+ return `[${currentStep}/${totalSteps}] ${label}`;
97
+ };
98
+
99
+ displaySection(step('Installing Core Content'), `Target: ${config.directory}`);
93
100
 
94
101
  // Run core installation
95
102
  const coreResult = await installer.install(config);
@@ -104,17 +111,81 @@ module.exports = {
104
111
  success(`Installed ${coreResult.counts.skills} skills`);
105
112
 
106
113
  // Setup IDE configurations
107
- displaySection('Configuring IDEs');
114
+ displaySection(step('Configuring IDEs'));
108
115
 
109
116
  ideManager.setAgileflowFolder(config.agileflowFolder);
110
117
  ideManager.setDocsFolder(config.docsFolder);
111
118
 
119
+ // Check for existing IDE configs before overwriting
120
+ if (!options.yes) {
121
+ const existingConfigs = [];
122
+ const ideConfigDirs = {
123
+ 'claude-code': '.claude',
124
+ cursor: '.cursor',
125
+ windsurf: '.windsurf',
126
+ };
127
+
128
+ for (const ide of config.ides) {
129
+ const configDir = ideConfigDirs[ide];
130
+ if (configDir) {
131
+ const fullPath = path.join(config.directory, configDir);
132
+ if (fs.existsSync(fullPath)) {
133
+ existingConfigs.push({ ide, dir: configDir });
134
+ }
135
+ }
136
+ }
137
+
138
+ if (existingConfigs.length > 0) {
139
+ const { confirmOverwrite } = require('inquirer');
140
+ const configList = existingConfigs.map(c => ` ${c.dir}/`).join('\n');
141
+ console.log(chalk.yellow(`\n Existing IDE configs detected:\n${configList}\n`));
142
+ console.log(
143
+ chalk.dim(
144
+ ' AgileFlow will add commands and hooks to these directories.\n' +
145
+ ' Existing settings will be merged (not replaced).\n'
146
+ )
147
+ );
148
+
149
+ let proceed = true;
150
+ try {
151
+ const inquirer = require('inquirer');
152
+ const answer = await inquirer.prompt([
153
+ {
154
+ type: 'confirm',
155
+ name: 'proceed',
156
+ message: 'Continue with IDE configuration?',
157
+ default: true,
158
+ },
159
+ ]);
160
+ proceed = answer.proceed;
161
+ } catch {
162
+ // If inquirer not available or stdin not interactive, proceed
163
+ proceed = true;
164
+ }
165
+
166
+ if (!proceed) {
167
+ info('Skipping IDE configuration. Core installation is complete.');
168
+ console.log(chalk.dim(' Run setup again to configure IDEs later.\n'));
169
+ // Skip to docs structure
170
+ displaySection('Creating Documentation Structure', `Folder: ${config.docsFolder}/`);
171
+ const docsResult = await createDocsStructure(config.directory, config.docsFolder, {
172
+ updateGitignore: config.updateGitignore,
173
+ });
174
+ if (!docsResult.success) {
175
+ error('Failed to create docs structure');
176
+ }
177
+ console.log(chalk.green('\n✨ Setup complete (without IDE configs)!\n'));
178
+ return;
179
+ }
180
+ }
181
+ }
182
+
112
183
  for (const ide of config.ides) {
113
184
  await ideManager.setup(ide, config.directory, coreResult.path);
114
185
  }
115
186
 
116
187
  // Create docs structure
117
- displaySection('Creating Documentation Structure', `Folder: ${config.docsFolder}/`);
188
+ displaySection(step('Creating Documentation Structure'), `Folder: ${config.docsFolder}/`);
118
189
  const docsResult = await createDocsStructure(config.directory, config.docsFolder, {
119
190
  updateGitignore: config.updateGitignore,
120
191
  });
@@ -127,6 +198,7 @@ module.exports = {
127
198
  }
128
199
 
129
200
  // Update metadata with config tracking
201
+ displaySection(step('Updating Configuration'));
130
202
  try {
131
203
  const metadataPath = path.join(
132
204
  config.directory,
@@ -149,6 +221,16 @@ module.exports = {
149
221
  }
150
222
 
151
223
  // Final summary
224
+ displaySection(step('Verifying Installation'));
225
+ const { counts } = coreResult;
226
+ const totalItems = (counts.commands || 0) + (counts.agents || 0) + (counts.skills || 0);
227
+ console.log(
228
+ chalk.green(
229
+ ` Setup complete: ${counts.commands} commands, ${counts.agents} agents, ${counts.skills} skills installed`
230
+ )
231
+ );
232
+ console.log(chalk.dim(` IDEs configured: ${config.ides.join(', ')}`));
233
+
152
234
  console.log(chalk.green('\n✨ Setup complete!\n'));
153
235
 
154
236
  console.log(chalk.bold('Get started:'));
@@ -230,6 +230,48 @@ module.exports = {
230
230
 
231
231
  console.log(chalk.green(`\n✨ Update complete! (${status.version} → ${latestVersion})\n`));
232
232
 
233
+ // Show changelog diff between old and new version
234
+ try {
235
+ const fs = require('node:fs');
236
+ const changelogPath = path.join(status.path, 'CHANGELOG.md');
237
+ if (fs.existsSync(changelogPath)) {
238
+ const changelog = fs.readFileSync(changelogPath, 'utf8');
239
+ const oldVer = status.version.replace(/^v/, '');
240
+ const newVer = latestVersion.replace(/^v/, '');
241
+
242
+ // Extract sections between old and new version headers
243
+ const versionPattern = /^##\s+\[?\d+\.\d+\.\d+\]?/m;
244
+ const lines = changelog.split('\n');
245
+ const relevantLines = [];
246
+ let capturing = false;
247
+
248
+ for (const line of lines) {
249
+ if (versionPattern.test(line)) {
250
+ if (line.includes(oldVer)) {
251
+ break; // Stop at old version
252
+ }
253
+ capturing = true;
254
+ }
255
+ if (capturing) {
256
+ relevantLines.push(line);
257
+ }
258
+ }
259
+
260
+ if (relevantLines.length > 0) {
261
+ const maxLines = 20;
262
+ const display = relevantLines.slice(0, maxLines);
263
+ console.log(chalk.hex('#e8683a').bold(` What's New in v${newVer}:\n`));
264
+ display.forEach(l => console.log(chalk.dim(` ${l}`)));
265
+ if (relevantLines.length > maxLines) {
266
+ console.log(chalk.dim(` ... and ${relevantLines.length - maxLines} more lines`));
267
+ }
268
+ console.log(chalk.dim(`\n Run /agileflow:whats-new for full changelog\n`));
269
+ }
270
+ }
271
+ } catch {
272
+ // Changelog display is non-critical
273
+ }
274
+
233
275
  // If running from outdated global installation, remind user to update it
234
276
  if (
235
277
  npmLatestVersion &&
@@ -82,15 +82,18 @@ class BaseIdeSetup {
82
82
  * Uses content-transformer module for consistent injection
83
83
  * @param {string} content - Template file content
84
84
  * @param {string} agileflowDir - AgileFlow installation directory
85
+ * @param {Object} [options] - Additional injection options
86
+ * @param {boolean} [options.minimal] - When true, skip full list injection (use discovery pointers)
85
87
  * @returns {string} Content with placeholders replaced
86
88
  */
87
- injectDynamicContent(content, agileflowDir) {
89
+ injectDynamicContent(content, agileflowDir, options = {}) {
88
90
  // agileflowDir is the user's .agileflow installation directory
89
91
  // which has agents/, commands/, skills/ at the root level
90
92
  return injectDynamicContentHelper(content, {
91
93
  coreDir: agileflowDir,
92
94
  agileflowFolder: this.agileflowFolder,
93
95
  version: this.getVersion(),
96
+ minimal: options.minimal || false,
94
97
  });
95
98
  }
96
99
 
@@ -107,6 +110,30 @@ class BaseIdeSetup {
107
110
  }
108
111
  }
109
112
 
113
+ /**
114
+ * Detect minimal context mode from project metadata.
115
+ * Reads the contextVerbosity setting from /configure.
116
+ * @param {string} projectDir - Project directory
117
+ * @returns {boolean} True if minimal mode should be used
118
+ */
119
+ _detectMinimalMode(projectDir) {
120
+ try {
121
+ const metadataPath = path.join(
122
+ projectDir,
123
+ this.docsFolder,
124
+ '00-meta',
125
+ 'agileflow-metadata.json'
126
+ );
127
+ if (!fs.existsSync(metadataPath)) return false;
128
+ const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
129
+ const mode = metadata?.features?.contextVerbosity?.mode;
130
+ if (mode === 'minimal') return true;
131
+ return false;
132
+ } catch {
133
+ return false;
134
+ }
135
+ }
136
+
110
137
  /**
111
138
  * Main setup method - must be implemented by subclasses
112
139
  * @param {string} projectDir - Project directory
@@ -128,6 +155,7 @@ class BaseIdeSetup {
128
155
  * @param {string} config.agileflowFolder - AgileFlow folder name (e.g., 'agileflow', 'AgileFlow')
129
156
  * @param {string} [config.commandLabel='commands'] - Label for commands in output (e.g., 'workflows')
130
157
  * @param {string} [config.agentLabel='agents'] - Label for agents in output
158
+ * @param {boolean} [config.minimal=false] - When true, skip full agent/command list injection. Auto-detected from metadata if not set.
131
159
  * @returns {Promise<{success: boolean, commands: number, agents: number}>}
132
160
  */
133
161
  async setupStandard(projectDir, agileflowDir, config) {
@@ -136,8 +164,12 @@ class BaseIdeSetup {
136
164
  agileflowFolder,
137
165
  commandLabel = 'commands',
138
166
  agentLabel = 'agents',
167
+ minimal: explicitMinimal,
139
168
  } = config;
140
169
 
170
+ // Auto-detect minimal mode from /configure context verbosity setting
171
+ const minimal = explicitMinimal ?? this._detectMinimalMode(projectDir);
172
+
141
173
  console.log(chalk.hex('#e8683a')(` Setting up ${this.displayName}...`));
142
174
 
143
175
  // Clean up old installation first
@@ -154,7 +186,9 @@ class BaseIdeSetup {
154
186
  commandsSource,
155
187
  agileflowTargetDir,
156
188
  agileflowDir,
157
- true // Inject dynamic content
189
+ true, // Inject dynamic content
190
+ null, // No IDE transform
191
+ { minimal } // Pass minimal flag for content injection
158
192
  );
159
193
 
160
194
  // Install agents as subdirectory
@@ -379,6 +413,7 @@ class BaseIdeSetup {
379
413
  * @param {string} agileflowDir - AgileFlow installation directory (for dynamic content)
380
414
  * @param {boolean} injectDynamic - Whether to inject dynamic content (only for top-level commands)
381
415
  * @param {Function} [ideTransform] - Optional IDE transformation function: (content, filename) => string
416
+ * @param {Object} [injectionOptions] - Options passed to injectDynamicContent (e.g., { minimal: true })
382
417
  * @returns {Promise<{commands: number, subdirs: number}>} Count of installed items
383
418
  * @throws {CommandInstallationError} If command installation fails
384
419
  * @throws {FilePermissionError} If permission denied
@@ -402,7 +437,8 @@ class BaseIdeSetup {
402
437
  targetDir,
403
438
  agileflowDir,
404
439
  injectDynamic = false,
405
- ideTransform = null
440
+ ideTransform = null,
441
+ injectionOptions = {}
406
442
  ) {
407
443
  let commandCount = 0;
408
444
  let subdirCount = 0;
@@ -434,7 +470,7 @@ class BaseIdeSetup {
434
470
  // Inject dynamic content if enabled (for top-level commands)
435
471
  if (injectDynamic) {
436
472
  try {
437
- content = this.injectDynamicContent(content, agileflowDir);
473
+ content = this.injectDynamicContent(content, agileflowDir, injectionOptions);
438
474
  } catch (injectionError) {
439
475
  throw new ContentInjectionError(this.displayName, sourcePath, injectionError.message);
440
476
  }
@@ -467,7 +503,8 @@ class BaseIdeSetup {
467
503
  targetPath,
468
504
  agileflowDir,
469
505
  false, // Don't inject dynamic content in subdirectories
470
- ideTransform // Pass ideTransform to recursive calls
506
+ ideTransform, // Pass ideTransform to recursive calls
507
+ injectionOptions // Pass injection options to recursive calls
471
508
  );
472
509
  commandCount += subResult.commands;
473
510
  subdirCount += 1 + subResult.subdirs;
@@ -52,11 +52,11 @@ class ClaudeCodeSetup extends BaseIdeSetup {
52
52
  await this.installCommandsRecursive(agentsSource, spawnableAgentsDir, agileflowDir, false);
53
53
  console.log(chalk.dim(` - Spawnable agents: .claude/agents/agileflow/`));
54
54
 
55
- // Claude Code specific: Create skills directory for user-generated skills
56
- // AgileFlow no longer ships static skills - users generate them via /agileflow:skill:create
55
+ // Claude Code specific: Create skills directory for marketplace skills
56
+ // Users browse and install skills via /agileflow:skill:recommend or npx skills add
57
57
  const skillsTargetDir = path.join(ideDir, 'skills');
58
58
  await this.ensureDir(skillsTargetDir);
59
- console.log(chalk.dim(` - Skills directory: .claude/skills/ (for user-generated skills)`));
59
+ console.log(chalk.dim(` - Skills directory: .claude/skills/ (for marketplace skills)`));
60
60
 
61
61
  // Claude Code specific: Setup damage control hooks
62
62
  await this.setupDamageControl(projectDir, agileflowDir, ideDir, options);
@@ -64,6 +64,9 @@ class ClaudeCodeSetup extends BaseIdeSetup {
64
64
  // Claude Code specific: Setup SessionStart hooks (welcome, archive, context-loader)
65
65
  await this.setupSessionStartHooks(projectDir, agileflowDir, ideDir, options);
66
66
 
67
+ // Claude Code specific: Setup PostToolUse hooks (native team observer)
68
+ await this.setupPostToolUseHooks(projectDir, agileflowDir, ideDir, options);
69
+
67
70
  return result;
68
71
  }
69
72
 
@@ -297,6 +300,71 @@ class ClaudeCodeSetup extends BaseIdeSetup {
297
300
  );
298
301
  }
299
302
 
303
+ /**
304
+ * Setup PostToolUse hooks for native Agent Teams observability.
305
+ * Registers native-team-observer.js for TeamCreate, SendMessage, ListTeams.
306
+ * @param {string} projectDir - Project directory
307
+ * @param {string} agileflowDir - AgileFlow installation directory
308
+ * @param {string} claudeDir - .claude directory path
309
+ * @param {Object} options - Setup options
310
+ */
311
+ async setupPostToolUseHooks(projectDir, agileflowDir, claudeDir, options = {}) {
312
+ const settingsPath = path.join(claudeDir, 'settings.json');
313
+ let settings = {};
314
+
315
+ if (fs.existsSync(settingsPath)) {
316
+ try {
317
+ settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
318
+ } catch (e) {
319
+ settings = {};
320
+ }
321
+ }
322
+
323
+ if (!settings.hooks) settings.hooks = {};
324
+ if (!settings.hooks.PostToolUse) settings.hooks.PostToolUse = [];
325
+
326
+ const observerCommand = 'node $CLAUDE_PROJECT_DIR/.agileflow/scripts/native-team-observer.js';
327
+
328
+ const postToolUseHooks = [
329
+ {
330
+ matcher: 'TeamCreate',
331
+ hooks: [{ type: 'command', command: observerCommand, timeout: 5000 }],
332
+ },
333
+ {
334
+ matcher: 'SendMessage',
335
+ hooks: [{ type: 'command', command: observerCommand, timeout: 5000 }],
336
+ },
337
+ {
338
+ matcher: 'ListTeams',
339
+ hooks: [{ type: 'command', command: observerCommand, timeout: 5000 }],
340
+ },
341
+ ];
342
+
343
+ // Merge with existing hooks (don't duplicate)
344
+ for (const newHook of postToolUseHooks) {
345
+ const existingIdx = settings.hooks.PostToolUse.findIndex(h => h.matcher === newHook.matcher);
346
+ if (existingIdx === -1) {
347
+ settings.hooks.PostToolUse.push(newHook);
348
+ } else {
349
+ const existing = settings.hooks.PostToolUse[existingIdx];
350
+ if (!existing.hooks) existing.hooks = [];
351
+ const hasObserver = existing.hooks.some(
352
+ h => h.type === 'command' && h.command && h.command.includes('native-team-observer')
353
+ );
354
+ if (!hasObserver) {
355
+ existing.hooks.push(newHook.hooks[0]);
356
+ }
357
+ }
358
+ }
359
+
360
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
361
+ console.log(
362
+ chalk.dim(
363
+ ` - PostToolUse hooks: native team observer (TeamCreate, SendMessage, ListTeams)`
364
+ )
365
+ );
366
+ }
367
+
300
368
  /**
301
369
  * Remove AgileFlow command duplicates from user-level ~/.claude/commands/
302
370
  * When the same command exists in both ~/.claude/commands/ and
@@ -70,9 +70,46 @@ function isPathSafe(filePath, baseDir) {
70
70
  }
71
71
 
72
72
  /**
73
- * Scan agents directory and generate formatted agent list
73
+ * Derive agent category from name for compact grouping.
74
+ * @param {string} name - Agent name
75
+ * @returns {string} Category name
76
+ */
77
+ function categorizeAgent(name) {
78
+ // Audit analyzer families
79
+ const analyzerMatch = name.match(/^(logic|security|perf|test|completeness|legal)-analyzer-/);
80
+ if (analyzerMatch) {
81
+ const familyNames = {
82
+ logic: 'Logic',
83
+ security: 'Security',
84
+ perf: 'Performance',
85
+ test: 'Tests',
86
+ completeness: 'Completeness',
87
+ legal: 'Legal',
88
+ };
89
+ return `Audit - ${familyNames[analyzerMatch[1]] || analyzerMatch[1]}`;
90
+ }
91
+ // Consensus coordinators for audit families
92
+ const consensusMatch = name.match(/^(logic|security|perf|test|completeness|legal)-consensus$/);
93
+ if (consensusMatch) {
94
+ const familyNames = {
95
+ logic: 'Logic',
96
+ security: 'Security',
97
+ perf: 'Performance',
98
+ test: 'Tests',
99
+ completeness: 'Completeness',
100
+ legal: 'Legal',
101
+ };
102
+ return `Audit - ${familyNames[consensusMatch[1]] || consensusMatch[1]}`;
103
+ }
104
+ if (name.startsWith('council-')) return 'Council';
105
+ if (name.endsWith('-validator')) return 'Validation';
106
+ return 'Domain';
107
+ }
108
+
109
+ /**
110
+ * Scan agents directory and generate compact category-grouped agent list
74
111
  * @param {string} agentsDir - Path to agents directory
75
- * @returns {string} Formatted agent list
112
+ * @returns {string} Formatted agent list grouped by category
76
113
  */
77
114
  function generateAgentList(agentsDir) {
78
115
  if (!fs.existsSync(agentsDir)) return '';
@@ -117,16 +154,20 @@ function generateAgentList(agentsDir) {
117
154
 
118
155
  // Sanitize the count value
119
156
  const safeCount = sanitize.count(agents.length);
157
+
158
+ // Group by category for compact output
159
+ const categories = {};
160
+ for (const agent of agents) {
161
+ const cat = categorizeAgent(agent.name);
162
+ if (!categories[cat]) categories[cat] = [];
163
+ categories[cat].push(agent.name);
164
+ }
165
+
120
166
  let output = `**AVAILABLE AGENTS (${safeCount} total)**:\n\n`;
121
167
 
122
- agents.forEach((agent, index) => {
123
- // All values are already sanitized by sanitizeAgentData
124
- output += `${index + 1}. **${agent.name}** (model: ${agent.model})\n`;
125
- output += ` - **Purpose**: ${agent.description}\n`;
126
- output += ` - **Tools**: ${agent.tools.join(', ')}\n`;
127
- output += ` - **Usage**: \`subagent_type: "agileflow-${agent.name}"\`\n`;
128
- output += `\n`;
129
- });
168
+ for (const [category, names] of Object.entries(categories)) {
169
+ output += `**${category}**: ${names.join(', ')}\n`;
170
+ }
130
171
 
131
172
  return output;
132
173
  }
@@ -235,6 +276,94 @@ function generateCommandList(commandsDir) {
235
276
  return output;
236
277
  }
237
278
 
279
+ /**
280
+ * Generate a compact category summary for agents (no individual names).
281
+ * Used by minimal mode and generators that want a discovery-oriented summary.
282
+ * @param {string} agentsDir - Path to agents directory
283
+ * @returns {string} Compact category summary with counts
284
+ */
285
+ function generateAgentSummary(agentsDir) {
286
+ if (!fs.existsSync(agentsDir)) return '';
287
+
288
+ const files = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
289
+ const agents = [];
290
+
291
+ for (const file of files) {
292
+ const filePath = path.join(agentsDir, file);
293
+ if (!isPathSafe(filePath, agentsDir)) continue;
294
+
295
+ const content = fs.readFileSync(filePath, 'utf8');
296
+ const frontmatter = parseFrontmatter(content);
297
+ if (!frontmatter || Object.keys(frontmatter).length === 0) continue;
298
+
299
+ const name = frontmatter.name || path.basename(file, '.md');
300
+ agents.push(name);
301
+ }
302
+
303
+ // Group by category, count per category
304
+ const categories = {};
305
+ for (const name of agents) {
306
+ const cat = categorizeAgent(name);
307
+ if (!categories[cat]) categories[cat] = 0;
308
+ categories[cat]++;
309
+ }
310
+
311
+ const safeCount = sanitize.count(agents.length);
312
+ let output = `**${safeCount} agents** across ${Object.keys(categories).length} categories:\n`;
313
+ for (const [category, count] of Object.entries(categories)) {
314
+ output += `- **${category}**: ${count} agents\n`;
315
+ }
316
+ output += `\nRun \`/agileflow:help agents\` or browse \`.agileflow/agents/\` for the full list.`;
317
+ return output;
318
+ }
319
+
320
+ /**
321
+ * Generate a compact category summary for commands (no individual names).
322
+ * Used by minimal mode and generators that want a discovery-oriented summary.
323
+ * @param {string} commandsDir - Path to commands directory
324
+ * @returns {string} Compact category summary with counts
325
+ */
326
+ function generateCommandSummary(commandsDir) {
327
+ if (!fs.existsSync(commandsDir)) return '';
328
+
329
+ const commands = [];
330
+
331
+ // Count main command files
332
+ const mainFiles = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
333
+ for (const file of mainFiles) {
334
+ const filePath = path.join(commandsDir, file);
335
+ if (!isPathSafe(filePath, commandsDir)) continue;
336
+
337
+ const content = fs.readFileSync(filePath, 'utf8');
338
+ const frontmatter = parseFrontmatter(content);
339
+ if (!frontmatter || Object.keys(frontmatter).length === 0) continue;
340
+ commands.push(path.basename(file, '.md'));
341
+ }
342
+
343
+ // Count subdirectory command files
344
+ const entries = fs.readdirSync(commandsDir, { withFileTypes: true });
345
+ for (const entry of entries) {
346
+ if (entry.isDirectory()) {
347
+ const subDir = path.join(commandsDir, entry.name);
348
+ if (!isPathSafe(subDir, commandsDir)) continue;
349
+
350
+ const subFiles = fs.readdirSync(subDir).filter(f => f.endsWith('.md'));
351
+ for (const file of subFiles) {
352
+ const filePath = path.join(subDir, file);
353
+ if (!isPathSafe(filePath, commandsDir)) continue;
354
+
355
+ const content = fs.readFileSync(filePath, 'utf8');
356
+ const frontmatter = parseFrontmatter(content);
357
+ if (!frontmatter || Object.keys(frontmatter).length === 0) continue;
358
+ commands.push(`${entry.name}:${path.basename(file, '.md')}`);
359
+ }
360
+ }
361
+ }
362
+
363
+ const safeCount = sanitize.count(commands.length);
364
+ return `**${safeCount} commands** available. Run \`/agileflow:help\` for the full list with descriptions.`;
365
+ }
366
+
238
367
  // =============================================================================
239
368
  // Template Generation Functions
240
369
  // =============================================================================
@@ -480,6 +609,8 @@ function clearPreserveRulesCache() {
480
609
  * @param {string} context.agileflowFolder - AgileFlow folder name
481
610
  * @param {string} context.docsFolder - Docs folder name (default: 'docs')
482
611
  * @param {string} context.version - AgileFlow version
612
+ * @param {boolean} context.minimal - When true, skip AGENT_LIST and COMMAND_LIST injection
613
+ * (replaces with discovery pointers). Keeps session harness, quality gates, preserve_rules.
483
614
  * @returns {string} Content with all placeholders replaced
484
615
  */
485
616
  function injectContent(content, context = {}) {
@@ -488,6 +619,7 @@ function injectContent(content, context = {}) {
488
619
  agileflowFolder = '.agileflow',
489
620
  docsFolder = 'docs',
490
621
  version = 'unknown',
622
+ minimal = false,
491
623
  } = context;
492
624
 
493
625
  let result = content;
@@ -541,7 +673,13 @@ function injectContent(content, context = {}) {
541
673
  // List generation already includes sanitization via sanitizeAgentData/sanitizeCommandData
542
674
  if (coreDir && fs.existsSync(coreDir)) {
543
675
  if (result.includes('{{AGENT_LIST}}')) {
544
- const agentList = generateAgentList(path.join(coreDir, 'agents'));
676
+ let agentList;
677
+ if (minimal) {
678
+ // Minimal mode: replace with compact discovery pointer
679
+ agentList = `**Agents**: ${safeAgentCount} available. Run \`/agileflow:help agents\` or \`ls .agileflow/agents/\` to browse.`;
680
+ } else {
681
+ agentList = generateAgentList(path.join(coreDir, 'agents'));
682
+ }
545
683
  result = replaceInBodyOnly(result, body => {
546
684
  let updated = body.replace(/<!-- \{\{AGENT_LIST\}\} -->/g, agentList);
547
685
  updated = updated.replace(/\{\{AGENT_LIST\}\}/g, agentList);
@@ -550,7 +688,13 @@ function injectContent(content, context = {}) {
550
688
  }
551
689
 
552
690
  if (result.includes('{{COMMAND_LIST}}')) {
553
- const commandList = generateCommandList(path.join(coreDir, 'commands'));
691
+ let commandList;
692
+ if (minimal) {
693
+ // Minimal mode: replace with compact discovery pointer
694
+ commandList = `**Commands**: ${safeCommandCount} available. Run \`/agileflow:help\` or \`ls .agileflow/commands/\` to browse.`;
695
+ } else {
696
+ commandList = generateCommandList(path.join(coreDir, 'commands'));
697
+ }
554
698
  result = replaceInBodyOnly(result, body => {
555
699
  let updated = body.replace(/<!-- \{\{COMMAND_LIST\}\} -->/g, commandList);
556
700
  updated = updated.replace(/\{\{COMMAND_LIST\}\}/g, commandList);
@@ -798,6 +942,10 @@ module.exports = {
798
942
  generateAgentList,
799
943
  generateCommandList,
800
944
 
945
+ // Summary generation (compact, for minimal mode)
946
+ generateAgentSummary,
947
+ generateCommandSummary,
948
+
801
949
  // Template generation
802
950
  generateSessionHarnessContent,
803
951
  clearSessionHarnessCache,
@@ -190,7 +190,7 @@ Project-level planning and tracking.
190
190
  - **milestones.md**: Release milestones
191
191
  - **risks.md**: Project risks and mitigation strategies
192
192
  - **ideation/**: Ideation reports from \`/agileflow:ideate:new\`
193
- - **logic-audits/**: Logic audit reports from \`/agileflow:audit:logic\`
193
+ - **code-audits/**: Code audit reports from \`/agileflow:code:logic\`
194
194
  `,
195
195
 
196
196
  [`${docsFolder}/09-agents/README.md`]: `# Agent Status Tracking