@claude-flow/cli 3.71.4 → 3.72.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 (124) hide show
  1. package/.claude/helpers/helpers.manifest.json +4 -4
  2. package/.claude/helpers/hook-handler.cjs +23 -10
  3. package/.claude/helpers/statusline.cjs +29 -14
  4. package/.claude/skills/fast-code-edits/SKILL.md +45 -0
  5. package/.claude/skills/graph-mincut/SKILL.md +32 -0
  6. package/.claude/skills/injection-defense/SKILL.md +36 -0
  7. package/.claude/skills/lora-learning/SKILL.md +30 -0
  8. package/.claude/skills/sublinear-solver/SKILL.md +34 -0
  9. package/.claude/skills/vector-quantization/SKILL.md +36 -0
  10. package/README.md +18 -3
  11. package/bin/cli.js +13 -18
  12. package/bin/mcp-server.js +13 -18
  13. package/catalog-manifest.json +4 -4
  14. package/dist/src/appliance/ruvllm-bridge.d.ts +6 -2
  15. package/dist/src/appliance/ruvllm-bridge.js +13 -8
  16. package/dist/src/appliance/rvfa-distribution.js +2 -2
  17. package/dist/src/benchmarks/gaia-critic.d.ts +1 -7
  18. package/dist/src/benchmarks/gaia-critic.js +1 -7
  19. package/dist/src/benchmarks/gaia-decomposer.d.ts +1 -8
  20. package/dist/src/benchmarks/gaia-decomposer.js +1 -8
  21. package/dist/src/commands/agent-wasm.js +2 -2
  22. package/dist/src/commands/analyze.js +1 -1
  23. package/dist/src/commands/daemon.js +1 -1
  24. package/dist/src/commands/doctor.js +3 -2
  25. package/dist/src/commands/guidance.js +9 -9
  26. package/dist/src/commands/hooks.js +13 -8
  27. package/dist/src/commands/init.js +16 -16
  28. package/dist/src/commands/neural.js +87 -77
  29. package/dist/src/commands/route.js +1 -1
  30. package/dist/src/commands/ruvector/backup.js +7 -5
  31. package/dist/src/commands/ruvector/benchmark.js +6 -1
  32. package/dist/src/commands/ruvector/import.js +19 -5
  33. package/dist/src/commands/ruvector/init.js +1 -1
  34. package/dist/src/commands/start.js +1 -1
  35. package/dist/src/commands/status.js +1 -1
  36. package/dist/src/commands/task.js +18 -1
  37. package/dist/src/commands/update.js +1 -1
  38. package/dist/src/funnel/local-signals.js +7 -2
  39. package/dist/src/init/executor.js +13 -0
  40. package/dist/src/init/types.d.ts +6 -0
  41. package/dist/src/init/types.js +3 -0
  42. package/dist/src/mcp-client.js +2 -0
  43. package/dist/src/mcp-protocol.d.ts +90 -0
  44. package/dist/src/mcp-protocol.js +179 -0
  45. package/dist/src/mcp-server.d.ts +1 -0
  46. package/dist/src/mcp-server.js +20 -22
  47. package/dist/src/mcp-tools/agent-execute-core.js +9 -1
  48. package/dist/src/mcp-tools/agent-tools.d.ts +13 -0
  49. package/dist/src/mcp-tools/agent-tools.js +59 -8
  50. package/dist/src/mcp-tools/agentdb-tools.js +34 -2
  51. package/dist/src/mcp-tools/browser-argv.d.ts +9 -0
  52. package/dist/src/mcp-tools/browser-argv.js +33 -0
  53. package/dist/src/mcp-tools/browser-session-tools.js +4 -0
  54. package/dist/src/mcp-tools/browser-tools.js +12 -2
  55. package/dist/src/mcp-tools/coordination-tools.js +5 -4
  56. package/dist/src/mcp-tools/embeddings-tools.js +12 -4
  57. package/dist/src/mcp-tools/fast-apply-tools.d.ts +4 -0
  58. package/dist/src/mcp-tools/fast-apply-tools.js +85 -0
  59. package/dist/src/mcp-tools/glob-exclusions.d.ts +6 -0
  60. package/dist/src/mcp-tools/glob-exclusions.js +81 -0
  61. package/dist/src/mcp-tools/hive-mind-tools.js +104 -35
  62. package/dist/src/mcp-tools/hooks-tools.js +14 -38
  63. package/dist/src/mcp-tools/import-limits.d.ts +4 -0
  64. package/dist/src/mcp-tools/import-limits.js +28 -0
  65. package/dist/src/mcp-tools/memory-tools.js +21 -42
  66. package/dist/src/mcp-tools/metaharness-tools.js +1 -1
  67. package/dist/src/mcp-tools/performance-tools.js +7 -2
  68. package/dist/src/mcp-tools/realpath-containment.d.ts +3 -0
  69. package/dist/src/mcp-tools/realpath-containment.js +39 -0
  70. package/dist/src/mcp-tools/record-store.d.ts +8 -0
  71. package/dist/src/mcp-tools/record-store.js +98 -1
  72. package/dist/src/mcp-tools/security-tools.d.ts +9 -0
  73. package/dist/src/mcp-tools/security-tools.js +39 -3
  74. package/dist/src/mcp-tools/session-tools.js +5 -3
  75. package/dist/src/mcp-tools/swarm-tools.js +35 -17
  76. package/dist/src/mcp-tools/task-tools.js +68 -5
  77. package/dist/src/mcp-tools/terminal-tools.js +9 -0
  78. package/dist/src/mcp-tools/workflow-tools.js +13 -12
  79. package/dist/src/mcp-tools/x-federation-join.js +55 -14
  80. package/dist/src/memory/intelligence.d.ts +11 -0
  81. package/dist/src/memory/intelligence.js +84 -6
  82. package/dist/src/memory/memory-initializer.d.ts +6 -2
  83. package/dist/src/memory/memory-initializer.js +15 -6
  84. package/dist/src/mods/command-registry/schema.d.ts +12 -12
  85. package/dist/src/ruvector/ast-analyzer.d.ts +1 -2
  86. package/dist/src/ruvector/ast-analyzer.js +4 -12
  87. package/dist/src/ruvector/coverage-router.d.ts +1 -2
  88. package/dist/src/ruvector/coverage-router.js +4 -12
  89. package/dist/src/ruvector/diff-classifier.d.ts +1 -2
  90. package/dist/src/ruvector/diff-classifier.js +3 -12
  91. package/dist/src/ruvector/fast-apply.d.ts +46 -0
  92. package/dist/src/ruvector/fast-apply.js +73 -0
  93. package/dist/src/ruvector/graph-analyzer.d.ts +11 -1
  94. package/dist/src/ruvector/graph-analyzer.js +22 -36
  95. package/dist/src/ruvector/mincut-bridge.d.ts +70 -0
  96. package/dist/src/ruvector/mincut-bridge.js +172 -0
  97. package/dist/src/ruvector/model-router.d.ts +6 -1
  98. package/dist/src/ruvector/model-router.js +16 -4
  99. package/dist/src/services/distill-oracle.d.ts +1 -1
  100. package/dist/src/services/distill-oracle.js +2 -2
  101. package/dist/src/services/worker-daemon.js +30 -12
  102. package/dist/src/transfer/storage/gcs.js +3 -2
  103. package/node_modules/@claude-flow/codex/.agents/skills/fast-code-edits/SKILL.md +42 -0
  104. package/node_modules/@claude-flow/codex/.agents/skills/graph-mincut/SKILL.md +42 -0
  105. package/node_modules/@claude-flow/codex/.agents/skills/injection-defense/SKILL.md +45 -0
  106. package/node_modules/@claude-flow/codex/.agents/skills/lora-learning/SKILL.md +39 -0
  107. package/node_modules/@claude-flow/codex/.agents/skills/sublinear-solver/SKILL.md +38 -0
  108. package/node_modules/@claude-flow/codex/.agents/skills/vector-quantization/SKILL.md +49 -0
  109. package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts.map +1 -1
  110. package/node_modules/@claude-flow/codex/dist/generators/skill-md.js +6 -0
  111. package/node_modules/@claude-flow/codex/dist/generators/skill-md.js.map +1 -1
  112. package/node_modules/@claude-flow/codex/dist/index.d.ts +3 -3
  113. package/node_modules/@claude-flow/codex/dist/index.js +1 -1
  114. package/node_modules/@claude-flow/codex/dist/templates/index.d.ts.map +1 -1
  115. package/node_modules/@claude-flow/codex/dist/templates/index.js +37 -0
  116. package/node_modules/@claude-flow/codex/dist/templates/index.js.map +1 -1
  117. package/node_modules/@claude-flow/codex/dist/types.d.ts +1 -1
  118. package/node_modules/@claude-flow/codex/dist/types.d.ts.map +1 -1
  119. package/node_modules/@claude-flow/codex/package.json +1 -1
  120. package/package.json +11 -9
  121. package/plugins/ruflo-metaharness/.claude-plugin/plugin.json +2 -1
  122. package/plugins/ruflo-metaharness/scripts/_darwin.mjs +4 -4
  123. package/plugins/ruflo-metaharness/scripts/_harness.mjs +1 -1
  124. package/plugins/ruflo-metaharness/scripts/smoke.sh +4 -4
package/bin/mcp-server.js CHANGED
@@ -33,8 +33,11 @@ import {
33
33
  loadMcpPolicy,
34
34
  evaluateToolCall,
35
35
  } from '../dist/src/mcp-tools/policy-enforcer.js';
36
+ // ADR-524: shared MCP revision handling (2026-07-28 + legacy initialize).
37
+ import * as mcpProtocol from '../dist/src/mcp-protocol.js';
36
38
 
37
- const VERSION = '3.0.0';
39
+ const MCP_CAPABILITIES = { tools: { listChanged: true }, resources: {} };
40
+ const VERSION = mcpProtocol.defaultServerIdentity().version;
38
41
  const sessionId = `mcp-${Date.now()}-${randomUUID().slice(0, 8)}`;
39
42
 
40
43
  // Log to stderr (doesn't corrupt stdout for MCP protocol)
@@ -132,27 +135,19 @@ async function handleMessage(message) {
132
135
  error: { code: -32600, message: 'Invalid Request: missing method' },
133
136
  };
134
137
  }
138
+ const preflight = mcpProtocol.protocolPreflight(message, MCP_CAPABILITIES);
139
+ if (preflight.response) return preflight.response;
140
+ const response = await dispatchMessage(message, preflight.context);
141
+ return mcpProtocol.finalizeResponse(response, message.method, preflight.context);
142
+ }
135
143
 
144
+ async function dispatchMessage(message, protocol) {
136
145
  const params = message.params || {};
137
146
 
138
147
  try {
139
148
  switch (message.method) {
140
- case 'initialize':
141
- return {
142
- jsonrpc: '2.0',
143
- id: message.id,
144
- result: {
145
- protocolVersion: '2024-11-05',
146
- serverInfo: { name: 'ruflo', version: VERSION },
147
- capabilities: {
148
- tools: { listChanged: true },
149
- resources: {},
150
- },
151
- },
152
- };
153
-
154
149
  case 'tools/list': {
155
- const tools = listMCPTools();
150
+ const tools = mcpProtocol.sortToolsDeterministically(listMCPTools());
156
151
  return {
157
152
  jsonrpc: '2.0',
158
153
  id: message.id,
@@ -190,7 +185,7 @@ async function handleMessage(message) {
190
185
  }
191
186
 
192
187
  try {
193
- const result = await callMCPTool(toolName, toolParams, { sessionId, transport: 'stdio' });
188
+ const result = await callMCPTool(toolName, toolParams, { sessionId, transport: 'stdio', ...mcpProtocol.traceContextFields(protocol) });
194
189
  return {
195
190
  jsonrpc: '2.0',
196
191
  id: message.id,
@@ -216,7 +211,7 @@ async function handleMessage(message) {
216
211
  return { jsonrpc: '2.0', id: message.id, result: { resourceTemplates: [] } };
217
212
 
218
213
  case 'resources/read':
219
- return { jsonrpc: '2.0', id: message.id, error: { code: -32002, message: 'Resource not found' } };
214
+ return { jsonrpc: '2.0', id: message.id, error: { code: mcpProtocol.resourceNotFoundCode(protocol), message: 'Resource not found' } };
220
215
 
221
216
  case 'notifications/initialized':
222
217
  console.error(`[${new Date().toISOString()}] INFO [claude-flow-mcp] Client initialized`);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generation": 7,
4
- "generatedAt": "2026-11-05T03:28:45.039Z",
5
- "gitSha": "bf5d71a1",
4
+ "generatedAt": "2026-11-06T02:50:18.000Z",
5
+ "gitSha": "29b327ee",
6
6
  "catalog": {
7
7
  "agents": 177,
8
- "tools": 450,
9
- "skills": 34
8
+ "tools": 451,
9
+ "skills": 40
10
10
  },
11
11
  "benchmark": null
12
12
  }
@@ -90,8 +90,12 @@ export declare class RuvllmBridge {
90
90
  shutdown(): Promise<void>;
91
91
  private scanModelsDir;
92
92
  private tryImport;
93
- /** Tier-1 Agent Booster: handle trivial transforms without any LLM. */
94
- private tryAgentBooster;
93
+ /**
94
+ * Tier-1 codemod hint for trivial transforms, no LLM. Not agent-booster:
95
+ * that engine merges a code snippet into code (hooks_fast-apply) and cannot
96
+ * act on an instruction alone.
97
+ */
98
+ private tryCodemodHint;
95
99
  }
96
100
  /** Get or create the singleton RuvllmBridge. Config required on first call. */
97
101
  export declare function getRuvllmBridge(config?: RuvllmConfig): RuvllmBridge;
@@ -135,10 +135,11 @@ export class RuvllmBridge {
135
135
  async generate(request) {
136
136
  const start = performance.now();
137
137
  const modelName = request.model ?? this.config.defaultModel ?? this.activeModel ?? '';
138
- // Tier 1: Agent Booster
139
- const booster = this.tryAgentBooster(request.prompt);
138
+ // Tier 1: deterministic codemod hint (ADR-143). The prompt carries no code,
139
+ // so nothing can be applied here; this points the caller at hooks_codemod.
140
+ const booster = this.tryCodemodHint(request.prompt);
140
141
  if (booster !== null) {
141
- return { text: booster, model: 'agent-booster', tokensUsed: 0, latencyMs: performance.now() - start, tier: 1, cached: false };
142
+ return { text: booster, model: 'codemod', tokensUsed: 0, latencyMs: performance.now() - start, tier: 1, cached: false };
142
143
  }
143
144
  // Tier 2: Local model (GGUF engine preferred, then @ruvector/core)
144
145
  const info = this.models.get(modelName);
@@ -183,7 +184,7 @@ export class RuvllmBridge {
183
184
  const complexity = estimateComplexity(description);
184
185
  const words = description.split(/\s+/).length;
185
186
  if (words < 15 && complexity < 0.25)
186
- return { tier: 1, model: 'agent-booster', confidence: 0.9 };
187
+ return { tier: 1, model: 'codemod', confidence: 0.9 };
187
188
  if (complexity < 0.55 && this.activeModel)
188
189
  return { tier: 2, model: this.activeModel, confidence: 0.7 };
189
190
  return { tier: 3, model: 'cloud', confidence: 0.6 };
@@ -252,17 +253,21 @@ export class RuvllmBridge {
252
253
  return null;
253
254
  }
254
255
  }
255
- /** Tier-1 Agent Booster: handle trivial transforms without any LLM. */
256
- tryAgentBooster(prompt) {
256
+ /**
257
+ * Tier-1 codemod hint for trivial transforms, no LLM. Not agent-booster:
258
+ * that engine merges a code snippet into code (hooks_fast-apply) and cannot
259
+ * act on an instruction alone.
260
+ */
261
+ tryCodemodHint(prompt) {
257
262
  const t = prompt.trim();
258
263
  if (t.length > 200)
259
264
  return null;
260
265
  if (/^(convert|change)\s+(var|let)\s+to\s+const$/i.test(t)) {
261
- return 'Use the Edit tool to replace `var`/`let` declarations with `const`.';
266
+ return 'Call hooks_codemod with intent="var-to-const" (deterministic, $0), or use the Edit tool.';
262
267
  }
263
268
  if (/^remove\s+console\.(log|warn|error|debug|info)$/i.test(t)) {
264
269
  const m = t.toLowerCase().match(/console\.(\w+)/)?.[1] ?? 'log';
265
- return `Use the Edit tool to remove all \`console.${m}\` calls.`;
270
+ return `Call hooks_codemod with intent="remove-console" (deterministic, $0), or use the Edit tool to remove all \`console.${m}\` calls.`;
266
271
  }
267
272
  return null;
268
273
  }
@@ -9,7 +9,7 @@
9
9
  */
10
10
  import { createHash, sign, verify as edVerify } from 'node:crypto';
11
11
  import { readFile, writeFile, rename, unlink, copyFile, mkdir } from 'node:fs/promises';
12
- import { dirname } from 'node:path';
12
+ import { basename, dirname } from 'node:path';
13
13
  import { request as httpsRequest } from 'node:https';
14
14
  import { gzipSync, gunzipSync } from 'node:zlib';
15
15
  import { RvfaReader, RvfaWriter } from './rvfa-format.js';
@@ -324,7 +324,7 @@ export class RvfaPublisher {
324
324
  }
325
325
  async publish(rvfaPath, meta) {
326
326
  const data = await readFile(rvfaPath);
327
- const name = meta?.name || rvfaPath.split('/').pop() || 'appliance.rvf';
327
+ const name = meta?.name || basename(rvfaPath) || 'appliance.rvf';
328
328
  return this.upload(name, data, {
329
329
  type: 'rvfa-appliance', version: meta?.version || '',
330
330
  profile: meta?.profile || '', description: meta?.description || '',
@@ -10,8 +10,7 @@
10
10
  * without requiring better search backends. Expected L1 lift: +3-5pp.
11
11
  *
12
12
  * Design:
13
- * - NEW file only; NOT wired into gaia-bench.ts yet to avoid merge conflicts
14
- * with in-flight iter 29/31/34 branches. Wiring is a small follow-up PR.
13
+ * - gaia-bench.ts loads the wrapper when critic review is enabled.
15
14
  * - `criticReview()` — single Sonnet call, returns structured verdict.
16
15
  * - `runGaiaAgentWithCritic()` — orchestration wrapper: runs agent, calls
17
16
  * critic, retries once on "fail". "uncertain" is treated as "pass" (don't
@@ -25,11 +24,6 @@
25
24
  * - One critic call + one optional retry = max 2 extra Sonnet calls per Q.
26
25
  * - Approximate extra cost per question: ~$0.003-0.005 (well within budget).
27
26
  *
28
- * Plugin sync TODO (follow-up PR after gaia-bench wiring):
29
- * - Update plugins/ruflo-workflows/commands/gaia-run.md with --enable-critic flag.
30
- * - Update plugins/ruflo-workflows/skills/gaia-debugging/SKILL.md: add critic
31
- * as a recommended diagnostic step for wrong-answer analysis.
32
- *
33
27
  * Refs: ADR-135, ADR-133, iter 29 finding, #2156
34
28
  */
35
29
  import { GaiaQuestion } from './gaia-loader.js';
@@ -10,8 +10,7 @@
10
10
  * without requiring better search backends. Expected L1 lift: +3-5pp.
11
11
  *
12
12
  * Design:
13
- * - NEW file only; NOT wired into gaia-bench.ts yet to avoid merge conflicts
14
- * with in-flight iter 29/31/34 branches. Wiring is a small follow-up PR.
13
+ * - gaia-bench.ts loads the wrapper when critic review is enabled.
15
14
  * - `criticReview()` — single Sonnet call, returns structured verdict.
16
15
  * - `runGaiaAgentWithCritic()` — orchestration wrapper: runs agent, calls
17
16
  * critic, retries once on "fail". "uncertain" is treated as "pass" (don't
@@ -25,11 +24,6 @@
25
24
  * - One critic call + one optional retry = max 2 extra Sonnet calls per Q.
26
25
  * - Approximate extra cost per question: ~$0.003-0.005 (well within budget).
27
26
  *
28
- * Plugin sync TODO (follow-up PR after gaia-bench wiring):
29
- * - Update plugins/ruflo-workflows/commands/gaia-run.md with --enable-critic flag.
30
- * - Update plugins/ruflo-workflows/skills/gaia-debugging/SKILL.md: add critic
31
- * as a recommended diagnostic step for wrong-answer analysis.
32
- *
33
27
  * Refs: ADR-135, ADR-133, iter 29 finding, #2156
34
28
  */
35
29
  import { execSync } from 'node:child_process';
@@ -11,9 +11,7 @@
11
11
  * Expected L1 lift: +5-10pp on multi-step questions (~30-40% of L1 set).
12
12
  *
13
13
  * Design:
14
- * - NEW standalone file only; NOT wired into gaia-bench.ts to avoid merge
15
- * conflicts with in-flight iter 29/31/34/35/36 branches.
16
- * Wiring is a small follow-up PR.
14
+ * - gaia-bench.ts loads the decomposer when decomposition is enabled.
17
15
  * - `decomposeQuestion()` — Haiku-cheap classification + decomposition
18
16
  * (~$0.0003 per question).
19
17
  * - `synthesizeFromSubAnswers()` — Sonnet synthesis from sub-answers
@@ -26,11 +24,6 @@
26
24
  * - Synthesis uses claude-sonnet-4-6 (~$0.002/question).
27
25
  * - Total overhead per question (when decomposed): ~$0.002-0.003.
28
26
  *
29
- * Plugin sync TODO (follow-up PR after gaia-bench wiring):
30
- * - Update plugins/ruflo-workflows/commands/gaia-run.md with --decompose flag.
31
- * - Update plugins/ruflo-workflows/skills/gaia-debugging/SKILL.md: add
32
- * decomposition as a recommended strategy for multi-step failures.
33
- *
34
27
  * Refs: ADR-135, ADR-133, iter 29 finding, #2156
35
28
  */
36
29
  export interface DecomposedQuestion {
@@ -11,9 +11,7 @@
11
11
  * Expected L1 lift: +5-10pp on multi-step questions (~30-40% of L1 set).
12
12
  *
13
13
  * Design:
14
- * - NEW standalone file only; NOT wired into gaia-bench.ts to avoid merge
15
- * conflicts with in-flight iter 29/31/34/35/36 branches.
16
- * Wiring is a small follow-up PR.
14
+ * - gaia-bench.ts loads the decomposer when decomposition is enabled.
17
15
  * - `decomposeQuestion()` — Haiku-cheap classification + decomposition
18
16
  * (~$0.0003 per question).
19
17
  * - `synthesizeFromSubAnswers()` — Sonnet synthesis from sub-answers
@@ -26,11 +24,6 @@
26
24
  * - Synthesis uses claude-sonnet-4-6 (~$0.002/question).
27
25
  * - Total overhead per question (when decomposed): ~$0.002-0.003.
28
26
  *
29
- * Plugin sync TODO (follow-up PR after gaia-bench wiring):
30
- * - Update plugins/ruflo-workflows/commands/gaia-run.md with --decompose flag.
31
- * - Update plugins/ruflo-workflows/skills/gaia-debugging/SKILL.md: add
32
- * decomposition as a recommended strategy for multi-step failures.
33
- *
34
27
  * Refs: ADR-135, ADR-133, iter 29 finding, #2156
35
28
  */
36
29
  import { execSync } from 'node:child_process';
@@ -146,7 +146,7 @@ export const wasmCreateCommand = {
146
146
  info = await wasm.createWasmAgent({
147
147
  model: ctx.flags.model,
148
148
  instructions: ctx.flags.instructions,
149
- maxTurns: ctx.flags['max-turns'],
149
+ maxTurns: ctx.flags.maxTurns,
150
150
  });
151
151
  }
152
152
  if (ctx.flags.format === 'json') {
@@ -201,7 +201,7 @@ export const wasmPromptCommand = {
201
201
  { command: 'claude-flow agent wasm-prompt -a wasm-agent-1-abc -i "Write a hello world"', description: 'Send prompt to WASM agent' },
202
202
  ],
203
203
  action: async (ctx) => {
204
- const agentId = ctx.flags['agent-id'] || ctx.args[0];
204
+ const agentId = ctx.flags.agentId || ctx.args[0];
205
205
  const promptInput = ctx.flags.input || ctx.args[1];
206
206
  if (!agentId) {
207
207
  output.printError('Agent ID is required. Use --agent-id or -a');
@@ -1556,7 +1556,7 @@ const modulesCommand = {
1556
1556
  const targetDir = ctx.args[0] || ctx.cwd;
1557
1557
  const outputFile = ctx.flags.output;
1558
1558
  const format = ctx.flags.format || 'text';
1559
- const minSize = ctx.flags['min-size'] || 2;
1559
+ const minSize = ctx.flags.minSize || 2;
1560
1560
  output.printInfo(`Detecting module communities in: ${output.highlight(targetDir)}`);
1561
1561
  output.writeln();
1562
1562
  const spinner = output.createSpinner({ text: 'Building dependency graph...', spinner: 'dots' });
@@ -1247,7 +1247,7 @@ const statusCommand = {
1247
1247
  ],
1248
1248
  action: async (ctx) => {
1249
1249
  const verbose = ctx.flags.verbose;
1250
- const showModes = ctx.flags['show-modes'];
1250
+ const showModes = ctx.flags.showModes;
1251
1251
  // #2356: global view across every workspace, not just cwd.
1252
1252
  if (ctx.flags.all) {
1253
1253
  return renderAllDaemonsStatus();
@@ -7,6 +7,7 @@
7
7
  import { output } from '../output.js';
8
8
  import { existsSync, readFileSync, statSync, openSync, readSync, closeSync } from 'fs';
9
9
  import { join, dirname } from 'path';
10
+ import { homedir } from 'node:os';
10
11
  import { fileURLToPath, pathToFileURL } from 'url';
11
12
  import { createHash } from 'crypto';
12
13
  import { ownInstallAncestors } from '../plugins/own-install.js';
@@ -182,7 +183,7 @@ async function checkStaleSettingsNpx() {
182
183
  // Look in both project-local and home-dir settings.
183
184
  const candidates = [
184
185
  join(process.cwd(), '.claude', 'settings.json'),
185
- join(process.env.HOME ?? '', '.claude', 'settings.json'),
186
+ join(homedir(), '.claude', 'settings.json'),
186
187
  ].filter((p, i, a) => p && a.indexOf(p) === i);
187
188
  const offenders = [];
188
189
  for (const settingsPath of candidates) {
@@ -248,7 +249,7 @@ export async function checkHelperIntegrity(opts = {}) {
248
249
  const { verifyInstalledCriticalHelpers } = await import('../init/helper-integrity.js');
249
250
  const { CRITICAL_HELPERS, findPackageHelpersDir } = await import('../init/helper-refresh.js');
250
251
  const envLocked = /^(1|true|on|yes)$/i.test(String(process.env.RUFLO_HELPERS_LOCKED || ''));
251
- const home = opts.homeDir ?? process.env.HOME ?? '';
252
+ const home = opts.homeDir ?? homedir();
252
253
  const dirs = [
253
254
  join(opts.cwd ?? process.cwd(), '.claude', 'helpers'),
254
255
  ...(home ? [join(home, '.claude', 'helpers')] : []),
@@ -34,7 +34,7 @@ const compileCommand = {
34
34
  output.writeln(output.error(`Root guidance file not found: ${rootPath}`));
35
35
  return { success: false, message: `File not found: ${rootPath}` };
36
36
  }
37
- const modExport = ctx.flags['mod-projection'] === true;
37
+ const modExport = (ctx.flags.modProjection ?? ctx.flags['mod-projection']) === true;
38
38
  const checked = modExport ? await (await import('../guidance/mod-sources.js')).readModGuidanceSources({
39
39
  rootPath, localPath, revision: String(ctx.flags.revision || ''),
40
40
  }) : undefined;
@@ -112,7 +112,7 @@ const retrieveCommand = {
112
112
  const task = ctx.flags.task;
113
113
  const rootPath = ctx.flags.root || './CLAUDE.md';
114
114
  const localPath = ctx.flags.local;
115
- const maxShards = parseInt(ctx.flags['max-shards'] || '5', 10);
115
+ const maxShards = parseInt(String(ctx.flags.maxShards ?? ctx.flags['max-shards'] ?? 5), 10);
116
116
  const intentOverride = ctx.flags.intent;
117
117
  const jsonOutput = ctx.flags.json === true;
118
118
  if (!task) {
@@ -338,9 +338,9 @@ const optimizeCommand = {
338
338
  const rootPath = ctx.flags.root || './CLAUDE.md';
339
339
  const localPath = ctx.flags.local;
340
340
  const applyChanges = ctx.flags.apply === true;
341
- const contextSize = (ctx.flags['context-size'] || 'standard');
342
- const targetScore = parseInt(ctx.flags['target-score'] || '90', 10);
343
- const maxIterations = parseInt(ctx.flags['max-iterations'] || '5', 10);
341
+ const contextSize = (ctx.flags.contextSize ?? ctx.flags['context-size'] ?? 'standard');
342
+ const targetScore = parseInt(String(ctx.flags.targetScore ?? ctx.flags['target-score'] ?? 90), 10);
343
+ const maxIterations = parseInt(String(ctx.flags.maxIterations ?? ctx.flags['max-iterations'] ?? 5), 10);
344
344
  const jsonOutput = ctx.flags.json === true;
345
345
  output.writeln();
346
346
  output.writeln(output.bold('Guidance Optimizer'));
@@ -437,10 +437,10 @@ const abTestCommand = {
437
437
  { command: 'claude-flow guidance ab-test --json', description: 'Output full report as JSON' },
438
438
  ],
439
439
  action: async (ctx) => {
440
- const configAPath = ctx.flags['config-a'];
441
- const configBPath = ctx.flags['config-b'] || './CLAUDE.md';
440
+ const configAPath = (ctx.flags.configA ?? ctx.flags['config-a']);
441
+ const configBPath = (ctx.flags.configB ?? ctx.flags['config-b'] ?? './CLAUDE.md');
442
442
  const tasksPath = ctx.flags.tasks;
443
- const workDir = ctx.flags['work-dir'];
443
+ const workDir = (ctx.flags.workDir ?? ctx.flags['work-dir']);
444
444
  const jsonOutput = ctx.flags.json === true;
445
445
  output.writeln();
446
446
  output.writeln(output.bold('A/B Behavioral Benchmark'));
@@ -541,7 +541,7 @@ const modCandidatesCommand = {
541
541
  action: async (ctx) => {
542
542
  try {
543
543
  const { collectModCandidates } = await import('../guidance/mod-projection.js');
544
- const data = await collectModCandidates(String(ctx.flags.directory || '.claude-flow/mods/guidance/observations'), ctx.flags['bundle-id']);
544
+ const data = await collectModCandidates(String(ctx.flags.directory || '.claude-flow/mods/guidance/observations'), (ctx.flags.bundleId ?? ctx.flags['bundle-id']));
545
545
  output.writeln(JSON.stringify(data, null, ctx.flags.json === true ? undefined : 2));
546
546
  return { success: true, data };
547
547
  }
@@ -2529,8 +2529,8 @@ const workerDetectCommand = {
2529
2529
  ],
2530
2530
  action: async (ctx) => {
2531
2531
  const prompt = ctx.flags['prompt'];
2532
- const autoDispatch = ctx.flags['auto-dispatch'];
2533
- const minConfidence = parseFloat(ctx.flags['min-confidence'] || '0.5');
2532
+ const autoDispatch = (ctx.flags.autoDispatch ?? ctx.flags['auto-dispatch']);
2533
+ const minConfidence = parseFloat(String(ctx.flags.minConfidence ?? ctx.flags['min-confidence'] ?? 0.5) || '0.5');
2534
2534
  if (!prompt) {
2535
2535
  output.printError('--prompt is required');
2536
2536
  return { success: false, exitCode: 1 };
@@ -2570,7 +2570,12 @@ const workerDetectCommand = {
2570
2570
  }
2571
2571
  if (result.autoDispatched && result.workerIds) {
2572
2572
  output.writeln();
2573
- output.writeln(output.success('Workers auto-dispatched:'));
2573
+ if (result.autoDispatchStatus === 'synthetic-completed') {
2574
+ output.printWarning(result.note ?? 'No executor ran. Worker records are synthetic placeholders.');
2575
+ }
2576
+ else {
2577
+ output.writeln(output.success('Workers auto-dispatched:'));
2578
+ }
2574
2579
  result.workerIds.forEach(id => {
2575
2580
  output.writeln(` - ${id}`);
2576
2581
  });
@@ -3079,8 +3084,8 @@ const coverageGapsCommand = {
3079
3084
  ],
3080
3085
  action: async (ctx) => {
3081
3086
  const threshold = ctx.flags.threshold ?? 80;
3082
- const groupByAgent = ctx.flags['group-by-agent'] !== false;
3083
- const criticalOnly = ctx.flags['critical-only'] || false;
3087
+ const groupByAgent = (ctx.flags.groupByAgent ?? ctx.flags['group-by-agent']) !== false;
3088
+ const criticalOnly = (ctx.flags.criticalOnly ?? ctx.flags['critical-only']) === true;
3084
3089
  const spinner = output.createSpinner({ text: 'Analyzing project coverage gaps...' });
3085
3090
  spinner.start();
3086
3091
  // Try reading coverage from disk first
@@ -4161,7 +4166,7 @@ const modelRouteCommand = {
4161
4166
  { name: 'task', short: 't', type: 'string', description: 'Task description to route', required: true },
4162
4167
  { name: 'context', short: 'c', type: 'string', description: 'Additional context' },
4163
4168
  { name: 'prefer-cost', type: 'boolean', description: 'Prefer lower cost models' },
4164
- { name: 'prefer-quality', type: 'boolean', description: 'Prefer higher quality models' },
4169
+ { name: 'prefer-speed', type: 'boolean', description: 'Prefer faster models when possible' },
4165
4170
  ],
4166
4171
  examples: [
4167
4172
  { command: 'claude-flow hooks model-route -t "fix typo"', description: 'Route simple task (likely haiku)' },
@@ -4178,8 +4183,8 @@ const modelRouteCommand = {
4178
4183
  const result = await callMCPTool('hooks_model-route', {
4179
4184
  task,
4180
4185
  context: ctx.flags.context,
4181
- preferCost: ctx.flags['prefer-cost'],
4182
- preferQuality: ctx.flags['prefer-quality'],
4186
+ preferCost: ctx.flags.preferCost,
4187
+ preferSpeed: ctx.flags.preferSpeed,
4183
4188
  });
4184
4189
  if (ctx.flags.format === 'json') {
4185
4190
  output.printJson(result);
@@ -816,16 +816,22 @@ const initClaudeAction = async (ctx) => {
816
816
  if (startDaemon || startAll) {
817
817
  output.writeln();
818
818
  output.printInfo('Starting services...');
819
- const { execSync } = await import('child_process');
819
+ const { execFileSync } = await import('child_process');
820
+ // #4770: drop stderr via stdio, not a shell redirect (breaks on cmd.exe).
821
+ // shell on win32 so npx.cmd resolves (#2770); args are fixed literals.
822
+ const runCli = (args) => {
823
+ execFileSync('npx', ['@claude-flow/cli@latest', ...args], {
824
+ stdio: ['ignore', 'pipe', 'ignore'],
825
+ cwd: ctx.cwd,
826
+ timeout: 30000,
827
+ shell: process.platform === 'win32',
828
+ });
829
+ };
820
830
  // Initialize memory database
821
831
  if (startAll) {
822
832
  try {
823
833
  output.writeln(output.dim(' Initializing memory database...'));
824
- execSync('npx @claude-flow/cli@latest memory init 2>/dev/null', {
825
- stdio: 'pipe',
826
- cwd: ctx.cwd,
827
- timeout: 30000
828
- });
834
+ runCli(['memory', 'init']);
829
835
  output.writeln(output.success(' ✓ Memory initialized'));
830
836
  }
831
837
  catch {
@@ -854,11 +860,7 @@ const initClaudeAction = async (ctx) => {
854
860
  if (startDaemon) {
855
861
  try {
856
862
  output.writeln(output.dim(' Starting daemon...'));
857
- execSync('npx @claude-flow/cli@latest daemon start 2>/dev/null', {
858
- stdio: 'pipe',
859
- cwd: ctx.cwd,
860
- timeout: 30000
861
- });
863
+ runCli(['daemon', 'start']);
862
864
  output.writeln(output.success(' ✓ Daemon started'));
863
865
  }
864
866
  catch {
@@ -872,11 +874,7 @@ const initClaudeAction = async (ctx) => {
872
874
  if (startAll) {
873
875
  try {
874
876
  output.writeln(output.dim(' Initializing swarm...'));
875
- execSync('npx @claude-flow/cli@latest swarm init --topology hierarchical 2>/dev/null', {
876
- stdio: 'pipe',
877
- cwd: ctx.cwd,
878
- timeout: 30000
879
- });
877
+ runCli(['swarm', 'init', '--topology', 'hierarchical']);
880
878
  output.writeln(output.success(' ✓ Swarm initialized'));
881
879
  }
882
880
  catch {
@@ -1357,6 +1355,7 @@ const skillsCommand = {
1357
1355
  { name: 'github', description: 'Install GitHub skills', type: 'boolean', default: false },
1358
1356
  { name: 'v3', description: 'Install V3 skills', type: 'boolean', default: false },
1359
1357
  { name: 'legacy', description: 'Install skills that document commands v3 does not ship (stream-chain, sparc)', type: 'boolean', default: false },
1358
+ { name: 'ecosystem', description: 'Install ecosystem skills (vector quantization, graph min-cut, sublinear solving, injection defense, fast edits, LoRA learning)', type: 'boolean', default: true },
1360
1359
  ],
1361
1360
  action: async (ctx) => {
1362
1361
  const options = {
@@ -1384,6 +1383,7 @@ const skillsCommand = {
1384
1383
  v3: ctx.flags.v3,
1385
1384
  dualMode: false,
1386
1385
  legacy: ctx.flags.legacy,
1386
+ ecosystem: ctx.flags.ecosystem,
1387
1387
  },
1388
1388
  };
1389
1389
  const spinner = output.createSpinner({ text: 'Installing skills...' });