@claude-flow/cli 3.42.4 → 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.
- package/.claude/helpers/helpers.manifest.json +2 -2
- package/.claude/helpers/router.js +1 -1
- package/catalog-manifest.json +2 -2
- package/dist/src/commands/doctor.js +22 -1
- package/dist/src/commands/hooks.js +9 -3
- package/dist/src/init/helpers-generator.js +11 -10
- package/dist/src/mcp-tools/capability-brain.js +4 -2
- package/dist/src/mcp-tools/hooks-tools.d.ts +5 -0
- package/dist/src/mcp-tools/hooks-tools.js +44 -11
- package/dist/src/mcp-tools/memory-tools.js +42 -0
- package/dist/src/memory/graph-edge-writer.d.ts +10 -0
- package/dist/src/memory/graph-edge-writer.js +77 -1
- package/dist/src/memory/memory-bridge.d.ts +6 -0
- package/dist/src/memory/memory-bridge.js +123 -41
- package/dist/src/memory/memory-initializer.d.ts +3 -0
- package/dist/src/memory/memory-initializer.js +53 -11
- package/dist/src/ruvector/typesafe-router.d.ts +119 -0
- package/dist/src/ruvector/typesafe-router.js +245 -0
- package/dist/src/services/policy-runtime.js +40 -11
- package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
- package/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
- package/package.json +5 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* typesafe-router.ts — opt-in `@ruvector/typesafe` augmentation for `hooks_route`.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors ADR-150's MetaHarness rules for optional integrations:
|
|
5
|
+
* 1. Removable — the package is loaded with a dynamic import only; any load,
|
|
6
|
+
* construction or decide error falls back to the existing router.
|
|
7
|
+
* 2. Opt-in — does nothing unless `CLAUDE_FLOW_ROUTER_TYPESAFE=1`. With the
|
|
8
|
+
* flag unset the package is never imported and the legacy result is
|
|
9
|
+
* returned unchanged (same object, no added fields).
|
|
10
|
+
* 3. Optional — declared as an optional peer of `@claude-flow/cli`.
|
|
11
|
+
* 4. Honest — the result carries `routedBy`, typesafe's confidence, abstain
|
|
12
|
+
* mass and `calibrated` flag verbatim. The default `hash` embedder is
|
|
13
|
+
* uncalibrated, so its confidence is reported as `confidenceCalibrated:
|
|
14
|
+
* false` and is never copied into `estimatedMetrics.successProbability`.
|
|
15
|
+
*
|
|
16
|
+
* Gate: typesafe's answer is used only when all hold —
|
|
17
|
+
* - `abstain <= maxAbstain` (default 0.30)
|
|
18
|
+
* - lift = top-1 probability × option count >= `minLift` (default 1.2, i.e.
|
|
19
|
+
* 20% above chance). Lift, not raw confidence, because confidence scales
|
|
20
|
+
* with the option count (~0.1 for ten agents) and differs per embedder.
|
|
21
|
+
* - top-1 beats the runner-up by >= `minMargin` (default 0.005); a uniform
|
|
22
|
+
* distribution — text that matches nothing — has margin 0.
|
|
23
|
+
* Otherwise the legacy route is kept and `typesafe.reason` says which gate failed.
|
|
24
|
+
*
|
|
25
|
+
* @module typesafe-router
|
|
26
|
+
*/
|
|
27
|
+
const MODULE_ID = '@ruvector/typesafe';
|
|
28
|
+
/**
|
|
29
|
+
* Default loader. The variable specifier keeps tsc/bundlers off the optional peer;
|
|
30
|
+
* `require` (the package is CJS) covers hosts that rewrite dynamic import (vite-node).
|
|
31
|
+
* An absent package still surfaces as MODULE_NOT_FOUND → "not installed".
|
|
32
|
+
*/
|
|
33
|
+
async function loadTypesafeModule() {
|
|
34
|
+
try {
|
|
35
|
+
return await import(/* @vite-ignore */ MODULE_ID);
|
|
36
|
+
}
|
|
37
|
+
catch (importErr) {
|
|
38
|
+
try {
|
|
39
|
+
const { createRequire } = await import('node:module');
|
|
40
|
+
return createRequire(import.meta.url)(MODULE_ID);
|
|
41
|
+
}
|
|
42
|
+
catch (requireErr) {
|
|
43
|
+
throw requireErr?.code === 'MODULE_NOT_FOUND' ? requireErr : importErr;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Agent descriptions + `not_for` hints that separate neighbouring roles. */
|
|
48
|
+
const AGENT_PROFILES = {
|
|
49
|
+
tester: { what: 'write and run unit tests, integration tests, e2e tests, test coverage and specs', not_for: 'reviewing code, researching issues or reading the latest news' },
|
|
50
|
+
reviewer: { what: 'review code quality, pull requests, diffs and best practices', not_for: 'writing tests, implementing features or researching background information' },
|
|
51
|
+
researcher: { what: 'research, investigate, explore, read and summarize issues, docs, discussions and prior art', not_for: 'writing code, writing tests or reviewing a diff' },
|
|
52
|
+
coder: { what: 'implement features, write code, fix bugs and build functionality', not_for: 'research, review or test-only work' },
|
|
53
|
+
architect: { what: 'design system architecture, module boundaries, APIs, schemas and refactoring plans', not_for: 'running tests or small bug fixes' },
|
|
54
|
+
'security-architect': { what: 'security, authentication, authorization, encryption, vulnerabilities, CVEs and audits', not_for: 'general feature work or performance tuning' },
|
|
55
|
+
'performance-engineer': { what: 'performance optimization, profiling, benchmarks, latency and bottlenecks', not_for: 'security review or writing documentation' },
|
|
56
|
+
devops: { what: 'deployment, CI/CD pipelines, docker, kubernetes and infrastructure', not_for: 'application feature code or unit tests' },
|
|
57
|
+
'memory-specialist': { what: 'memory systems, caches, vector stores, embeddings and persistence', not_for: 'UI work or deployment pipelines' },
|
|
58
|
+
'swarm-specialist': { what: 'multi-agent swarms, coordinators, hive-mind, mesh topology and agent orchestration', not_for: 'single-file code edits' },
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Build choice options from the router's pattern table: every primary agent of
|
|
62
|
+
* a pattern, plus the profiled roles (researcher/reviewer) the table only lists
|
|
63
|
+
* as alternates. Each pattern's keywords are appended to its primary agent's
|
|
64
|
+
* `what`, so the options track TASK_PATTERNS rather than a parallel list.
|
|
65
|
+
*/
|
|
66
|
+
export function buildAgentCriteria(patterns) {
|
|
67
|
+
const keywordsByAgent = new Map();
|
|
68
|
+
for (const { agents, keywords } of Object.values(patterns)) {
|
|
69
|
+
const primary = agents[0];
|
|
70
|
+
if (!primary)
|
|
71
|
+
continue;
|
|
72
|
+
const set = keywordsByAgent.get(primary) ?? new Set();
|
|
73
|
+
keywords.forEach(k => set.add(k));
|
|
74
|
+
keywordsByAgent.set(primary, set);
|
|
75
|
+
}
|
|
76
|
+
for (const agent of ['researcher', 'reviewer', 'tester', 'coder']) {
|
|
77
|
+
if (!keywordsByAgent.has(agent))
|
|
78
|
+
keywordsByAgent.set(agent, new Set());
|
|
79
|
+
}
|
|
80
|
+
const criteria = {};
|
|
81
|
+
for (const [agent, kws] of keywordsByAgent) {
|
|
82
|
+
const profile = AGENT_PROFILES[agent] ?? { what: `${agent.replace(/-/g, ' ')} tasks` };
|
|
83
|
+
const kw = [...kws].join(', ');
|
|
84
|
+
criteria[agent] = {
|
|
85
|
+
what: kw ? `${profile.what}; keywords: ${kw}` : profile.what,
|
|
86
|
+
...(profile.not_for ? { not_for: profile.not_for } : {}),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return criteria;
|
|
90
|
+
}
|
|
91
|
+
function num(raw, dflt, max = 1) {
|
|
92
|
+
const n = raw === undefined || raw === '' ? NaN : Number(raw);
|
|
93
|
+
return Number.isFinite(n) && n >= 0 && n <= max ? n : dflt;
|
|
94
|
+
}
|
|
95
|
+
/** Read config from env. Invalid numeric values fall back to the defaults. */
|
|
96
|
+
export function readTypesafeConfig(env = process.env) {
|
|
97
|
+
const modelDir = env.CLAUDE_FLOW_ROUTER_TYPESAFE_MODEL_DIR;
|
|
98
|
+
const manifest = env.CLAUDE_FLOW_ROUTER_TYPESAFE_MANIFEST;
|
|
99
|
+
return {
|
|
100
|
+
enabled: env.CLAUDE_FLOW_ROUTER_TYPESAFE === '1',
|
|
101
|
+
minLift: num(env.CLAUDE_FLOW_ROUTER_TYPESAFE_MIN_LIFT, 1.2, 255),
|
|
102
|
+
maxAbstain: num(env.CLAUDE_FLOW_ROUTER_TYPESAFE_MAX_ABSTAIN, 0.3),
|
|
103
|
+
minMargin: num(env.CLAUDE_FLOW_ROUTER_TYPESAFE_MIN_MARGIN, 0.005),
|
|
104
|
+
embedder: modelDir && manifest ? { kind: 'onnx', modelDir, manifest } : 'hash',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Stateful router: loads the module and builds one engine on first use, caches
|
|
109
|
+
* a load failure so a missing package costs one import attempt per process.
|
|
110
|
+
*/
|
|
111
|
+
export class TypesafeRouter {
|
|
112
|
+
engine = null;
|
|
113
|
+
mod = null;
|
|
114
|
+
loadError = null;
|
|
115
|
+
env;
|
|
116
|
+
loadModule;
|
|
117
|
+
debug;
|
|
118
|
+
constructor(deps = {}) {
|
|
119
|
+
this.env = deps.env ?? process.env;
|
|
120
|
+
this.loadModule = deps.loadModule ?? loadTypesafeModule;
|
|
121
|
+
this.debug = deps.debug ?? ((m) => { if (this.env.CLAUDE_FLOW_LOG_LEVEL === 'debug')
|
|
122
|
+
console.error(`[typesafe-router] ${m}`); });
|
|
123
|
+
}
|
|
124
|
+
isEnabled() { return readTypesafeConfig(this.env).enabled; }
|
|
125
|
+
async ensureEngine(cfg) {
|
|
126
|
+
if (this.engine || this.loadError)
|
|
127
|
+
return this.engine;
|
|
128
|
+
try {
|
|
129
|
+
const raw = (await this.loadModule());
|
|
130
|
+
const mod = (typeof raw.createTypesafe === 'function' ? raw : raw.default);
|
|
131
|
+
if (!mod || typeof mod.createTypesafe !== 'function')
|
|
132
|
+
throw new Error('module has no createTypesafe export');
|
|
133
|
+
this.mod = mod;
|
|
134
|
+
this.engine = mod.createTypesafe({ embedder: cfg.embedder });
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
const e = err;
|
|
138
|
+
this.loadError = e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND'
|
|
139
|
+
? `${MODULE_ID} not installed`
|
|
140
|
+
: `${MODULE_ID} failed to load: ${e?.message ?? String(err)}`;
|
|
141
|
+
this.debug(this.loadError);
|
|
142
|
+
}
|
|
143
|
+
return this.engine;
|
|
144
|
+
}
|
|
145
|
+
/** Ask typesafe for an agent. Never throws; `used: false` means keep the legacy route. */
|
|
146
|
+
async route(task, patterns) {
|
|
147
|
+
const cfg = readTypesafeConfig(this.env);
|
|
148
|
+
const thresholds = { minLift: cfg.minLift, maxAbstain: cfg.maxAbstain, minMargin: cfg.minMargin };
|
|
149
|
+
const embedder = cfg.embedder === 'hash' ? 'hash' : 'onnx';
|
|
150
|
+
if (!cfg.enabled)
|
|
151
|
+
return { used: false, reason: 'CLAUDE_FLOW_ROUTER_TYPESAFE is not 1', thresholds };
|
|
152
|
+
const engine = await this.ensureEngine(cfg);
|
|
153
|
+
if (!engine)
|
|
154
|
+
return { used: false, reason: this.loadError ?? 'typesafe unavailable', thresholds, embedder };
|
|
155
|
+
let answer;
|
|
156
|
+
try {
|
|
157
|
+
const criteria = buildAgentCriteria(patterns);
|
|
158
|
+
const question = this.mod?.choice ? this.mod.choice(criteria) : { type: 'choice', criteria };
|
|
159
|
+
const res = await engine.decide(task, { agent: question });
|
|
160
|
+
answer = res.agent;
|
|
161
|
+
if (!answer || typeof answer.choice !== 'string')
|
|
162
|
+
throw new Error('no choice in answer');
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
const reason = `typesafe decide failed: ${err?.message ?? String(err)}`;
|
|
166
|
+
this.debug(reason);
|
|
167
|
+
return { used: false, reason, thresholds, embedder, backend: engine.backend };
|
|
168
|
+
}
|
|
169
|
+
const probs = Object.values(answer.probabilities ?? {}).sort((a, b) => b - a);
|
|
170
|
+
const margin = (probs[0] ?? 0) - (probs[1] ?? 0);
|
|
171
|
+
const lift = (probs[0] ?? 0) * probs.length;
|
|
172
|
+
const base = { answer, lift, thresholds, embedder, backend: engine.backend };
|
|
173
|
+
const f = (n) => n.toFixed(2);
|
|
174
|
+
if (answer.abstain > cfg.maxAbstain) {
|
|
175
|
+
return { ...base, used: false, reason: `typesafe abstain ${f(answer.abstain)} > max ${f(cfg.maxAbstain)}; kept existing router` };
|
|
176
|
+
}
|
|
177
|
+
if (lift < cfg.minLift) {
|
|
178
|
+
return { ...base, used: false, reason: `typesafe lift ${f(lift)} (top-1 × ${probs.length} options) < min ${f(cfg.minLift)}; kept existing router` };
|
|
179
|
+
}
|
|
180
|
+
if (margin < cfg.minMargin) {
|
|
181
|
+
return { ...base, used: false, reason: `typesafe top-1 margin ${margin.toFixed(3)} < min ${cfg.minMargin.toFixed(3)} (no clear winner); kept existing router` };
|
|
182
|
+
}
|
|
183
|
+
return { ...base, used: true, reason: `typesafe choice "${answer.choice}" (confidence ${f(answer.confidence)}, lift ${f(lift)}, abstain ${f(answer.abstain)}, ${answer.calibrated ? 'calibrated' : 'UNCALIBRATED'} ${embedder} embedder)` };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const round2 = (n) => Math.round(n * 100) / 100;
|
|
187
|
+
/**
|
|
188
|
+
* Merge a typesafe outcome into a legacy `hooks_route` result. Disabled or
|
|
189
|
+
* error results (`success: false`) pass through untouched.
|
|
190
|
+
*/
|
|
191
|
+
export async function applyTypesafeRouting(params, legacy, patterns, router) {
|
|
192
|
+
if (!router.isEnabled() || !legacy || legacy.success === false || typeof params.task !== 'string')
|
|
193
|
+
return legacy;
|
|
194
|
+
const text = typeof params.context === 'string' && params.context ? `${params.task} ${params.context}` : params.task;
|
|
195
|
+
const outcome = await router.route(text, patterns);
|
|
196
|
+
const legacyRouting = (legacy.routing ?? {});
|
|
197
|
+
const legacyPrimary = (legacy.primaryAgent ?? {});
|
|
198
|
+
const a = outcome.answer;
|
|
199
|
+
const typesafe = {
|
|
200
|
+
used: outcome.used,
|
|
201
|
+
reason: outcome.reason,
|
|
202
|
+
...(a ? {
|
|
203
|
+
choice: a.choice,
|
|
204
|
+
confidence: round2(a.confidence),
|
|
205
|
+
abstain: round2(a.abstain),
|
|
206
|
+
lift: outcome.lift === undefined ? undefined : round2(outcome.lift),
|
|
207
|
+
calibrated: a.calibrated,
|
|
208
|
+
head: a.head,
|
|
209
|
+
model: a.model,
|
|
210
|
+
probabilities: Object.fromEntries(Object.entries(a.probabilities).map(([k, v]) => [k, round2(v)])),
|
|
211
|
+
} : {}),
|
|
212
|
+
backend: outcome.backend,
|
|
213
|
+
embedder: outcome.embedder,
|
|
214
|
+
thresholds: outcome.thresholds,
|
|
215
|
+
};
|
|
216
|
+
if (!outcome.used || !a) {
|
|
217
|
+
return { ...legacy, routedBy: String(legacyRouting.method ?? 'legacy'), typesafe };
|
|
218
|
+
}
|
|
219
|
+
const alternatives = Object.entries(a.probabilities)
|
|
220
|
+
.filter(([k]) => k !== a.choice)
|
|
221
|
+
.sort((x, y) => y[1] - x[1])
|
|
222
|
+
.slice(0, 2)
|
|
223
|
+
.map(([type, p]) => ({ type, confidence: round2(p), reason: 'typesafe runner-up (probability share)' }));
|
|
224
|
+
return {
|
|
225
|
+
...legacy,
|
|
226
|
+
routing: { ...legacyRouting, method: 'typesafe', backend: `@ruvector/typesafe (${outcome.backend ?? 'unknown'}, ${outcome.embedder} embedder)` },
|
|
227
|
+
routedBy: 'typesafe',
|
|
228
|
+
matchedPattern: `typesafe:${a.choice}`,
|
|
229
|
+
primaryAgent: {
|
|
230
|
+
type: a.choice,
|
|
231
|
+
confidence: round2(a.confidence),
|
|
232
|
+
confidenceCalibrated: a.calibrated,
|
|
233
|
+
reason: outcome.reason,
|
|
234
|
+
},
|
|
235
|
+
alternativeAgents: alternatives,
|
|
236
|
+
fallbackRoute: { agent: legacyPrimary.type, confidence: legacyPrimary.confidence, method: legacyRouting.method },
|
|
237
|
+
typesafe,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
let sharedRouter = null;
|
|
241
|
+
/** Process-wide router used by hooks_route. */
|
|
242
|
+
export function getTypesafeRouter() {
|
|
243
|
+
return (sharedRouter ??= new TypesafeRouter());
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=typesafe-router.js.map
|
|
@@ -42,11 +42,40 @@ async function acquireLock(lockPath) {
|
|
|
42
42
|
}
|
|
43
43
|
throw new Error('policy-state-lock-timeout');
|
|
44
44
|
}
|
|
45
|
-
|
|
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
|
-
|
|
49
|
-
|
|
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 {
|
|
File without changes
|
|
File without changes
|
|
@@ -159,14 +159,14 @@ export declare const SpawnAgentSchema: z.ZodObject<{
|
|
|
159
159
|
timeout: z.ZodOptional<z.ZodNumber>;
|
|
160
160
|
}, "strip", z.ZodTypeAny, {
|
|
161
161
|
type: "coder" | "reviewer" | "tester" | "planner" | "researcher" | "security-architect" | "security-auditor" | "memory-specialist" | "swarm-specialist" | "integration-architect" | "performance-engineer" | "core-architect" | "test-architect" | "queen-coordinator" | "project-coordinator";
|
|
162
|
+
id?: string | undefined;
|
|
162
163
|
config?: Record<string, unknown> | undefined;
|
|
163
164
|
timeout?: number | undefined;
|
|
164
|
-
id?: string | undefined;
|
|
165
165
|
}, {
|
|
166
166
|
type: "coder" | "reviewer" | "tester" | "planner" | "researcher" | "security-architect" | "security-auditor" | "memory-specialist" | "swarm-specialist" | "integration-architect" | "performance-engineer" | "core-architect" | "test-architect" | "queen-coordinator" | "project-coordinator";
|
|
167
|
+
id?: string | undefined;
|
|
167
168
|
config?: Record<string, unknown> | undefined;
|
|
168
169
|
timeout?: number | undefined;
|
|
169
|
-
id?: string | undefined;
|
|
170
170
|
}>;
|
|
171
171
|
/**
|
|
172
172
|
* Task input schema
|
|
@@ -181,13 +181,13 @@ export declare const TaskInputSchema: z.ZodObject<{
|
|
|
181
181
|
taskId: string;
|
|
182
182
|
content: string;
|
|
183
183
|
agentType: "coder" | "reviewer" | "tester" | "planner" | "researcher" | "security-architect" | "security-auditor" | "memory-specialist" | "swarm-specialist" | "integration-architect" | "performance-engineer" | "core-architect" | "test-architect" | "queen-coordinator" | "project-coordinator";
|
|
184
|
-
priority?: "
|
|
184
|
+
priority?: "low" | "medium" | "high" | "critical" | undefined;
|
|
185
185
|
metadata?: Record<string, unknown> | undefined;
|
|
186
186
|
}, {
|
|
187
187
|
taskId: string;
|
|
188
188
|
content: string;
|
|
189
189
|
agentType: "coder" | "reviewer" | "tester" | "planner" | "researcher" | "security-architect" | "security-auditor" | "memory-specialist" | "swarm-specialist" | "integration-architect" | "performance-engineer" | "core-architect" | "test-architect" | "queen-coordinator" | "project-coordinator";
|
|
190
|
-
priority?: "
|
|
190
|
+
priority?: "low" | "medium" | "high" | "critical" | undefined;
|
|
191
191
|
metadata?: Record<string, unknown> | undefined;
|
|
192
192
|
}>;
|
|
193
193
|
/**
|
|
@@ -234,16 +234,16 @@ export declare const ExecutorConfigSchema: z.ZodObject<{
|
|
|
234
234
|
cwd: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
235
235
|
allowSudo: z.ZodDefault<z.ZodBoolean>;
|
|
236
236
|
}, "strip", z.ZodTypeAny, {
|
|
237
|
-
allowedCommands: string[];
|
|
238
237
|
timeout: number;
|
|
238
|
+
allowedCommands: string[];
|
|
239
239
|
maxBuffer: number;
|
|
240
240
|
allowSudo: boolean;
|
|
241
241
|
blockedPatterns?: string[] | undefined;
|
|
242
242
|
cwd?: string | undefined;
|
|
243
243
|
}, {
|
|
244
244
|
allowedCommands: string[];
|
|
245
|
-
blockedPatterns?: string[] | undefined;
|
|
246
245
|
timeout?: number | undefined;
|
|
246
|
+
blockedPatterns?: string[] | undefined;
|
|
247
247
|
maxBuffer?: number | undefined;
|
|
248
248
|
cwd?: string | undefined;
|
|
249
249
|
allowSudo?: boolean | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.
|
|
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
|
}
|