claude-flow 3.45.0 → 3.46.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 (60) hide show
  1. package/README.md +2 -0
  2. package/README.zh-CN.md +424 -0
  3. package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
  4. package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.d.ts.map +1 -1
  5. package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.js +2 -6
  6. package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.js.map +1 -1
  7. package/node_modules/@claude-flow/mcp/dist/transport/http.d.ts.map +1 -1
  8. package/node_modules/@claude-flow/mcp/dist/transport/http.js +14 -1
  9. package/node_modules/@claude-flow/mcp/dist/transport/http.js.map +1 -1
  10. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/planner-descriptor.d.ts +40 -0
  11. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/planner-descriptor.d.ts.map +1 -0
  12. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/planner-descriptor.js +100 -0
  13. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/planner-descriptor.js.map +1 -0
  14. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
  15. package/node_modules/@claude-flow/plugin-agent-federation/dist/index.d.ts +1 -0
  16. package/node_modules/@claude-flow/plugin-agent-federation/dist/index.d.ts.map +1 -1
  17. package/node_modules/@claude-flow/plugin-agent-federation/dist/index.js +1 -0
  18. package/node_modules/@claude-flow/plugin-agent-federation/dist/index.js.map +1 -1
  19. package/node_modules/@claude-flow/plugin-agent-federation/package.json +1 -0
  20. package/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
  21. package/node_modules/@claude-flow/security/dist/safe-git.d.ts +22 -0
  22. package/node_modules/@claude-flow/security/dist/safe-git.d.ts.map +1 -0
  23. package/node_modules/@claude-flow/security/dist/safe-git.js +63 -0
  24. package/node_modules/@claude-flow/security/dist/safe-git.js.map +1 -0
  25. package/package.json +3 -3
  26. package/v3/@claude-flow/cli/README.md +2 -0
  27. package/v3/@claude-flow/cli/bin/cli.js +13 -0
  28. package/v3/@claude-flow/cli/bin/mcp-server.js +16 -0
  29. package/v3/@claude-flow/cli/catalog-manifest.json +2 -2
  30. package/v3/@claude-flow/cli/dist/src/commands/doctor.d.ts +3 -0
  31. package/v3/@claude-flow/cli/dist/src/commands/doctor.js +131 -2
  32. package/v3/@claude-flow/cli/dist/src/commands/embeddings.js +50 -7
  33. package/v3/@claude-flow/cli/dist/src/commands/init.js +5 -2
  34. package/v3/@claude-flow/cli/dist/src/commands/mcp.js +27 -4
  35. package/v3/@claude-flow/cli/dist/src/mcp-server.d.ts +50 -6
  36. package/v3/@claude-flow/cli/dist/src/mcp-server.js +267 -33
  37. package/v3/@claude-flow/cli/dist/src/mcp-tools/agent-execute-core.js +7 -0
  38. package/v3/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.js +20 -8
  39. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.js +59 -48
  40. package/v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.js +9 -4
  41. package/v3/@claude-flow/cli/dist/src/mcp-tools/metaharness-tools.js +1 -1
  42. package/v3/@claude-flow/cli/dist/src/mcp-tools/policy-enforcer.d.ts +4 -4
  43. package/v3/@claude-flow/cli/dist/src/mcp-tools/policy-enforcer.js +4 -4
  44. package/v3/@claude-flow/cli/dist/src/mcp-tools/terminal-tools.js +11 -1
  45. package/v3/@claude-flow/cli/dist/src/mcp-tools/workflow-tools.js +1 -1
  46. package/v3/@claude-flow/cli/dist/src/memory/ewc-consolidation.d.ts +16 -1
  47. package/v3/@claude-flow/cli/dist/src/memory/ewc-consolidation.js +63 -13
  48. package/v3/@claude-flow/cli/dist/src/memory/intelligence.d.ts +6 -2
  49. package/v3/@claude-flow/cli/dist/src/memory/intelligence.js +18 -11
  50. package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +84 -0
  51. package/v3/@claude-flow/cli/dist/src/runtime/browser-command.d.ts +29 -0
  52. package/v3/@claude-flow/cli/dist/src/runtime/browser-command.js +101 -0
  53. package/v3/@claude-flow/cli/dist/src/ruvector/model-router.js +19 -1
  54. package/v3/@claude-flow/cli/dist/src/services/distill-oracle.js +2 -1
  55. package/v3/@claude-flow/cli/dist/src/services/git-workspace-identity.js +5 -8
  56. package/v3/@claude-flow/cli/dist/src/services/policy-runtime.js +114 -4
  57. package/v3/@claude-flow/cli/dist/src/services/worker-daemon.js +8 -3
  58. package/v3/@claude-flow/cli/package.json +5 -5
  59. package/.claude/.proven-config-version +0 -1
  60. package/.claude/proven-config.json +0 -42
@@ -1,14 +1,39 @@
1
1
  import { AgenticPolicyEngine, createLegacyCompatibleState, isMcpCallerAuthEnabled, decodeTokenEnvelope, publicKeyFromHex, verifyInvocationToken, } from '@claude-flow/security';
2
2
  import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';
3
3
  import { execFileSync } from 'node:child_process';
4
- import { closeSync, existsSync, mkdirSync, openSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
4
+ import { closeSync, constants as fsConstants, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readlinkSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
5
5
  import { dirname, join, resolve } from 'node:path';
6
- import { userInfo } from 'node:os';
6
+ import { hostname, userInfo } from 'node:os';
7
7
  const POLICY_DIR = join('.claude-flow', 'policy');
8
8
  const POLICY_FILE = 'state.json';
9
9
  const LOCK_FILE = 'state.lock';
10
10
  const LOCK_STALE_MS = 30_000;
11
11
  const LOCK_WAIT_MS = 5_000;
12
+ // A lock is ~170 bytes plus the hostname (at most 255 bytes).
13
+ const LOCK_MAX_BYTES = 1_024;
14
+ // Linux PID namespace of this process, e.g. `pid:[4026531836]`; undefined on
15
+ // other platforms or without /proc. Recorded in the lock because a pid only
16
+ // identifies a process inside the namespace that wrote it.
17
+ const PID_NAMESPACE = (() => {
18
+ try {
19
+ return readlinkSync('/proc/self/ns/pid');
20
+ }
21
+ catch {
22
+ return undefined;
23
+ }
24
+ })();
25
+ // Linux boot id: one uuid per kernel boot, shared by every process on that
26
+ // kernel and readable inside containers. Recorded because `host` is only a
27
+ // name: two machines that share a project directory can report the same
28
+ // hostname, and the init PID namespace has the same inode on every Linux host.
29
+ const BOOT_ID = (() => {
30
+ try {
31
+ return readFileSync('/proc/sys/kernel/random/boot_id', 'utf8').trim();
32
+ }
33
+ catch {
34
+ return undefined;
35
+ }
36
+ })();
12
37
  function paths(projectRoot) {
13
38
  const root = resolve(projectRoot);
14
39
  const dir = join(root, POLICY_DIR);
@@ -17,12 +42,96 @@ function paths(projectRoot) {
17
42
  function sleep(ms) {
18
43
  return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
19
44
  }
45
+ /**
46
+ * Signal-0 existence probe, as in #1799 (`isPidAlive` in swarm-tools.ts), but
47
+ * only ESRCH counts as dead (as `processIsAlive` in helper-refresh.ts): here a
48
+ * false "dead" breaks mutual exclusion, so EPERM (another user's process) and
49
+ * any unexpected error mean alive.
50
+ */
51
+ function isPidAlive(pid) {
52
+ try {
53
+ process.kill(pid, 0);
54
+ return true;
55
+ }
56
+ catch (e) {
57
+ return e.code !== 'ESRCH';
58
+ }
59
+ }
60
+ /**
61
+ * Reads a lock only if it is a small regular file: never follows a symlink,
62
+ * never blocks on a FIFO or device, never reads more than LOCK_MAX_BYTES.
63
+ * Anything else returns undefined and the caller keeps the mtime rule.
64
+ */
65
+ function readLockFile(lockPath) {
66
+ if (!lstatSync(lockPath).isFile())
67
+ return undefined;
68
+ const fd = openSync(lockPath, fsConstants.O_RDONLY | (fsConstants.O_NOFOLLOW ?? 0) | (fsConstants.O_NONBLOCK ?? 0));
69
+ try {
70
+ const stat = fstatSync(fd);
71
+ if (!stat.isFile() || stat.size > LOCK_MAX_BYTES)
72
+ return undefined;
73
+ const buffer = Buffer.alloc(LOCK_MAX_BYTES);
74
+ return buffer.toString('utf8', 0, readSync(fd, buffer, 0, LOCK_MAX_BYTES, 0));
75
+ }
76
+ finally {
77
+ closeSync(fd);
78
+ }
79
+ }
80
+ /**
81
+ * A process killed inside a transaction (SIGKILL, OOM, or a signal whose
82
+ * default action terminates it) never runs `finally { release() }`, so every
83
+ * caller, MCP reads included, waited LOCK_WAIT_MS and failed with
84
+ * policy-state-lock-timeout until the orphan's mtime crossed LOCK_STALE_MS.
85
+ * The pid is trusted only if the lock was written by this OS, on this kernel
86
+ * boot and in this PID namespace: anywhere else (a bwrap --unshare-pid
87
+ * sandbox, a container, another machine on a shared filesystem) a live owner
88
+ * also answers ESRCH. Locks without that identity (older ruflo, a crash
89
+ * between create and write, anything unparsable) return false and keep the
90
+ * mtime rule.
91
+ */
92
+ function lockOwnerIsDead(lockPath) {
93
+ try {
94
+ const read = readLockFile(lockPath);
95
+ if (read === undefined)
96
+ return false;
97
+ const owner = JSON.parse(read);
98
+ if (!owner || owner.host !== hostname() || owner.platform !== process.platform
99
+ || owner.pidns !== PID_NAMESPACE || owner.boot !== BOOT_ID)
100
+ return false;
101
+ // Without /proc, one Linux kernel boot or PID namespace cannot be told
102
+ // from another, and `host` is only a name.
103
+ if (process.platform === 'linux'
104
+ && (PID_NAMESPACE === undefined || BOOT_ID === undefined))
105
+ return false;
106
+ const pid = owner.pid;
107
+ if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0 || pid > 0x7fffffff
108
+ || isPidAlive(pid))
109
+ return false;
110
+ // The lock can change hands while it is read and probed (its owner
111
+ // releases and exits, another process acquires). Re-read it and answer
112
+ // only if it is byte for byte the lock that was read: the next owner's
113
+ // lock always differs in `pid` or `acquiredAt`. `dev`/`ino`/`ctime` cannot
114
+ // stand in for that — ext4 reuses a freed inode number at once, and before
115
+ // Linux 6.13 two files created in one clock tick share a ctime.
116
+ return readLockFile(lockPath) === read;
117
+ }
118
+ catch {
119
+ return false;
120
+ }
121
+ }
20
122
  async function acquireLock(lockPath) {
21
123
  const started = Date.now();
22
124
  while (Date.now() - started < LOCK_WAIT_MS) {
23
125
  try {
24
126
  const fd = openSync(lockPath, 'wx', 0o600);
25
- writeFileSync(fd, JSON.stringify({ pid: process.pid, acquiredAt: Date.now() }));
127
+ writeFileSync(fd, JSON.stringify({
128
+ pid: process.pid,
129
+ acquiredAt: Date.now(),
130
+ host: hostname(),
131
+ platform: process.platform,
132
+ pidns: PID_NAMESPACE,
133
+ boot: BOOT_ID,
134
+ }));
26
135
  closeSync(fd);
27
136
  return () => {
28
137
  try {
@@ -33,7 +142,8 @@ async function acquireLock(lockPath) {
33
142
  }
34
143
  catch {
35
144
  try {
36
- if (Date.now() - statSync(lockPath).mtimeMs > LOCK_STALE_MS)
145
+ if (lockOwnerIsDead(lockPath)
146
+ || Date.now() - statSync(lockPath).mtimeMs > LOCK_STALE_MS)
37
147
  unlinkSync(lockPath);
38
148
  }
39
149
  catch { /* another process changed the lock */ }
@@ -14,6 +14,7 @@ import { EventEmitter } from 'events';
14
14
  import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync, unlinkSync } from 'fs';
15
15
  import { cpus } from 'os';
16
16
  import { join } from 'path';
17
+ import { createRequire } from 'node:module';
17
18
  import { writeFileAtomic } from '../fs-secure.js';
18
19
  import { HeadlessWorkerExecutor, isHeadlessWorker, } from './headless-worker-executor.js';
19
20
  // ADR-174 M3: the consolidate worker below drives the real DISTILL/CONSOLIDATE
@@ -26,6 +27,9 @@ import { backupMemoryDb } from './memory-backup.js';
26
27
  import { resolveGitWorkspaceIdentity } from './git-workspace-identity.js';
27
28
  import { getWorkspaceLeaseRegistry } from './workspace-lease.js';
28
29
  import { getRepoSupervisorRegistry } from './repo-supervisor.js';
30
+ // Daemon config is read synchronously from the constructor. In an ESM build,
31
+ // bare `require` is undefined, so use a module-relative require for YAML.
32
+ const requireYaml = createRequire(import.meta.url);
29
33
  // Default worker configurations with improved intervals (P0 fix: map 5min -> 15min)
30
34
  const DEFAULT_WORKERS = [
31
35
  { type: 'map', intervalMs: 15 * 60 * 1000, offsetMs: 0, priority: 'normal', description: 'Codebase mapping', enabled: true },
@@ -368,8 +372,7 @@ export class WorkerDaemon extends EventEmitter {
368
372
  try {
369
373
  // Lazy-load yaml so the daemon doesn't hard-require it; if the
370
374
  // dep isn't installed, fall back to the previous warn-only path.
371
- // eslint-disable-next-line @typescript-eslint/no-var-requires
372
- const yamlMod = require('yaml');
375
+ const yamlMod = requireYaml('yaml');
373
376
  const parsed = yamlMod.parse(readFileSync(yPath, 'utf-8'));
374
377
  if (parsed && typeof parsed === 'object') {
375
378
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1013,7 +1016,9 @@ export class WorkerDaemon extends EventEmitter {
1013
1016
  return `max age ${Math.round(ttlMs / 1000)}s reached`;
1014
1017
  }
1015
1018
  if (idleMs > 0) {
1016
- const lastActivity = this.lastWorkerActivityMs() ?? startedMs;
1019
+ // Worker timestamps survive restarts; they cannot make this process
1020
+ // idle before it has been alive for a full idle window (#3194).
1021
+ const lastActivity = Math.max(this.lastWorkerActivityMs() ?? startedMs, startedMs);
1017
1022
  if (now - lastActivity >= idleMs) {
1018
1023
  return `idle for ${Math.round(idleMs / 1000)}s (no worker activity)`;
1019
1024
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.45.0",
3
+ "version": "3.46.1",
4
4
  "type": "module",
5
5
  "description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -98,10 +98,10 @@
98
98
  "vitest": "^4.1.0"
99
99
  },
100
100
  "dependencies": {
101
- "@claude-flow/cli-core": "3.7.0-alpha.5",
101
+ "@claude-flow/cli-core": "3.7.0-alpha.6",
102
102
  "@claude-flow/codex": "3.0.3",
103
103
  "@claude-flow/mcp": "3.0.0-alpha.10",
104
- "@claude-flow/neural": "3.0.0-alpha.9",
104
+ "@claude-flow/neural": "3.0.0-alpha.10",
105
105
  "@claude-flow/plugin-agent-federation": "1.0.0-alpha.18",
106
106
  "@claude-flow/security": "3.0.0-alpha.14",
107
107
  "@claude-flow/shared": "3.0.0-alpha.7",
@@ -125,11 +125,11 @@
125
125
  "ws": "^8.21.0",
126
126
  "yaml": "^2.8.0",
127
127
  "zod": "^3.22.0",
128
- "@claude-flow/memory": "3.0.0-alpha.25"
128
+ "@claude-flow/memory": "3.0.0-alpha.26"
129
129
  },
130
130
  "optionalDependencies": {
131
131
  "@agntcy/slim-bindings": "2.0.0-alpha.5",
132
- "@claude-flow/memory": "3.0.0-alpha.25",
132
+ "@claude-flow/memory": "3.0.0-alpha.26",
133
133
  "@metaharness/darwin": "~0.10.2",
134
134
  "@metaharness/flywheel": "~0.1.10",
135
135
  "@metaharness/radio": "~0.1.0",
@@ -1 +0,0 @@
1
- sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319
@@ -1,42 +0,0 @@
1
- {
2
- "adoptedAt": 1790287605043,
3
- "championId": "sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319",
4
- "manifest": {
5
- "schema": "ruflo.proven-config/v1",
6
- "policy": {
7
- "ref": "sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319",
8
- "value": {
9
- "alpha": 0.3,
10
- "subjectWeight": 1,
11
- "mmrLambda": 0.5,
12
- "bodyWeight": 1.5,
13
- "typePenaltyFactor": 0.5
14
- }
15
- },
16
- "layer": "framework/node-cli",
17
- "compatibility": {
18
- "ruflo": ">=3.24.0"
19
- },
20
- "benchmark": {
21
- "corpus": "ADR-081-labelled-v1",
22
- "corpusHash": "sha256:2f700b5c363e20a3bd88ce2bc9b87bbbbaa61732c6177894c6ec37890f888982"
23
- },
24
- "receipt": {
25
- "heldOutDelta": 0.07381404928570845,
26
- "redblue": "PASS",
27
- "drift": 0,
28
- "canary": {
29
- "rollbackRate": 0,
30
- "latencyP95": 244.612458000076,
31
- "costPerTask": 0
32
- },
33
- "receiptCoverage": 1
34
- },
35
- "platform": [
36
- "linux",
37
- "macOS",
38
- "windows"
39
- ]
40
- },
41
- "previous": ""
42
- }