@claude-flow/cli 3.25.6 → 3.26.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.
- package/.claude/.proven-config-version +1 -0
- package/.claude/helpers/.helpers-version +1 -1
- package/.claude/helpers/helpers.manifest.json +5 -4
- package/.claude/helpers/hook-handler.cjs +129 -0
- package/.claude/helpers/statusline.cjs +781 -505
- package/.claude/proven-config.json +42 -0
- package/catalog-manifest.json +12 -0
- package/dist/src/commands/advisor.d.ts +15 -0
- package/dist/src/commands/advisor.js +94 -0
- package/dist/src/commands/doctor.js +77 -3
- package/dist/src/commands/funnel.d.ts +13 -0
- package/dist/src/commands/funnel.js +103 -0
- package/dist/src/commands/hooks.js +112 -46
- package/dist/src/commands/index.js +10 -0
- package/dist/src/commands/init.js +44 -0
- package/dist/src/commands/proxy.d.ts +21 -0
- package/dist/src/commands/proxy.js +310 -0
- package/dist/src/commands/security.js +29 -0
- package/dist/src/commands/settings.d.ts +19 -0
- package/dist/src/commands/settings.js +180 -0
- package/dist/src/commands/version.d.ts +42 -0
- package/dist/src/commands/version.js +106 -0
- package/dist/src/funnel/advisor-tip.d.ts +58 -0
- package/dist/src/funnel/advisor-tip.js +92 -0
- package/dist/src/funnel/attribution.d.ts +37 -0
- package/dist/src/funnel/attribution.js +101 -0
- package/dist/src/funnel/consent.d.ts +22 -0
- package/dist/src/funnel/consent.js +55 -0
- package/dist/src/funnel/credit-errors.d.ts +31 -0
- package/dist/src/funnel/credit-errors.js +88 -0
- package/dist/src/funnel/credit-notifier.d.ts +44 -0
- package/dist/src/funnel/credit-notifier.js +74 -0
- package/dist/src/funnel/disclosure.d.ts +46 -0
- package/dist/src/funnel/disclosure.js +97 -0
- package/dist/src/funnel/enrollment.d.ts +36 -0
- package/dist/src/funnel/enrollment.js +64 -0
- package/dist/src/funnel/environment.d.ts +17 -0
- package/dist/src/funnel/environment.js +39 -0
- package/dist/src/funnel/event-transport.d.ts +51 -0
- package/dist/src/funnel/event-transport.js +199 -0
- package/dist/src/funnel/events.d.ts +42 -0
- package/dist/src/funnel/events.js +150 -0
- package/dist/src/funnel/index.d.ts +20 -0
- package/dist/src/funnel/index.js +20 -0
- package/dist/src/funnel/insights.d.ts +49 -0
- package/dist/src/funnel/insights.js +120 -0
- package/dist/src/funnel/local-signals.d.ts +15 -0
- package/dist/src/funnel/local-signals.js +68 -0
- package/dist/src/funnel/message-transport.d.ts +51 -0
- package/dist/src/funnel/message-transport.js +149 -0
- package/dist/src/funnel/messages.d.ts +55 -0
- package/dist/src/funnel/messages.js +160 -0
- package/dist/src/funnel/power-saver-notifier.d.ts +44 -0
- package/dist/src/funnel/power-saver-notifier.js +92 -0
- package/dist/src/funnel/precedence.d.ts +16 -0
- package/dist/src/funnel/precedence.js +85 -0
- package/dist/src/funnel/promo.d.ts +41 -0
- package/dist/src/funnel/promo.js +144 -0
- package/dist/src/funnel/rate-limit-notifier.d.ts +55 -0
- package/dist/src/funnel/rate-limit-notifier.js +102 -0
- package/dist/src/funnel/rotation.d.ts +19 -0
- package/dist/src/funnel/rotation.js +70 -0
- package/dist/src/funnel/state.d.ts +13 -0
- package/dist/src/funnel/state.js +52 -0
- package/dist/src/funnel/toggle-cooldown.d.ts +17 -0
- package/dist/src/funnel/toggle-cooldown.js +32 -0
- package/dist/src/funnel/types.d.ts +86 -0
- package/dist/src/funnel/types.js +26 -0
- package/dist/src/init/executor.js +9 -3
- package/dist/src/init/helper-refresh.d.ts +33 -2
- package/dist/src/init/helper-refresh.js +102 -12
- package/dist/src/init/helpers-generator.js +52 -0
- package/dist/src/init/statusline-generator.js +292 -116
- package/dist/src/services/daemon-autostart.js +28 -5
- package/dist/src/services/fable-harness.d.ts +39 -0
- package/dist/src/services/fable-harness.js +41 -0
- package/package.json +13 -4
- package/dist/src/ruvector/lattice-wasm.d.ts +0 -14
- package/dist/src/ruvector/lattice-wasm.js +0 -144
- package/plugins/ruflo-metaharness/.claude-flow/daemon-state.json +0 -178
- package/plugins/ruflo-metaharness/.claude-flow/daemon.pid +0 -1
- package/plugins/ruflo-metaharness/.claude-flow/data/pending-insights.jsonl +0 -5
- package/plugins/ruflo-metaharness/.claude-flow/logs/daemon.log +0 -43
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/audit_1783604774864_ozbujc_prompt.log +0 -19
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/audit_1783604774864_ozbujc_result.log +0 -108
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/audit_1783605513587_ulvmpb_prompt.log +0 -19
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/audit_1783605513587_ulvmpb_result.log +0 -209
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/audit_1783606368867_ahysui_prompt.log +0 -19
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/audit_1783606368867_ahysui_result.log +0 -192
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/optimize_1783604894861_v6n3ut_prompt.log +0 -14
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/optimize_1783604894861_v6n3ut_result.log +0 -66
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/optimize_1783605934532_9h8ikb_prompt.log +0 -14
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/optimize_1783605934532_9h8ikb_result.log +0 -68
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/testgaps_1783605134860_9jssz9_prompt.log +0 -14
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/testgaps_1783605134860_9jssz9_result.log +0 -69
- package/plugins/ruflo-metaharness/.claude-flow/logs/headless/testgaps_1783606516743_zftbaa_prompt.log +0 -14
- package/plugins/ruflo-metaharness/.claude-flow/metrics/backup.json +0 -7
- package/plugins/ruflo-metaharness/.claude-flow/metrics/codebase-map.json +0 -11
- package/plugins/ruflo-metaharness/.claude-flow/metrics/consolidation.json +0 -16
- package/plugins/ruflo-metaharness/.claude-flow/metrics/harness-loop.json +0 -83
- package/plugins/ruflo-metaharness/.claude-flow/metrics/performance.json +0 -67
- package/plugins/ruflo-metaharness/.claude-flow/metrics/security-audit.json +0 -191
- package/plugins/ruflo-metaharness/.claude-flow/metrics/test-gaps.json +0 -68
- package/plugins/ruflo-metaharness/.claude-flow/neural/stats.json +0 -6
|
@@ -79,6 +79,17 @@ const REFLECT_SYSTEM_PROMPT = [
|
|
|
79
79
|
'Reply with ONLY a JSON array, one object per input id, no prose:',
|
|
80
80
|
'[{"id":"...","failureClass":"<short label>","diagnosis":"<one sentence>","mutationHint":"<actionable>"}]',
|
|
81
81
|
].join('\n');
|
|
82
|
+
const ADVISOR_SYSTEM_PROMPT = [
|
|
83
|
+
"You are RuFlo's co-pilot advisor: ONE short, proactive, actionable tip for",
|
|
84
|
+
'a developer, based on a single JSON object describing STRUCTURAL signals',
|
|
85
|
+
'from their current coding session (security scan status, swarm/agent',
|
|
86
|
+
'state, count of uncommitted files, context-window usage). There is no',
|
|
87
|
+
'prompt, command, or file content in the input — never assume or invent any.',
|
|
88
|
+
'If nothing in the snapshot genuinely warrants a tip, say so by returning',
|
|
89
|
+
'an empty array. Never pad with generic advice not grounded in the snapshot.',
|
|
90
|
+
'Reply with ONLY a JSON array containing zero or one object, no prose:',
|
|
91
|
+
'[] or [{"headline":"<=60 chars","detail":"<one actionable sentence>","confidence":0.0-1.0}]',
|
|
92
|
+
].join('\n');
|
|
82
93
|
// ── Default spawner (real CLI) ───────────────────────────────────────────────
|
|
83
94
|
/**
|
|
84
95
|
* Default `claude -p` spawner. Pipes the prompt via stdin (never as an argv
|
|
@@ -213,6 +224,24 @@ export class FableHarness {
|
|
|
213
224
|
}
|
|
214
225
|
return out;
|
|
215
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* ADR-316 — one proactive co-pilot tip from a structural session snapshot
|
|
229
|
+
* (no raw prompt/command/file content). A single-item "batch" — same
|
|
230
|
+
* budget/cwd/parsing discipline as judgeBatch/reflectFailures, just with
|
|
231
|
+
* exactly one call instead of a loop. Returns null when disabled, over
|
|
232
|
+
* budget, or the model found nothing worth surfacing (an empty verdict
|
|
233
|
+
* array is a valid, non-error answer here, not a parse failure).
|
|
234
|
+
*/
|
|
235
|
+
async adviseCoPilotTip(snapshot) {
|
|
236
|
+
if (!this.isEnabled())
|
|
237
|
+
return null;
|
|
238
|
+
if (this.spentUsd >= this.maxBudgetUsd)
|
|
239
|
+
return null;
|
|
240
|
+
const parsed = await this.runBatch(ADVISOR_SYSTEM_PROMPT, [snapshot]);
|
|
241
|
+
if (parsed.length === 0)
|
|
242
|
+
return null;
|
|
243
|
+
return normalizeCoPilotTip(parsed[0]);
|
|
244
|
+
}
|
|
216
245
|
/** Build the argv for a `claude -p` call. Exposed shape for testability. */
|
|
217
246
|
buildArgv(systemPrompt) {
|
|
218
247
|
const perCallCap = Math.max(0, this.maxBudgetUsd - this.spentUsd);
|
|
@@ -321,6 +350,18 @@ function normalizeReflect(raw) {
|
|
|
321
350
|
mutationHint: typeof o.mutationHint === 'string' ? o.mutationHint : '',
|
|
322
351
|
};
|
|
323
352
|
}
|
|
353
|
+
function normalizeCoPilotTip(raw) {
|
|
354
|
+
if (!raw || typeof raw !== 'object')
|
|
355
|
+
return null;
|
|
356
|
+
const o = raw;
|
|
357
|
+
if (typeof o.headline !== 'string' || !o.headline.trim())
|
|
358
|
+
return null;
|
|
359
|
+
return {
|
|
360
|
+
headline: o.headline.slice(0, 80),
|
|
361
|
+
detail: typeof o.detail === 'string' ? o.detail.slice(0, 200) : '',
|
|
362
|
+
confidence: clamp01(typeof o.confidence === 'number' ? o.confidence : Number(o.confidence)),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
324
365
|
function tryParseJson(s) {
|
|
325
366
|
try {
|
|
326
367
|
return JSON.parse(s);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.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",
|
|
@@ -81,7 +81,8 @@
|
|
|
81
81
|
"scripts/postinstall.cjs",
|
|
82
82
|
".claude",
|
|
83
83
|
"plugins",
|
|
84
|
-
"README.md"
|
|
84
|
+
"README.md",
|
|
85
|
+
"catalog-manifest.json"
|
|
85
86
|
],
|
|
86
87
|
"scripts": {
|
|
87
88
|
"build": "tsc",
|
|
@@ -89,7 +90,7 @@
|
|
|
89
90
|
"test:plugin-store": "npx tsx src/plugins/tests/standalone-test.ts",
|
|
90
91
|
"test:pattern-store": "npx tsx src/transfer/store/tests/standalone-test.ts",
|
|
91
92
|
"postinstall": "node ./scripts/postinstall.cjs",
|
|
92
|
-
"prepublishOnly": "cp ../../../README.md ./README.md && rm -rf plugins && mkdir -p plugins && cp -r ../../../plugins/ruflo-metaharness plugins/ && node scripts/sign-helpers.mjs && node scripts/verify-helpers.mjs",
|
|
93
|
+
"prepublishOnly": "cp ../../../README.md ./README.md && rm -rf plugins && mkdir -p plugins && cp -r ../../../plugins/ruflo-metaharness plugins/ && node scripts/generate-catalog-manifest.mjs && node scripts/sign-helpers.mjs && node scripts/verify-helpers.mjs",
|
|
93
94
|
"release": "npm version prerelease --preid=alpha && npm run publish:all",
|
|
94
95
|
"publish:all": "./scripts/publish.sh"
|
|
95
96
|
},
|
|
@@ -119,6 +120,14 @@
|
|
|
119
120
|
"tag": "latest"
|
|
120
121
|
},
|
|
121
122
|
"overrides": {
|
|
122
|
-
"protobufjs": ">=7.5.6"
|
|
123
|
+
"protobufjs": ">=7.5.6",
|
|
124
|
+
"js-yaml": ">=4.3.0",
|
|
125
|
+
"express": ">=4.22.2",
|
|
126
|
+
"qs": ">=6.15.2",
|
|
127
|
+
"@opentelemetry/core": ">=2.8.0",
|
|
128
|
+
"@opentelemetry/resources": ">=2.8.0",
|
|
129
|
+
"@opentelemetry/sdk-trace-base": ">=2.8.0",
|
|
130
|
+
"@opentelemetry/sdk-node": ">=0.220.0",
|
|
131
|
+
"agentdb": "$agentdb"
|
|
123
132
|
}
|
|
124
133
|
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/** Default package name (ruvnet WASM convention); override with RUFLO_LATTICE_WASM_PKG. */
|
|
2
|
-
export declare const LATTICE_WASM_PKG: string;
|
|
3
|
-
export type LatticeModel = 'minilm' | 'bge' | 'paraphrase-minilm' | 'qwen3-0.6b' | string;
|
|
4
|
-
export declare const DEFAULT_LATTICE_MODEL: LatticeModel;
|
|
5
|
-
/** Is the Lattice WASM embedder installed + initializable? Cached; never throws. */
|
|
6
|
-
export declare function latticeAvailable(): Promise<boolean>;
|
|
7
|
-
/** The models Lattice reports (empty until availability is probed). */
|
|
8
|
-
export declare function latticeModels(): LatticeModel[];
|
|
9
|
-
/**
|
|
10
|
-
* Embed `text` with `model` via Lattice WASM. Returns null on any failure so the
|
|
11
|
-
* caller can fall through to the next tier. Never throws.
|
|
12
|
-
*/
|
|
13
|
-
export declare function latticeEmbed(text: string, model?: LatticeModel): Promise<number[] | null>;
|
|
14
|
-
//# sourceMappingURL=lattice-wasm.d.ts.map
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lattice WASM embedder adapter — the primary embedding tier (ADR: embedding
|
|
3
|
-
* substrate upgrade). Replaces hash placeholders with real semantic embeddings
|
|
4
|
-
* and adds multiple models (miniLM, bge, multi-paraphrase-miniLM, GPU qwen3-0.6B).
|
|
5
|
-
*
|
|
6
|
-
* Built on the proven `@ruvector/ruvllm-wasm` optional-dependency convention:
|
|
7
|
-
* - dynamically imported (never a hard dependency),
|
|
8
|
-
* - WASM initialized from bundled bytes,
|
|
9
|
-
* - fully FAIL-CLOSED: if the package is absent, the WASM fails to init, or the
|
|
10
|
-
* embed API differs, `latticeAvailable()` returns false and callers fall
|
|
11
|
-
* through to the existing ruvector-ONNX → hash tiers with ZERO regression.
|
|
12
|
-
*
|
|
13
|
-
* The package specifier is configurable (`RUFLO_LATTICE_WASM_PKG`) so the exact
|
|
14
|
-
* published name can be set without a code change; the API is probed tolerantly.
|
|
15
|
-
* Opt-in for the GPU model: qwen3 is only selected when explicitly requested.
|
|
16
|
-
*/
|
|
17
|
-
import { createRequire } from 'module';
|
|
18
|
-
import { readFileSync } from 'fs';
|
|
19
|
-
const require_ = createRequire(import.meta.url);
|
|
20
|
-
/** Default package name (ruvnet WASM convention); override with RUFLO_LATTICE_WASM_PKG. */
|
|
21
|
-
export const LATTICE_WASM_PKG = process.env.RUFLO_LATTICE_WASM_PKG || '@ruvector/lattice-wasm';
|
|
22
|
-
export const DEFAULT_LATTICE_MODEL = process.env.RUFLO_EMBED_MODEL || 'minilm';
|
|
23
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
24
|
-
let _mod = null;
|
|
25
|
-
let _ready = false;
|
|
26
|
-
let _probed = false;
|
|
27
|
-
let _available = false;
|
|
28
|
-
let _models = [];
|
|
29
|
-
async function loadModule() {
|
|
30
|
-
if (_mod)
|
|
31
|
-
return _mod;
|
|
32
|
-
const spec = LATTICE_WASM_PKG;
|
|
33
|
-
_mod = await import(spec).catch(() => null); // optional — absent ⇒ null ⇒ unavailable
|
|
34
|
-
return _mod;
|
|
35
|
-
}
|
|
36
|
-
async function ensureInit() {
|
|
37
|
-
if (_ready)
|
|
38
|
-
return true;
|
|
39
|
-
const mod = await loadModule();
|
|
40
|
-
if (!mod)
|
|
41
|
-
return false;
|
|
42
|
-
try {
|
|
43
|
-
// ruvnet WASM convention: initSync({ module: <wasm bytes> }); tolerate variants.
|
|
44
|
-
if (!_ready && typeof mod.initSync === 'function') {
|
|
45
|
-
let wasmBytes;
|
|
46
|
-
for (const cand of ['lattice_wasm_bg.wasm', 'lattice_bg.wasm', 'index_bg.wasm']) {
|
|
47
|
-
try {
|
|
48
|
-
wasmBytes = readFileSync(require_.resolve(`${LATTICE_WASM_PKG}/${cand}`));
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
catch { /* try next */ }
|
|
52
|
-
}
|
|
53
|
-
mod.initSync(wasmBytes ? { module: wasmBytes } : undefined);
|
|
54
|
-
}
|
|
55
|
-
else if (typeof mod.default === 'function') {
|
|
56
|
-
await mod.default(); // some wasm-bindgen builds export an async default init
|
|
57
|
-
}
|
|
58
|
-
_ready = true;
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
return false; // init failed ⇒ fail closed
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
/** Extract a plain number[] from whatever shape the module's embed returns. */
|
|
66
|
-
function toVec(r) {
|
|
67
|
-
const v = (r && typeof r === 'object' && 'embedding' in r) ? r.embedding : r;
|
|
68
|
-
if (!v)
|
|
69
|
-
return null;
|
|
70
|
-
if (Array.isArray(v))
|
|
71
|
-
return v;
|
|
72
|
-
if (v.length !== undefined)
|
|
73
|
-
return Array.from(v);
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
/** Is the Lattice WASM embedder installed + initializable? Cached; never throws. */
|
|
77
|
-
export async function latticeAvailable() {
|
|
78
|
-
if (_probed)
|
|
79
|
-
return _available;
|
|
80
|
-
_probed = true;
|
|
81
|
-
try {
|
|
82
|
-
if (!(await ensureInit())) {
|
|
83
|
-
_available = false;
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
const mod = _mod;
|
|
87
|
-
// discover models (tolerant): listModels() / models / MODELS
|
|
88
|
-
try {
|
|
89
|
-
const list = typeof mod.listModels === 'function' ? mod.listModels() : (mod.models ?? mod.MODELS);
|
|
90
|
-
if (Array.isArray(list) && list.length)
|
|
91
|
-
_models = list;
|
|
92
|
-
}
|
|
93
|
-
catch { /* leave default */ }
|
|
94
|
-
if (!_models.length)
|
|
95
|
-
_models = [DEFAULT_LATTICE_MODEL];
|
|
96
|
-
// verify an actual embed succeeds (the ADR-086 "loads but runtime-fails" trap).
|
|
97
|
-
const probe = await latticeEmbedRaw('probe', DEFAULT_LATTICE_MODEL);
|
|
98
|
-
_available = !!probe && probe.length > 0;
|
|
99
|
-
return _available;
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
_available = false;
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
/** The models Lattice reports (empty until availability is probed). */
|
|
107
|
-
export function latticeModels() { return [..._models]; }
|
|
108
|
-
async function latticeEmbedRaw(text, model) {
|
|
109
|
-
const mod = _mod;
|
|
110
|
-
if (!mod)
|
|
111
|
-
return null;
|
|
112
|
-
// tolerant API probing across plausible wasm-bindgen surfaces.
|
|
113
|
-
const attempts = [
|
|
114
|
-
() => typeof mod.embed === 'function' ? mod.embed(text, model) : undefined,
|
|
115
|
-
() => typeof mod.embed === 'function' ? mod.embed(text) : undefined,
|
|
116
|
-
() => typeof mod.embedText === 'function' ? mod.embedText(text, model) : undefined,
|
|
117
|
-
() => typeof mod.Embedder === 'function' ? new mod.Embedder(model).embed(text) : undefined,
|
|
118
|
-
];
|
|
119
|
-
for (const a of attempts) {
|
|
120
|
-
try {
|
|
121
|
-
const r = await a();
|
|
122
|
-
const v = toVec(r);
|
|
123
|
-
if (v)
|
|
124
|
-
return v;
|
|
125
|
-
}
|
|
126
|
-
catch { /* try next surface */ }
|
|
127
|
-
}
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Embed `text` with `model` via Lattice WASM. Returns null on any failure so the
|
|
132
|
-
* caller can fall through to the next tier. Never throws.
|
|
133
|
-
*/
|
|
134
|
-
export async function latticeEmbed(text, model = DEFAULT_LATTICE_MODEL) {
|
|
135
|
-
try {
|
|
136
|
-
if (!(await latticeAvailable()))
|
|
137
|
-
return null;
|
|
138
|
-
return await latticeEmbedRaw(text, model);
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
//# sourceMappingURL=lattice-wasm.js.map
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"running": true,
|
|
3
|
-
"startedAt": "2026-07-09T13:44:14.858Z",
|
|
4
|
-
"workers": {
|
|
5
|
-
"map": {
|
|
6
|
-
"runCount": 3,
|
|
7
|
-
"successCount": 3,
|
|
8
|
-
"failureCount": 0,
|
|
9
|
-
"averageDurationMs": 2,
|
|
10
|
-
"isRunning": false,
|
|
11
|
-
"nextRun": "2026-07-09T14:29:14.860Z",
|
|
12
|
-
"lastStartedAt": "2026-07-09T14:14:14.854Z",
|
|
13
|
-
"lastRun": "2026-07-09T14:14:14.858Z"
|
|
14
|
-
},
|
|
15
|
-
"audit": {
|
|
16
|
-
"runCount": 3,
|
|
17
|
-
"successCount": 3,
|
|
18
|
-
"failureCount": 0,
|
|
19
|
-
"averageDurationMs": 181799,
|
|
20
|
-
"isRunning": false,
|
|
21
|
-
"nextRun": "2026-07-09T14:12:48.865Z",
|
|
22
|
-
"lastStartedAt": "2026-07-09T14:12:48.864Z",
|
|
23
|
-
"lastRun": "2026-07-09T14:15:20.256Z"
|
|
24
|
-
},
|
|
25
|
-
"optimize": {
|
|
26
|
-
"runCount": 2,
|
|
27
|
-
"successCount": 2,
|
|
28
|
-
"failureCount": 0,
|
|
29
|
-
"averageDurationMs": 243440.5,
|
|
30
|
-
"isRunning": false,
|
|
31
|
-
"nextRun": "2026-07-09T14:26:21.738Z",
|
|
32
|
-
"lastStartedAt": "2026-07-09T14:05:34.528Z",
|
|
33
|
-
"lastRun": "2026-07-09T14:11:21.737Z"
|
|
34
|
-
},
|
|
35
|
-
"consolidate": {
|
|
36
|
-
"runCount": 1,
|
|
37
|
-
"successCount": 1,
|
|
38
|
-
"failureCount": 0,
|
|
39
|
-
"averageDurationMs": 0,
|
|
40
|
-
"isRunning": false,
|
|
41
|
-
"nextRun": "2026-07-09T14:20:14.861Z",
|
|
42
|
-
"lastStartedAt": "2026-07-09T13:50:14.860Z",
|
|
43
|
-
"lastRun": "2026-07-09T13:50:14.860Z"
|
|
44
|
-
},
|
|
45
|
-
"testgaps": {
|
|
46
|
-
"runCount": 1,
|
|
47
|
-
"successCount": 1,
|
|
48
|
-
"failureCount": 0,
|
|
49
|
-
"averageDurationMs": 181886,
|
|
50
|
-
"isRunning": true,
|
|
51
|
-
"nextRun": "2026-07-09T14:15:16.745Z",
|
|
52
|
-
"lastStartedAt": "2026-07-09T14:15:16.740Z",
|
|
53
|
-
"lastRun": "2026-07-09T13:55:16.744Z"
|
|
54
|
-
},
|
|
55
|
-
"backup": {
|
|
56
|
-
"runCount": 1,
|
|
57
|
-
"successCount": 1,
|
|
58
|
-
"failureCount": 0,
|
|
59
|
-
"averageDurationMs": 4,
|
|
60
|
-
"isRunning": false,
|
|
61
|
-
"nextRun": "2026-07-10T13:54:14.862Z",
|
|
62
|
-
"lastStartedAt": "2026-07-09T13:54:14.856Z",
|
|
63
|
-
"lastRun": "2026-07-09T13:54:14.860Z"
|
|
64
|
-
},
|
|
65
|
-
"harness": {
|
|
66
|
-
"runCount": 1,
|
|
67
|
-
"successCount": 1,
|
|
68
|
-
"failureCount": 0,
|
|
69
|
-
"averageDurationMs": 7,
|
|
70
|
-
"isRunning": false,
|
|
71
|
-
"nextRun": "2026-07-09T19:56:14.864Z",
|
|
72
|
-
"lastStartedAt": "2026-07-09T13:56:14.856Z",
|
|
73
|
-
"lastRun": "2026-07-09T13:56:14.863Z"
|
|
74
|
-
},
|
|
75
|
-
"predict": {
|
|
76
|
-
"runCount": 0,
|
|
77
|
-
"successCount": 0,
|
|
78
|
-
"failureCount": 0,
|
|
79
|
-
"averageDurationMs": 0,
|
|
80
|
-
"isRunning": false
|
|
81
|
-
},
|
|
82
|
-
"document": {
|
|
83
|
-
"runCount": 0,
|
|
84
|
-
"successCount": 0,
|
|
85
|
-
"failureCount": 0,
|
|
86
|
-
"averageDurationMs": 0,
|
|
87
|
-
"isRunning": false
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
"config": {
|
|
91
|
-
"autoStart": false,
|
|
92
|
-
"logDir": "/Users/cohen/Projects/ruflo/plugins/ruflo-metaharness/.claude-flow/logs",
|
|
93
|
-
"stateFile": "/Users/cohen/Projects/ruflo/plugins/ruflo-metaharness/.claude-flow/daemon-state.json",
|
|
94
|
-
"maxConcurrent": 2,
|
|
95
|
-
"workerTimeoutMs": 960000,
|
|
96
|
-
"resourceThresholds": {
|
|
97
|
-
"maxCpuLoad": 9.600000000000001,
|
|
98
|
-
"minFreeMemoryPercent": 5
|
|
99
|
-
},
|
|
100
|
-
"ttlMs": 43200000,
|
|
101
|
-
"idleShutdownMs": 0,
|
|
102
|
-
"workers": [
|
|
103
|
-
{
|
|
104
|
-
"type": "map",
|
|
105
|
-
"intervalMs": 900000,
|
|
106
|
-
"offsetMs": 0,
|
|
107
|
-
"priority": "normal",
|
|
108
|
-
"description": "Codebase mapping",
|
|
109
|
-
"enabled": true
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
"type": "audit",
|
|
113
|
-
"intervalMs": 600000,
|
|
114
|
-
"offsetMs": 120000,
|
|
115
|
-
"priority": "critical",
|
|
116
|
-
"description": "Security analysis",
|
|
117
|
-
"enabled": true
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
"type": "optimize",
|
|
121
|
-
"intervalMs": 900000,
|
|
122
|
-
"offsetMs": 240000,
|
|
123
|
-
"priority": "high",
|
|
124
|
-
"description": "Performance optimization",
|
|
125
|
-
"enabled": true
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
"type": "consolidate",
|
|
129
|
-
"intervalMs": 1800000,
|
|
130
|
-
"offsetMs": 360000,
|
|
131
|
-
"priority": "low",
|
|
132
|
-
"description": "Memory distillation (ADR-174)",
|
|
133
|
-
"enabled": true
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
"type": "testgaps",
|
|
137
|
-
"intervalMs": 1200000,
|
|
138
|
-
"offsetMs": 480000,
|
|
139
|
-
"priority": "normal",
|
|
140
|
-
"description": "Test coverage analysis",
|
|
141
|
-
"enabled": true
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
"type": "backup",
|
|
145
|
-
"intervalMs": 86400000,
|
|
146
|
-
"offsetMs": 600000,
|
|
147
|
-
"priority": "low",
|
|
148
|
-
"description": "Nightly memory DB backup (WAL-safe, rotated)",
|
|
149
|
-
"enabled": true
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
"type": "harness",
|
|
153
|
-
"intervalMs": 21600000,
|
|
154
|
-
"offsetMs": 720000,
|
|
155
|
-
"priority": "low",
|
|
156
|
-
"description": "Self-optimizing harness loop (opt-in RUFLO_HARNESS_LOOP, $0-default)",
|
|
157
|
-
"enabled": true
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
"type": "predict",
|
|
161
|
-
"intervalMs": 600000,
|
|
162
|
-
"offsetMs": 0,
|
|
163
|
-
"priority": "low",
|
|
164
|
-
"description": "Predictive preloading",
|
|
165
|
-
"enabled": false
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
"type": "document",
|
|
169
|
-
"intervalMs": 3600000,
|
|
170
|
-
"offsetMs": 0,
|
|
171
|
-
"priority": "low",
|
|
172
|
-
"description": "Auto-documentation",
|
|
173
|
-
"enabled": false
|
|
174
|
-
}
|
|
175
|
-
]
|
|
176
|
-
},
|
|
177
|
-
"savedAt": "2026-07-09T14:15:20.256Z"
|
|
178
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
22169
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
{"type":"edit","file":"/Users/cohen/Projects/ruflo/plugins/ruflo-metaharness/scripts/test-mcp-tools.mjs","timestamp":1781649922735}
|
|
2
|
-
{"type":"edit","file":"/Users/cohen/Projects/ruflo/plugins/ruflo-metaharness/scripts/smoke.sh","timestamp":1782427183074}
|
|
3
|
-
{"type":"edit","file":"/Users/cohen/Projects/ruflo/plugins/ruflo-metaharness/scripts/smoke.sh","timestamp":1782427195692}
|
|
4
|
-
{"type":"edit","file":"/Users/cohen/Projects/ruflo/plugins/ruflo-metaharness/scripts/smoke.sh","timestamp":1782427207802}
|
|
5
|
-
{"type":"edit","file":"/Users/cohen/Projects/ruflo/plugins/ruflo-metaharness/scripts/test-mcp-tools.mjs","timestamp":1782427272241}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
[2026-07-09T13:44:14.859Z] [INFO] Scheduled map (interval: 900s, first run in 0s)
|
|
2
|
-
[2026-07-09T13:44:14.859Z] [INFO] Scheduled audit (interval: 600s, first run in 120s)
|
|
3
|
-
[2026-07-09T13:44:14.859Z] [INFO] Scheduled optimize (interval: 900s, first run in 240s)
|
|
4
|
-
[2026-07-09T13:44:14.859Z] [INFO] Scheduled consolidate (interval: 1800s, first run in 360s)
|
|
5
|
-
[2026-07-09T13:44:14.859Z] [INFO] Scheduled testgaps (interval: 1200s, first run in 480s)
|
|
6
|
-
[2026-07-09T13:44:14.859Z] [INFO] Scheduled backup (interval: 86400s, first run in 600s)
|
|
7
|
-
[2026-07-09T13:44:14.859Z] [INFO] Scheduled harness (interval: 21600s, first run in 720s)
|
|
8
|
-
[2026-07-09T13:44:14.859Z] [INFO] Lifecycle monitor active (ttl=43200s)
|
|
9
|
-
[2026-07-09T13:44:14.860Z] [INFO] Daemon started (PID: 22169, CPUs: 12, workers: 7, maxCpuLoad: 9.600000000000001, minFreeMemoryPercent: 5%)
|
|
10
|
-
[2026-07-09T13:44:14.860Z] [INFO] Claude Code headless mode available - AI workers enabled
|
|
11
|
-
[2026-07-09T13:44:14.860Z] [INFO] Starting worker: map (1/2 concurrent)
|
|
12
|
-
[2026-07-09T13:44:14.861Z] [INFO] Worker map completed in 1ms
|
|
13
|
-
[2026-07-09T13:46:14.862Z] [INFO] Starting worker: audit (1/2 concurrent)
|
|
14
|
-
[2026-07-09T13:46:14.863Z] [INFO] Running audit in headless mode (Claude Code AI)
|
|
15
|
-
[2026-07-09T13:48:14.860Z] [INFO] Starting worker: optimize (2/2 concurrent)
|
|
16
|
-
[2026-07-09T13:48:14.860Z] [INFO] Running optimize in headless mode (Claude Code AI)
|
|
17
|
-
[2026-07-09T13:48:33.588Z] [INFO] Worker audit completed in 138728ms
|
|
18
|
-
[2026-07-09T13:50:14.860Z] [INFO] Starting worker: consolidate (2/2 concurrent)
|
|
19
|
-
[2026-07-09T13:50:14.860Z] [INFO] Consolidate worker: distillation skipped (no-db)
|
|
20
|
-
[2026-07-09T13:50:14.860Z] [INFO] Worker consolidate completed in 0ms
|
|
21
|
-
[2026-07-09T13:50:34.530Z] [INFO] Worker optimize completed in 139672ms
|
|
22
|
-
[2026-07-09T13:52:14.860Z] [INFO] Starting worker: testgaps (1/2 concurrent)
|
|
23
|
-
[2026-07-09T13:52:14.860Z] [INFO] Running testgaps in headless mode (Claude Code AI)
|
|
24
|
-
[2026-07-09T13:54:14.858Z] [INFO] Starting worker: backup (2/2 concurrent)
|
|
25
|
-
[2026-07-09T13:54:14.860Z] [INFO] Worker backup completed in 4ms
|
|
26
|
-
[2026-07-09T13:55:16.744Z] [INFO] Worker testgaps completed in 181886ms
|
|
27
|
-
[2026-07-09T13:56:14.857Z] [INFO] Starting worker: harness (1/2 concurrent)
|
|
28
|
-
[2026-07-09T13:56:14.863Z] [INFO] Worker harness completed in 7ms
|
|
29
|
-
[2026-07-09T13:58:33.587Z] [INFO] Starting worker: audit (1/2 concurrent)
|
|
30
|
-
[2026-07-09T13:58:33.587Z] [INFO] Running audit in headless mode (Claude Code AI)
|
|
31
|
-
[2026-07-09T13:59:14.859Z] [INFO] Starting worker: map (2/2 concurrent)
|
|
32
|
-
[2026-07-09T13:59:14.859Z] [INFO] Worker map completed in 1ms
|
|
33
|
-
[2026-07-09T14:02:48.864Z] [INFO] Worker audit completed in 255277ms
|
|
34
|
-
[2026-07-09T14:05:34.531Z] [INFO] Starting worker: optimize (1/2 concurrent)
|
|
35
|
-
[2026-07-09T14:05:34.531Z] [INFO] Running optimize in headless mode (Claude Code AI)
|
|
36
|
-
[2026-07-09T14:11:21.737Z] [INFO] Worker optimize completed in 347209ms
|
|
37
|
-
[2026-07-09T14:12:48.866Z] [INFO] Starting worker: audit (1/2 concurrent)
|
|
38
|
-
[2026-07-09T14:12:48.867Z] [INFO] Running audit in headless mode (Claude Code AI)
|
|
39
|
-
[2026-07-09T14:14:14.857Z] [INFO] Starting worker: map (2/2 concurrent)
|
|
40
|
-
[2026-07-09T14:14:14.858Z] [INFO] Worker map completed in 4ms
|
|
41
|
-
[2026-07-09T14:15:16.742Z] [INFO] Starting worker: testgaps (2/2 concurrent)
|
|
42
|
-
[2026-07-09T14:15:16.743Z] [INFO] Running testgaps in headless mode (Claude Code AI)
|
|
43
|
-
[2026-07-09T14:15:20.256Z] [INFO] Worker audit completed in 151392ms
|
package/plugins/ruflo-metaharness/.claude-flow/logs/headless/audit_1783604774864_ozbujc_prompt.log
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
[2026-07-09T13:46:14.882Z] PROMPT
|
|
2
|
-
============================================================
|
|
3
|
-
Analyze this codebase for security vulnerabilities:
|
|
4
|
-
- Check for hardcoded secrets (API keys, passwords)
|
|
5
|
-
- Identify SQL injection risks
|
|
6
|
-
- Find XSS vulnerabilities
|
|
7
|
-
- Check for insecure dependencies
|
|
8
|
-
- Identify authentication/authorization issues
|
|
9
|
-
|
|
10
|
-
Provide a JSON report with:
|
|
11
|
-
{
|
|
12
|
-
"vulnerabilities": [{ "severity": "high|medium|low", "file": "...", "line": N, "description": "..." }],
|
|
13
|
-
"riskScore": 0-100,
|
|
14
|
-
"recommendations": ["..."]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
## Instructions
|
|
18
|
-
|
|
19
|
-
Analyze the codebase and provide your response following the format specified in the task.
|
package/plugins/ruflo-metaharness/.claude-flow/logs/headless/audit_1783604774864_ozbujc_result.log
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
[2026-07-09T13:48:33.587Z] RESULT
|
|
2
|
-
============================================================
|
|
3
|
-
{
|
|
4
|
-
"success": true,
|
|
5
|
-
"output": "## Security Audit Complete\n\nThe security auditor agent has completed a comprehensive scan. Combined with my manual analysis, here's the consolidated **Security Audit Report**:\n\n```json\n{\n \"vulnerabilities\": [\n {\n \"severity\": \"high\",\n \"file\": \"scripts/test-with-openrouter.mjs\",\n \"line\": 64,\n \"description\": \"Command injection vulnerability via execSync with template string interpolation. The secretName parameter is directly interpolated into a shell command without proper escaping. Although currently hardcoded as 'OPENROUTER_API_KEY', this is an unsafe code pattern that violates Node.js security best practices.\",\n \"codeSnippet\": \"const out = execSync(\\n `gcloud secrets versions access latest --secret=${secretName}`,\\n { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 15_000 },\\n);\",\n \"recommendation\": \"Replace with spawnSync using array arguments: spawnSync('gcloud', ['secrets', 'versions', 'access', 'latest', '--secret', secretName], {...})\"\n },\n {\n \"severity\": \"medium\",\n \"file\": \"scripts/audit-trend.mjs, audit-list.mjs, similarity.mjs, oia-audit.mjs, drift-from-history.mjs\",\n \"line\": \"22-24 (various)\",\n \"description\": \"Uses @claude-flow/cli@latest which fetches the latest version on every invocation. This contradicts ADR-150's pinning requirement and creates supply chain risk if npm registry is compromised or package account hijacked.\",\n \"codeSnippet\": \"const CLI_PKG = process.env.CLI_CORE === '1'\\n ? '@claude-flow/cli-core@alpha'\\n : '@claude-flow/cli@latest';\",\n \"recommendation\": \"Pin to specific semver range: '@claude-flow/cli@~3.7.0' (aligns with ADR-150 architecture)\"\n },\n {\n \"severity\": \"low\",\n \"file\": \"scripts/test-with-openrouter.mjs\",\n \"line\": 144,\n \"description\": \"API key prefix exposure in logging. Logs first 7 characters of API key which could help attackers identify which key type and potentially which account it belongs to.\",\n \"codeSnippet\": \"console.log(` key length: ${apiKey.length}, prefix: ${apiKey.slice(0, 7)}…`);\",\n \"recommendation\": \"Remove prefix logging. Use generic message: 'OPENROUTER_API_KEY loaded successfully'\"\n },\n {\n \"severity\": \"low\",\n \"file\": \"scripts/redblue.mjs\",\n \"line\": 217,\n \"description\": \"Path resolution doesn't canonicalize symlinks. User-provided paths are resolved but not checked for symlink attacks pointing outside intended directories.\",\n \"codeSnippet\": \"const reportPath = resolve(ARGS.out);\\nif (existsSync(reportPath)) {\\n try { payload = JSON.parse(readFileSync(reportPath, 'utf-8'));\",\n \"recommendation\": \"Use fs.realpathSync() to canonicalize paths: const realPath = realpathSync(reportPath)\"\n },\n {\n \"severity\": \"low\",\n \"file\": \"scripts/router-parallel-analyze.mjs\",\n \"line\": \"89-92\",\n \"description\": \"JSONL parsing lacks error context. If JSON.parse fails on a line, no line number is reported, making debugging difficult.\",\n \"codeSnippet\": \"rows = readFileSync(ARGS.input, 'utf-8')\\n .split('\\\\n')\\n .filter((l) => l.trim())\\n .map((l) => JSON.parse(l));\",\n \"recommendation\": \"Add try-catch with line number: .map((l, idx) => { try { return JSON.parse(l); } catch(e) { throw new Error(`Line ${idx+1}: ${e.message}`); } })\"\n },\n {\n \"severity\": \"low\",\n \"file\": \"scripts/test-with-openrouter.mjs\",\n \"line\": 138,\n \"description\": \"Weak API key validation. Checks length > 20, but modern API keys are typically 40+ characters. Weak validation could pass invalid or truncated keys.\",\n \"codeSnippet\": \"assert(typeof apiKey === 'string' && apiKey.length > 20, 'OPENROUTER_API_KEY fetched (length OK)');\",\n \"recommendation\": \"Use stricter validation: apiKey.length >= 40 && /^[a-zA-Z0-9_-]+$/.test(apiKey)\"\n }\n ],\n \"riskScore\": 32,\n \"summary\": \"The ruflo-metaharness plugin demonstrates strong overall security practices: all 30+ subprocess calls use shell:false with array arguments (preventing injection), no eval/Function() usage, no hardcoded secrets, and proper error handling. However, there is one high-severity command injection vulnerability (execSync with template strings) and medium-severity supply chain risks from using @latest instead of pinned versions. Four additional low-severity issues affect defense-in-depth. With these fixes, the plugin would achieve excellent security posture.\",\n \"recommendations\": [\n {\n \"priority\": \"CRITICAL\",\n \"action\": \"Fix command injection in test-with-openrouter.mjs line 64. Replace execSync with template strings with spawnSync array-based arguments.\"\n },\n {\n \"priority\": \"HIGH\",\n \"action\": \"Pin all @claude-flow/cli@latest references to specific versions (e.g., ~3.7.0) in: audit-trend.mjs, drift-from-history.mjs, similarity.mjs, oia-audit.mjs, audit-list.mjs\"\n },\n {\n \"priority\": \"MEDIUM\",\n \"action\": \"Remove API key prefix logging from console output (line 144 of test-with-openrouter.mjs)\"\n },\n {\n \"priority\": \"MEDIUM\",\n \"action\": \"Add fs.realpathSync() path canonicalization in redblue.mjs and other file operations\"\n },\n {\n \"priority\": \"LOW\",\n \"action\": \"Improve JSONL parsing error reporting with line numbers in router-parallel-analyze.mjs\"\n },\n {\n \"priority\": \"LOW\",\n \"action\": \"Strengthen API key validation to check for minimum 40-character length and valid character patterns\"\n },\n {\n \"priority\": \"INFORMATIONAL\",\n \"action\": \"Add security.md documentation with secure coding guidelines for this plugin\"\n }\n ],\n \"positives\": [\n \"✓ All subprocess calls use shell:false with array arguments (prevents shell injection)\",\n \"✓ Zero instances of eval, Function(), or dynamic code execution\",\n \"✓ No hardcoded secrets, API keys, or credentials anywhere in codebase\",\n \"✓ Proper input validation with explicit type conversions\",\n \"✓ Safe JSON parsing with try-catch error handling\",\n \"✓ Graceful degradation for missing optional dependencies (ADR-150 compliant)\",\n \"✓ Correct path handling with resolve() and existsSync() checks\",\n \"✓ Proper error handling with explicit exit codes\",\n \"✓ Environment variables used safely with explicit defaults\",\n \"✓ No dangerous use of template literals in subprocess/file operations\"\n ]\n}\n```\n\n### Summary\n\n**Risk Score: 32/100** (Low-Medium Risk)\n\n**Key Issues:**\n1. **1 Critical** - Command injection pattern (execSync + template strings)\n2. **1 Medium** - Supply chain risk (@latest npm packages)\n3. **4 Low** - Defense-in-depth improvements needed\n\n**Strengths:**\n- 30+ subprocess calls properly secured with shell:false\n- No code execution vulnerabilities\n- No credential leaks\n- Strong error handling throughout\n\n**Next Steps:**\n1. Address the critical execSync vulnerability immediately\n2. Pin npm package versions per ADR-150\n3. Apply defense-in-depth improvements for path handling and validation\n\nAll issues are straightforward to fix and align with the project's own architectural guidelines.\n",
|
|
6
|
-
"parsedOutput": {
|
|
7
|
-
"vulnerabilities": [
|
|
8
|
-
{
|
|
9
|
-
"severity": "high",
|
|
10
|
-
"file": "scripts/test-with-openrouter.mjs",
|
|
11
|
-
"line": 64,
|
|
12
|
-
"description": "Command injection vulnerability via execSync with template string interpolation. The secretName parameter is directly interpolated into a shell command without proper escaping. Although currently hardcoded as 'OPENROUTER_API_KEY', this is an unsafe code pattern that violates Node.js security best practices.",
|
|
13
|
-
"codeSnippet": "const out = execSync(\n `gcloud secrets versions access latest --secret=${secretName}`,\n { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 15_000 },\n);",
|
|
14
|
-
"recommendation": "Replace with spawnSync using array arguments: spawnSync('gcloud', ['secrets', 'versions', 'access', 'latest', '--secret', secretName], {...})"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"severity": "medium",
|
|
18
|
-
"file": "scripts/audit-trend.mjs, audit-list.mjs, similarity.mjs, oia-audit.mjs, drift-from-history.mjs",
|
|
19
|
-
"line": "22-24 (various)",
|
|
20
|
-
"description": "Uses @claude-flow/cli@latest which fetches the latest version on every invocation. This contradicts ADR-150's pinning requirement and creates supply chain risk if npm registry is compromised or package account hijacked.",
|
|
21
|
-
"codeSnippet": "const CLI_PKG = process.env.CLI_CORE === '1'\n ? '@claude-flow/cli-core@alpha'\n : '@claude-flow/cli@latest';",
|
|
22
|
-
"recommendation": "Pin to specific semver range: '@claude-flow/cli@~3.7.0' (aligns with ADR-150 architecture)"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"severity": "low",
|
|
26
|
-
"file": "scripts/test-with-openrouter.mjs",
|
|
27
|
-
"line": 144,
|
|
28
|
-
"description": "API key prefix exposure in logging. Logs first 7 characters of API key which could help attackers identify which key type and potentially which account it belongs to.",
|
|
29
|
-
"codeSnippet": "console.log(` key length: ${apiKey.length}, prefix: ${apiKey.slice(0, 7)}…`);",
|
|
30
|
-
"recommendation": "Remove prefix logging. Use generic message: 'OPENROUTER_API_KEY loaded successfully'"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"severity": "low",
|
|
34
|
-
"file": "scripts/redblue.mjs",
|
|
35
|
-
"line": 217,
|
|
36
|
-
"description": "Path resolution doesn't canonicalize symlinks. User-provided paths are resolved but not checked for symlink attacks pointing outside intended directories.",
|
|
37
|
-
"codeSnippet": "const reportPath = resolve(ARGS.out);\nif (existsSync(reportPath)) {\n try { payload = JSON.parse(readFileSync(reportPath, 'utf-8'));",
|
|
38
|
-
"recommendation": "Use fs.realpathSync() to canonicalize paths: const realPath = realpathSync(reportPath)"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"severity": "low",
|
|
42
|
-
"file": "scripts/router-parallel-analyze.mjs",
|
|
43
|
-
"line": "89-92",
|
|
44
|
-
"description": "JSONL parsing lacks error context. If JSON.parse fails on a line, no line number is reported, making debugging difficult.",
|
|
45
|
-
"codeSnippet": "rows = readFileSync(ARGS.input, 'utf-8')\n .split('\\n')\n .filter((l) => l.trim())\n .map((l) => JSON.parse(l));",
|
|
46
|
-
"recommendation": "Add try-catch with line number: .map((l, idx) => { try { return JSON.parse(l); } catch(e) { throw new Error(`Line ${idx+1}: ${e.message}`); } })"
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"severity": "low",
|
|
50
|
-
"file": "scripts/test-with-openrouter.mjs",
|
|
51
|
-
"line": 138,
|
|
52
|
-
"description": "Weak API key validation. Checks length > 20, but modern API keys are typically 40+ characters. Weak validation could pass invalid or truncated keys.",
|
|
53
|
-
"codeSnippet": "assert(typeof apiKey === 'string' && apiKey.length > 20, 'OPENROUTER_API_KEY fetched (length OK)');",
|
|
54
|
-
"recommendation": "Use stricter validation: apiKey.length >= 40 && /^[a-zA-Z0-9_-]+$/.test(apiKey)"
|
|
55
|
-
}
|
|
56
|
-
],
|
|
57
|
-
"riskScore": 32,
|
|
58
|
-
"summary": "The ruflo-metaharness plugin demonstrates strong overall security practices: all 30+ subprocess calls use shell:false with array arguments (preventing injection), no eval/Function() usage, no hardcoded secrets, and proper error handling. However, there is one high-severity command injection vulnerability (execSync with template strings) and medium-severity supply chain risks from using @latest instead of pinned versions. Four additional low-severity issues affect defense-in-depth. With these fixes, the plugin would achieve excellent security posture.",
|
|
59
|
-
"recommendations": [
|
|
60
|
-
{
|
|
61
|
-
"priority": "CRITICAL",
|
|
62
|
-
"action": "Fix command injection in test-with-openrouter.mjs line 64. Replace execSync with template strings with spawnSync array-based arguments."
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
"priority": "HIGH",
|
|
66
|
-
"action": "Pin all @claude-flow/cli@latest references to specific versions (e.g., ~3.7.0) in: audit-trend.mjs, drift-from-history.mjs, similarity.mjs, oia-audit.mjs, audit-list.mjs"
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
"priority": "MEDIUM",
|
|
70
|
-
"action": "Remove API key prefix logging from console output (line 144 of test-with-openrouter.mjs)"
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"priority": "MEDIUM",
|
|
74
|
-
"action": "Add fs.realpathSync() path canonicalization in redblue.mjs and other file operations"
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
"priority": "LOW",
|
|
78
|
-
"action": "Improve JSONL parsing error reporting with line numbers in router-parallel-analyze.mjs"
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
"priority": "LOW",
|
|
82
|
-
"action": "Strengthen API key validation to check for minimum 40-character length and valid character patterns"
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
"priority": "INFORMATIONAL",
|
|
86
|
-
"action": "Add security.md documentation with secure coding guidelines for this plugin"
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
"positives": [
|
|
90
|
-
"✓ All subprocess calls use shell:false with array arguments (prevents shell injection)",
|
|
91
|
-
"✓ Zero instances of eval, Function(), or dynamic code execution",
|
|
92
|
-
"✓ No hardcoded secrets, API keys, or credentials anywhere in codebase",
|
|
93
|
-
"✓ Proper input validation with explicit type conversions",
|
|
94
|
-
"✓ Safe JSON parsing with try-catch error handling",
|
|
95
|
-
"✓ Graceful degradation for missing optional dependencies (ADR-150 compliant)",
|
|
96
|
-
"✓ Correct path handling with resolve() and existsSync() checks",
|
|
97
|
-
"✓ Proper error handling with explicit exit codes",
|
|
98
|
-
"✓ Environment variables used safely with explicit defaults",
|
|
99
|
-
"✓ No dangerous use of template literals in subprocess/file operations"
|
|
100
|
-
]
|
|
101
|
-
},
|
|
102
|
-
"durationMs": 138723,
|
|
103
|
-
"model": "haiku",
|
|
104
|
-
"sandboxMode": "strict",
|
|
105
|
-
"workerType": "audit",
|
|
106
|
-
"timestamp": "2026-07-09T13:48:33.587Z",
|
|
107
|
-
"executionId": "audit_1783604774864_ozbujc"
|
|
108
|
-
}
|