claude-flow 3.14.4 → 3.15.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/settings.local.json +2 -1
- package/package.json +1 -1
- package/v3/@claude-flow/cli/dist/src/commands/metaharness.js +20 -5
- package/v3/@claude-flow/cli/dist/src/mcp-client.js +5 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agenticow-tools.d.ts +36 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agenticow-tools.js +253 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/index.d.ts +1 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/index.js +2 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/metaharness-tools.d.ts +6 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/metaharness-tools.js +83 -4
- package/v3/@claude-flow/cli/package.json +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.0",
|
|
4
4
|
"description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -56,6 +56,9 @@ const SUBCOMMANDS = {
|
|
|
56
56
|
// iter 53 — one-command drift detection (compose audit-list + oia-audit + audit-trend)
|
|
57
57
|
'drift-from-history': 'drift-from-history.mjs',
|
|
58
58
|
mint: 'mint.mjs',
|
|
59
|
+
// @metaharness/redblue@~0.1.1 — adversarial red/blue LLM testing
|
|
60
|
+
// (init|run|patch|attack|report sub-subcommands handled by redblue.mjs)
|
|
61
|
+
redblue: 'redblue.mjs',
|
|
59
62
|
};
|
|
60
63
|
/**
|
|
61
64
|
* Walk up from the current dirname to find the ruflo repo root that
|
|
@@ -63,8 +66,16 @@ const SUBCOMMANDS = {
|
|
|
63
66
|
* 1. ruflo dev tree (cwd / ../plugins/...)
|
|
64
67
|
* 2. ruflo wrapper (ruflo/node_modules/@claude-flow/cli/...)
|
|
65
68
|
* 3. npx (npm-cache/__npx/... — fall back to cwd-scan)
|
|
69
|
+
*
|
|
70
|
+
* `requiredScript`, if provided, narrows the match: the returned dir must
|
|
71
|
+
* contain BOTH `_harness.mjs` (proves it's a plugin-scripts dir) AND the
|
|
72
|
+
* named script. This guards against the publish-artifact mirror at
|
|
73
|
+
* `v3/@claude-flow/cli/plugins/ruflo-metaharness/scripts/` getting picked
|
|
74
|
+
* over the source `plugins/ruflo-metaharness/scripts/` when the mirror
|
|
75
|
+
* lags the source (the mirror is regenerated only at publish time by
|
|
76
|
+
* `prepublishOnly`).
|
|
66
77
|
*/
|
|
67
|
-
function locatePluginScripts() {
|
|
78
|
+
function locatePluginScripts(requiredScript) {
|
|
68
79
|
const candidates = [];
|
|
69
80
|
// Up from the cli dist dir
|
|
70
81
|
let p = resolve(__dirname);
|
|
@@ -80,8 +91,11 @@ function locatePluginScripts() {
|
|
|
80
91
|
candidates.push(join(cwd, 'plugins', 'ruflo-metaharness', 'scripts'));
|
|
81
92
|
candidates.push(join(cwd, 'node_modules', '@claude-flow', 'cli', 'plugins', 'ruflo-metaharness', 'scripts'));
|
|
82
93
|
for (const c of candidates) {
|
|
83
|
-
if (existsSync(join(c, '_harness.mjs')))
|
|
84
|
-
|
|
94
|
+
if (!existsSync(join(c, '_harness.mjs')))
|
|
95
|
+
continue;
|
|
96
|
+
if (requiredScript && !existsSync(join(c, requiredScript)))
|
|
97
|
+
continue;
|
|
98
|
+
return c;
|
|
85
99
|
}
|
|
86
100
|
return null;
|
|
87
101
|
}
|
|
@@ -107,7 +121,7 @@ export const metaharnessCommand = {
|
|
|
107
121
|
// iter 73 — list reflects all 10 dispatchable subcommands (was
|
|
108
122
|
// stale at the iter-3 list of 5). Keep this synced with the
|
|
109
123
|
// SUBCOMMANDS map above.
|
|
110
|
-
description: 'One of: score | genome | mcp-scan | threat-model | oia-audit | audit-list | audit-trend | similarity | drift-from-history | mint',
|
|
124
|
+
description: 'One of: score | genome | mcp-scan | threat-model | oia-audit | audit-list | audit-trend | similarity | drift-from-history | mint | redblue',
|
|
111
125
|
type: 'string',
|
|
112
126
|
},
|
|
113
127
|
],
|
|
@@ -169,6 +183,7 @@ export const metaharnessCommand = {
|
|
|
169
183
|
output.writeln(' similarity ADR-152 — weighted similarity between two harness fingerprints');
|
|
170
184
|
output.writeln(' drift-from-history iter 53 — diff current state against most recent audit (1-command drift)');
|
|
171
185
|
output.writeln(' mint scaffold a custom harness (dry-run by default)');
|
|
186
|
+
output.writeln(' redblue adversarial red/blue LLM testing (init|run|patch|attack|report)');
|
|
172
187
|
output.writeln('');
|
|
173
188
|
output.writeln('Each subcommand accepts --format json|table and --help.');
|
|
174
189
|
output.writeln('');
|
|
@@ -180,7 +195,7 @@ export const metaharnessCommand = {
|
|
|
180
195
|
output.writeln(`Valid: ${Object.keys(SUBCOMMANDS).join(', ')}`);
|
|
181
196
|
return { success: false, exitCode: 2, data: { subcommand } };
|
|
182
197
|
}
|
|
183
|
-
const scriptDir = locatePluginScripts();
|
|
198
|
+
const scriptDir = locatePluginScripts(SUBCOMMANDS[subcommand]);
|
|
184
199
|
if (!scriptDir) {
|
|
185
200
|
output.writeln(output.warning('metaharness: plugins/ruflo-metaharness/scripts/ not found. Install ruflo with `npm i ruflo` or run from the ruflo repo.'));
|
|
186
201
|
output.writeln(output.dim('(ADR-150 graceful degradation: this command is a thin delegator over the plugin; the plugin must be present.)'));
|
|
@@ -47,6 +47,9 @@ import { guidanceTools } from './mcp-tools/guidance-tools.js';
|
|
|
47
47
|
import { autopilotTools } from './mcp-tools/autopilot-tools.js';
|
|
48
48
|
// ADR-150 — MetaHarness MCP tools (score / genome / mcp-scan / threat-model / oia-audit)
|
|
49
49
|
import { metaharnessTools } from './mcp-tools/metaharness-tools.js';
|
|
50
|
+
// agenticow@~0.2.3 — Copy-On-Write memory branching tools (162-byte branches);
|
|
51
|
+
// optional runtime dep, every handler returns `{degraded: true}` when missing.
|
|
52
|
+
import { agenticowTools } from './mcp-tools/agenticow-tools.js';
|
|
50
53
|
// #1916: coverage-aware routing tools — defined in ruvector/coverage-tools.ts
|
|
51
54
|
// but were never registered, so the `ruflo hooks coverage-*` CLI subcommands
|
|
52
55
|
// failed with `Tool not found: hooks_coverage-route`.
|
|
@@ -127,6 +130,8 @@ registerTools([
|
|
|
127
130
|
...coverageRouterTools,
|
|
128
131
|
// ADR-150 — MetaHarness static-analysis tools (5)
|
|
129
132
|
...metaharnessTools,
|
|
133
|
+
// agenticow@~0.2.3 — COW memory branching (4 tools, graceful-degraded when missing)
|
|
134
|
+
...agenticowTools,
|
|
130
135
|
]);
|
|
131
136
|
/**
|
|
132
137
|
* MCP Client Error
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agenticow MCP Tools — Copy-On-Write memory branching surface.
|
|
3
|
+
*
|
|
4
|
+
* Exposes `agenticow@~0.2.3` (a sibling RVF-based COW vector store by the same
|
|
5
|
+
* author as ruflo) as MCP tools so agents can branch, checkpoint, rollback,
|
|
6
|
+
* and promote memory state without copying GB-scale `.rvf` files.
|
|
7
|
+
*
|
|
8
|
+
* Motivation:
|
|
9
|
+
* The v3.14.4 release uncovered a tarball-bloat regression where Darwin
|
|
10
|
+
* loops' git-worktree-per-agent pattern accumulated 3.3 GB of disk. The
|
|
11
|
+
* structural cause was full-copy snapshot semantics. Measured agenticow
|
|
12
|
+
* branches are exactly 162 bytes regardless of base size (see
|
|
13
|
+
* `docs/agenticow/findings.md` for the bench data).
|
|
14
|
+
*
|
|
15
|
+
* Architectural constraint (mirrors metaharness-tools.ts / testgen-tools.ts):
|
|
16
|
+
* - `agenticow` lives in `optionalDependencies` — must NOT be a hard runtime dep
|
|
17
|
+
* - When the package is missing, every tool returns
|
|
18
|
+
* `{success: true, degraded: true, reason: 'agenticow-not-found'}`
|
|
19
|
+
* so callers see one contract regardless of install state
|
|
20
|
+
*
|
|
21
|
+
* Measured performance vs published claims (agenticow@0.2.3):
|
|
22
|
+
* ✅ 162-byte branches — confirmed exact
|
|
23
|
+
* ✅ 3,000×–180,000× smaller than full-copy at N=1k–50k
|
|
24
|
+
* ❌ 0.5 ms branch — measured ~10ms (fixed cost, not size-proportional)
|
|
25
|
+
* ❌ 83× faster — only beats full-copy past N ≈ 30k crossover
|
|
26
|
+
*
|
|
27
|
+
* Use cases (per ADR / findings doc):
|
|
28
|
+
* - Per-Darwin-iteration memory branching (eliminates worktree bloat)
|
|
29
|
+
* - Per-user / per-session personalization (cheap fork, no full copy)
|
|
30
|
+
* - Federation: branch → promote back as merge semantics
|
|
31
|
+
*
|
|
32
|
+
* @module @claude-flow/cli/mcp-tools/agenticow
|
|
33
|
+
*/
|
|
34
|
+
import type { MCPTool } from './types.js';
|
|
35
|
+
export declare const agenticowTools: MCPTool[];
|
|
36
|
+
//# sourceMappingURL=agenticow-tools.d.ts.map
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agenticow MCP Tools — Copy-On-Write memory branching surface.
|
|
3
|
+
*
|
|
4
|
+
* Exposes `agenticow@~0.2.3` (a sibling RVF-based COW vector store by the same
|
|
5
|
+
* author as ruflo) as MCP tools so agents can branch, checkpoint, rollback,
|
|
6
|
+
* and promote memory state without copying GB-scale `.rvf` files.
|
|
7
|
+
*
|
|
8
|
+
* Motivation:
|
|
9
|
+
* The v3.14.4 release uncovered a tarball-bloat regression where Darwin
|
|
10
|
+
* loops' git-worktree-per-agent pattern accumulated 3.3 GB of disk. The
|
|
11
|
+
* structural cause was full-copy snapshot semantics. Measured agenticow
|
|
12
|
+
* branches are exactly 162 bytes regardless of base size (see
|
|
13
|
+
* `docs/agenticow/findings.md` for the bench data).
|
|
14
|
+
*
|
|
15
|
+
* Architectural constraint (mirrors metaharness-tools.ts / testgen-tools.ts):
|
|
16
|
+
* - `agenticow` lives in `optionalDependencies` — must NOT be a hard runtime dep
|
|
17
|
+
* - When the package is missing, every tool returns
|
|
18
|
+
* `{success: true, degraded: true, reason: 'agenticow-not-found'}`
|
|
19
|
+
* so callers see one contract regardless of install state
|
|
20
|
+
*
|
|
21
|
+
* Measured performance vs published claims (agenticow@0.2.3):
|
|
22
|
+
* ✅ 162-byte branches — confirmed exact
|
|
23
|
+
* ✅ 3,000×–180,000× smaller than full-copy at N=1k–50k
|
|
24
|
+
* ❌ 0.5 ms branch — measured ~10ms (fixed cost, not size-proportional)
|
|
25
|
+
* ❌ 83× faster — only beats full-copy past N ≈ 30k crossover
|
|
26
|
+
*
|
|
27
|
+
* Use cases (per ADR / findings doc):
|
|
28
|
+
* - Per-Darwin-iteration memory branching (eliminates worktree bloat)
|
|
29
|
+
* - Per-user / per-session personalization (cheap fork, no full copy)
|
|
30
|
+
* - Federation: branch → promote back as merge semantics
|
|
31
|
+
*
|
|
32
|
+
* @module @claude-flow/cli/mcp-tools/agenticow
|
|
33
|
+
*/
|
|
34
|
+
import { existsSync } from 'node:fs';
|
|
35
|
+
import { getProjectCwd } from './types.js';
|
|
36
|
+
import { resolve, isAbsolute } from 'node:path';
|
|
37
|
+
const PACKAGE_NAME = 'agenticow';
|
|
38
|
+
// Cache: module load is expensive enough to amortize across handler calls.
|
|
39
|
+
// null = not yet attempted; false = attempted and unavailable; module = loaded.
|
|
40
|
+
let _agenticowMod = null;
|
|
41
|
+
let _loadAttempted = false;
|
|
42
|
+
async function loadAgenticow() {
|
|
43
|
+
if (_loadAttempted)
|
|
44
|
+
return _agenticowMod;
|
|
45
|
+
_loadAttempted = true;
|
|
46
|
+
try {
|
|
47
|
+
_agenticowMod = await import(PACKAGE_NAME);
|
|
48
|
+
return _agenticowMod;
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err && (err.code === 'ERR_MODULE_NOT_FOUND' || err.code === 'MODULE_NOT_FOUND' ||
|
|
52
|
+
/Cannot find (module|package)/i.test(String(err.message)))) {
|
|
53
|
+
_agenticowMod = false;
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function degradedResult(reason) {
|
|
60
|
+
return { success: true, degraded: true, reason };
|
|
61
|
+
}
|
|
62
|
+
function resolveMemoryPath(path) {
|
|
63
|
+
if (!path || typeof path !== 'string')
|
|
64
|
+
throw new Error('memory path is required');
|
|
65
|
+
// D-2 style: reject path traversal in user-supplied paths
|
|
66
|
+
if (/\.\.[\\/]|\0/.test(path))
|
|
67
|
+
throw new Error('memory path contains disallowed characters');
|
|
68
|
+
return isAbsolute(path) ? path : resolve(getProjectCwd(), path);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Lineage manifest companion path. agenticow persists the COW chain
|
|
72
|
+
* (working → checkpoints → base) into `<file>.agenticow.json` next to the
|
|
73
|
+
* `.rvf` data file. Without this, checkpoints and forks are in-memory only
|
|
74
|
+
* and disappear when the AgenticMemory handle closes. Mirrors the bin
|
|
75
|
+
* CLI's `manifestFor(file)` helper.
|
|
76
|
+
*/
|
|
77
|
+
function manifestFor(file) {
|
|
78
|
+
return `${file}.agenticow.json`;
|
|
79
|
+
}
|
|
80
|
+
function validateLabel(label) {
|
|
81
|
+
if (!label || typeof label !== 'string')
|
|
82
|
+
throw new Error('label is required');
|
|
83
|
+
if (label.length > 256)
|
|
84
|
+
throw new Error('label exceeds 256 chars');
|
|
85
|
+
if (!/^[A-Za-z0-9_.\-:/@]+$/.test(label)) {
|
|
86
|
+
throw new Error('label may only contain [A-Za-z0-9_.\\-:/@]');
|
|
87
|
+
}
|
|
88
|
+
return label;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Open (or create) a base memory file. When a lineage manifest exists at
|
|
92
|
+
* `<file>.agenticow.json`, we load that to restore the COW chain (checkpoints,
|
|
93
|
+
* ancestors). When only the `.rvf` exists, fresh-open it. When neither exists,
|
|
94
|
+
* dimension is required to create. Mirrors the bin CLI's `loadMem()` helper.
|
|
95
|
+
*/
|
|
96
|
+
async function openWithLineage(api, file, dimension) {
|
|
97
|
+
const manifest = manifestFor(file);
|
|
98
|
+
if (existsSync(manifest)) {
|
|
99
|
+
// The class-level static method `load` reconstructs the full chain.
|
|
100
|
+
return api.AgenticMemory.load(manifest);
|
|
101
|
+
}
|
|
102
|
+
const opts = {};
|
|
103
|
+
if (typeof dimension === 'number' && Number.isInteger(dimension) && dimension > 0) {
|
|
104
|
+
opts.dimension = dimension;
|
|
105
|
+
}
|
|
106
|
+
else if (!existsSync(file)) {
|
|
107
|
+
throw new Error('dimension is required when creating a new memory file');
|
|
108
|
+
}
|
|
109
|
+
return api.open(file, opts);
|
|
110
|
+
}
|
|
111
|
+
export const agenticowTools = [
|
|
112
|
+
{
|
|
113
|
+
name: 'agenticow_branch',
|
|
114
|
+
description: 'agenticow@~0.2.3 — COW-fork a base .rvf memory file. Measured 162-byte branches regardless of base size (verified at N=1k/10k/50k). Use when you need per-Darwin-iteration / per-user / per-session memory personalization. Copying the parent .rvf file is wrong because full-copy snapshots grow linearly (the 3.3 GB Darwin-worktree bloat fixed in v3.14.4); agenticow gives read-through semantics (parent ∪ edits, child wins) at constant 162 B. Optional dep — degrades to {degraded:true} when missing.',
|
|
115
|
+
category: 'memory',
|
|
116
|
+
tags: ['agenticow', 'memory', 'cow', 'branch'],
|
|
117
|
+
inputSchema: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: {
|
|
120
|
+
basePath: { type: 'string', description: 'Path to base .rvf memory file (absolute or relative to cwd)' },
|
|
121
|
+
branchPath: { type: 'string', description: 'Path to write the branch file' },
|
|
122
|
+
label: { type: 'string', description: 'Human-readable label for the branch (alnum + _.-:/@ only)' },
|
|
123
|
+
dimension: { type: 'integer', description: 'Vector dimension (required only when basePath does not exist yet)' },
|
|
124
|
+
},
|
|
125
|
+
required: ['basePath', 'branchPath', 'label'],
|
|
126
|
+
},
|
|
127
|
+
handler: async (input) => {
|
|
128
|
+
const api = await loadAgenticow();
|
|
129
|
+
if (!api)
|
|
130
|
+
return degradedResult('agenticow-not-found');
|
|
131
|
+
const label = validateLabel(String(input.label));
|
|
132
|
+
const basePath = resolveMemoryPath(String(input.basePath));
|
|
133
|
+
const branchPath = resolveMemoryPath(String(input.branchPath));
|
|
134
|
+
const dim = input.dimension;
|
|
135
|
+
const base = await openWithLineage(api, basePath, dim);
|
|
136
|
+
try {
|
|
137
|
+
const branch = await base.fork(label, branchPath);
|
|
138
|
+
// Persist lineage manifests so the branch (and base) reopen with
|
|
139
|
+
// their COW chain intact. Without this, fork is in-memory only.
|
|
140
|
+
await branch.save?.(manifestFor(branchPath));
|
|
141
|
+
await base.save?.(manifestFor(basePath));
|
|
142
|
+
await branch.close?.();
|
|
143
|
+
return {
|
|
144
|
+
success: true,
|
|
145
|
+
basePath,
|
|
146
|
+
branchPath,
|
|
147
|
+
label,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
await base.close?.();
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'agenticow_checkpoint',
|
|
157
|
+
description: 'agenticow — freeze a labelled restore point on an .rvf memory file. Subsequent edits stay in a fresh COW child; rollback returns here. Use when you are about to run an experimental Darwin tick or speculative agent edit that may need to be discarded. Relying on the working node alone is wrong because there is no "undo last N writes" semantics — without a checkpoint, a bad ingest contaminates the base. Persists via .agenticow.json lineage manifest so it survives close+reopen.',
|
|
158
|
+
category: 'memory',
|
|
159
|
+
tags: ['agenticow', 'memory', 'cow', 'checkpoint'],
|
|
160
|
+
inputSchema: {
|
|
161
|
+
type: 'object',
|
|
162
|
+
properties: {
|
|
163
|
+
path: { type: 'string', description: 'Path to .rvf memory file' },
|
|
164
|
+
label: { type: 'string', description: 'Checkpoint label (alnum + _.-:/@ only)' },
|
|
165
|
+
},
|
|
166
|
+
required: ['path', 'label'],
|
|
167
|
+
},
|
|
168
|
+
handler: async (input) => {
|
|
169
|
+
const api = await loadAgenticow();
|
|
170
|
+
if (!api)
|
|
171
|
+
return degradedResult('agenticow-not-found');
|
|
172
|
+
const label = validateLabel(String(input.label));
|
|
173
|
+
const path = resolveMemoryPath(String(input.path));
|
|
174
|
+
const mem = await openWithLineage(api, path);
|
|
175
|
+
try {
|
|
176
|
+
const cp = await mem.checkpoint(label);
|
|
177
|
+
await mem.save?.(manifestFor(path));
|
|
178
|
+
return { success: true, path, label, checkpoint: cp };
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
await mem.close?.();
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: 'agenticow_rollback',
|
|
187
|
+
description: 'agenticow — discard all edits since the most recent checkpoint on an .rvf memory file. Reuses a fresh COW child derived from the checkpoint. Use when a Darwin tick or agent experiment regressed and you want to revert memory state without re-running. Deleting+rebuilding the .rvf is wrong because rebuild cost is O(N) and the data after the bad point is lost; rollback is O(edits-since-checkpoint) and the earlier history stays intact via the lineage manifest.',
|
|
188
|
+
category: 'memory',
|
|
189
|
+
tags: ['agenticow', 'memory', 'cow', 'rollback'],
|
|
190
|
+
inputSchema: {
|
|
191
|
+
type: 'object',
|
|
192
|
+
properties: {
|
|
193
|
+
path: { type: 'string', description: 'Path to .rvf memory file' },
|
|
194
|
+
},
|
|
195
|
+
required: ['path'],
|
|
196
|
+
},
|
|
197
|
+
handler: async (input) => {
|
|
198
|
+
const api = await loadAgenticow();
|
|
199
|
+
if (!api)
|
|
200
|
+
return degradedResult('agenticow-not-found');
|
|
201
|
+
const path = resolveMemoryPath(String(input.path));
|
|
202
|
+
const mem = await openWithLineage(api, path);
|
|
203
|
+
try {
|
|
204
|
+
const r = await mem.rollback();
|
|
205
|
+
await mem.save?.(manifestFor(path));
|
|
206
|
+
return { success: true, path, rolledBack: true, result: r };
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
await mem.close?.();
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: 'agenticow_promote',
|
|
215
|
+
description: 'agenticow — merge a branch\'s edits back into its base (or an explicit target) memory file. After promote, branch edits become part of base lineage. Use when a per-user / per-Darwin-iteration branch has been validated and should graduate to shared memory (federation merge, A/B winner). Manually re-ingesting edits into the base is wrong because the edit set is opaque to the caller and tombstones (deletions) are easily missed; promote applies the full edit + tombstone set atomically.',
|
|
216
|
+
category: 'memory',
|
|
217
|
+
tags: ['agenticow', 'memory', 'cow', 'promote', 'merge'],
|
|
218
|
+
inputSchema: {
|
|
219
|
+
type: 'object',
|
|
220
|
+
properties: {
|
|
221
|
+
branchPath: { type: 'string', description: 'Path to branch .rvf file' },
|
|
222
|
+
basePath: {
|
|
223
|
+
type: 'string',
|
|
224
|
+
description: 'Path to base .rvf file. When omitted, promote merges into the ' +
|
|
225
|
+
'recorded fork parent (most common case).',
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
required: ['branchPath'],
|
|
229
|
+
},
|
|
230
|
+
handler: async (input) => {
|
|
231
|
+
const api = await loadAgenticow();
|
|
232
|
+
if (!api)
|
|
233
|
+
return degradedResult('agenticow-not-found');
|
|
234
|
+
const branchPath = resolveMemoryPath(String(input.branchPath));
|
|
235
|
+
const basePath = input.basePath ? resolveMemoryPath(String(input.basePath)) : undefined;
|
|
236
|
+
const branch = await openWithLineage(api, branchPath);
|
|
237
|
+
const base = basePath ? await openWithLineage(api, basePath) : undefined;
|
|
238
|
+
try {
|
|
239
|
+
const result = base ? await branch.promote(base) : await branch.promote();
|
|
240
|
+
// Persist mutated lineage so promote survives close+reopen
|
|
241
|
+
await branch.save?.(manifestFor(branchPath));
|
|
242
|
+
if (base && basePath)
|
|
243
|
+
await base.save?.(manifestFor(basePath));
|
|
244
|
+
return { success: true, branchPath, basePath: basePath ?? null, promoted: result ?? true };
|
|
245
|
+
}
|
|
246
|
+
finally {
|
|
247
|
+
await branch.close?.();
|
|
248
|
+
await base?.close?.();
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
//# sourceMappingURL=agenticow-tools.js.map
|
|
@@ -26,4 +26,5 @@ export { guidanceTools } from './guidance-tools.js';
|
|
|
26
26
|
export { autopilotTools } from './autopilot-tools.js';
|
|
27
27
|
export { metaharnessTools } from './metaharness-tools.js';
|
|
28
28
|
export { testgenTools } from './testgen-tools.js';
|
|
29
|
+
export { agenticowTools } from './agenticow-tools.js';
|
|
29
30
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -27,4 +27,6 @@ export { autopilotTools } from './autopilot-tools.js';
|
|
|
27
27
|
export { metaharnessTools } from './metaharness-tools.js';
|
|
28
28
|
// ADR-175-inspired — Test-Driven Repair via headless `claude -p`
|
|
29
29
|
export { testgenTools } from './testgen-tools.js';
|
|
30
|
+
// agenticow@~0.2.3 — Copy-On-Write memory branching (162-byte branches)
|
|
31
|
+
export { agenticowTools } from './agenticow-tools.js';
|
|
30
32
|
//# sourceMappingURL=index.js.map
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
* - metaharness_security_bench upstream's "Darwin Shield" (their own ADR-155)
|
|
19
19
|
* - metaharness_bench create/verify bench suites used by evolve --bench
|
|
20
20
|
*
|
|
21
|
+
* @metaharness/redblue integration adds one tool that targets the standalone
|
|
22
|
+
* `@metaharness/redblue` npm package — adversarial red/blue LLM testing
|
|
23
|
+
* for the agents and apps you own:
|
|
24
|
+
*
|
|
25
|
+
* - metaharness_redblue red-team → judge → blue-patch → retest → report
|
|
26
|
+
*
|
|
21
27
|
* Every tool resolves the corresponding plugin script
|
|
22
28
|
* (`plugins/ruflo-metaharness/scripts/<X>.mjs`) via the same locator
|
|
23
29
|
* the commands/metaharness.ts dispatcher uses, then spawns it with
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
* - metaharness_security_bench upstream's "Darwin Shield" (their own ADR-155)
|
|
19
19
|
* - metaharness_bench create/verify bench suites used by evolve --bench
|
|
20
20
|
*
|
|
21
|
+
* @metaharness/redblue integration adds one tool that targets the standalone
|
|
22
|
+
* `@metaharness/redblue` npm package — adversarial red/blue LLM testing
|
|
23
|
+
* for the agents and apps you own:
|
|
24
|
+
*
|
|
25
|
+
* - metaharness_redblue red-team → judge → blue-patch → retest → report
|
|
26
|
+
*
|
|
21
27
|
* Every tool resolves the corresponding plugin script
|
|
22
28
|
* (`plugins/ruflo-metaharness/scripts/<X>.mjs`) via the same locator
|
|
23
29
|
* the commands/metaharness.ts dispatcher uses, then spawns it with
|
|
@@ -42,8 +48,14 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
42
48
|
/**
|
|
43
49
|
* Walk up from this module to find plugins/ruflo-metaharness/scripts/.
|
|
44
50
|
* Handles three install layouts (mirrors commands/metaharness.ts).
|
|
51
|
+
*
|
|
52
|
+
* `requiredScript`, if provided, narrows the match the same way the
|
|
53
|
+
* commands dispatcher does — guards against the publish-artifact mirror
|
|
54
|
+
* (`v3/@claude-flow/cli/plugins/ruflo-metaharness/scripts/`, regenerated
|
|
55
|
+
* by `prepublishOnly`) shadowing the source when it's stale on a new
|
|
56
|
+
* script.
|
|
45
57
|
*/
|
|
46
|
-
function locatePluginScripts() {
|
|
58
|
+
function locatePluginScripts(requiredScript) {
|
|
47
59
|
const candidates = [];
|
|
48
60
|
let p = resolve(__dirname);
|
|
49
61
|
for (let i = 0; i < 8; i++) {
|
|
@@ -55,8 +67,11 @@ function locatePluginScripts() {
|
|
|
55
67
|
candidates.push(join(cwd, 'plugins', 'ruflo-metaharness', 'scripts'));
|
|
56
68
|
candidates.push(join(cwd, 'node_modules', '@claude-flow', 'cli', 'plugins', 'ruflo-metaharness', 'scripts'));
|
|
57
69
|
for (const c of candidates) {
|
|
58
|
-
if (existsSync(join(c, '_harness.mjs')))
|
|
59
|
-
|
|
70
|
+
if (!existsSync(join(c, '_harness.mjs')))
|
|
71
|
+
continue;
|
|
72
|
+
if (requiredScript && !existsSync(join(c, requiredScript)))
|
|
73
|
+
continue;
|
|
74
|
+
return c;
|
|
60
75
|
}
|
|
61
76
|
return null;
|
|
62
77
|
}
|
|
@@ -90,7 +105,7 @@ function locatePluginScripts() {
|
|
|
90
105
|
*/
|
|
91
106
|
function runScript(scriptName, args) {
|
|
92
107
|
return new Promise((resolve) => {
|
|
93
|
-
const dir = locatePluginScripts();
|
|
108
|
+
const dir = locatePluginScripts(scriptName);
|
|
94
109
|
if (!dir) {
|
|
95
110
|
resolve({
|
|
96
111
|
exitCode: 0, stdout: '', json: { degraded: true, reason: 'plugin-not-found' },
|
|
@@ -512,5 +527,69 @@ export const metaharnessTools = [
|
|
|
512
527
|
return { success: r.success, data: r.json, degraded: r.degraded, exitCode: r.exitCode };
|
|
513
528
|
},
|
|
514
529
|
},
|
|
530
|
+
// ───────────────────────────────────────────────────────────────────────
|
|
531
|
+
// @metaharness/redblue integration (1 tool).
|
|
532
|
+
// Backed by `@metaharness/redblue@~0.1.1`. Plugin script shells out via
|
|
533
|
+
// _redblue.mjs. Same {success, data, degraded, exitCode} contract.
|
|
534
|
+
//
|
|
535
|
+
// SAFETY: redblue itself enforces hard boundaries (no real creds, no live
|
|
536
|
+
// targets, no shell, no arbitrary network, no eval) in upstream's
|
|
537
|
+
// src/config/safety.ts at config-load time. The wrapper does NOT relax
|
|
538
|
+
// those — it only forwards argv with shell:false. `--mock-judge` is the
|
|
539
|
+
// $0 marker-fixture CI path; the real model judge requires
|
|
540
|
+
// $OPENROUTER_API_KEY which we never inject.
|
|
541
|
+
// ───────────────────────────────────────────────────────────────────────
|
|
542
|
+
{
|
|
543
|
+
name: 'metaharness_redblue',
|
|
544
|
+
description: 'Adversarial red/blue LLM testing via @metaharness/redblue — generates attacks across OWASP LLM Top-10 / NIST AI RMF families (prompt injection, tool misuse, data leakage, jailbreaks, denial-of-wallet), runs them against an LLM target YOU OWN, judges compromise, optionally applies declarative blue-team patches, retests, and emits a board-readable report with measured failure reduction. Use when shipping an LLM-powered product and you need a repeatable security gate before exposing it to users — eyeballing prompts is wrong because attack surface coverage requires the OWASP/NIST taxonomy and the judge has to be model-driven for jailbreak detection. SAFETY: upstream hard-enforces no-creds / no-live-targets / no-shell / no-network / no-eval at config-load time; cannot be relaxed via flags. For CI / offline use --mockJudge=true ($0 marker fixture). For real model judging set $OPENROUTER_API_KEY and accept the per-run cost capped by max_cost_usd (default $3). ' + MCP_SUCCESS_SEMANTIC,
|
|
545
|
+
category: 'metaharness',
|
|
546
|
+
inputSchema: {
|
|
547
|
+
type: 'object',
|
|
548
|
+
properties: {
|
|
549
|
+
subcommand: {
|
|
550
|
+
type: 'string',
|
|
551
|
+
enum: ['init', 'run', 'patch', 'attack', 'report'],
|
|
552
|
+
description: 'init = scaffold redblue.yaml; run = baseline (+ optional --patch); patch = baseline → patch → retest delta; attack = preview attacks; report = render existing report.json',
|
|
553
|
+
default: 'run',
|
|
554
|
+
},
|
|
555
|
+
config: { type: 'string', description: 'Path to redblue.yaml (default: ./redblue.yaml)' },
|
|
556
|
+
out: { type: 'string', description: 'Output report path for run/patch (default: temp file we read back inline)' },
|
|
557
|
+
in: { type: 'string', description: 'Input report path for `report` subcommand' },
|
|
558
|
+
tests: { type: 'number', description: 'How many test cases (run/patch only)' },
|
|
559
|
+
patch: { type: 'boolean', description: '`run` only — after baseline, apply blue-team patches and retest', default: false },
|
|
560
|
+
mockJudge: { type: 'boolean', description: '$0 TEST-ONLY marker fixture (no model calls). Use for CI / offline. Real judging requires OPENROUTER_API_KEY.', default: false },
|
|
561
|
+
family: { type: 'string', enum: ['prompt', 'tools', 'data', 'all'], description: '`attack` subcommand only — which attack family to preview' },
|
|
562
|
+
count: { type: 'number', description: '`attack` only — how many cases to preview' },
|
|
563
|
+
alertOnFail: { type: 'boolean', description: 'Exit 1 when post-patch verdict is FAIL (gate-style)', default: false },
|
|
564
|
+
timeoutMs: { type: 'number', description: 'Subprocess hard timeout (default 120000; mock-judge runs complete in seconds)' },
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
handler: async (input) => {
|
|
568
|
+
const args = [String(input.subcommand ?? 'run')];
|
|
569
|
+
// attack family is positional
|
|
570
|
+
if (input.subcommand === 'attack' && input.family)
|
|
571
|
+
args.push(String(input.family));
|
|
572
|
+
if (input.config)
|
|
573
|
+
args.push('--config', String(input.config));
|
|
574
|
+
if (input.out)
|
|
575
|
+
args.push('--out', String(input.out));
|
|
576
|
+
if (input.in)
|
|
577
|
+
args.push('--in', String(input.in));
|
|
578
|
+
if (input.tests !== undefined)
|
|
579
|
+
args.push('--tests', String(input.tests));
|
|
580
|
+
if (input.patch === true)
|
|
581
|
+
args.push('--patch');
|
|
582
|
+
if (input.mockJudge === true)
|
|
583
|
+
args.push('--mock-judge');
|
|
584
|
+
if (input.count !== undefined)
|
|
585
|
+
args.push('--count', String(input.count));
|
|
586
|
+
if (input.alertOnFail === true)
|
|
587
|
+
args.push('--alert-on-fail');
|
|
588
|
+
if (input.timeoutMs !== undefined)
|
|
589
|
+
args.push('--timeout-ms', String(input.timeoutMs));
|
|
590
|
+
const r = await runScript('redblue.mjs', args);
|
|
591
|
+
return { success: r.success, data: r.json, degraded: r.degraded, exitCode: r.exitCode };
|
|
592
|
+
},
|
|
593
|
+
},
|
|
515
594
|
];
|
|
516
595
|
//# sourceMappingURL=metaharness-tools.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.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",
|
|
@@ -106,6 +106,7 @@
|
|
|
106
106
|
"yaml": "^2.8.0"
|
|
107
107
|
},
|
|
108
108
|
"optionalDependencies": {
|
|
109
|
+
"agenticow": "~0.2.3",
|
|
109
110
|
"@claude-flow/aidefence": "^3.0.2",
|
|
110
111
|
"@claude-flow/codex": "^3.0.0-alpha.8",
|
|
111
112
|
"@claude-flow/embeddings": "^3.0.0-alpha.18",
|
|
@@ -115,6 +116,7 @@
|
|
|
115
116
|
"@claude-flow/security": "^3.0.0-alpha.10",
|
|
116
117
|
"@metaharness/darwin": "~0.3.1",
|
|
117
118
|
"@metaharness/kernel": "~0.1.0",
|
|
119
|
+
"@metaharness/redblue": "~0.1.1",
|
|
118
120
|
"@metaharness/router": "~0.3.2",
|
|
119
121
|
"metaharness": "~0.2.6",
|
|
120
122
|
"@ruvector/attention": "^0.1.32",
|