23f7624596
ADR-166 MCP Bridge Security Lock / Static-source security lock (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / Compose default binds loopback + Mongo has auth (push) Failing after 2s
CodeQL Advanced / Analyze (rust) (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / plugin-agent-federation bindHost default (push) Failing after 1s
ADR-166 MCP Bridge Security Lock / Runtime behavior — 401 + terminal gate + fail-closed (push) Failing after 4s
business-pods-smoke / smoke (push) Failing after 1s
all-plugins-smoke / smoke-all (push) Failing after 2s
CI/CD Pipeline / Security & Code Quality (push) Failing after 1s
CI/CD Pipeline / Test Suite (ubuntu-latest) (push) Failing after 1s
CI/CD Pipeline / Build & Package (macos-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (ubuntu-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (windows-latest) (push) Has been skipped
CI/CD Pipeline / Documentation & Examples (push) Failing after 1s
Clone Tracker (14-day rolling) / Snapshot clones for ruflo ecosystem (push) Failing after 1s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
federation-peer-rust / stable-noop (push) Failing after 1s
metaharness-ci / score (push) Failing after 1s
metaharness-ci / router-compat (push) Failing after 0s
metaharness-ci / similarity-tests (push) Failing after 0s
no-agentbbs-smoke / smoke-without-agentbbs (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (windows-latest) (push) Has been skipped
codex-integration-audit / Codex integration audit (push) Failing after 1s
helpers-manifest-guard / guard (push) Failing after 1s
🔗 Cross-Agent Integration Tests / 🤝 Agent Coordination Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🧠 Memory Sharing Integration (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🛡️ Fault Tolerance Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / ⚡ Performance Integration Tests (push) Has been skipped
metaharness-ci / mcp-scan (push) Failing after 1s
metaharness-ci / eject-dryrun (push) Failing after 1s
metaharness-ci / metaharness-real-data (push) Failing after 0s
no-cli-optdep-bloat-2561 / guard (push) Failing after 1s
no-metaharness-smoke / smoke-without-metaharness (push) Failing after 1s
no-phantom-agentic-flow-subpath / guard (push) Failing after 1s
🔄 Automated Rollback Manager / 🚨 Failure Detection (push) Failing after 1s
V3 CI/CD Pipeline / Plugin hooks smoke / ubuntu-latest / Node 22 (push) Failing after 1s
V3 CI/CD Pipeline / ruflo-graph-intelligence build + test smoke (#2044, ADR-123) (push) Failing after 1s
CVE Audit Gate / Audit root (critical-blocking) (push) Failing after 2s
cost-tracker-smoke / smoke (push) Failing after 3s
oia-audit-weekly / audit (push) Failing after 2s
ruflo-agent-smoke / ruflo-agent structural smoke (push) Failing after 1s
📊 Status Badges Update / 📊 Update Status Badges (push) Failing after 1s
V3 CI/CD Pipeline / Static regression guards (#2267 YAML + (push) Failing after 1s
V3 CI/CD Pipeline / Test V3 Packages (push) Failing after 0s
V3 CI/CD Pipeline / agent_execute provider routing smoke (#2042) (push) Failing after 0s
CVE Audit Gate / Audit v3 (critical-blocking) (push) Failing after 1s
federation-peer-rust / stable-native (push) Failing after 2s
🔗 Cross-Agent Integration Tests / 🚀 Integration Test Setup (push) Failing after 2s
neural-trader-smoke / runtime-smoke (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (macos-latest) (push) Has been skipped
V3 CI/CD Pipeline / Build V3 (ubuntu-latest) (push) Has been skipped
V3 CI/CD Pipeline / Type Check V3 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 24 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 22 (push) Failing after 2s
V3 CI/CD Pipeline / browser rvf create flag smoke (#2015) (push) Failing after 0s
V3 CI/CD Pipeline / Dependency review (#2046) (push) Has been skipped
V3 CI/CD Pipeline / Supply-chain audit (#2046) (push) Failing after 0s
V3 CI/CD Pipeline / witness marker drift smoke (#2021) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader backtest signing smoke (#2068, ADR-126 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / kg-extract type-import classification smoke (#2049) (push) Failing after 0s
V3 CI/CD Pipeline / witness verify precondition smoke (#1880) (push) Failing after 2s
V3 CI/CD Pipeline / neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5) (push) Failing after 0s
V3 CI/CD Pipeline / neural-trader feature attribution smoke (#2068, ADR-126 Phase 6) (push) Failing after 0s
V3 CI/CD Pipeline / plugin-registry signature verification smoke (#1922, CWE-347) (push) Failing after 4s
V3 CI/CD Pipeline / memory stats legacy-DB smoke (#2120) (push) Failing after 4s
V3 CI/CD Pipeline / github deprecated actions smoke (#2089, ADR-127 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / graph query + pathfinder smoke (ADR-130 P2+P5) (push) Has been skipped
V3 CI/CD Pipeline / graph trajectory hooks smoke (ADR-130 P3) (push) Has been skipped
V3 CI/CD Pipeline / graph plugin adapter smoke (ADR-130 P4) (push) Has been skipped
V3 CI/CD Pipeline / graph benchmark (ADR-130 P6) (push) Has been skipped
V3 CI/CD Pipeline / statusline generator delegation smoke (#2195) (push) Failing after 1s
V3 CI/CD Pipeline / wizard init regression guard (#2206 (push) Failing after 1s
V3 CI/CD Pipeline / memory no-stray-db smoke (ADR-125 P7) (push) Failing after 1s
V3 CI/CD Pipeline / github-safe injection smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github actions pin smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github attribution opt-in smoke (#2089, ADR-127 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / pre-bash hook safety smoke (#2017) (push) Failing after 1s
V3 CI/CD Pipeline / Memory import smoke / ubuntu-latest (push) Failing after 0s
V3 CI/CD Pipeline / MCP protocol smoke / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / ruvllm WASM auto-init smoke (#2086) (push) Failing after 4s
V3 CI/CD Pipeline / MCP paired-tool round-trip smoke (#1889) (push) Failing after 1s
V3 CI/CD Pipeline / Plugin package install-safety (#1902/#1903/#1904) (push) Failing after 1s
V3 CI/CD Pipeline / Tool description discoverability (ADR-112) (push) Failing after 3s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (22) (push) Failing after 1s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (24) (push) Failing after 1s
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Vector-index dimension audit (#1947) (push) Failing after 0s
V3 CI/CD Pipeline / Hook-command install safety (#1921) (push) Failing after 1s
V3 CI/CD Pipeline / ToolOutputGuardrail smoke (ADR-131, (push) Failing after 1s
V3 CI/CD Pipeline / init-bundle invariants smoke (#2095, ADR-128 Phase 5) (push) Failing after 1s
V3 CI/CD Pipeline / wasm provider bridge smoke (ADR-129 P1) (push) Failing after 2s
V3 CI/CD Pipeline / wasm gallery CRUD smoke (ADR-129 P3) (push) Failing after 1s
V3 CI/CD Pipeline / wasm plugin bridge smoke (ADR-129 P4) (push) Failing after 0s
V3 CI/CD Pipeline / wasm compose smoke (ADR-129 P2) (push) Failing after 4s
V3 CI/CD Pipeline / graph schema smoke (ADR-130 P1) (push) Failing after 0s
Validate Marketplace / validate (push) Failing after 1s
🔍 Verification Pipeline / 🚀 Setup Verification (push) Failing after 1s
🔍 Verification Pipeline / 🛡️ Security Verification (push) Has been skipped
🔍 Verification Pipeline / 📝 Code Quality (push) Has been skipped
🔍 Verification Pipeline / 🧪 Test Verification (${{ matrix.os }}, Node ${{ matrix.node }}) (push) Has been skipped
🔍 Verification Pipeline / 🏗️ Build Verification (push) Has been skipped
🔍 Verification Pipeline / 📚 Documentation Verification (push) Has been skipped
CVE Audit Gate / High-severity report (warn only) (push) Has been cancelled
🔄 Automated Rollback Manager / 🔄 Execute Rollback (push) Has been cancelled
🔄 Automated Rollback Manager / ✅ Post-Rollback Verification (push) Has been cancelled
🔄 Automated Rollback Manager / 📊 Rollback Monitoring (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / windows-latest (push) Has been cancelled
🔄 Automated Rollback Manager / ⏳ Manual Rollback Approval (push) Has been cancelled
V3 CI/CD Pipeline / MCP protocol smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Memory import smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / ubuntu-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Publish to npm (alpha) (push) Has been cancelled
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / macos-latest / Node 22 (push) Has been cancelled
V3 CI/CD Pipeline / Plugin hooks smoke / macos-latest / Node 22 (push) Has been cancelled
CI/CD Pipeline / Deploy & Release (push) Has been cancelled
CI/CD Pipeline / CI Status (push) Has been cancelled
🔗 Cross-Agent Integration Tests / 📊 Integration Test Report (push) Has been cancelled
🔄 Automated Rollback Manager / 🔍 Pre-Rollback Validation (push) Has been cancelled
🔍 Verification Pipeline / ⚡ Performance Verification (push) Has been cancelled
🔍 Verification Pipeline / 📊 Verification Report (push) Has been cancelled
221 lines
9.0 KiB
TypeScript
221 lines
9.0 KiB
TypeScript
/**
|
|
* ADR-174 Milestone 4 — self-optimization harness ("ruflo tuning ruflo").
|
|
*
|
|
* Proves `tuneDistillation`:
|
|
* - scores every grid point via runDistillation (M1, frozen) on isolated
|
|
* temp copies, never the source DB;
|
|
* - splits train/held-out by rowid with no overlap;
|
|
* - picks a winner by train score and scores it once on the true held-out
|
|
* set;
|
|
* - never mutates the source DB (checksum unchanged);
|
|
* - persists the winning config to a plain JSON-shaped object.
|
|
*/
|
|
import { describe, it, expect, beforeAll } from 'vitest';
|
|
import { mkdtempSync, readFileSync, existsSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { tmpdir } from 'node:os';
|
|
import { createHash } from 'node:crypto';
|
|
|
|
import {
|
|
tuneDistillation,
|
|
computeTimeSplit,
|
|
buildTunedConfigFile,
|
|
writeTunedConfigFile,
|
|
defaultTunedConfigPath,
|
|
DEFAULT_GRID_BATCH_SIZE,
|
|
DEFAULT_GRID_DEDUP_DISTANCE,
|
|
DEFAULT_GRID_PROMOTE_THRESHOLD,
|
|
} from '../src/services/distill-tuning.js';
|
|
|
|
let Database: any;
|
|
let haveNative = false;
|
|
try {
|
|
Database = (await import('better-sqlite3')).default;
|
|
haveNative = true;
|
|
} catch {
|
|
haveNative = false;
|
|
}
|
|
|
|
const TOPICS = [
|
|
{ label: 'auth', path: 'src/auth.ts', text: 'refactor the auth module in src/auth.ts to validate tokens' },
|
|
{ label: 'api', path: 'src/api/handler.ts', text: 'add validation to src/api/handler.ts for malformed input' },
|
|
{ label: 'db', path: 'src/db/store.ts', text: 'optimize the query in src/db/store.ts to cache results' },
|
|
{ label: 'memory', path: 'src/memory/bridge.ts', text: 'fix the memory leak in src/memory/bridge.ts on close' },
|
|
{ label: 'test', path: 'src/tests/runner.ts', text: 'debug the flaky test in src/tests/runner.ts and stub it' },
|
|
];
|
|
|
|
/** Deterministic per-topic vector cluster with a bit of jitter per row. */
|
|
function vec(topicIndex: number, jitterSeed: number): number[] {
|
|
return Array.from({ length: 16 }, (_, i) => Math.sin(topicIndex * 10 + i) + 0.01 * Math.sin(jitterSeed + i));
|
|
}
|
|
|
|
/** Build a fixture DB with the source + agentdb target schemas (M1's shape). */
|
|
function seedDb(dbPath: string, rowCount: number): void {
|
|
const db = new Database(dbPath);
|
|
db.exec(`CREATE TABLE memory_entries (
|
|
id TEXT PRIMARY KEY, key TEXT, namespace TEXT DEFAULT 'default',
|
|
content TEXT, embedding TEXT, status TEXT DEFAULT 'active'
|
|
)`);
|
|
db.exec(`CREATE TABLE episodes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, ts INTEGER DEFAULT 0, session_id TEXT NOT NULL,
|
|
task TEXT NOT NULL, input TEXT, output TEXT, critique TEXT, reward REAL DEFAULT 0,
|
|
success BOOLEAN DEFAULT 0, latency_ms INTEGER, tokens_used INTEGER, tags TEXT,
|
|
metadata JSON, created_at INTEGER DEFAULT 0
|
|
)`);
|
|
db.exec(`CREATE TABLE reasoning_patterns (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, ts INTEGER DEFAULT 0, task_type TEXT NOT NULL,
|
|
approach TEXT NOT NULL, success_rate REAL NOT NULL DEFAULT 0, uses INTEGER DEFAULT 0,
|
|
avg_reward REAL DEFAULT 0, tags TEXT, metadata TEXT
|
|
)`);
|
|
db.exec(`CREATE TABLE pattern_embeddings (
|
|
pattern_id INTEGER PRIMARY KEY, embedding BLOB NOT NULL
|
|
)`);
|
|
db.exec(`CREATE TABLE causal_edges (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, from_memory_id INTEGER NOT NULL, from_memory_type TEXT NOT NULL,
|
|
to_memory_id INTEGER NOT NULL, to_memory_type TEXT NOT NULL, similarity REAL DEFAULT 0,
|
|
confidence REAL DEFAULT 0.5, mechanism TEXT, metadata JSON, created_at INTEGER DEFAULT 0
|
|
)`);
|
|
|
|
const ins = db.prepare('INSERT INTO memory_entries (id, key, namespace, content, embedding) VALUES (?,?,?,?,?)');
|
|
const commit = db.transaction(() => {
|
|
for (let i = 0; i < rowCount; i++) {
|
|
const topicIndex = i % TOPICS.length;
|
|
const topic = TOPICS[topicIndex];
|
|
const namespace = i % 3 === 0 ? 'feedback' : 'commands';
|
|
const content =
|
|
namespace === 'feedback'
|
|
? JSON.stringify({ taskId: `t${i}`, success: i % 2 === 0, note: topic.text })
|
|
: `${topic.text} (row ${i})`;
|
|
ins.run(`row-${i}`, `k${i}`, namespace, content, JSON.stringify(vec(topicIndex, i)));
|
|
}
|
|
});
|
|
commit();
|
|
db.close();
|
|
}
|
|
|
|
function sha256(p: string): string {
|
|
return createHash('sha256').update(readFileSync(p)).digest('hex');
|
|
}
|
|
|
|
describe.skipIf(!haveNative)('tuneDistillation — Milestone 4 self-optimization harness', () => {
|
|
let workdir: string;
|
|
beforeAll(() => {
|
|
workdir = mkdtempSync(join(tmpdir(), 'distill-tune-'));
|
|
});
|
|
|
|
it('exposes the ADR-174 default grid (batchSize x dedupDistance x promoteThreshold)', () => {
|
|
expect(DEFAULT_GRID_BATCH_SIZE).toEqual([100, 200, 500]);
|
|
expect(DEFAULT_GRID_DEDUP_DISTANCE).toEqual([0.05, 0.1, 0.15, 0.2, 0.3]);
|
|
expect(DEFAULT_GRID_PROMOTE_THRESHOLD).toEqual(['execution-only', 'execution+corroborated']);
|
|
});
|
|
|
|
it(
|
|
'scores every grid point, picks a winner, and scores held-out exactly once',
|
|
async () => {
|
|
const dbPath = join(workdir, 'main.db');
|
|
seedDb(dbPath, 90);
|
|
const before = sha256(dbPath);
|
|
|
|
const report = await tuneDistillation({
|
|
dbPath,
|
|
grid: {
|
|
batchSize: [50, 200],
|
|
dedupDistance: [0.1, 0.2],
|
|
promoteThreshold: ['execution-only', 'execution+corroborated'],
|
|
},
|
|
tmpDir: join(workdir, 'tmp'),
|
|
now: 1750000000000,
|
|
});
|
|
|
|
// All grid points scored.
|
|
expect(report.candidates.length).toBe(2 * 2 * 2);
|
|
for (const c of report.candidates) {
|
|
expect(typeof c.trainScore).toBe('number');
|
|
expect(c.trainScore).toBeGreaterThanOrEqual(0);
|
|
}
|
|
|
|
// Winner is a real candidate with the best train score among scored ones.
|
|
const scored = report.candidates.filter((c) => !c.skipped);
|
|
const maxScore = Math.max(...scored.map((c) => c.trainScore));
|
|
expect(report.winner.trainScore).toBe(maxScore);
|
|
expect(report.candidates).toContainEqual(report.winner);
|
|
|
|
// Held-out scored once, with its own query count and a baseline comparison.
|
|
expect(report.heldOut.queryCount).toBeGreaterThan(0);
|
|
expect(typeof report.heldOut.mrrAt10).toBe('number');
|
|
expect(typeof report.heldOut.baselineMrrAt10).toBe('number');
|
|
expect(typeof report.overfit).toBe('boolean');
|
|
|
|
// Provenance is stamped from the caller-supplied `now`, not Date.now().
|
|
expect(report.provenance.tunedAt).toBe(1750000000000);
|
|
expect(report.provenance.gridSize).toBe(8);
|
|
expect(report.provenance.trainSize + report.provenance.heldOutSize).toBe(report.provenance.corpusSize);
|
|
|
|
// Source DB byte-for-byte unchanged.
|
|
const after = sha256(dbPath);
|
|
expect(after).toBe(before);
|
|
expect(report.provenance.sourceChecksumSha256).toBe(after);
|
|
},
|
|
30000,
|
|
);
|
|
|
|
it('splits train/held-out by rowid with no overlap', () => {
|
|
const dbPath = join(workdir, 'split.db');
|
|
seedDb(dbPath, 40);
|
|
const db = new Database(dbPath, { readonly: true });
|
|
try {
|
|
const split = computeTimeSplit(db, 0.8);
|
|
expect(split.totalRows).toBe(40);
|
|
expect(split.trainRowids.length + split.heldOutRowids.length).toBe(40);
|
|
const trainSet = new Set(split.trainRowids);
|
|
const overlap = split.heldOutRowids.filter((r) => trainSet.has(r));
|
|
expect(overlap).toEqual([]);
|
|
// Earliest ~80% is train: every train rowid precedes every held-out rowid.
|
|
expect(Math.max(...split.trainRowids)).toBeLessThan(Math.min(...split.heldOutRowids));
|
|
} finally {
|
|
db.close();
|
|
}
|
|
});
|
|
|
|
it('flags overfitting only when held-out is meaningfully worse than train', async () => {
|
|
const dbPath = join(workdir, 'overfit.db');
|
|
seedDb(dbPath, 60);
|
|
const report = await tuneDistillation({
|
|
dbPath,
|
|
grid: { batchSize: [50], dedupDistance: [0.1], promoteThreshold: ['execution-only'] },
|
|
tmpDir: join(workdir, 'tmp2'),
|
|
now: 1750000000001,
|
|
});
|
|
// Deterministic check on the documented rule, not a specific outcome
|
|
// (which depends on the synthetic corpus): overfit iff heldOut < 0.8*train.
|
|
const expected = report.winner.trainScore > 0 && report.heldOut.mrrAt10 < report.winner.trainScore * 0.8;
|
|
expect(report.overfit).toBe(expected);
|
|
});
|
|
|
|
it('builds a persistable config artifact carrying provenance', async () => {
|
|
const dbPath = join(workdir, 'persist.db');
|
|
seedDb(dbPath, 50);
|
|
const report = await tuneDistillation({
|
|
dbPath,
|
|
grid: { batchSize: [100], dedupDistance: [0.15], promoteThreshold: ['execution-only'] },
|
|
tmpDir: join(workdir, 'tmp3'),
|
|
now: 1750000000002,
|
|
});
|
|
|
|
const artifact = buildTunedConfigFile(report);
|
|
expect(artifact.batchSize).toBe(100);
|
|
expect(artifact.dedupDistance).toBe(0.15);
|
|
expect(artifact.promoteThreshold).toBe('execution-only');
|
|
expect(artifact.provenance.tunedAt).toBe(1750000000002);
|
|
expect(artifact.provenance.winnerTrainScore).toBe(report.winner.trainScore);
|
|
|
|
const outPath = join(workdir, 'out', 'distill-tuned.json');
|
|
writeTunedConfigFile(report, outPath);
|
|
expect(existsSync(outPath)).toBe(true);
|
|
const written = JSON.parse(readFileSync(outPath, 'utf8'));
|
|
expect(written).toEqual(artifact);
|
|
|
|
expect(defaultTunedConfigPath('/tmp/some-project')).toBe(join('/tmp/some-project', '.claude-flow', 'distill-tuned.json'));
|
|
});
|
|
});
|