claude-flow 3.50.0 → 3.51.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 (60) hide show
  1. package/.claude/proven-config.json +1 -1
  2. package/.claude/settings.json +11 -2
  3. package/.claude-plugin/marketplace.json +5 -0
  4. package/package.json +1 -1
  5. package/v3/@claude-flow/cli/README.md +0 -2
  6. package/v3/@claude-flow/cli/catalog-manifest.json +4 -4
  7. package/v3/@claude-flow/cli/dist/src/commands/catalog.d.ts +18 -0
  8. package/v3/@claude-flow/cli/dist/src/commands/catalog.js +89 -0
  9. package/v3/@claude-flow/cli/dist/src/commands/doctor.js +8 -3
  10. package/v3/@claude-flow/cli/dist/src/commands/index.js +3 -0
  11. package/v3/@claude-flow/cli/dist/src/commands/init.js +50 -11
  12. package/v3/@claude-flow/cli/dist/src/commands/mission.d.ts +24 -0
  13. package/v3/@claude-flow/cli/dist/src/commands/mission.js +116 -0
  14. package/v3/@claude-flow/cli/dist/src/commands/mods.d.ts +1 -1
  15. package/v3/@claude-flow/cli/dist/src/commands/mods.js +67 -23
  16. package/v3/@claude-flow/cli/dist/src/mcp-client.js +3 -0
  17. package/v3/@claude-flow/cli/dist/src/mcp-tools/capability-brain.js +1 -1
  18. package/v3/@claude-flow/cli/dist/src/mcp-tools/index.d.ts +1 -0
  19. package/v3/@claude-flow/cli/dist/src/mcp-tools/index.js +2 -0
  20. package/v3/@claude-flow/cli/dist/src/mcp-tools/mission-tools.d.ts +22 -0
  21. package/v3/@claude-flow/cli/dist/src/mcp-tools/mission-tools.js +75 -0
  22. package/v3/@claude-flow/cli/dist/src/missions/fold.d.ts +19 -0
  23. package/v3/@claude-flow/cli/dist/src/missions/fold.js +238 -0
  24. package/v3/@claude-flow/cli/dist/src/missions/index.d.ts +10 -0
  25. package/v3/@claude-flow/cli/dist/src/missions/index.js +10 -0
  26. package/v3/@claude-flow/cli/dist/src/missions/observation.d.ts +70 -0
  27. package/v3/@claude-flow/cli/dist/src/missions/observation.js +77 -0
  28. package/v3/@claude-flow/cli/dist/src/missions/schemas.d.ts +735 -0
  29. package/v3/@claude-flow/cli/dist/src/missions/schemas.js +150 -0
  30. package/v3/@claude-flow/cli/dist/src/missions/service.d.ts +88 -0
  31. package/v3/@claude-flow/cli/dist/src/missions/service.js +278 -0
  32. package/v3/@claude-flow/cli/dist/src/missions/store.d.ts +68 -0
  33. package/v3/@claude-flow/cli/dist/src/missions/store.js +209 -0
  34. package/v3/@claude-flow/cli/dist/src/missions/transitions.d.ts +81 -0
  35. package/v3/@claude-flow/cli/dist/src/missions/transitions.js +178 -0
  36. package/v3/@claude-flow/cli/dist/src/mods/apply.d.ts +50 -0
  37. package/v3/@claude-flow/cli/dist/src/mods/apply.js +186 -0
  38. package/v3/@claude-flow/cli/dist/src/mods/command-registry/catalog.d.ts +45 -0
  39. package/v3/@claude-flow/cli/dist/src/mods/command-registry/catalog.js +234 -0
  40. package/v3/@claude-flow/cli/dist/src/mods/command-registry/engine-report.d.ts +66 -0
  41. package/v3/@claude-flow/cli/dist/src/mods/command-registry/engine-report.js +119 -0
  42. package/v3/@claude-flow/cli/dist/src/mods/command-registry/generate.d.ts +51 -0
  43. package/v3/@claude-flow/cli/dist/src/mods/command-registry/generate.js +166 -0
  44. package/v3/@claude-flow/cli/dist/src/mods/command-registry/index.d.ts +9 -0
  45. package/v3/@claude-flow/cli/dist/src/mods/command-registry/index.js +9 -0
  46. package/v3/@claude-flow/cli/dist/src/mods/command-registry/inventory.d.ts +63 -0
  47. package/v3/@claude-flow/cli/dist/src/mods/command-registry/inventory.js +230 -0
  48. package/v3/@claude-flow/cli/dist/src/mods/command-registry/schema.d.ts +836 -0
  49. package/v3/@claude-flow/cli/dist/src/mods/command-registry/schema.js +137 -0
  50. package/v3/@claude-flow/cli/dist/src/mods/install.d.ts +60 -22
  51. package/v3/@claude-flow/cli/dist/src/mods/install.js +91 -41
  52. package/v3/@claude-flow/cli/dist/src/mods/plugin-repair.d.ts +81 -0
  53. package/v3/@claude-flow/cli/dist/src/mods/plugin-repair.js +120 -0
  54. package/v3/@claude-flow/cli/dist/src/mods/plugin-resolve.d.ts +63 -0
  55. package/v3/@claude-flow/cli/dist/src/mods/plugin-resolve.js +182 -0
  56. package/v3/@claude-flow/cli/dist/src/mods/probe.d.ts +5 -0
  57. package/v3/@claude-flow/cli/dist/src/mods/probe.js +28 -3
  58. package/v3/@claude-flow/cli/dist/src/services/policy-runtime.d.ts +5 -0
  59. package/v3/@claude-flow/cli/dist/src/services/policy-runtime.js +5 -1
  60. package/v3/@claude-flow/cli/package.json +1 -1
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Whether Claude Code can actually load the ruflo mod plugins (ADR-404).
3
+ *
4
+ * `enabledPlugins["ruflo-mods@ruflo"] = true` in settings is only a request.
5
+ * Observed live on Claude Code 2.1.287: an interactive, trusted session clones
6
+ * the `ruflo` marketplace a project declares and loads an enabled plugin
7
+ * straight from that clone (no install record needed); a headless `-p` run
8
+ * clones nothing. A clone from before ruflo-mods shipped has no
9
+ * `plugins/ruflo-mods`, and Claude Code skips the enabled plugin without a
10
+ * word: `/ruflo-mods` is an unknown command, and the clone is not refreshed
11
+ * on start. So the clone decides; an install record (`installed_plugins.json`,
12
+ * pointing into `plugins/cache/`) is a cached copy that still loads when the
13
+ * clone goes stale.
14
+ *
15
+ * Read-only. The config directory is `CLAUDE_CONFIG_DIR` when set, else
16
+ * `~/.claude`, as Claude Code itself resolves it.
17
+ */
18
+ import { type MarketplaceEntry, type ModPlugin, type Scope } from './install.js';
19
+ import type { Finding } from './probe.js';
20
+ /** The two filesystem reads detection needs; injectable for tests. */
21
+ export interface ReadFs {
22
+ exists(path: string): boolean;
23
+ readText(path: string): string | undefined;
24
+ }
25
+ export declare const nodeReadFs: ReadFs;
26
+ export declare function claudeConfigDir(env: NodeJS.ProcessEnv, home: string): string;
27
+ export interface MarketplaceState {
28
+ /** Listed in known_marketplaces.json (so `marketplace update ruflo` works). */
29
+ known: boolean;
30
+ /** The local clone (or, for a directory source, the directory), when it exists on disk. */
31
+ location: string | null;
32
+ /** The source Claude Code knows the marketplace by, when known. */
33
+ source?: MarketplaceEntry['source'];
34
+ }
35
+ /** "github ruvnet/ruflo" or "directory /path" (a working tree: no clone, nothing to go stale). */
36
+ export declare function describeSource(source: unknown): string;
37
+ export declare function sameSource(a: unknown, b: unknown): boolean;
38
+ export declare function marketplaceState(configDir: string, fs?: ReadFs): MarketplaceState;
39
+ /** The plugin's manifest inside a clone: its marketplace.json `source`, else plugins/<name>. */
40
+ export declare function pluginManifestIn(clone: string, id: string, fs?: ReadFs): string;
41
+ /** The clone carries this plugin. */
42
+ export declare function cloneHas(market: MarketplaceState, id: string, fs?: ReadFs): boolean;
43
+ export interface InstalledState {
44
+ installed: boolean;
45
+ scope?: string;
46
+ installPath?: string;
47
+ }
48
+ /** Installed for this project: user scope anywhere, local/project scope for this root; its cache dir present. */
49
+ export declare function installedState(projectRoot: string, configDir: string, id: string, fs?: ReadFs): InstalledState;
50
+ /**
51
+ * The exact commands that refresh the marketplace and install the plugins,
52
+ * for a person to run. `known` is true only when Claude Code already knows
53
+ * the marketplace by the wanted source (then an update suffices). A
54
+ * directory source loads live from the working tree: nothing to install.
55
+ */
56
+ export declare function repairCommands(projectRoot: string, scope: Scope | 'user', known: boolean, plugins?: readonly ModPlugin[], wanted?: MarketplaceEntry): string[];
57
+ /**
58
+ * The marketplace finding plus one finding per plugin enabled in settings.
59
+ * A required plugin missing from the clone with no cached install is the
60
+ * failure Claude Code hides; a plugin not yet released is "pending".
61
+ */
62
+ export declare function resolveFindings(projectRoot: string, scope: Scope | 'user', configDir: string, fs?: ReadFs, enabled?: readonly string[], declared?: unknown): Finding[];
63
+ //# sourceMappingURL=plugin-resolve.d.ts.map
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Whether Claude Code can actually load the ruflo mod plugins (ADR-404).
3
+ *
4
+ * `enabledPlugins["ruflo-mods@ruflo"] = true` in settings is only a request.
5
+ * Observed live on Claude Code 2.1.287: an interactive, trusted session clones
6
+ * the `ruflo` marketplace a project declares and loads an enabled plugin
7
+ * straight from that clone (no install record needed); a headless `-p` run
8
+ * clones nothing. A clone from before ruflo-mods shipped has no
9
+ * `plugins/ruflo-mods`, and Claude Code skips the enabled plugin without a
10
+ * word: `/ruflo-mods` is an unknown command, and the clone is not refreshed
11
+ * on start. So the clone decides; an install record (`installed_plugins.json`,
12
+ * pointing into `plugins/cache/`) is a cached copy that still loads when the
13
+ * clone goes stale.
14
+ *
15
+ * Read-only. The config directory is `CLAUDE_CONFIG_DIR` when set, else
16
+ * `~/.claude`, as Claude Code itself resolves it.
17
+ */
18
+ import { existsSync, readFileSync, realpathSync } from 'node:fs';
19
+ import { join, resolve } from 'node:path';
20
+ import { MARKETPLACE_NAME, MARKETPLACE_SOURCE, MOD_PLUGINS } from './install.js';
21
+ export const nodeReadFs = {
22
+ exists: (p) => existsSync(p),
23
+ readText: (p) => {
24
+ try {
25
+ return readFileSync(p, 'utf8');
26
+ }
27
+ catch {
28
+ return undefined;
29
+ }
30
+ },
31
+ };
32
+ export function claudeConfigDir(env, home) {
33
+ return env.CLAUDE_CONFIG_DIR || join(home, '.claude');
34
+ }
35
+ function readJson(fs, path) {
36
+ const text = fs.readText(path);
37
+ if (text === undefined)
38
+ return undefined;
39
+ try {
40
+ return JSON.parse(text);
41
+ }
42
+ catch {
43
+ return undefined;
44
+ }
45
+ }
46
+ function isRecord(v) {
47
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
48
+ }
49
+ const nameOf = (id) => id.split('@')[0];
50
+ /** "github ruvnet/ruflo" or "directory /path" (a working tree: no clone, nothing to go stale). */
51
+ export function describeSource(source) {
52
+ if (!isRecord(source))
53
+ return 'unknown source';
54
+ if (source.source === 'directory')
55
+ return `directory ${String(source.path)}`;
56
+ if (source.source === 'github')
57
+ return `github ${String(source.repo)}`;
58
+ return String(source.source ?? 'unknown source');
59
+ }
60
+ export function sameSource(a, b) {
61
+ if (!isRecord(a) || !isRecord(b) || a.source !== b.source)
62
+ return false;
63
+ return a.source === 'directory' ? resolve(String(a.path)) === resolve(String(b.path)) : a.repo === b.repo;
64
+ }
65
+ export function marketplaceState(configDir, fs = nodeReadFs) {
66
+ const known = readJson(fs, join(configDir, 'plugins', 'known_marketplaces.json'));
67
+ const entry = isRecord(known) ? known[MARKETPLACE_NAME] : undefined;
68
+ const declared = isRecord(entry) && typeof entry.installLocation === 'string' ? entry.installLocation : undefined;
69
+ const candidates = [declared, join(configDir, 'plugins', 'marketplaces', MARKETPLACE_NAME)].filter((p) => !!p);
70
+ const source = isRecord(entry) && isRecord(entry.source) ? entry.source : undefined;
71
+ return { known: isRecord(entry), location: candidates.find((p) => fs.exists(p)) ?? null, source };
72
+ }
73
+ /** The plugin's manifest inside a clone: its marketplace.json `source`, else plugins/<name>. */
74
+ export function pluginManifestIn(clone, id, fs = nodeReadFs) {
75
+ const catalog = readJson(fs, join(clone, '.claude-plugin', 'marketplace.json'));
76
+ const listed = isRecord(catalog) && Array.isArray(catalog.plugins)
77
+ ? catalog.plugins.find((p) => isRecord(p) && p.name === nameOf(id))
78
+ : undefined;
79
+ const source = isRecord(listed) && typeof listed.source === 'string' ? listed.source : `./plugins/${nameOf(id)}`;
80
+ return join(clone, source, '.claude-plugin', 'plugin.json');
81
+ }
82
+ /** The clone carries this plugin. */
83
+ export function cloneHas(market, id, fs = nodeReadFs) {
84
+ return market.location !== null && fs.exists(pluginManifestIn(market.location, id, fs));
85
+ }
86
+ function sameDir(a, b) {
87
+ if (resolve(a) === resolve(b))
88
+ return true;
89
+ try {
90
+ return realpathSync(a) === realpathSync(b);
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ }
96
+ /** Installed for this project: user scope anywhere, local/project scope for this root; its cache dir present. */
97
+ export function installedState(projectRoot, configDir, id, fs = nodeReadFs) {
98
+ const record = readJson(fs, join(configDir, 'plugins', 'installed_plugins.json'));
99
+ const plugins = isRecord(record) && isRecord(record.plugins) ? record.plugins : undefined;
100
+ const entries = plugins && Array.isArray(plugins[id]) ? plugins[id] : [];
101
+ for (const e of entries) {
102
+ if (!isRecord(e) || typeof e.installPath !== 'string' || !fs.exists(e.installPath))
103
+ continue;
104
+ const forHere = e.scope === 'user' || (typeof e.projectPath === 'string' && sameDir(e.projectPath, projectRoot));
105
+ if (forHere)
106
+ return { installed: true, scope: String(e.scope), installPath: e.installPath };
107
+ }
108
+ return { installed: false };
109
+ }
110
+ /**
111
+ * The exact commands that refresh the marketplace and install the plugins,
112
+ * for a person to run. `known` is true only when Claude Code already knows
113
+ * the marketplace by the wanted source (then an update suffices). A
114
+ * directory source loads live from the working tree: nothing to install.
115
+ */
116
+ export function repairCommands(projectRoot, scope, known, plugins = MOD_PLUGINS, wanted = MARKETPLACE_SOURCE) {
117
+ const dir = wanted.source.source === 'directory' ? wanted.source.path : null;
118
+ return [
119
+ `cd ${JSON.stringify(resolve(projectRoot))}`,
120
+ known
121
+ ? `claude plugin marketplace update ${MARKETPLACE_NAME}`
122
+ : `claude plugin marketplace add ${dir ? JSON.stringify(dir) : 'ruvnet/ruflo'} --scope ${scope}`,
123
+ ...(dir ? [] : plugins.filter((p) => p.required).map((p) => `claude plugin install ${p.id} --scope ${scope}`)),
124
+ ];
125
+ }
126
+ /**
127
+ * The marketplace finding plus one finding per plugin enabled in settings.
128
+ * A required plugin missing from the clone with no cached install is the
129
+ * failure Claude Code hides; a plugin not yet released is "pending".
130
+ */
131
+ export function resolveFindings(projectRoot, scope, configDir, fs = nodeReadFs, enabled = MOD_PLUGINS.map((p) => p.id), declared) {
132
+ const market = marketplaceState(configDir, fs);
133
+ const wanted = (isRecord(declared) && isRecord(declared.source) ? declared : MARKETPLACE_SOURCE);
134
+ const matches = market.known && sameSource(market.source, wanted.source);
135
+ const fix = repairCommands(projectRoot, scope, matches, MOD_PLUGINS.filter((p) => enabled.includes(p.id)), wanted).join(' && ');
136
+ const findings = [];
137
+ const kind = market.source?.source === 'directory' ? 'directory (loads live from the working tree)' : `cloned at ${market.location}`;
138
+ findings.push(market.location && market.known && !sameSource(market.source, wanted.source)
139
+ ? {
140
+ name: 'ruflo marketplace',
141
+ status: 'warn',
142
+ message: `this project declares ${describeSource(wanted.source)}, but Claude Code knows ruflo as ${describeSource(market.source)} (one ruflo marketplace per config dir)`,
143
+ fix,
144
+ }
145
+ : market.location
146
+ ? { name: 'ruflo marketplace', status: 'pass', message: `${describeSource(market.source ?? wanted.source)}: ${kind}` }
147
+ : {
148
+ name: 'ruflo marketplace',
149
+ status: 'warn',
150
+ message: `not cloned under ${join(configDir, 'plugins')}: Claude Code clones it at the next interactive start of a trusted session (headless -p runs do not)`,
151
+ fix,
152
+ });
153
+ for (const plugin of MOD_PLUGINS.filter((p) => enabled.includes(p.id))) {
154
+ const name = `plugin ${plugin.id}`;
155
+ const installed = installedState(projectRoot, configDir, plugin.id, fs);
156
+ const also = installed.installed ? `; also installed (${installed.scope} scope)` : '';
157
+ if (cloneHas(market, plugin.id, fs)) {
158
+ findings.push({ name, status: 'pass', message: `loads from the marketplace clone${also}` });
159
+ }
160
+ else if (!market.location) {
161
+ findings.push(installed.installed
162
+ ? { name, status: 'pass', message: `installed (${installed.scope} scope, ${installed.installPath})` }
163
+ : { name, status: 'warn', message: plugin.required ? 'loads once Claude Code has cloned the marketplace' : 'pending: not released in the ruflo marketplace yet' });
164
+ }
165
+ else if (!plugin.required) {
166
+ findings.push({ name, status: 'warn', message: `pending: not in the ruflo marketplace yet (${market.location})${also}` });
167
+ }
168
+ else if (installed.installed) {
169
+ findings.push({ name, status: 'warn', message: `the clone at ${market.location} is stale (no ${nameOf(plugin.id)}); the cached install still loads`, fix });
170
+ }
171
+ else {
172
+ findings.push({
173
+ name,
174
+ status: 'fail',
175
+ message: `the clone at ${market.location} is stale: it predates ${nameOf(plugin.id)}, so Claude Code skips the enabled plugin without a word${plugin.id.startsWith('ruflo-mods@') ? ' (/ruflo-mods is an unknown command)' : ''}`,
176
+ fix,
177
+ });
178
+ }
179
+ }
180
+ return findings;
181
+ }
182
+ //# sourceMappingURL=plugin-resolve.js.map
@@ -5,6 +5,7 @@
5
5
  * evidence of a load is the heartbeat the mod writes at session start.
6
6
  */
7
7
  import { type ClaudeInstall } from './claude-installs.js';
8
+ import { type ReadFs } from './plugin-resolve.js';
8
9
  export declare const HANDSHAKE_MARKER = "RUFLO_MODS_OWNS";
9
10
  export declare const HEARTBEAT_RELATIVE: string;
10
11
  export type Status = 'pass' | 'warn' | 'fail';
@@ -23,6 +24,10 @@ export interface ProbeInputs {
23
24
  managedPath?: string;
24
25
  /** Claude Code binaries on PATH; discovered (each `--version` run) when absent. */
25
26
  installs?: ClaudeInstall[];
27
+ /** Claude Code's config directory; CLAUDE_CONFIG_DIR, else ~/.claude, when absent. */
28
+ configDir?: string;
29
+ /** Reads for the plugin-resolution findings; the real filesystem when absent. */
30
+ fs?: ReadFs;
26
31
  }
27
32
  export declare function probeMods(inputs: ProbeInputs): Finding[];
28
33
  //# sourceMappingURL=probe.d.ts.map
@@ -8,7 +8,8 @@ import { existsSync, readFileSync } from 'node:fs';
8
8
  import { homedir, platform } from 'node:os';
9
9
  import { join, resolve } from 'node:path';
10
10
  import { findClaudeInstalls, judgeInstalls } from './claude-installs.js';
11
- import { ENABLE_ENV, MOD_PLUGIN_ID, readRecord, readSettingsFile, settingsFileFor } from './install.js';
11
+ import { ENABLE_ENV, MOD_PLUGIN_ID, MOD_PLUGIN_IDS, readRecord, readSettingsFile, settingsFileFor } from './install.js';
12
+ import { claudeConfigDir, resolveFindings } from './plugin-resolve.js';
12
13
  import { PROJECTION_RELATIVE } from './policy-projection.js';
13
14
  export const HANDSHAKE_MARKER = 'RUFLO_MODS_OWNS';
14
15
  export const HEARTBEAT_RELATIVE = join('.claude-flow', 'mods', 'session.json');
@@ -36,9 +37,10 @@ export function probeMods(inputs) {
36
37
  const root = resolve(inputs.projectRoot);
37
38
  const home = inputs.home ?? homedir();
38
39
  const env = inputs.env ?? process.env;
40
+ const configDir = inputs.configDir ?? claudeConfigDir(env, home);
39
41
  const findings = [];
40
42
  // 1. Enabled for this project?
41
- const files = [settingsFileFor(root, 'local'), settingsFileFor(root, 'project'), join(home, '.claude', 'settings.json')];
43
+ const files = [settingsFileFor(root, 'local'), settingsFileFor(root, 'project'), join(configDir, 'settings.json')];
42
44
  const enabledIn = files.find((f) => {
43
45
  try {
44
46
  return get(readSettingsFile(f), 'enabledPlugins', MOD_PLUGIN_ID) === true;
@@ -48,8 +50,31 @@ export function probeMods(inputs) {
48
50
  }
49
51
  });
50
52
  findings.push(enabledIn
51
- ? { name: 'ruflo-mods plugin', status: 'pass', message: `enabled in ${enabledIn}` }
53
+ ? { name: 'ruflo-mods plugin', status: 'pass', message: `enabled in settings: ${enabledIn} (whether Claude Code can load it: see below)` }
52
54
  : { name: 'ruflo-mods plugin', status: 'warn', message: 'not enabled; classic hooks handle every event', fix: 'ruflo mods install' });
55
+ // 1a. Enabled is a request; Claude Code silently skips a plugin its
56
+ // marketplace clone does not carry (a clone older than the plugin).
57
+ if (enabledIn) {
58
+ const scope = enabledIn === files[0] ? 'local' : enabledIn === files[1] ? 'project' : 'user';
59
+ const enabled = MOD_PLUGIN_IDS.filter((id) => files.some((f) => {
60
+ try {
61
+ return get(readSettingsFile(f), 'enabledPlugins', id) === true;
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ }));
67
+ // The marketplace the first settings file declaring one names (local wins, as in Claude Code).
68
+ const declared = files.map((f) => {
69
+ try {
70
+ return get(readSettingsFile(f), 'extraKnownMarketplaces', 'ruflo');
71
+ }
72
+ catch {
73
+ return undefined;
74
+ }
75
+ }).find((d) => d !== undefined);
76
+ findings.push(...resolveFindings(root, scope, configDir, inputs.fs, enabled, declared));
77
+ }
53
78
  // 2. Function hooks switched on for installed plugins (early access).
54
79
  const envOn = env[ENABLE_ENV] === '1';
55
80
  const settingsOn = files.some((f) => {
@@ -1,4 +1,9 @@
1
1
  import { AgenticPolicyEngine, type BudgetLimit, type CapabilityEnvelope, type PolicyApproval, type PolicyDecision, type PolicyRequest, type PolicyRule, type PolicyState } from '@claude-flow/security';
2
+ /**
3
+ * Exported for ADR-406 mission storage, which takes the same per-file lock
4
+ * (pid, pid namespace and boot id identify a dead owner) rather than a copy.
5
+ */
6
+ export declare function acquireLock(lockPath: string): Promise<() => void>;
2
7
  export declare function loadPolicyState(projectRoot?: string): PolicyState;
3
8
  export declare function autoMigratePolicyStateIfNeeded(projectRoot?: string): Promise<{
4
9
  migrated: boolean;
@@ -120,7 +120,11 @@ function lockOwnerIsDead(lockPath) {
120
120
  return false;
121
121
  }
122
122
  }
123
- async function acquireLock(lockPath) {
123
+ /**
124
+ * Exported for ADR-406 mission storage, which takes the same per-file lock
125
+ * (pid, pid namespace and boot id identify a dead owner) rather than a copy.
126
+ */
127
+ export async function acquireLock(lockPath) {
124
128
  const started = Date.now();
125
129
  while (Date.now() - started < LOCK_WAIT_MS) {
126
130
  try {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.50.0",
3
+ "version": "3.51.0",
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",