@claude-flow/cli 3.42.5 → 3.43.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.
@@ -42,11 +42,40 @@ async function acquireLock(lockPath) {
42
42
  }
43
43
  throw new Error('policy-state-lock-timeout');
44
44
  }
45
- function writeJsonAtomic(file, value) {
45
+ // #3398: Windows rename over a file another process holds open fails with
46
+ // EPERM/EBUSY/EACCES. Retry (~1.3s total, inside LOCK_WAIT_MS), never leave the
47
+ // temp file; a final failure still throws — the state holds the receipt ledger
48
+ // and consumed approval uses, so dropping it would let an approval be reused.
49
+ const RENAME_RETRY_DELAYS_MS = [25, 50, 100, 150, 250, 300, 400];
50
+ const TRANSIENT_RENAME_CODES = new Set(['EPERM', 'EBUSY', 'EACCES']);
51
+ async function writeJsonAtomic(file, value) {
46
52
  mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
47
53
  const temporary = `${file}.${process.pid}.${randomUUID()}.tmp`;
48
- writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
49
- renameSync(temporary, file);
54
+ let renamed = false;
55
+ try {
56
+ writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
57
+ for (let attempt = 0;; attempt++) {
58
+ try {
59
+ renameSync(temporary, file);
60
+ renamed = true;
61
+ return;
62
+ }
63
+ catch (error) {
64
+ const code = error?.code ?? '';
65
+ if (!TRANSIENT_RENAME_CODES.has(code) || attempt >= RENAME_RETRY_DELAYS_MS.length)
66
+ throw error;
67
+ await sleep(RENAME_RETRY_DELAYS_MS[attempt]);
68
+ }
69
+ }
70
+ }
71
+ finally {
72
+ if (!renamed) {
73
+ try {
74
+ unlinkSync(temporary);
75
+ }
76
+ catch { /* never created or already gone */ }
77
+ }
78
+ }
50
79
  }
51
80
  function trustPaths(projectRoot) {
52
81
  const trustRoot = join(userInfo().homedir, '.config', 'ruflo', 'policy-trust');
@@ -87,7 +116,7 @@ function verifyStateAnchor(projectRoot, state) {
87
116
  throw new Error('policy-state-authentication-failed');
88
117
  }
89
118
  }
90
- function writePolicyState(projectRoot, statePath, state) {
119
+ async function writePolicyState(projectRoot, statePath, state) {
91
120
  const anchorPath = trustPaths(projectRoot).anchor;
92
121
  if (state.mode === 'enforce' || existsSync(anchorPath)) {
93
122
  const key = trustKey(projectRoot, true);
@@ -102,15 +131,15 @@ function writePolicyState(projectRoot, statePath, state) {
102
131
  // crash then leaves either a valid pair or an anchored mismatch that
103
132
  // fails closed; it can never leave enforce state silently unanchored.
104
133
  if (!existsSync(anchorPath)) {
105
- writeJsonAtomic(anchorPath, anchor);
106
- writeJsonAtomic(statePath, state);
134
+ await writeJsonAtomic(anchorPath, anchor);
135
+ await writeJsonAtomic(statePath, state);
107
136
  return;
108
137
  }
109
- writeJsonAtomic(statePath, state);
110
- writeJsonAtomic(anchorPath, anchor);
138
+ await writeJsonAtomic(statePath, state);
139
+ await writeJsonAtomic(anchorPath, anchor);
111
140
  return;
112
141
  }
113
- writeJsonAtomic(statePath, state);
142
+ await writeJsonAtomic(statePath, state);
114
143
  }
115
144
  function detectLegacyCapabilities(projectRoot) {
116
145
  const candidates = [
@@ -179,7 +208,7 @@ export async function autoMigratePolicyStateIfNeeded(projectRoot = process.cwd()
179
208
  state.mode = configured;
180
209
  state.configuredMode = configured;
181
210
  }
182
- writePolicyState(projectRoot, target.state, state);
211
+ await writePolicyState(projectRoot, target.state, state);
183
212
  }
184
213
  }
185
214
  finally {
@@ -202,7 +231,7 @@ export async function withPolicyTransaction(projectRoot, operation, options = {}
202
231
  const nextState = engine.exportState();
203
232
  if (!engine.verifyLedger().valid)
204
233
  throw new Error('policy-ledger-verification-failed');
205
- writePolicyState(projectRoot, target.state, nextState);
234
+ await writePolicyState(projectRoot, target.state, nextState);
206
235
  return result;
207
236
  }
208
237
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.42.5",
3
+ "version": "3.43.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",
@@ -143,12 +143,16 @@
143
143
  },
144
144
  "peerDependencies": {
145
145
  "@metaharness/router": "^0.4.0",
146
+ "@ruvector/typesafe": "^0.1.0",
146
147
  "metaharness": "^0.4.1"
147
148
  },
148
149
  "peerDependenciesMeta": {
149
150
  "@metaharness/router": {
150
151
  "optional": true
151
152
  },
153
+ "@ruvector/typesafe": {
154
+ "optional": true
155
+ },
152
156
  "metaharness": {
153
157
  "optional": true
154
158
  }