agileflow 3.1.0 → 3.2.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 (106) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +57 -85
  3. package/lib/dashboard-automations.js +130 -0
  4. package/lib/dashboard-git.js +254 -0
  5. package/lib/dashboard-inbox.js +64 -0
  6. package/lib/dashboard-protocol.js +1 -0
  7. package/lib/dashboard-server.js +114 -924
  8. package/lib/dashboard-session.js +136 -0
  9. package/lib/dashboard-status.js +72 -0
  10. package/lib/dashboard-terminal.js +354 -0
  11. package/lib/dashboard-websocket.js +88 -0
  12. package/lib/drivers/codex-driver.ts +4 -4
  13. package/lib/logger.js +106 -0
  14. package/package.json +4 -2
  15. package/scripts/agileflow-configure.js +2 -2
  16. package/scripts/agileflow-welcome.js +409 -434
  17. package/scripts/claude-tmux.sh +80 -2
  18. package/scripts/context-loader.js +4 -9
  19. package/scripts/lib/browser-qa-evidence.js +409 -0
  20. package/scripts/lib/browser-qa-status.js +192 -0
  21. package/scripts/lib/command-prereqs.js +280 -0
  22. package/scripts/lib/configure-detect.js +92 -2
  23. package/scripts/lib/configure-features.js +295 -1
  24. package/scripts/lib/context-formatter.js +468 -233
  25. package/scripts/lib/context-loader.js +27 -15
  26. package/scripts/lib/damage-control-utils.js +8 -1
  27. package/scripts/lib/feature-catalog.js +321 -0
  28. package/scripts/lib/portable-tasks-cli.js +274 -0
  29. package/scripts/lib/portable-tasks.js +479 -0
  30. package/scripts/lib/signal-detectors.js +1 -1
  31. package/scripts/lib/team-events.js +86 -1
  32. package/scripts/obtain-context.js +28 -4
  33. package/scripts/smart-detect.js +17 -0
  34. package/scripts/strip-ai-attribution.js +63 -0
  35. package/scripts/team-manager.js +7 -2
  36. package/scripts/welcome-deferred.js +437 -0
  37. package/src/core/agents/browser-qa.md +328 -0
  38. package/src/core/agents/perf-analyzer-assets.md +174 -0
  39. package/src/core/agents/perf-analyzer-bundle.md +165 -0
  40. package/src/core/agents/perf-analyzer-caching.md +160 -0
  41. package/src/core/agents/perf-analyzer-compute.md +165 -0
  42. package/src/core/agents/perf-analyzer-memory.md +182 -0
  43. package/src/core/agents/perf-analyzer-network.md +157 -0
  44. package/src/core/agents/perf-analyzer-queries.md +155 -0
  45. package/src/core/agents/perf-analyzer-rendering.md +156 -0
  46. package/src/core/agents/perf-consensus.md +280 -0
  47. package/src/core/agents/security-analyzer-api.md +199 -0
  48. package/src/core/agents/security-analyzer-auth.md +160 -0
  49. package/src/core/agents/security-analyzer-authz.md +168 -0
  50. package/src/core/agents/security-analyzer-deps.md +147 -0
  51. package/src/core/agents/security-analyzer-infra.md +176 -0
  52. package/src/core/agents/security-analyzer-injection.md +148 -0
  53. package/src/core/agents/security-analyzer-input.md +191 -0
  54. package/src/core/agents/security-analyzer-secrets.md +175 -0
  55. package/src/core/agents/security-consensus.md +276 -0
  56. package/src/core/agents/test-analyzer-assertions.md +181 -0
  57. package/src/core/agents/test-analyzer-coverage.md +183 -0
  58. package/src/core/agents/test-analyzer-fragility.md +185 -0
  59. package/src/core/agents/test-analyzer-integration.md +155 -0
  60. package/src/core/agents/test-analyzer-maintenance.md +173 -0
  61. package/src/core/agents/test-analyzer-mocking.md +178 -0
  62. package/src/core/agents/test-analyzer-patterns.md +189 -0
  63. package/src/core/agents/test-analyzer-structure.md +177 -0
  64. package/src/core/agents/test-consensus.md +294 -0
  65. package/src/core/commands/{legal/audit.md → audit/legal.md} +13 -13
  66. package/src/core/commands/{logic/audit.md → audit/logic.md} +12 -12
  67. package/src/core/commands/audit/performance.md +443 -0
  68. package/src/core/commands/audit/security.md +443 -0
  69. package/src/core/commands/audit/test.md +442 -0
  70. package/src/core/commands/babysit.md +505 -463
  71. package/src/core/commands/browser-qa.md +240 -0
  72. package/src/core/commands/configure.md +8 -8
  73. package/src/core/commands/research/ask.md +42 -9
  74. package/src/core/commands/research/import.md +14 -8
  75. package/src/core/commands/research/list.md +17 -16
  76. package/src/core/commands/research/synthesize.md +8 -8
  77. package/src/core/commands/research/view.md +28 -4
  78. package/src/core/commands/whats-new.md +2 -2
  79. package/src/core/experts/devops/expertise.yaml +13 -2
  80. package/src/core/experts/documentation/expertise.yaml +26 -4
  81. package/src/core/profiles/COMPARISON.md +170 -0
  82. package/src/core/profiles/README.md +178 -0
  83. package/src/core/profiles/claude-code.yaml +111 -0
  84. package/src/core/profiles/codex.yaml +103 -0
  85. package/src/core/profiles/cursor.yaml +134 -0
  86. package/src/core/profiles/examples.js +250 -0
  87. package/src/core/profiles/loader.js +235 -0
  88. package/src/core/profiles/windsurf.yaml +159 -0
  89. package/src/core/teams/logic-audit.json +6 -0
  90. package/src/core/teams/perf-audit.json +71 -0
  91. package/src/core/teams/security-audit.json +71 -0
  92. package/src/core/teams/test-audit.json +71 -0
  93. package/src/core/templates/browser-qa-spec.yaml +94 -0
  94. package/src/core/templates/command-prerequisites.yaml +169 -0
  95. package/src/core/templates/damage-control-patterns.yaml +9 -0
  96. package/tools/cli/installers/ide/_base-ide.js +33 -3
  97. package/tools/cli/installers/ide/claude-code.js +2 -69
  98. package/tools/cli/installers/ide/codex.js +9 -9
  99. package/tools/cli/installers/ide/cursor.js +165 -4
  100. package/tools/cli/installers/ide/windsurf.js +237 -6
  101. package/tools/cli/lib/content-transformer.js +234 -9
  102. package/tools/cli/lib/docs-setup.js +1 -1
  103. package/tools/cli/lib/ide-generator.js +357 -0
  104. package/tools/cli/lib/ide-registry.js +2 -2
  105. package/scripts/tmux-task-name.sh +0 -105
  106. package/scripts/tmux-task-watcher.sh +0 -344
@@ -1,14 +1,26 @@
1
1
  /**
2
2
  * AgileFlow CLI - Windsurf IDE Installer
3
3
  *
4
- * Installs AgileFlow workflows for Windsurf IDE.
5
- * Windsurf uses markdown files in .windsurf/workflows/
4
+ * Installs AgileFlow for Windsurf IDE:
5
+ * - Commands as workflows to .windsurf/workflows/agileflow/
6
+ * - Agents as skills to .windsurf/skills/agileflow-<NAME>/SKILL.md
7
+ * - Damage control hooks to .windsurf/hooks.json
8
+ *
9
+ * Windsurf supports 11 lifecycle events and 12,000 character limit per workflow.
10
+ * Skills follow agentskills.io specification with YAML frontmatter.
6
11
  */
7
12
 
8
13
  const path = require('node:path');
9
14
  const fs = require('fs-extra');
10
15
  const chalk = require('chalk');
16
+ const { yaml } = require('../../../../lib/yaml-utils');
11
17
  const { BaseIdeSetup } = require('./_base-ide');
18
+ const {
19
+ getFrontmatter,
20
+ stripFrontmatter,
21
+ replaceReferences,
22
+ IDE_REPLACEMENTS,
23
+ } = require('../../lib/content-transformer');
12
24
 
13
25
  /**
14
26
  * Windsurf IDE setup handler
@@ -20,6 +32,187 @@ class WindsurfSetup extends BaseIdeSetup {
20
32
  this.workflowsDir = 'workflows';
21
33
  }
22
34
 
35
+ /**
36
+ * Convert an AgileFlow agent markdown file to Windsurf SKILL.md format
37
+ * Windsurf skills follow the agentskills.io specification with YAML frontmatter
38
+ *
39
+ * @param {string} content - Original agent markdown content
40
+ * @param {string} agentName - Agent name (e.g., 'database')
41
+ * @returns {string} Windsurf SKILL.md content
42
+ */
43
+ convertAgentToSkill(content, agentName) {
44
+ // Extract frontmatter using content-transformer
45
+ const frontmatter = getFrontmatter(content);
46
+ const description = frontmatter.description || `AgileFlow ${agentName} agent`;
47
+
48
+ // Create SKILL.md with YAML frontmatter (agentskills.io spec)
49
+ const skillFrontmatter = yaml
50
+ .dump({
51
+ name: `agileflow-${agentName}`,
52
+ description: description,
53
+ })
54
+ .trim();
55
+
56
+ // Remove original frontmatter from content using content-transformer
57
+ let bodyContent = stripFrontmatter(content);
58
+
59
+ // Add Windsurf-specific header
60
+ const windsurfHeader = `# AgileFlow: ${agentName.charAt(0).toUpperCase() + agentName.slice(1)} Skill
61
+
62
+ > Use this skill via \`@agileflow-${agentName}\` or /cascade
63
+
64
+ `;
65
+
66
+ // Replace Claude-specific references using content-transformer
67
+ bodyContent = replaceReferences(bodyContent, IDE_REPLACEMENTS.windsurf);
68
+
69
+ // Add Windsurf-specific replacements
70
+ bodyContent = replaceReferences(bodyContent, {
71
+ 'Task tool': 'workflow chaining',
72
+ AskUserQuestion: 'numbered list prompt',
73
+ '.claude/agents/agileflow': '.windsurf/skills/agileflow',
74
+ });
75
+
76
+ // Replace /agileflow: prefix for Windsurf workflow chaining
77
+ // e.g., /agileflow:story:list → /agileflow-story-list
78
+ bodyContent = bodyContent.replace(/\/agileflow:([a-zA-Z0-9:_-]+)/g, (_match, rest) => {
79
+ return '/agileflow-' + rest.replace(/:/g, '-');
80
+ });
81
+
82
+ // Warn if content exceeds Windsurf's 12,000 character limit
83
+ const totalLength = skillFrontmatter.length + windsurfHeader.length + bodyContent.length;
84
+ if (totalLength > 12000) {
85
+ console.warn(
86
+ chalk.yellow(
87
+ ` ⚠ Skill '${agentName}' exceeds 12,000 character limit (${totalLength} chars). Consider splitting.`
88
+ )
89
+ );
90
+ }
91
+
92
+ return `---
93
+ ${skillFrontmatter}
94
+ ---
95
+
96
+ ${windsurfHeader}${bodyContent}`;
97
+ }
98
+
99
+ /**
100
+ * Install AgileFlow agents as Windsurf skills
101
+ * Skills are installed to .windsurf/skills/agileflow-{name}/SKILL.md
102
+ *
103
+ * @param {string} projectDir - Project directory
104
+ * @param {string} agileflowDir - AgileFlow installation directory
105
+ * @returns {Promise<number>} Number of skills installed
106
+ */
107
+ async installSkills(projectDir, agileflowDir) {
108
+ const agentsSource = path.join(agileflowDir, 'agents');
109
+ const skillsTarget = path.join(projectDir, this.configDir, 'skills');
110
+
111
+ if (!(await this.exists(agentsSource))) {
112
+ return 0;
113
+ }
114
+
115
+ let skillCount = 0;
116
+ const agents = await this.scanDirectory(agentsSource, '.md');
117
+
118
+ for (const agent of agents) {
119
+ const content = await this.readFile(agent.path);
120
+ const skillContent = this.convertAgentToSkill(content, agent.name);
121
+
122
+ // Create skill directory: .windsurf/skills/agileflow-{name}/
123
+ const skillDir = path.join(skillsTarget, `agileflow-${agent.name}`);
124
+ await this.ensureDir(skillDir);
125
+
126
+ // Write SKILL.md
127
+ await this.writeFile(path.join(skillDir, 'SKILL.md'), skillContent);
128
+ skillCount++;
129
+ }
130
+
131
+ return skillCount;
132
+ }
133
+
134
+ /**
135
+ * Setup damage control hooks for Windsurf
136
+ * Maps Claude Code's PreToolUse hooks to Windsurf's lifecycle events:
137
+ * - pre_run_command (for bash commands)
138
+ * - post_write_code (for file edits)
139
+ * - pre_mcp_tool_use (for MCP tools)
140
+ *
141
+ * @param {string} projectDir - Project directory
142
+ * @param {string} agileflowDir - AgileFlow installation directory
143
+ * @param {string} windsurfDir - .windsurf directory path
144
+ * @param {Object} options - Setup options
145
+ */
146
+ async setupDamageControlHooks(projectDir, agileflowDir, windsurfDir, options = {}) {
147
+ if (options.skipDamageControl) {
148
+ return;
149
+ }
150
+
151
+ const hooksPath = path.join(windsurfDir, 'hooks.json');
152
+ let hooks = [];
153
+
154
+ // Load existing hooks if they exist
155
+ if (fs.existsSync(hooksPath)) {
156
+ try {
157
+ const content = await fs.readFile(hooksPath, 'utf8');
158
+ const parsed = JSON.parse(content);
159
+ if (!Array.isArray(parsed)) {
160
+ console.warn(
161
+ '[AgileFlow] hooks.json exists but is not an array, preserving existing file'
162
+ );
163
+ return;
164
+ }
165
+ hooks = parsed;
166
+ } catch (e) {
167
+ console.warn(
168
+ `[AgileFlow] hooks.json exists but is malformed (${e.message}), preserving existing file`
169
+ );
170
+ return;
171
+ }
172
+ }
173
+
174
+ // Define damage control hooks for Windsurf
175
+ // Windsurf's hooks.json format differs from Cursor - it uses event, command, args
176
+ const damageControlHooks = [
177
+ {
178
+ event: 'pre_run_command',
179
+ command: 'node',
180
+ args: ['.agileflow/scripts/damage-control/damage-control-bash.js'],
181
+ description: 'AgileFlow damage control for shell commands',
182
+ },
183
+ {
184
+ event: 'post_write_code',
185
+ command: 'node',
186
+ args: ['.agileflow/scripts/damage-control/damage-control-edit.js'],
187
+ description: 'AgileFlow damage control for file edits',
188
+ },
189
+ ];
190
+
191
+ // Check if damage control hooks already exist and merge
192
+ let hasUpdates = false;
193
+ for (const newHook of damageControlHooks) {
194
+ const existingIdx = hooks.findIndex(
195
+ h =>
196
+ h.event === newHook.event &&
197
+ h.command === newHook.command &&
198
+ (h.args?.join(' ') === newHook.args?.join(' ') ||
199
+ (h.args && h.args.some(arg => arg.includes('damage-control'))))
200
+ );
201
+
202
+ if (existingIdx === -1) {
203
+ hooks.push(newHook);
204
+ hasUpdates = true;
205
+ }
206
+ }
207
+
208
+ // Only write if we have updates or if file didn't exist
209
+ if (hasUpdates || !fs.existsSync(hooksPath)) {
210
+ await fs.ensureDir(path.dirname(hooksPath));
211
+ await fs.writeFile(hooksPath, JSON.stringify(hooks, null, 2));
212
+ console.log(chalk.dim(` - Damage control: hooks enabled`));
213
+ }
214
+ }
215
+
23
216
  /**
24
217
  * Setup Windsurf IDE configuration
25
218
  * @param {string} projectDir - Project directory
@@ -27,12 +220,37 @@ class WindsurfSetup extends BaseIdeSetup {
27
220
  * @param {Object} options - Setup options
28
221
  */
29
222
  async setup(projectDir, agileflowDir, options = {}) {
30
- return this.setupStandard(projectDir, agileflowDir, {
223
+ console.log(chalk.hex('#e8683a')(` Setting up ${this.displayName}...`));
224
+
225
+ // Note: cleanup is handled inside setupStandard(), no need to call explicitly
226
+
227
+ // 1. Install workflows using standard setup
228
+ const workflowsResult = await this.setupStandard(projectDir, agileflowDir, {
31
229
  targetSubdir: this.workflowsDir,
32
230
  agileflowFolder: 'agileflow',
33
231
  commandLabel: 'workflows',
34
232
  agentLabel: 'agent workflows',
35
233
  });
234
+
235
+ // 2. Install agents as skills
236
+ const skillCount = await this.installSkills(projectDir, agileflowDir);
237
+ if (skillCount > 0) {
238
+ console.log(chalk.dim(` - ${skillCount} skills installed to .windsurf/skills/`));
239
+ }
240
+
241
+ // 3. Setup damage control hooks
242
+ const windsurfDir = path.join(projectDir, this.configDir);
243
+ await this.setupDamageControlHooks(projectDir, agileflowDir, windsurfDir, options);
244
+
245
+ console.log(chalk.green(` ✓ ${this.displayName} configured:`));
246
+ console.log(chalk.dim(` - Workflows: .windsurf/workflows/agileflow/`));
247
+ console.log(chalk.dim(` - Skills: .windsurf/skills/agileflow-*/`));
248
+ console.log(chalk.dim(` - Hooks: .windsurf/hooks.json`));
249
+
250
+ return {
251
+ ...workflowsResult,
252
+ skills: skillCount,
253
+ };
36
254
  }
37
255
 
38
256
  /**
@@ -40,11 +258,24 @@ class WindsurfSetup extends BaseIdeSetup {
40
258
  * @param {string} projectDir - Project directory
41
259
  */
42
260
  async cleanup(projectDir) {
43
- const agileflowPath = path.join(projectDir, this.configDir, this.workflowsDir, 'agileflow');
44
- if (await this.exists(agileflowPath)) {
45
- await fs.remove(agileflowPath);
261
+ // Remove old workflows directory
262
+ const workflowsPath = path.join(projectDir, this.configDir, this.workflowsDir, 'agileflow');
263
+ if (await this.exists(workflowsPath)) {
264
+ await fs.remove(workflowsPath);
46
265
  console.log(chalk.dim(` Removed old AgileFlow workflows from ${this.displayName}`));
47
266
  }
267
+
268
+ // Remove old skills directories
269
+ const skillsDir = path.join(projectDir, this.configDir, 'skills');
270
+ if (await this.exists(skillsDir)) {
271
+ const entries = await fs.readdir(skillsDir);
272
+ for (const entry of entries) {
273
+ if (entry.startsWith('agileflow-')) {
274
+ await fs.remove(path.join(skillsDir, entry));
275
+ }
276
+ }
277
+ console.log(chalk.dim(` Removed old AgileFlow skills from ${this.displayName}`));
278
+ }
48
279
  }
49
280
  }
50
281
 
@@ -23,7 +23,7 @@ const { parseFrontmatter, extractBody } = require('../../../scripts/lib/frontmat
23
23
  * @example
24
24
  * // Object form (simple string replacement)
25
25
  * replaceReferences(content, {
26
- * 'Claude Code': 'Codex CLI',
26
+ * 'Claude Code': 'OpenAI Codex',
27
27
  * '.claude/': '.codex/',
28
28
  * 'CLAUDE.md': 'AGENTS.md'
29
29
  * });
@@ -31,7 +31,7 @@ const { parseFrontmatter, extractBody } = require('../../../scripts/lib/frontmat
31
31
  * @example
32
32
  * // Array form (with regex flags)
33
33
  * replaceReferences(content, [
34
- * { pattern: 'Claude Code', replacement: 'Codex CLI', flags: 'gi' },
34
+ * { pattern: 'Claude Code', replacement: 'OpenAI Codex', flags: 'gi' },
35
35
  * { pattern: /\.claude\//g, replacement: '.codex/' }
36
36
  * ]);
37
37
  */
@@ -54,7 +54,10 @@ function replaceReferences(content, replacements) {
54
54
  const flags = item.flags || 'g';
55
55
  regex = new RegExp(escapeRegex(item.pattern), flags);
56
56
  }
57
- result = result.replace(regex, item.replacement || '');
57
+ result = result.replace(
58
+ regex,
59
+ item.replacement !== undefined && item.replacement !== null ? item.replacement : ''
60
+ );
58
61
  }
59
62
  } else if (typeof replacements === 'object' && replacements !== null) {
60
63
  // Object form: {pattern: replacement}
@@ -176,11 +179,11 @@ function getFrontmatter(content) {
176
179
  */
177
180
  const IDE_REPLACEMENTS = {
178
181
  /**
179
- * Claude Code to Codex CLI conversions
182
+ * Claude Code to OpenAI Codex conversions
180
183
  */
181
184
  codex: {
182
- 'Claude Code': 'Codex CLI',
183
- 'claude code': 'Codex CLI',
185
+ 'Claude Code': 'OpenAI Codex',
186
+ 'claude code': 'OpenAI Codex',
184
187
  CLAUDE_CODE: 'CODEX_CLI',
185
188
  'CLAUDE.md': 'AGENTS.md',
186
189
  '.claude/': '.codex/',
@@ -197,6 +200,10 @@ const IDE_REPLACEMENTS = {
197
200
  'claude code': 'Cursor',
198
201
  '.claude/': '.cursor/',
199
202
  '.claude\\': '.cursor\\',
203
+ '.claude/agents/agileflow': '.cursor/agents/AgileFlow',
204
+ 'Task tool': 'subagent spawning',
205
+ 'Task agent': 'subagent',
206
+ AskUserQuestion: 'numbered list prompt',
200
207
  },
201
208
 
202
209
  /**
@@ -207,9 +214,173 @@ const IDE_REPLACEMENTS = {
207
214
  'claude code': 'Windsurf',
208
215
  '.claude/': '.windsurf/',
209
216
  '.claude\\': '.windsurf\\',
217
+ 'Task tool': 'workflow chaining',
218
+ 'Task agent': 'workflow',
219
+ AskUserQuestion: 'numbered list prompt',
220
+ '.claude/agents/agileflow': '.windsurf/skills/agileflow',
210
221
  },
211
222
  };
212
223
 
224
+ /**
225
+ * Tool reference replacements for IDE capability-aware transformation
226
+ * Maps Claude Code tool/pattern names to IDE-appropriate alternatives
227
+ *
228
+ * @private
229
+ */
230
+ const TOOL_REFERENCE_REPLACEMENTS = {
231
+ /**
232
+ * Cursor: Has subagents but no structured AskUserQuestion
233
+ * Replaces abstract tool patterns with concrete instructions
234
+ */
235
+ cursor: [
236
+ // AskUserQuestion references
237
+ {
238
+ pattern: /call the AskUserQuestion tool/gi,
239
+ replacement: 'ask the user to reply with their choice (as a numbered list)',
240
+ },
241
+ {
242
+ pattern: /\bAskUserQuestion\b/g,
243
+ replacement: 'numbered list prompt',
244
+ },
245
+ // Task-related references (keep Task, but clarify it's for subagents)
246
+ {
247
+ pattern: /Task\(\s*$/gm,
248
+ replacement: '/* Use Cursor subagents to spawn async work */',
249
+ },
250
+ // Task tracking references (not available in Cursor)
251
+ {
252
+ pattern: /TaskCreate\b/g,
253
+ replacement: '(not available - track progress in conversation)',
254
+ },
255
+ {
256
+ pattern: /TaskUpdate\b/g,
257
+ replacement: '(not available in Cursor)',
258
+ },
259
+ {
260
+ pattern: /TaskList\b/g,
261
+ replacement: '(not available in Cursor)',
262
+ },
263
+ ],
264
+
265
+ /**
266
+ * Windsurf: No subagents, suggests workflow chaining instead
267
+ * Uses "megaplan" for plan mode
268
+ */
269
+ windsurf: [
270
+ // AskUserQuestion references
271
+ {
272
+ pattern: /call the AskUserQuestion tool/gi,
273
+ replacement: 'ask the user to reply with their choice (as a numbered list)',
274
+ },
275
+ {
276
+ pattern: /\bAskUserQuestion\b/g,
277
+ replacement: 'numbered list prompt',
278
+ },
279
+ // Task references - suggest workflows instead
280
+ {
281
+ pattern: /\bTask\s*tool\b/gi,
282
+ replacement: 'workflow chaining',
283
+ },
284
+ {
285
+ pattern: /call the Task tool/gi,
286
+ replacement: 'suggest running the relevant /workflow',
287
+ },
288
+ {
289
+ pattern: /Task\(\s*$/gm,
290
+ replacement: '/* Suggest running /agileflow workflow via cascade */',
291
+ },
292
+ // Subagent type references - convert to workflow
293
+ {
294
+ pattern: /subagent_type:\s*"agileflow-([^"]+)"/g,
295
+ replacement: 'workflow: "/agileflow-$1"',
296
+ },
297
+ // Task tracking (not available)
298
+ {
299
+ pattern: /TaskCreate\b/g,
300
+ replacement: '(not available - use conversation comments)',
301
+ },
302
+ {
303
+ pattern: /TaskUpdate\b/g,
304
+ replacement: '(not available)',
305
+ },
306
+ {
307
+ pattern: /TaskList\b/g,
308
+ replacement: '(not available)',
309
+ },
310
+ // Plan mode - use megaplan keyword
311
+ {
312
+ pattern: /EnterPlanMode/g,
313
+ replacement: 'megaplan',
314
+ },
315
+ {
316
+ pattern: /ExitPlanMode/g,
317
+ replacement: '(end megaplan)',
318
+ },
319
+ ],
320
+
321
+ /**
322
+ * Codex: Most limited - no plan mode, hooks, or subagents
323
+ * Suggests skills and text-only interaction instead
324
+ */
325
+ codex: [
326
+ // AskUserQuestion references - use text-only function
327
+ {
328
+ pattern: /call the AskUserQuestion tool/gi,
329
+ replacement: 'call ask_user_question (text-only, no menus)',
330
+ },
331
+ {
332
+ pattern: /\bAskUserQuestion\b/g,
333
+ replacement: 'ask_user_question',
334
+ },
335
+ // Task/delegation references - suggest skills instead
336
+ {
337
+ pattern: /\bTask\s*tool\b/gi,
338
+ replacement: 'skill invocation',
339
+ },
340
+ {
341
+ pattern: /call the Task tool/gi,
342
+ replacement: 'invoke the relevant $agileflow skill',
343
+ },
344
+ {
345
+ pattern: /Task\(\s*$/gm,
346
+ replacement: '/* Invoke relevant skill via $agileflow-name */',
347
+ },
348
+ // Subagent type references - convert to skill syntax
349
+ {
350
+ pattern: /subagent_type:\s*"agileflow-([^"]+)"/g,
351
+ replacement: 'skill: "$agileflow-$1"',
352
+ },
353
+ // Task tracking (not available)
354
+ {
355
+ pattern: /TaskCreate\b/g,
356
+ replacement: '(not available in Codex)',
357
+ },
358
+ {
359
+ pattern: /TaskUpdate\b/g,
360
+ replacement: '(not available)',
361
+ },
362
+ {
363
+ pattern: /TaskList\b/g,
364
+ replacement: '(not available)',
365
+ },
366
+ // Plan mode (available in Codex since v0.96 - keep references)
367
+ // EnterPlanMode and ExitPlanMode are native in Codex, no transformation needed
368
+ // Hooks (not available)
369
+ {
370
+ pattern: /PreToolUse\b/g,
371
+ replacement: '(not available - no hooks)',
372
+ },
373
+ {
374
+ pattern: /PostToolUse\b/g,
375
+ replacement: '(not available - no hooks)',
376
+ },
377
+ {
378
+ pattern: /SessionStart\b/g,
379
+ replacement: '(not available - no hooks)',
380
+ },
381
+ ],
382
+ };
383
+
213
384
  /**
214
385
  * Create docs folder reference replacements
215
386
  *
@@ -231,18 +402,63 @@ function createDocsReplacements(targetFolder) {
231
402
  };
232
403
  }
233
404
 
405
+ /**
406
+ * Transform tool references in content based on IDE capabilities.
407
+ * Replaces Claude Code tool names and patterns with IDE-appropriate alternatives.
408
+ *
409
+ * For Claude Code (canonical format), returns content unchanged.
410
+ * For other IDEs, replaces tool references with alternatives based on capabilities:
411
+ * - Cursor: Converts AskUserQuestion to "numbered list prompt", Task stays as subagents
412
+ * - Windsurf: Converts to "megaplan" and workflow suggestions, removes Task references
413
+ * - Codex: Converts to skill invocations, text-only prompts, removes Plan mode
414
+ *
415
+ * @param {string} content - Content with Claude Code tool references
416
+ * @param {string} targetIde - Target IDE name: 'claude-code', 'cursor', 'windsurf', 'codex'
417
+ * @returns {string} Content with IDE-appropriate tool references
418
+ *
419
+ * @example
420
+ * const content = 'Use the AskUserQuestion tool to get user input';
421
+ * const cursor = transformToolReferences(content, 'cursor');
422
+ * // Returns: 'Use numbered list prompt to get user input'
423
+ *
424
+ * @example
425
+ * const content = 'Call the Task tool with subagent_type: "agileflow-test"';
426
+ * const windsurf = transformToolReferences(content, 'windsurf');
427
+ * // Returns: 'Suggest running the relevant /workflow with workflow: "/agileflow-test"'
428
+ */
429
+ function transformToolReferences(content, targetIde) {
430
+ // Claude Code is the canonical format - return unchanged
431
+ if (targetIde === 'claude-code') {
432
+ return content;
433
+ }
434
+
435
+ if (!content || typeof content !== 'string') {
436
+ return content || '';
437
+ }
438
+
439
+ const replacements = TOOL_REFERENCE_REPLACEMENTS[targetIde];
440
+ if (!replacements) {
441
+ // Unknown IDE - return unchanged
442
+ return content;
443
+ }
444
+
445
+ // Apply all replacements in order
446
+ return replaceReferences(content, replacements);
447
+ }
448
+
234
449
  /**
235
450
  * Transform content for a specific IDE target
236
451
  *
237
452
  * @param {string} content - Source content
238
- * @param {string} targetIde - Target IDE: 'codex', 'cursor', 'windsurf'
453
+ * @param {string} targetIde - Target IDE: 'codex', 'cursor', 'windsurf', 'claude-code'
239
454
  * @param {Object} [options] - Additional options
240
455
  * @param {string} [options.docsFolder] - Custom docs folder name
241
456
  * @param {Object} [options.additionalReplacements] - Extra replacements to apply
457
+ * @param {boolean} [options.transformTools] - Apply tool reference transformations (default: false for backward compatibility)
242
458
  * @returns {string} Transformed content
243
459
  */
244
460
  function transformForIde(content, targetIde, options = {}) {
245
- const { docsFolder, additionalReplacements = {} } = options;
461
+ const { docsFolder, additionalReplacements = {}, transformTools = false } = options;
246
462
 
247
463
  // Start with IDE-specific replacements
248
464
  const replacements = { ...(IDE_REPLACEMENTS[targetIde] || {}) };
@@ -255,7 +471,14 @@ function transformForIde(content, targetIde, options = {}) {
255
471
  // Add any additional custom replacements
256
472
  Object.assign(replacements, additionalReplacements);
257
473
 
258
- return replaceReferences(content, replacements);
474
+ let result = replaceReferences(content, replacements);
475
+
476
+ // Apply tool reference transformations if requested
477
+ if (transformTools) {
478
+ result = transformToolReferences(result, targetIde);
479
+ }
480
+
481
+ return result;
259
482
  }
260
483
 
261
484
  module.exports = {
@@ -266,6 +489,8 @@ module.exports = {
266
489
  getFrontmatter,
267
490
  escapeRegex,
268
491
  IDE_REPLACEMENTS,
492
+ TOOL_REFERENCE_REPLACEMENTS,
269
493
  createDocsReplacements,
494
+ transformToolReferences,
270
495
  transformForIde,
271
496
  };
@@ -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:logic:audit\`
193
+ - **logic-audits/**: Logic audit reports from \`/agileflow:audit:logic\`
194
194
  `,
195
195
 
196
196
  [`${docsFolder}/09-agents/README.md`]: `# Agent Status Tracking