@claude-flow/cli 3.17.0 → 3.18.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/dist/src/commands/neural.d.ts.map +1 -1
- package/dist/src/commands/neural.js +16 -6
- package/dist/src/commands/neural.js.map +1 -1
- package/dist/src/mcp-tools/agentdb-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agentdb-tools.js +52 -1
- package/dist/src/mcp-tools/agentdb-tools.js.map +1 -1
- package/dist/src/mcp-tools/browser-session-tools.d.ts +5 -1
- package/dist/src/mcp-tools/browser-session-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/browser-session-tools.js +92 -18
- package/dist/src/mcp-tools/browser-session-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.d.ts +1 -0
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +131 -0
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/neural-tools.js +119 -84
- package/dist/src/mcp-tools/neural-tools.js.map +1 -1
- package/dist/src/memory/intelligence.d.ts.map +1 -1
- package/dist/src/memory/intelligence.js +20 -5
- package/dist/src/memory/intelligence.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts +15 -2
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +64 -10
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/ruvector/lora-adapter.d.ts +9 -0
- package/dist/src/ruvector/lora-adapter.d.ts.map +1 -1
- package/dist/src/ruvector/lora-adapter.js +21 -3
- package/dist/src/ruvector/lora-adapter.js.map +1 -1
- package/dist/src/ruvector/output-verifier.d.ts +83 -0
- package/dist/src/ruvector/output-verifier.d.ts.map +1 -0
- package/dist/src/ruvector/output-verifier.js +277 -0
- package/dist/src/ruvector/output-verifier.js.map +1 -0
- package/dist/src/ruvector/trajectory-tree.d.ts +113 -0
- package/dist/src/ruvector/trajectory-tree.d.ts.map +1 -0
- package/dist/src/ruvector/trajectory-tree.js +237 -0
- package/dist/src/ruvector/trajectory-tree.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/plugins/ruflo-metaharness/agents/metaharness-architect.md +1 -1
- package/plugins/ruflo-metaharness/commands/ruflo-metaharness.md +5 -3
- package/plugins/ruflo-metaharness/scripts/_darwin.mjs +47 -39
- package/plugins/ruflo-metaharness/scripts/_harness.mjs +173 -104
- package/plugins/ruflo-metaharness/scripts/_invoke.mjs +231 -0
- package/plugins/ruflo-metaharness/scripts/_redblue.mjs +36 -75
- package/plugins/ruflo-metaharness/scripts/evolve.mjs +163 -3
- package/plugins/ruflo-metaharness/scripts/gepa.mjs +7 -53
- package/plugins/ruflo-metaharness/scripts/smoke.sh +98 -47
- package/plugins/ruflo-metaharness/scripts/test-graceful-degradation.mjs +16 -0
- package/plugins/ruflo-metaharness/skills/harness-evolve/SKILL.md +41 -2
- package/plugins/ruflo-metaharness/skills/harness-learn/SKILL.md +4 -2
- package/plugins/ruflo-metaharness/skills/harness-mcp-scan/SKILL.md +3 -1
- package/plugins/ruflo-metaharness/skills/harness-score/SKILL.md +1 -1
- package/plugins/ruflo-metaharness/skills/harness-threat-model/SKILL.md +3 -1
|
@@ -22,11 +22,12 @@
|
|
|
22
22
|
//
|
|
23
23
|
// MODULE RESOLUTION (ADR-150 graceful degradation)
|
|
24
24
|
// ================================================
|
|
25
|
+
// Delegated to _invoke.importOptionalLibrary (family-wide consolidation):
|
|
25
26
|
// 1. Try bare `import('@metaharness/darwin/gepa')` — free when the optional
|
|
26
27
|
// dep is installed in an ancestor node_modules.
|
|
27
28
|
// 2. Fall back to a ruflo-owned versioned cache install
|
|
28
|
-
// (~/.ruflo/darwin-cache-<pin>) —
|
|
29
|
-
//
|
|
29
|
+
// (~/.ruflo/darwin-cache-<pin>) — the versioned dir means pin bumps
|
|
30
|
+
// invalidate stale caches automatically.
|
|
30
31
|
// 3. Both fail → `{degraded: true}` exit 0. Never throws.
|
|
31
32
|
//
|
|
32
33
|
// EXIT CODES
|
|
@@ -34,20 +35,11 @@
|
|
|
34
35
|
// 1 --alert-on-invalid and validate found errors
|
|
35
36
|
// 2 config error (bad op / missing file)
|
|
36
37
|
|
|
37
|
-
import { readFileSync, existsSync
|
|
38
|
-
import {
|
|
39
|
-
import { homedir } from 'node:os';
|
|
40
|
-
import { join } from 'node:path';
|
|
41
|
-
import { pathToFileURL } from 'node:url';
|
|
38
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
39
|
+
import { importGepa, DARWIN_VERSION_PIN } from './_darwin.mjs';
|
|
42
40
|
|
|
43
|
-
//
|
|
44
|
-
const DARWIN_PIN_VERSION = '
|
|
45
|
-
const CACHE_DIR = join(
|
|
46
|
-
homedir(), '.ruflo', `darwin-cache-${DARWIN_PIN_VERSION.replace(/[~^]/g, '')}`,
|
|
47
|
-
);
|
|
48
|
-
const CACHED_GEPA = join(
|
|
49
|
-
CACHE_DIR, 'node_modules', '@metaharness', 'darwin', 'dist', 'gepa', 'index.js',
|
|
50
|
-
);
|
|
41
|
+
// Pin lives in _darwin.mjs (DARWIN_VERSION_PIN) — single source of truth.
|
|
42
|
+
const DARWIN_PIN_VERSION = DARWIN_VERSION_PIN.split('@').pop();
|
|
51
43
|
|
|
52
44
|
const ARGS = (() => {
|
|
53
45
|
const a = {
|
|
@@ -83,44 +75,6 @@ function emitDegradedAndExit(reason) {
|
|
|
83
75
|
process.exit(0); // ADR-150 — ruflo stays operational without MetaHarness
|
|
84
76
|
}
|
|
85
77
|
|
|
86
|
-
async function importGepa() {
|
|
87
|
-
try {
|
|
88
|
-
return await import('@metaharness/darwin/gepa');
|
|
89
|
-
} catch (e) {
|
|
90
|
-
const msg = String(e?.message ?? e);
|
|
91
|
-
// Fall back on absence AND on stale installs: a pre-0.8.0 darwin in an
|
|
92
|
-
// ancestor node_modules has no './gepa' subpath, which throws
|
|
93
|
-
// ERR_PACKAGE_PATH_NOT_EXPORTED rather than MODULE_NOT_FOUND.
|
|
94
|
-
const recoverable = /Cannot find (module|package)|ERR_MODULE_NOT_FOUND|MODULE_NOT_FOUND|ERR_PACKAGE_PATH_NOT_EXPORTED|is not defined by "exports"/i;
|
|
95
|
-
if (!recoverable.test(msg)) throw e;
|
|
96
|
-
}
|
|
97
|
-
// Cached-install fallback.
|
|
98
|
-
if (!existsSync(CACHED_GEPA)) {
|
|
99
|
-
try {
|
|
100
|
-
mkdirSync(CACHE_DIR, { recursive: true });
|
|
101
|
-
} catch {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
const r = spawnSync('npm', [
|
|
105
|
-
'install',
|
|
106
|
-
'--no-audit', '--no-fund', '--no-package-lock',
|
|
107
|
-
'--prefix', CACHE_DIR,
|
|
108
|
-
`@metaharness/darwin@${DARWIN_PIN_VERSION}`,
|
|
109
|
-
], {
|
|
110
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
111
|
-
encoding: 'utf-8',
|
|
112
|
-
timeout: 180_000,
|
|
113
|
-
shell: process.platform === 'win32',
|
|
114
|
-
});
|
|
115
|
-
if (r.status !== 0 || !existsSync(CACHED_GEPA)) return null;
|
|
116
|
-
}
|
|
117
|
-
try {
|
|
118
|
-
return await import(pathToFileURL(CACHED_GEPA).href);
|
|
119
|
-
} catch {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
78
|
function readJsonFile(path, label) {
|
|
125
79
|
if (!path || !existsSync(path)) {
|
|
126
80
|
console.error(`gepa: ${label} file not found: ${path}`);
|
|
@@ -8,6 +8,29 @@ step() { printf "→ %s ... " "$1"; }
|
|
|
8
8
|
ok() { printf "PASS\n"; PASS=$((PASS+1)); }
|
|
9
9
|
bad() { printf "FAIL: %s\n" "$1"; FAIL=$((FAIL+1)); }
|
|
10
10
|
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
# Derived surface counts (converged arch review, 2026-07).
|
|
13
|
+
# The MCP-tool count (was hardcoded 15 in 4 places) and the CLI-subcommand
|
|
14
|
+
# count (was hardcoded 13 in 2 places, plus the 16 footnote) are derived ONCE
|
|
15
|
+
# from the source-of-truth files here. Every assertion below compares an
|
|
16
|
+
# INDEPENDENT surface (CLAUDE.md catalog, test-mcp-tools literal, footnote
|
|
17
|
+
# occurrences, runScript refs) against these derived values — never a surface
|
|
18
|
+
# against itself. Adding a tool/subcommand upstream now only requires updating
|
|
19
|
+
# the OTHER surfaces, not this script.
|
|
20
|
+
TOOLS_SRC="$ROOT/../../v3/@claude-flow/cli/src/mcp-tools/metaharness-tools.ts"
|
|
21
|
+
SUBS_SRC="$ROOT/../../v3/@claude-flow/cli/src/commands/metaharness.ts"
|
|
22
|
+
EXPECTED_TOOLS=$(grep -cE "name: 'metaharness_" "$TOOLS_SRC" 2>/dev/null; true)
|
|
23
|
+
EXPECTED_SUBS=$(grep -cE "^[[:space:]]+'?[a-z-]+'?:[[:space:]]*'[a-z-]+\.mjs'" "$SUBS_SRC" 2>/dev/null; true)
|
|
24
|
+
: "${EXPECTED_TOOLS:=0}"
|
|
25
|
+
: "${EXPECTED_SUBS:=0}"
|
|
26
|
+
|
|
27
|
+
step "0. derived surface counts extracted (tools >= 15, subcommands >= 13 — regex-rot floor)"
|
|
28
|
+
if [[ "$EXPECTED_TOOLS" -ge 15 && "$EXPECTED_SUBS" -ge 13 ]]; then
|
|
29
|
+
ok
|
|
30
|
+
else
|
|
31
|
+
bad "extraction-regex-rot: EXPECTED_TOOLS=$EXPECTED_TOOLS EXPECTED_SUBS=$EXPECTED_SUBS"
|
|
32
|
+
fi
|
|
33
|
+
|
|
11
34
|
step "1. plugin.json declares 0.1.0 with adr-150 keywords"
|
|
12
35
|
v=$(grep -E '"version"' "$ROOT/.claude-plugin/plugin.json" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
|
13
36
|
if [[ "$v" != "0.1.0" ]]; then
|
|
@@ -45,6 +68,26 @@ grep -q "metaharness-not-available" "$F" || miss="$miss no-degraded-reason"
|
|
|
45
68
|
grep -q "degraded: true" "$F" || miss="$miss no-degraded-flag"
|
|
46
69
|
[[ -z "$miss" ]] && ok || bad "$miss"
|
|
47
70
|
|
|
71
|
+
step "3b. _invoke.mjs shared plumbing layer (consolidation, 2026-07)"
|
|
72
|
+
F="$ROOT/scripts/_invoke.mjs"
|
|
73
|
+
miss=""
|
|
74
|
+
[[ -f "$F" ]] || miss="$miss missing"
|
|
75
|
+
node --check "$F" 2>/dev/null || miss="$miss syntax-error"
|
|
76
|
+
# The consolidated helpers every adapter (_harness/_darwin/_redblue/gepa) uses
|
|
77
|
+
for sym in DEGRADED_RX classifyDegraded injectJson parseTrailingJson ensureCachedInstall makeDegradedEmitter importOptionalLibrary findLocalPackageDir; do
|
|
78
|
+
grep -q "export.*${sym}" "$F" || miss="$miss no-${sym}"
|
|
79
|
+
done
|
|
80
|
+
# Superset degraded regex must include the npm-level failure marker
|
|
81
|
+
grep -q "npm ERR" "$F" || miss="$miss degraded-rx-missing-npm-err"
|
|
82
|
+
# The -timeout vs -not-available distinction is load-bearing
|
|
83
|
+
grep -q -- "-timeout" "$F" || miss="$miss no-timeout-reason"
|
|
84
|
+
grep -q -- "-not-available" "$F" || miss="$miss no-not-available-reason"
|
|
85
|
+
# All four adapters import from it
|
|
86
|
+
for a in _harness _darwin _redblue gepa; do
|
|
87
|
+
grep -q "from './_invoke.mjs'\|from './_darwin.mjs'" "$ROOT/scripts/${a}.mjs" || miss="$miss ${a}-not-adapting"
|
|
88
|
+
done
|
|
89
|
+
[[ -z "$miss" ]] && ok || bad "$miss"
|
|
90
|
+
|
|
48
91
|
step "4. score.mjs harness present + parses + uses _harness.mjs + alert"
|
|
49
92
|
F="$ROOT/scripts/score.mjs"
|
|
50
93
|
miss=""
|
|
@@ -170,24 +213,29 @@ if (!od.metaharness) { console.error('missing metaharness in optionalDependencie
|
|
|
170
213
|
if (j.dependencies && j.dependencies.metaharness) { console.error('metaharness leaked into dependencies'); process.exit(1); }
|
|
171
214
|
" 2>/dev/null && ok || bad "ruflo wrapper missing metaharness optionalDep"
|
|
172
215
|
|
|
173
|
-
step "17r. _harness.mjs
|
|
216
|
+
step "17r. _harness.mjs pinned-version + no-@latest regression guard (supersedes iter 27)"
|
|
174
217
|
F="$ROOT/scripts/_harness.mjs"
|
|
175
218
|
miss=""
|
|
176
|
-
#
|
|
177
|
-
# to
|
|
178
|
-
#
|
|
179
|
-
#
|
|
180
|
-
#
|
|
181
|
-
#
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if grep -qE "execCli\(\s*['\"]-y metaharness@latest['\"]" "$F" 2>/dev/null; then
|
|
185
|
-
miss="$miss bug-regressed-string-form"
|
|
219
|
+
# SECURITY (HIGH, converged review 2026-07): the pre-consolidation helper
|
|
220
|
+
# shelled to `npx -y metaharness@latest` — a compromised upstream publish
|
|
221
|
+
# would execute arbitrary code on user machines, and @latest forced a
|
|
222
|
+
# registry check per call. Lock the fix: NO @latest anywhere in the loader,
|
|
223
|
+
# a pinned tilde range, and node-direct invocation of resolved bin paths
|
|
224
|
+
# (local walk-up install or one-time versioned cache).
|
|
225
|
+
if grep -q "metaharness@latest" "$F" 2>/dev/null; then
|
|
226
|
+
miss="$miss at-latest-regressed"
|
|
186
227
|
fi
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
228
|
+
grep -q "METAHARNESS_PIN_VERSION = '~" "$F" 2>/dev/null || miss="$miss no-pinned-range"
|
|
229
|
+
# node-direct spawn of the resolved bin (not an npx shim)
|
|
230
|
+
grep -qE "spawnSync\('node'" "$F" 2>/dev/null || miss="$miss no-node-direct-sync"
|
|
231
|
+
grep -qE "spawn\('node'" "$F" 2>/dev/null || miss="$miss no-node-direct-async"
|
|
232
|
+
# resolution order: local install first, then versioned cache install
|
|
233
|
+
grep -q "findLocalPackageDir" "$F" 2>/dev/null || miss="$miss no-local-resolution"
|
|
234
|
+
grep -q "ensureCachedInstall" "$F" 2>/dev/null || miss="$miss no-cache-install"
|
|
235
|
+
# BOTH bins resolved from the package.json bin map (metaharness + harness)
|
|
236
|
+
grep -q "bin.metaharness" "$F" 2>/dev/null || miss="$miss no-metaharness-bin"
|
|
237
|
+
grep -q "bin.harness" "$F" 2>/dev/null || miss="$miss no-harness-bin"
|
|
238
|
+
# cwd + env pass-through (iter 27 behavior retained)
|
|
191
239
|
grep -q "cwd: opts" "$F" || miss="$miss no-cwd-passthrough"
|
|
192
240
|
[[ -z "$miss" ]] && ok || bad "$miss"
|
|
193
241
|
|
|
@@ -722,7 +770,7 @@ for k in $KEYS; do
|
|
|
722
770
|
grep -qE "npx ruflo metaharness ${k}([ \\\\]|$)" "$CMD" 2>/dev/null \
|
|
723
771
|
|| miss="$miss subcommand-${k}-not-in-claude-md"
|
|
724
772
|
done
|
|
725
|
-
[[ "$COUNT" == "
|
|
773
|
+
[[ "$COUNT" == "$EXPECTED_SUBS" ]] || miss="$miss subcommand-count-stale:$COUNT-expected-$EXPECTED_SUBS"
|
|
726
774
|
[[ -z "$miss" ]] && ok || bad "$miss"
|
|
727
775
|
|
|
728
776
|
step "17z56. every MCP tool documented in CLAUDE.md (iter 93)"
|
|
@@ -742,12 +790,12 @@ for t in $TOOLS; do
|
|
|
742
790
|
grep -q "mcp__claude-flow__${t}" "$CMD" 2>/dev/null \
|
|
743
791
|
|| miss="$miss ${t}-not-in-claude-md"
|
|
744
792
|
done
|
|
745
|
-
#
|
|
746
|
-
#
|
|
747
|
-
#
|
|
748
|
-
#
|
|
749
|
-
#
|
|
750
|
-
[[ "$COUNT" == "
|
|
793
|
+
# Count derived from the wrapper source (mint deliberately excluded — see
|
|
794
|
+
# iter 73). The historical bump ladder (9→12→13→15) is gone: the extraction
|
|
795
|
+
# loop above and $EXPECTED_TOOLS both come from metaharness-tools.ts, so this
|
|
796
|
+
# equality only catches loop/derivation divergence; the REAL cross-surface
|
|
797
|
+
# check is the per-tool CLAUDE.md grep in the loop.
|
|
798
|
+
[[ "$COUNT" == "$EXPECTED_TOOLS" ]] || miss="$miss mcp-tool-count-stale:$COUNT-expected-$EXPECTED_TOOLS"
|
|
751
799
|
[[ -z "$miss" ]] && ok || bad "$miss"
|
|
752
800
|
|
|
753
801
|
step "17z55. MCP enum + SEVERITY_RANK vocabulary aligned (iter 92)"
|
|
@@ -822,11 +870,11 @@ for f in $REFS; do
|
|
|
822
870
|
COUNT=$((COUNT + 1))
|
|
823
871
|
[[ -f "$SCRIPTS_DIR/$f" ]] || miss="$miss mcp-script-${f}-missing"
|
|
824
872
|
done
|
|
825
|
-
#
|
|
826
|
-
#
|
|
827
|
-
#
|
|
828
|
-
#
|
|
829
|
-
[[ "$COUNT" == "
|
|
873
|
+
# One unique runScript() ref per MCP tool (mint deliberately excluded).
|
|
874
|
+
# Cross-aspect check: runScript('*.mjs') call sites vs the derived
|
|
875
|
+
# `name: 'metaharness_*'` declaration count in the same file — a handler
|
|
876
|
+
# added without a script ref (or vice-versa) diverges these.
|
|
877
|
+
[[ "$COUNT" == "$EXPECTED_TOOLS" ]] || miss="$miss mcp-script-count-stale:$COUNT-expected-$EXPECTED_TOOLS"
|
|
830
878
|
[[ -z "$miss" ]] && ok || bad "$miss"
|
|
831
879
|
|
|
832
880
|
step "17z52. SUBCOMMANDS map entries point at existing script files (iter 89)"
|
|
@@ -846,9 +894,10 @@ for f in $MAPPINGS; do
|
|
|
846
894
|
COUNT=$((COUNT + 1))
|
|
847
895
|
[[ -f "$SCRIPTS_DIR/$f" ]] || miss="$miss script-${f}-missing"
|
|
848
896
|
done
|
|
849
|
-
#
|
|
850
|
-
#
|
|
851
|
-
|
|
897
|
+
# SUBCOMMANDS map entry count vs the derived $EXPECTED_SUBS (same source,
|
|
898
|
+
# so this catches loop/derivation divergence; the real check is the per-file
|
|
899
|
+
# existence assertion in the loop above).
|
|
900
|
+
[[ "$COUNT" == "$EXPECTED_SUBS" ]] || miss="$miss mapping-count-stale:$COUNT-expected-$EXPECTED_SUBS"
|
|
852
901
|
[[ -z "$miss" ]] && ok || bad "$miss"
|
|
853
902
|
|
|
854
903
|
step "17z51. all metaharness scripts produce parseable JSON in --format json mode (iter 88)"
|
|
@@ -1401,10 +1450,13 @@ grep -q "iter 58 — reuse auditResult from the parallel batch" "$F" 2>/dev/null
|
|
|
1401
1450
|
|
|
1402
1451
|
step "17z20. iter-55 gaps B + C closed (iter 57)"
|
|
1403
1452
|
miss=""
|
|
1404
|
-
# Gap B:
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1453
|
+
# Gap B: the degraded-classification regex catches ENOTFOUND-class network
|
|
1454
|
+
# errors. Consolidation (2026-07) moved DEGRADED_RX to _invoke.mjs — check it
|
|
1455
|
+
# there, plus confirm _harness.mjs actually routes through the shared classifier.
|
|
1456
|
+
INVOKE="$ROOT/scripts/_invoke.mjs"
|
|
1457
|
+
grep -q "ENOTFOUND" "$INVOKE" 2>/dev/null || miss="$miss no-enotfound-regex"
|
|
1458
|
+
grep -q "getaddrinfo\|ECONNREFUSED\|ETIMEDOUT" "$INVOKE" 2>/dev/null || miss="$miss no-network-error-regex"
|
|
1459
|
+
grep -q "classifyDegraded" "$ROOT/scripts/_harness.mjs" 2>/dev/null || miss="$miss harness-not-using-shared-classifier"
|
|
1408
1460
|
# Gap C: drift-from-history probes oia-audit to disambiguate no-history vs dep-absent
|
|
1409
1461
|
DRIFT="$ROOT/scripts/drift-from-history.mjs"
|
|
1410
1462
|
grep -q "disambiguate" "$DRIFT" 2>/dev/null || miss="$miss no-disambiguate-comment"
|
|
@@ -1630,13 +1682,11 @@ CODE=$?
|
|
|
1630
1682
|
step "17z9. MCP success-semantic footnote + audit_trend file inputs (iter 46)"
|
|
1631
1683
|
miss=""
|
|
1632
1684
|
WRAPPER="$ROOT/../../v3/@claude-flow/cli/src/mcp-tools/metaharness-tools.ts"
|
|
1633
|
-
# Success-semantic constant declared + appended to N descriptions =
|
|
1634
|
-
#
|
|
1635
|
-
#
|
|
1636
|
-
# @metaharness/redblue integration added 1 more → 1 + 13 = 14.
|
|
1637
|
-
# learn + gepa (metaharness@0.3.0 / darwin@0.8.0) added 2 more → 1 + 15 = 16.
|
|
1685
|
+
# Success-semantic constant declared + appended to N tool descriptions =
|
|
1686
|
+
# N+1 occurrences. N is the derived tool count — cross-aspect check within
|
|
1687
|
+
# the wrapper: footnote appends vs `name:` declarations.
|
|
1638
1688
|
COUNT=$(grep -c "MCP_SUCCESS_SEMANTIC" "$WRAPPER" 2>/dev/null; true)
|
|
1639
|
-
[[ "$COUNT" == "
|
|
1689
|
+
[[ "$COUNT" == "$((EXPECTED_TOOLS + 1))" ]] || miss="$miss footnote-count:$COUNT-expected-$((EXPECTED_TOOLS + 1))"
|
|
1640
1690
|
# audit_trend now exposes baselineFile / currentFile
|
|
1641
1691
|
grep -q "baselineFile" "$WRAPPER" 2>/dev/null || miss="$miss no-baseline-file"
|
|
1642
1692
|
grep -q "currentFile" "$WRAPPER" 2>/dev/null || miss="$miss no-current-file"
|
|
@@ -1674,10 +1724,9 @@ grep -q "success = exitCode === 0" "$WRAPPER" 2>/dev/null || miss="$miss no-exit
|
|
|
1674
1724
|
COUNT_OLD=$(grep -c "success: !r.degraded" "$WRAPPER" 2>/dev/null; true)
|
|
1675
1725
|
[[ "$COUNT_OLD" == "0" ]] || miss="$miss old-pattern-still-present:$COUNT_OLD"
|
|
1676
1726
|
COUNT_NEW=$(grep -c "success: r.success" "$WRAPPER" 2>/dev/null; true)
|
|
1677
|
-
#
|
|
1678
|
-
#
|
|
1679
|
-
|
|
1680
|
-
[[ "$COUNT_NEW" == "15" ]] || miss="$miss new-pattern-count:$COUNT_NEW-expected-15"
|
|
1727
|
+
# One `success: r.success` per handler = the derived tool count. Cross-aspect
|
|
1728
|
+
# check within the wrapper: handler success-wiring vs `name:` declarations.
|
|
1729
|
+
[[ "$COUNT_NEW" == "$EXPECTED_TOOLS" ]] || miss="$miss new-pattern-count:$COUNT_NEW-expected-$EXPECTED_TOOLS"
|
|
1681
1730
|
# Runtime anchors: iter 44 success assertions present
|
|
1682
1731
|
T="$ROOT/scripts/test-mcp-tools.mjs"
|
|
1683
1732
|
grep -q "iter 44 fix" "$T" 2>/dev/null || miss="$miss no-iter44-anchors"
|
|
@@ -2041,9 +2090,11 @@ grep -q "result has 'exitCode'" "$F" || miss="$miss no-exitcode-assertion"
|
|
|
2041
2090
|
for tool in metaharness_score metaharness_genome metaharness_mcp_scan metaharness_threat_model metaharness_oia_audit metaharness_audit_list metaharness_audit_trend metaharness_similarity metaharness_drift_from_history metaharness_bench metaharness_evolve metaharness_security_bench metaharness_redblue metaharness_learn metaharness_gepa; do
|
|
2042
2091
|
grep -q "${tool}" "$F" || miss="$miss missing-${tool}"
|
|
2043
2092
|
done
|
|
2044
|
-
#
|
|
2045
|
-
#
|
|
2046
|
-
|
|
2093
|
+
# test-mcp-tools.mjs keeps its own hardcoded `tools.length === N` literal —
|
|
2094
|
+
# it is the RUNTIME side of the cross-check. This grep derives N from the
|
|
2095
|
+
# wrapper source, so adding a tool without bumping the test literal fails
|
|
2096
|
+
# here (independent surfaces compared, per the derived-counts contract).
|
|
2097
|
+
grep -q "tools.length === $EXPECTED_TOOLS" "$F" || miss="$miss tool-count-assertion-stale:expected-tools.length===$EXPECTED_TOOLS"
|
|
2047
2098
|
# Graceful skip when dist absent (so the script is smoke-runnable pre-build)
|
|
2048
2099
|
grep -q "SKIPPED" "$F" || miss="$miss no-skip-doc"
|
|
2049
2100
|
[[ -z "$miss" ]] && ok || bad "$miss"
|
|
@@ -31,11 +31,21 @@
|
|
|
31
31
|
// 2 setup error
|
|
32
32
|
|
|
33
33
|
import { spawnSync } from 'node:child_process';
|
|
34
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
35
|
+
import { tmpdir } from 'node:os';
|
|
34
36
|
import { dirname, join } from 'node:path';
|
|
35
37
|
import { fileURLToPath } from 'node:url';
|
|
36
38
|
|
|
37
39
|
const SCRIPTS_DIR = dirname(fileURLToPath(import.meta.url));
|
|
38
40
|
|
|
41
|
+
// Since the versioned-cache consolidation (_invoke.mjs), a warm
|
|
42
|
+
// ~/.ruflo/<pkg>-cache-<pin> or a locally installed metaharness would satisfy
|
|
43
|
+
// resolution WITHOUT touching the (unreachable) registry — making this drill
|
|
44
|
+
// vacuous on developer machines. Point the cache base at an empty temp dir
|
|
45
|
+
// and disable local walk-up resolution so the install path (and therefore
|
|
46
|
+
// the degraded contract) is actually exercised.
|
|
47
|
+
const EMPTY_CACHE_BASE = mkdtempSync(join(tmpdir(), 'ruflo-degradation-drill-'));
|
|
48
|
+
|
|
39
49
|
const ARGS = (() => {
|
|
40
50
|
const a = { keep: false };
|
|
41
51
|
for (let i = 2; i < process.argv.length; i++) {
|
|
@@ -61,6 +71,8 @@ function runWithUnreachableRegistry(scriptName, extraArgs) {
|
|
|
61
71
|
...process.env,
|
|
62
72
|
npm_config_registry: UNREACHABLE_REGISTRY,
|
|
63
73
|
NPM_CONFIG_REGISTRY: UNREACHABLE_REGISTRY,
|
|
74
|
+
RUFLO_METAHARNESS_CACHE_BASE: EMPTY_CACHE_BASE,
|
|
75
|
+
RUFLO_METAHARNESS_SKIP_LOCAL: '1',
|
|
64
76
|
},
|
|
65
77
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
66
78
|
encoding: 'utf-8',
|
|
@@ -137,6 +149,10 @@ function main() {
|
|
|
137
149
|
assert(/"degraded"\s*:\s*true/.test(r.stdout), `${s.name} emits "degraded": true`);
|
|
138
150
|
}
|
|
139
151
|
|
|
152
|
+
if (!ARGS.keep) {
|
|
153
|
+
try { rmSync(EMPTY_CACHE_BASE, { recursive: true, force: true }); } catch { /* best-effort */ }
|
|
154
|
+
}
|
|
155
|
+
|
|
140
156
|
console.log(`\n${passed} passed, ${failed} failed`);
|
|
141
157
|
if (failed > 0) {
|
|
142
158
|
console.log('\nFailures:');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: harness-evolve
|
|
3
3
|
description: Run `@metaharness/darwin evolve <repo>` to mutate a harness's seven policy surfaces (planner/contextBuilder/reviewer/retryPolicy/toolPolicy/memoryPolicy/scorePolicy), sandbox-score each variant, and promote only measured wins. The model is frozen; the harness evolves. Closes the loop ADR-150 opens (score+genome describe; evolve changes). Degrades gracefully when @metaharness/darwin is absent (ADR-150 + ADR-153 architectural constraints).
|
|
4
|
-
argument-hint: "--repo <path> [--generations 3] [--children 3] [--concurrency 2] [--sandbox real|mock|agent] [--selection pareto|quality-diversity|...] [--mutator deterministic|ruvllm] [--confirm]"
|
|
4
|
+
argument-hint: "--repo <path> [--generations 3] [--children 3] [--concurrency 2] [--sandbox real|mock|agent] [--selection pareto|quality-diversity|...] [--mutator deterministic|ruvllm] [--diagnose] [--confirm]"
|
|
5
5
|
allowed-tools: Bash
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -73,7 +73,46 @@ Reports land under `<repo>/.metaharness/`:
|
|
|
73
73
|
reports/winner.json # final champion + score delta vs parent
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
Skill stdout = JSON `{success, data: {champion, plan, durationMs, improved}}
|
|
76
|
+
Skill stdout = JSON `{success, data: {champion, plan, durationMs, improved}}`
|
|
77
|
+
(plus `data.diagnosis` when `--diagnose` is passed — see below).
|
|
78
|
+
|
|
79
|
+
## Failure diagnosis (`--diagnose`)
|
|
80
|
+
|
|
81
|
+
GEPA's key trick is natural-language failure diagnosis from execution traces
|
|
82
|
+
feeding the next mutation — not just scalar fitness. `--diagnose` adds a
|
|
83
|
+
modest slice of that: after the evolution completes, the losing / failed
|
|
84
|
+
variants' transcripts are run through darwin's GEPA library ops
|
|
85
|
+
(`analyzeTranscript` + `classifyFailure`, via the shared `importGepa`
|
|
86
|
+
resolver in `scripts/_darwin.mjs`) and a `diagnosis` section is appended to
|
|
87
|
+
the emitted JSON:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
"diagnosis": {
|
|
91
|
+
"available": true,
|
|
92
|
+
"scope": "losing-variants",
|
|
93
|
+
"variants": [
|
|
94
|
+
{ "id": "g1_v0", "transcripts": 2,
|
|
95
|
+
"failureClasses": { "exploration-loop": 1, "edit-mechanics": 1 },
|
|
96
|
+
"dominantClass": "exploration-loop" }
|
|
97
|
+
],
|
|
98
|
+
"totals": { "exploration-loop": 1, "edit-mechanics": 1 }
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Upstream shape caveats (verified against `@metaharness/darwin@0.8.0`):
|
|
103
|
+
|
|
104
|
+
- `metaharness-darwin evolve --json` prints a TEXT leaderboard — the stdout
|
|
105
|
+
carries no JSON and no transcripts. Per-variant run records live at
|
|
106
|
+
`<repo>/.metaharness/runs/<id>.json`.
|
|
107
|
+
- Those run records hold sandbox exec traces (`{taskId, exitCode, stdout,
|
|
108
|
+
stderr}`), which are NOT GEPA `{actionRaw, obs}` transcripts. Diagnosis
|
|
109
|
+
therefore uses GEPA-shaped transcripts when a run record embeds them
|
|
110
|
+
(agent sandbox / future upstream), falls back to the champion's transcript,
|
|
111
|
+
and otherwise emits `diagnosis: {available: false, reason, traceSummary}`
|
|
112
|
+
where `traceSummary` is a mechanical per-variant tally (tasks / failed /
|
|
113
|
+
timedOut / blockedActions).
|
|
114
|
+
- `--diagnose` NEVER fails the run — any internal error degrades to
|
|
115
|
+
`{available: false, reason: "diagnosis-failed: ..."}`.
|
|
77
116
|
|
|
78
117
|
## Exit codes
|
|
79
118
|
|
|
@@ -41,8 +41,10 @@ ADR-235 follow-up and not available yet.
|
|
|
41
41
|
Implementation: [`scripts/learn.mjs`](../../scripts/learn.mjs).
|
|
42
42
|
|
|
43
43
|
1. Validate `--repo` exists when given; export it as `$METAHARNESS_REPO`.
|
|
44
|
-
2.
|
|
45
|
-
|
|
44
|
+
2. Invoke the pinned `metaharness` binary (`metaharness@~0.3.0`, local install
|
|
45
|
+
or one-time versioned cache — never `@latest`): `metaharness learn --host <h>
|
|
46
|
+
--model <m> --slice <s> [--run]` via `_harness.mjs` (graceful degradation,
|
|
47
|
+
hard timeout).
|
|
46
48
|
3. Default timeouts: 120s dry-run, 600s with `--run` — real runs on larger
|
|
47
49
|
slices need an explicit `--timeout-ms` matched to slice size × model cost.
|
|
48
50
|
4. Detect the checkout-required message → structured payload, exit 0.
|
|
@@ -13,7 +13,9 @@ tool; pure static analysis.
|
|
|
13
13
|
|
|
14
14
|
Implementation: [`scripts/mcp-scan.mjs`](../../scripts/mcp-scan.mjs).
|
|
15
15
|
|
|
16
|
-
1.
|
|
16
|
+
1. Invoke the pinned `harness` binary (`metaharness@~0.3.0`, resolved from a
|
|
17
|
+
local install or the one-time `~/.ruflo/metaharness-cache-<pin>` cache —
|
|
18
|
+
never `@latest`): `harness mcp-scan <path> --json`.
|
|
17
19
|
2. Parse `findings[]` with `{ severity, id, server, tool, message }`.
|
|
18
20
|
3. `--fail-on <severity>`: exit 1 when any finding is at or above that
|
|
19
21
|
level. Default `high`.
|
|
@@ -58,7 +58,7 @@ no network, registry unreachable), the script emits:
|
|
|
58
58
|
{
|
|
59
59
|
"degraded": true,
|
|
60
60
|
"reason": "metaharness-not-available",
|
|
61
|
-
"hint": "Install
|
|
61
|
+
"hint": "Install with `npm i -D metaharness@~0.3.0` (pinned range — this plugin never fetches @latest) or verify network access for the one-time cache install."
|
|
62
62
|
}
|
|
63
63
|
```
|
|
64
64
|
|
|
@@ -13,7 +13,9 @@ categorized report suitable for sharing with an InfoSec team.
|
|
|
13
13
|
|
|
14
14
|
Implementation: [`scripts/threat-model.mjs`](../../scripts/threat-model.mjs).
|
|
15
15
|
|
|
16
|
-
1.
|
|
16
|
+
1. Invoke the pinned `harness` binary (`metaharness@~0.3.0`, resolved from a
|
|
17
|
+
local install or the one-time `~/.ruflo/metaharness-cache-<pin>` cache —
|
|
18
|
+
never `@latest`): `harness threat-model <path> --json`.
|
|
17
19
|
2. Parse `{ worst, findings[] }`.
|
|
18
20
|
3. `--fail-on <severity>`: exit 1 when `worst >= fail-on`. Default `high`.
|
|
19
21
|
|