Ferrell Synthetic Intelligence commited on
Commit ·
5232c15
1
Parent(s): c3360ca
Add Task Replay and Model Arena
Browse files- app.js +13 -0
- benchmarks/arena.mjs +6 -0
- benchmarks/test-arena.mjs +5 -0
- daemon/replay-store.mjs +17 -0
- daemon/server.mjs +18 -1
- daemon/test-replay-store.mjs +9 -0
- package.json +2 -1
- replays/README.md +3 -0
- replays/store.json +1 -0
app.js
CHANGED
|
@@ -165,6 +165,7 @@ async function runReview() {
|
|
| 165 |
} catch (error) {
|
| 166 |
appendLog('STOPPED', error.message, 'warning');
|
| 167 |
} finally {
|
|
|
|
| 168 |
$('#review-button').disabled = false;
|
| 169 |
$('#review-button').textContent = 'START BOUNDED REVIEW';
|
| 170 |
}
|
|
@@ -342,6 +343,17 @@ async function refreshTrainingStatus() {
|
|
| 342 |
} catch { /* daemon is optional while the static shell is offline */ }
|
| 343 |
}
|
| 344 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 345 |
async function digestFile(file) {
|
| 346 |
const buffer = await file.arrayBuffer();
|
| 347 |
const digest = await crypto.subtle.digest('SHA-256', buffer);
|
|
@@ -410,6 +422,7 @@ async function boot() {
|
|
| 410 |
$('#debug-file').onclick = debugActiveFile;
|
| 411 |
$('#training-verify').onclick = () => trainingRequest('start', { id: 'verify-release', approved: true });
|
| 412 |
$('#training-stop').onclick = () => trainingRequest('stop');
|
|
|
|
| 413 |
refreshTrainingStatus();
|
| 414 |
setInterval(refreshTrainingStatus, 5000);
|
| 415 |
loadCommunity();
|
|
|
|
| 165 |
} catch (error) {
|
| 166 |
appendLog('STOPPED', error.message, 'warning');
|
| 167 |
} finally {
|
| 168 |
+
await saveReplay('review-complete');
|
| 169 |
$('#review-button').disabled = false;
|
| 170 |
$('#review-button').textContent = 'START BOUNDED REVIEW';
|
| 171 |
}
|
|
|
|
| 343 |
} catch { /* daemon is optional while the static shell is offline */ }
|
| 344 |
}
|
| 345 |
|
| 346 |
+
async function saveReplay(status = 'verified') {
|
| 347 |
+
try { await fetch('http://127.0.0.1:4777/api/replays', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ task_class: 'code-change', model: state.selected?.id || 'unknown', status, checks: { human_approval_required: true, source_exported: false } }) }); } catch { /* replay is optional while daemon is offline */ }
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
async function compareModels() {
|
| 351 |
+
const scores = { 'smollm2-360m-q8': 0.667, 'qwen-coder-0.5b-q4': 0.667, 'qwen-coder-1.5b-q4': 0.667 };
|
| 352 |
+
const winner = Object.entries(scores).sort((a, b) => b[1] - a[1])[0];
|
| 353 |
+
$('#arena-status').textContent = `Smoke winner: ${winner[0]} (${(winner[1] * 100).toFixed(1)}%). Equal tie; use role and memory to choose.`;
|
| 354 |
+
appendLog('MODEL ARENA', 'Comparison uses the recorded live smoke scorecard; no general capability claim.');
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
async function digestFile(file) {
|
| 358 |
const buffer = await file.arrayBuffer();
|
| 359 |
const digest = await crypto.subtle.digest('SHA-256', buffer);
|
|
|
|
| 422 |
$('#debug-file').onclick = debugActiveFile;
|
| 423 |
$('#training-verify').onclick = () => trainingRequest('start', { id: 'verify-release', approved: true });
|
| 424 |
$('#training-stop').onclick = () => trainingRequest('stop');
|
| 425 |
+
$('#arena-button').onclick = compareModels;
|
| 426 |
refreshTrainingStatus();
|
| 427 |
setInterval(refreshTrainingStatus, 5000);
|
| 428 |
loadCommunity();
|
benchmarks/arena.mjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { promises as fs } from 'node:fs';
|
| 2 |
+
import path from 'node:path';
|
| 3 |
+
const file = process.argv[2] || path.join(process.cwd(), 'benchmarks/live-results-2026-08-10.json');
|
| 4 |
+
const data = JSON.parse(await fs.readFile(file, 'utf8'));
|
| 5 |
+
const ranking = data.results.map(row => ({ model: row.model, score: row.score, failed: row.failed })).sort((a, b) => b.score - a.score);
|
| 6 |
+
console.log(JSON.stringify({ suite: data.suite, ranking, winner: ranking[0] || null, rule: 'Winner is benchmark-local only; never infer general intelligence from this smoke suite.' }, null, 2));
|
benchmarks/test-arena.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import assert from 'node:assert/strict';
|
| 2 |
+
import { execFile } from 'node:child_process';
|
| 3 |
+
import { promisify } from 'node:util';
|
| 4 |
+
const run = promisify(execFile); const { stdout } = await run(process.execPath, ['benchmarks/arena.mjs'], { cwd: process.cwd() });
|
| 5 |
+
const result = JSON.parse(stdout); assert.equal(result.ranking.length, 3); assert.equal(result.winner.score, 0.667); console.log('arena test passed');
|
daemon/replay-store.mjs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { promises as fs } from 'node:fs';
|
| 2 |
+
import path from 'node:path';
|
| 3 |
+
|
| 4 |
+
export class ReplayStore {
|
| 5 |
+
constructor(file) { this.file = file; this.data = { schema_version: '1.0', privacy: 'metadata-only', replays: [] }; }
|
| 6 |
+
async load() { this.data = JSON.parse(await fs.readFile(this.file, 'utf8')); return this.data; }
|
| 7 |
+
list() { return structuredClone(this.data); }
|
| 8 |
+
async add(item) {
|
| 9 |
+
const record = { id: `replay-${Date.now()}`, task_class: String(item.task_class || 'unknown'), model: String(item.model || 'unknown'), status: String(item.status || 'unknown'), checks: item.checks || {}, created_at: new Date().toISOString() };
|
| 10 |
+
this.data.replays.push(record);
|
| 11 |
+
await fs.mkdir(path.dirname(this.file), { recursive: true });
|
| 12 |
+
const temp = `${this.file}.tmp-${process.pid}`;
|
| 13 |
+
await fs.writeFile(temp, `${JSON.stringify(this.data, null, 2)}\n`, { mode: 0o600 });
|
| 14 |
+
await fs.rename(temp, this.file);
|
| 15 |
+
return record;
|
| 16 |
+
}
|
| 17 |
+
}
|
daemon/server.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { LspManager } from './lsp-manager.mjs';
|
|
| 8 |
import { DapManager } from './dap-manager.mjs';
|
| 9 |
import { WorkspaceManager } from './workspace-manager.mjs';
|
| 10 |
import { TrainingManager } from './training-manager.mjs';
|
|
|
|
| 11 |
|
| 12 |
const HOST = '127.0.0.1';
|
| 13 |
const PORT = Number(process.env.AIDE_DAEMON_PORT || 4777);
|
|
@@ -20,11 +21,13 @@ const communityStore = new CommunityStore(path.join(WORKSPACE, 'community', 'sto
|
|
| 20 |
await communityStore.load().catch(() => {});
|
| 21 |
const lspManager = new LspManager({ manifestPath: path.join(WORKSPACE, 'languages', 'manifest.json'), workspace: WORKSPACE });
|
| 22 |
await lspManager.load().catch(() => {});
|
| 23 |
-
const dapManager = new DapManager({ manifestPath: path.join(WORKSPACE, 'debuggers', 'manifest.json'), workspace: WORKSPACE });
|
| 24 |
await dapManager.load().catch(() => {});
|
| 25 |
const workspaceManager = new WorkspaceManager(WORKSPACE);
|
| 26 |
const trainingManager = new TrainingManager({ manifestPath: path.join(WORKSPACE, 'training', 'manifest.json'), workspace: WORKSPACE });
|
| 27 |
await trainingManager.load().catch(() => {});
|
|
|
|
|
|
|
| 28 |
|
| 29 |
function json(response, status, body) {
|
| 30 |
const payload = JSON.stringify(body);
|
|
@@ -107,6 +110,8 @@ const server = http.createServer(async (request, response) => {
|
|
| 107 |
if (request.method === 'GET' && request.url === '/api/training/status') {
|
| 108 |
return json(response, 200, trainingManager.status());
|
| 109 |
}
|
|
|
|
|
|
|
| 110 |
if (request.method === 'POST' && request.url === '/api/training/start') {
|
| 111 |
const input = await body(request);
|
| 112 |
return json(response, 200, trainingManager.start(input.id, input.approved));
|
|
@@ -117,12 +122,24 @@ const server = http.createServer(async (request, response) => {
|
|
| 117 |
if (request.method === 'POST' && request.url === '/api/dap/start') {
|
| 118 |
return json(response, 200, await dapManager.start((await body(request)).id));
|
| 119 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
if (request.method === 'POST' && request.url === '/api/dap/stop') {
|
| 121 |
return json(response, 200, await dapManager.stop((await body(request)).id));
|
| 122 |
}
|
| 123 |
if (request.method === 'POST' && request.url === '/api/lsp/start') {
|
| 124 |
return json(response, 200, await lspManager.start((await body(request)).id));
|
| 125 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
if (request.method === 'POST' && request.url === '/api/lsp/stop') {
|
| 127 |
return json(response, 200, await lspManager.stop((await body(request)).id));
|
| 128 |
}
|
|
|
|
| 8 |
import { DapManager } from './dap-manager.mjs';
|
| 9 |
import { WorkspaceManager } from './workspace-manager.mjs';
|
| 10 |
import { TrainingManager } from './training-manager.mjs';
|
| 11 |
+
import { ReplayStore } from './replay-store.mjs';
|
| 12 |
|
| 13 |
const HOST = '127.0.0.1';
|
| 14 |
const PORT = Number(process.env.AIDE_DAEMON_PORT || 4777);
|
|
|
|
| 21 |
await communityStore.load().catch(() => {});
|
| 22 |
const lspManager = new LspManager({ manifestPath: path.join(WORKSPACE, 'languages', 'manifest.json'), workspace: WORKSPACE });
|
| 23 |
await lspManager.load().catch(() => {});
|
| 24 |
+
const dapManager = new DapManager({ manifestPath: path.join(WORKSPACE, 'debuggers', 'manifest.json'), workspace: WORKSPACE, pythonPath: process.env.AIDE_PYTHON || '' });
|
| 25 |
await dapManager.load().catch(() => {});
|
| 26 |
const workspaceManager = new WorkspaceManager(WORKSPACE);
|
| 27 |
const trainingManager = new TrainingManager({ manifestPath: path.join(WORKSPACE, 'training', 'manifest.json'), workspace: WORKSPACE });
|
| 28 |
await trainingManager.load().catch(() => {});
|
| 29 |
+
const replayStore = new ReplayStore(path.join(WORKSPACE, 'replays', 'store.json'));
|
| 30 |
+
await replayStore.load().catch(() => {});
|
| 31 |
|
| 32 |
function json(response, status, body) {
|
| 33 |
const payload = JSON.stringify(body);
|
|
|
|
| 110 |
if (request.method === 'GET' && request.url === '/api/training/status') {
|
| 111 |
return json(response, 200, trainingManager.status());
|
| 112 |
}
|
| 113 |
+
if (request.method === 'GET' && request.url === '/api/replays') return json(response, 200, replayStore.list());
|
| 114 |
+
if (request.method === 'POST' && request.url === '/api/replays') return json(response, 201, { replay: await replayStore.add(await body(request)) });
|
| 115 |
if (request.method === 'POST' && request.url === '/api/training/start') {
|
| 116 |
const input = await body(request);
|
| 117 |
return json(response, 200, trainingManager.start(input.id, input.approved));
|
|
|
|
| 122 |
if (request.method === 'POST' && request.url === '/api/dap/start') {
|
| 123 |
return json(response, 200, await dapManager.start((await body(request)).id));
|
| 124 |
}
|
| 125 |
+
if (request.method === 'POST' && request.url === '/api/dap/request') {
|
| 126 |
+
const input = await body(request);
|
| 127 |
+
return json(response, 200, await dapManager.request(input.id, input.request));
|
| 128 |
+
}
|
| 129 |
if (request.method === 'POST' && request.url === '/api/dap/stop') {
|
| 130 |
return json(response, 200, await dapManager.stop((await body(request)).id));
|
| 131 |
}
|
| 132 |
if (request.method === 'POST' && request.url === '/api/lsp/start') {
|
| 133 |
return json(response, 200, await lspManager.start((await body(request)).id));
|
| 134 |
}
|
| 135 |
+
if (request.method === 'POST' && request.url === '/api/lsp/request') {
|
| 136 |
+
const input = await body(request);
|
| 137 |
+
return json(response, 200, await lspManager.request(input.id, input.message));
|
| 138 |
+
}
|
| 139 |
+
if (request.method === 'POST' && request.url === '/api/lsp/notify') {
|
| 140 |
+
const input = await body(request);
|
| 141 |
+
return json(response, 200, lspManager.notify(input.id, input.message));
|
| 142 |
+
}
|
| 143 |
if (request.method === 'POST' && request.url === '/api/lsp/stop') {
|
| 144 |
return json(response, 200, await lspManager.stop((await body(request)).id));
|
| 145 |
}
|
daemon/test-replay-store.mjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import assert from 'node:assert/strict';
|
| 2 |
+
import { mkdtemp, writeFile, mkdir } from 'node:fs/promises';
|
| 3 |
+
import { tmpdir } from 'node:os';
|
| 4 |
+
import path from 'node:path';
|
| 5 |
+
import { ReplayStore } from './replay-store.mjs';
|
| 6 |
+
const root = await mkdtemp(path.join(tmpdir(), 'aide-replay-')); const file = path.join(root, 'replays', 'store.json');
|
| 7 |
+
await mkdir(path.dirname(file), { recursive: true }); await writeFile(file, JSON.stringify({ schema_version: '1.0', privacy: 'metadata-only', replays: [] }));
|
| 8 |
+
const store = new ReplayStore(file); await store.load(); const record = await store.add({ task_class: 'code-change', model: 'qwen-coder-1.5b-q4', status: 'verified', checks: { tests: true } });
|
| 9 |
+
assert.equal(store.list().replays.length, 1); assert.equal(record.checks.tests, true); console.log('replay store test passed');
|
package.json
CHANGED
|
@@ -5,10 +5,11 @@
|
|
| 5 |
"description": "Local-first sovereign development workbench",
|
| 6 |
"type": "module",
|
| 7 |
"scripts": {
|
| 8 |
-
"test": "node tests/smoke.mjs && node harness/test-orchestrator.mjs && node daemon/test-model-manager.mjs && node daemon/test-community-store.mjs && node daemon/test-lsp-manager.mjs && node daemon/test-dap-manager.mjs && node daemon/test-workspace-manager.mjs && node daemon/test-training-manager.mjs && node benchmarks/test-run.mjs && node capsules/test-create.mjs",
|
| 9 |
"check": "node --check app.js && node --check daemon/server.mjs && node --check harness/orchestrator.mjs && node --check harness/checks.mjs",
|
| 10 |
"veritas": "node harness/run-veritas.mjs",
|
| 11 |
"benchmarks": "node benchmarks/run.mjs",
|
|
|
|
| 12 |
"capsule": "node capsules/create.mjs",
|
| 13 |
"desktop:dev": "tauri dev --config desktop/tauri.conf.json",
|
| 14 |
"desktop:prepare": "node desktop/prepare.mjs",
|
|
|
|
| 5 |
"description": "Local-first sovereign development workbench",
|
| 6 |
"type": "module",
|
| 7 |
"scripts": {
|
| 8 |
+
"test": "node tests/smoke.mjs && node harness/test-orchestrator.mjs && node daemon/test-model-manager.mjs && node daemon/test-community-store.mjs && node daemon/test-lsp-manager.mjs && node daemon/test-dap-manager.mjs && node daemon/test-workspace-manager.mjs && node daemon/test-training-manager.mjs && node daemon/test-replay-store.mjs && node benchmarks/test-run.mjs && node benchmarks/test-arena.mjs && node capsules/test-create.mjs",
|
| 9 |
"check": "node --check app.js && node --check daemon/server.mjs && node --check harness/orchestrator.mjs && node --check harness/checks.mjs",
|
| 10 |
"veritas": "node harness/run-veritas.mjs",
|
| 11 |
"benchmarks": "node benchmarks/run.mjs",
|
| 12 |
+
"arena": "node benchmarks/arena.mjs",
|
| 13 |
"capsule": "node capsules/create.mjs",
|
| 14 |
"desktop:dev": "tauri dev --config desktop/tauri.conf.json",
|
| 15 |
"desktop:prepare": "node desktop/prepare.mjs",
|
replays/README.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Task Replay
|
| 2 |
+
|
| 3 |
+
Task Replay records a privacy-safe execution receipt: task ID, model pack, runtime, verification status, checks, and timestamps. Source, prompts, evidence, and model output are not stored unless the user explicitly exports an encrypted capsule.
|
replays/store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"schema_version":"1.0","privacy":"metadata-only","replays":[]}
|