agileflow 3.2.1 → 3.4.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 (134) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +6 -6
  3. package/lib/feature-flags.js +32 -4
  4. package/lib/skill-loader.js +0 -1
  5. package/package.json +1 -1
  6. package/scripts/agileflow-statusline.sh +81 -0
  7. package/scripts/babysit-clear-restore.js +154 -0
  8. package/scripts/claude-tmux.sh +120 -24
  9. package/scripts/claude-watchdog.sh +225 -0
  10. package/scripts/generators/agent-registry.js +14 -1
  11. package/scripts/generators/inject-babysit.js +22 -9
  12. package/scripts/generators/inject-help.js +19 -9
  13. package/scripts/lib/README-portable-tasks.md +424 -0
  14. package/scripts/lib/audit-cleanup.js +250 -0
  15. package/scripts/lib/audit-registry.js +248 -0
  16. package/scripts/lib/configure-detect.js +20 -0
  17. package/scripts/lib/feature-catalog.js +13 -2
  18. package/scripts/lib/gate-enforcer.js +295 -0
  19. package/scripts/lib/model-profiles.js +98 -0
  20. package/scripts/lib/signal-detectors.js +1 -1
  21. package/scripts/lib/skill-catalog.js +557 -0
  22. package/scripts/lib/skill-recommender.js +311 -0
  23. package/scripts/lib/tdd-phase-manager.js +455 -0
  24. package/scripts/lib/team-events.js +76 -8
  25. package/scripts/lib/tmux-group-colors.js +113 -0
  26. package/scripts/messaging-bridge.js +209 -1
  27. package/scripts/spawn-audit-sessions.js +549 -0
  28. package/scripts/team-manager.js +37 -16
  29. package/scripts/tmux-close-windows.sh +180 -0
  30. package/scripts/tmux-restore-window.sh +67 -0
  31. package/scripts/tmux-save-closed-window.sh +35 -0
  32. package/src/core/agents/ads-audit-budget.md +181 -0
  33. package/src/core/agents/ads-audit-compliance.md +169 -0
  34. package/src/core/agents/ads-audit-creative.md +164 -0
  35. package/src/core/agents/ads-audit-google.md +226 -0
  36. package/src/core/agents/ads-audit-meta.md +183 -0
  37. package/src/core/agents/ads-audit-tracking.md +197 -0
  38. package/src/core/agents/ads-consensus.md +322 -0
  39. package/src/core/agents/brainstorm-analyzer-features.md +169 -0
  40. package/src/core/agents/brainstorm-analyzer-growth.md +161 -0
  41. package/src/core/agents/brainstorm-analyzer-integration.md +172 -0
  42. package/src/core/agents/brainstorm-analyzer-market.md +147 -0
  43. package/src/core/agents/brainstorm-analyzer-ux.md +167 -0
  44. package/src/core/agents/brainstorm-consensus.md +237 -0
  45. package/src/core/agents/completeness-analyzer-api.md +190 -0
  46. package/src/core/agents/completeness-analyzer-conditional.md +201 -0
  47. package/src/core/agents/completeness-analyzer-handlers.md +159 -0
  48. package/src/core/agents/completeness-analyzer-imports.md +159 -0
  49. package/src/core/agents/completeness-analyzer-routes.md +182 -0
  50. package/src/core/agents/completeness-analyzer-state.md +188 -0
  51. package/src/core/agents/completeness-analyzer-stubs.md +198 -0
  52. package/src/core/agents/completeness-consensus.md +286 -0
  53. package/src/core/agents/perf-consensus.md +2 -2
  54. package/src/core/agents/security-consensus.md +2 -2
  55. package/src/core/agents/seo-analyzer-content.md +167 -0
  56. package/src/core/agents/seo-analyzer-images.md +187 -0
  57. package/src/core/agents/seo-analyzer-performance.md +206 -0
  58. package/src/core/agents/seo-analyzer-schema.md +176 -0
  59. package/src/core/agents/seo-analyzer-sitemap.md +172 -0
  60. package/src/core/agents/seo-analyzer-technical.md +144 -0
  61. package/src/core/agents/seo-consensus.md +289 -0
  62. package/src/core/agents/test-consensus.md +2 -2
  63. package/src/core/commands/ads/audit.md +375 -0
  64. package/src/core/commands/ads/budget.md +97 -0
  65. package/src/core/commands/ads/competitor.md +112 -0
  66. package/src/core/commands/ads/creative.md +85 -0
  67. package/src/core/commands/ads/google.md +112 -0
  68. package/src/core/commands/ads/landing.md +119 -0
  69. package/src/core/commands/ads/linkedin.md +112 -0
  70. package/src/core/commands/ads/meta.md +91 -0
  71. package/src/core/commands/ads/microsoft.md +115 -0
  72. package/src/core/commands/ads/plan.md +321 -0
  73. package/src/core/commands/ads/tiktok.md +129 -0
  74. package/src/core/commands/ads/youtube.md +124 -0
  75. package/src/core/commands/ads.md +128 -0
  76. package/src/core/commands/babysit.md +250 -1344
  77. package/src/core/commands/code/completeness.md +466 -0
  78. package/src/core/commands/{audit → code}/legal.md +26 -16
  79. package/src/core/commands/{audit → code}/logic.md +27 -16
  80. package/src/core/commands/{audit → code}/performance.md +30 -20
  81. package/src/core/commands/{audit → code}/security.md +32 -19
  82. package/src/core/commands/{audit → code}/test.md +30 -20
  83. package/src/core/commands/{discovery → ideate}/brief.md +12 -12
  84. package/src/core/commands/{discovery/new.md → ideate/discover.md} +13 -13
  85. package/src/core/commands/ideate/features.md +435 -0
  86. package/src/core/commands/seo/audit.md +373 -0
  87. package/src/core/commands/seo/competitor.md +174 -0
  88. package/src/core/commands/seo/content.md +107 -0
  89. package/src/core/commands/seo/geo.md +229 -0
  90. package/src/core/commands/seo/hreflang.md +140 -0
  91. package/src/core/commands/seo/images.md +96 -0
  92. package/src/core/commands/seo/page.md +198 -0
  93. package/src/core/commands/seo/plan.md +163 -0
  94. package/src/core/commands/seo/programmatic.md +131 -0
  95. package/src/core/commands/seo/references/cwv-thresholds.md +64 -0
  96. package/src/core/commands/seo/references/eeat-framework.md +110 -0
  97. package/src/core/commands/seo/references/quality-gates.md +91 -0
  98. package/src/core/commands/seo/references/schema-types.md +102 -0
  99. package/src/core/commands/seo/schema.md +183 -0
  100. package/src/core/commands/seo/sitemap.md +97 -0
  101. package/src/core/commands/seo/technical.md +100 -0
  102. package/src/core/commands/seo.md +107 -0
  103. package/src/core/commands/skill/list.md +68 -212
  104. package/src/core/commands/skill/recommend.md +216 -0
  105. package/src/core/commands/tdd-next.md +238 -0
  106. package/src/core/commands/tdd.md +210 -0
  107. package/src/core/experts/_core-expertise.yaml +105 -0
  108. package/src/core/experts/analytics/expertise.yaml +5 -99
  109. package/src/core/experts/codebase-query/expertise.yaml +3 -72
  110. package/src/core/experts/compliance/expertise.yaml +6 -72
  111. package/src/core/experts/database/expertise.yaml +9 -52
  112. package/src/core/experts/documentation/expertise.yaml +7 -140
  113. package/src/core/experts/integrations/expertise.yaml +7 -127
  114. package/src/core/experts/mentor/expertise.yaml +8 -35
  115. package/src/core/experts/monitoring/expertise.yaml +7 -49
  116. package/src/core/experts/performance/expertise.yaml +1 -26
  117. package/src/core/experts/security/expertise.yaml +9 -34
  118. package/src/core/experts/ui/expertise.yaml +6 -36
  119. package/src/core/knowledge/ads/ad-audit-checklist-scoring.md +424 -0
  120. package/src/core/knowledge/ads/ad-optimization-logic.md +590 -0
  121. package/src/core/knowledge/ads/ad-technical-specifications.md +385 -0
  122. package/src/core/knowledge/ads/definitive-advertising-reference-2026.md +506 -0
  123. package/src/core/knowledge/ads/paid-advertising-research-2026.md +445 -0
  124. package/src/core/templates/agileflow-metadata.json +15 -1
  125. package/tools/cli/installers/ide/_base-ide.js +42 -5
  126. package/tools/cli/installers/ide/claude-code.js +13 -4
  127. package/tools/cli/lib/content-injector.js +160 -12
  128. package/tools/cli/lib/docs-setup.js +1 -1
  129. package/src/core/commands/skill/create.md +0 -698
  130. package/src/core/commands/skill/delete.md +0 -316
  131. package/src/core/commands/skill/edit.md +0 -359
  132. package/src/core/commands/skill/test.md +0 -394
  133. package/src/core/commands/skill/upgrade.md +0 -552
  134. package/src/core/templates/skill-template.md +0 -117
@@ -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);
@@ -237,7 +237,14 @@ class ClaudeCodeSetup extends BaseIdeSetup {
237
237
  if (!settings.hooks.SessionStart) settings.hooks.SessionStart = [];
238
238
 
239
239
  // Define SessionStart hooks
240
+ // babysit-clear-restore MUST run before welcome to set last_precompact_at flag
240
241
  const sessionStartHooks = [
242
+ {
243
+ type: 'command',
244
+ command:
245
+ 'node $CLAUDE_PROJECT_DIR/.agileflow/scripts/babysit-clear-restore.js 2>/dev/null || true',
246
+ timeout: 5000,
247
+ },
241
248
  {
242
249
  type: 'command',
243
250
  command:
@@ -285,7 +292,9 @@ class ClaudeCodeSetup extends BaseIdeSetup {
285
292
 
286
293
  // Write settings
287
294
  await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
288
- console.log(chalk.dim(` - SessionStart hooks: welcome, archive, context-loader`));
295
+ console.log(
296
+ chalk.dim(` - SessionStart hooks: babysit-restore, welcome, archive, context-loader`)
297
+ );
289
298
  }
290
299
 
291
300
  /**
@@ -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