AI 首答试用:验收重放源码
研究总览 · 2026-09-20
附录 G.11:原始评估器;重放不构成新增独立 AI 采样。
G.11 evaluate.mjs
Section titled “G.11 evaluate.mjs”import fs from 'node:fs';import vm from 'node:vm';import crypto from 'node:crypto';import os from 'node:os';import { createRequire } from 'node:module';import { pathToFileURL, fileURLToPath } from 'node:url';const require = createRequire(import.meta.url), folder = fileURLToPath(new URL('.', import.meta.url));const hash = x => crypto.createHash('sha256').update(x).digest('hex'), eps = 1e-7;const base = { width: 83, height: 31, thickness: 4, d: 6, n: 4, edge: 7, web: 3 };const make = (task, init, edits) => edits.map((edit, i) => ({ task, id: task + '-' + i, disclosed: i === 0, p: { ...init, ...edit } }));const cases = [ ...make('T1', base, [{}, { width: 47 }, { width: 46 }, { width: 101 }, { width: 80, n: 7 }, { height: 19 }, { width: 51, d: 9, n: 3, edge: 5, web: 4 }, { width: 20, n: 2 }]), ...make('T2', { ...base, width: 91, height: 30, pitch: 19 }, [{}, { width: 77 }, { width: 76 }, { height: 19 }, { pitch: 8 }, { width: 146, n: 7 }, { d: 10, pitch: 13 }, { width: 101, n: 2 }]), ...make('T3', { ...base, width: 30, height: 30, allowed: ['row', 'grid'] }, [{}, { width: 80 }, { width: 29 }, { width: 28 }, { allowed: ['row'] }, { width: 80, height: 28 }, { width: 80, height: 28, allowed: ['grid'] }, { allowed: [] }]), ...make('T4', { ...base, width: 80, height: 72, n: 6, rho: 22, phase: .21 }, [{}, { width: 66, height: 64, n: 4, rho: 30, phase: Math.PI / 4 }, { width: 66, height: 64, n: 4, rho: 30, phase: 0 }, { rho: 3 }, { width: 40, height: 40, n: 2, rho: 10, phase: 0 }, { width: 60, height: 60, n: 3, rho: 18, phase: Math.PI / 6 }, { width: 60, height: 60, n: 8, rho: 15, phase: .52 }, { height: 19 }]), ...make('T5', { height: 30, thickness: 4, d: 6, n: 4, edge: 7, web: 3, pitch: 19, minWidth: 20, maxWidth: 120 }, [{}, { minWidth: 90 }, { maxWidth: 76 }, { height: 19 }, { pitch: 8 }, { d: 9, edge: 5, n: 5, pitch: 14, maxWidth: 100 }, { n: 2, pitch: 9 }, { minWidth: 100, maxWidth: 99 }]),];const protocol = { scope: 'closed-contract first-submission authoring; 5 task families, 40 inputs, 5 disclosed examples and 35 undisclosed parameter variants; not unseen-family generalization', noFeedback: true, candidates: ['F', 'P', 'R', 'H'], tolerance: eps, cases, limits: ['same internal Codex model configuration, one authoring session per candidate; no statistical superiority', 'No live Aira Interface, persistence, undo/redo, interactive discovery, human rescue, or failure recovery is measured', 'Pure-JS eval is for trusted isolated researcher/agent expressions, not a product sandbox'] };const lockPath = folder + 'protocol.json';if (process.argv.includes('--freeze')) { if (fs.existsSync(lockPath)) throw Error('protocol already frozen'); const files = ['tasks.md', 'common-contract.md', 'feature-contract.md', 'program-contract.md', 'relation-contract.md', 'hybrid-contract.md']; fs.writeFileSync(lockPath, JSON.stringify({ ...protocol, frozenAt: new Date().toISOString(), files: Object.fromEntries(files.map(f => [f, hash(fs.readFileSync(folder + f))])) }, null, 2)); console.log(JSON.stringify({ protocol: lockPath, inputs: cases.length, hash: hash(fs.readFileSync(lockPath)) })); process.exit(0);}const locked = JSON.parse(fs.readFileSync(lockPath, 'utf8'));if (JSON.stringify(locked.cases) !== JSON.stringify(cases)) throw Error('protocol drift');for (const [f, digest] of Object.entries(locked.files)) if (hash(fs.readFileSync(folder + f)) !== digest) throw Error('contract drift ' + f);const root = '<workspace-root>';const runtime = root + '/packages/aira-geometry-kernel/runtime/feature-graph/aira_occt_feature_graph';const { default: init } = await import(pathToFileURL(runtime + '.js'));const wasm = fs.readFileSync(runtime + '.wasm'), oc = await init({ wasmBinary: wasm });const highPath = os.tmpdir() + '/aira-highs-standalone-research-20260920/highs.js', high = await require(highPath)();// Reuse Appendix F's already-inspected OCCT constructors/checkers in memory.const previousPath = os.tmpdir() + '/aira-intent-representation-probe-20260920.mjs';const previous = fs.readFileSync(previousPath, 'utf8');if (hash(previous) !== 'e6ce700fa8b6078776b736ce7d38aa427492813c010b406c8fcf8a7fc96d3f45') throw Error('geometry source drift');let geometrySource = previous.slice(previous.indexOf('function scope('), previous.indexOf('const methods ='));const replaceOnce = (a, b) => { if (geometrySource.split(a).length !== 2) throw Error('geometry transform mismatch'); geometrySource = geometrySource.replace(a, b); };replaceOnce('for (const x of xs)', 'for (const {x,y,r} of xs)');replaceOnce('point(x, p.height / 2, 0)', 'point(x, y, 0)');replaceOnce('new oc.gp_Circ(axis, p.radius)', 'new oc.gp_Circ(axis, r)');replaceOnce('&& Math.abs(c.y - p.height / 2) < eps ', '');replaceOnce('requirements(p, intent, cylinders.map(c => c.x))', 'null');const native = new Function('oc', 'eps', geometrySource + ';return {build,inspect};')(oc, eps);const evaluate = (expr, ctx) => typeof expr === 'string' ? new vm.Script('(' + expr + ')').runInNewContext({ Math, ...ctx }, { timeout: 100 }) : expr;const booleanExpr = (expr, ctx) => { const value = evaluate(expr, ctx); if (typeof value !== 'boolean') throw Error('expected boolean expression'); return value; };function fields(o, allowed, label) { if (!o || typeof o !== 'object' || Array.isArray(o)) throw Error('invalid object: ' + label); const extra = Object.keys(o).filter(k => !allowed.includes(k)); if (extra.length) throw Error('unsupported fields in ' + label + ': ' + extra.join(','));}function physical(g) { fields(g, ['width', 'height', 'thickness', 'holes'], 'numeric geometry'); if (!g || !['width', 'height', 'thickness'].every(k => Number.isFinite(g[k]) && g[k] > 0) || !Array.isArray(g.holes)) throw Error('invalid numeric geometry'); for (const h of g.holes) { fields(h, ['x', 'y', 'r'], 'numeric hole'); if (![h.x, h.y, h.r].every(Number.isFinite) || h.r <= 0) throw Error('invalid hole'); } for (let i = 0; i < g.holes.length; i++) { const h = g.holes[i]; if (Math.min(h.x, h.y, g.width - h.x, g.height - h.y) <= h.r) return false; for (const b of g.holes.slice(i + 1)) if (Math.hypot(h.x - b.x, h.y - b.y) <= h.r + b.r) return false; } return true;}function geometryFromFeatures(features, ctx) { let g; const ev = x => evaluate(x, ctx), count = x => { const n = ev(x); if (!Number.isInteger(n) || n < 1 || n > 1000) throw Error('invalid count'); return n; }; for (const [at, f] of features.entries()) { const keys = { plate: ['width','height','thickness'], hole: ['x','y','r'], linear: ['n','x','y','dx','dy','r'], grid: ['nx','ny','x','y','dx','dy','r'], circular: ['n','cx','cy','rho','phase','r'] }; if (!keys[f.kind]) throw Error('unsupported feature ' + f.kind); fields(f, ['kind', ...keys[f.kind]], 'feature'); if (f.kind === 'plate') { if (at !== 0) throw Error('plate must be first and unique'); g = { width: ev(f.width), height: ev(f.height), thickness: ev(f.thickness), holes: [] }; continue; } if (!g) throw Error('missing plate'); const add = (x, y) => g.holes.push({ x, y, r: ev(f.r) }); if (f.kind === 'hole') add(ev(f.x), ev(f.y)); else if (f.kind === 'linear') for (let i = 0, n = count(f.n); i < n; i++) add(ev(f.x) + i * ev(f.dx), ev(f.y) + i * ev(f.dy)); else if (f.kind === 'grid') for (let i = 0, nx = count(f.nx); i < nx; i++) for (let j = 0, ny = count(f.ny); j < ny; j++) add(ev(f.x) + i * ev(f.dx), ev(f.y) + j * ev(f.dy)); else if (f.kind === 'circular') for (let i = 0, n = count(f.n); i < n; i++) { const a = ev(f.phase) + 2 * Math.PI * i / n; add(ev(f.cx) + ev(f.rho) * Math.cos(a), ev(f.cy) + ev(f.rho) * Math.sin(a)); } else throw Error('unsupported feature ' + f.kind); } return g;}function geometryFromDeclaration(d, ctx) { fields(d, ['width', 'height', 'thickness', 'holes'], 'declarative geometry'); const ev = x => evaluate(x, ctx), g = { width: ev(d.width), height: ev(d.height), thickness: ev(d.thickness), holes: [] }; for (const group of d.holes) { fields(group, ['count', 'x', 'y', 'r'], 'declarative hole group'); const n = ev(group.count); if (!Number.isInteger(n) || n < 1 || n > 1000) throw Error('invalid count'); for (let i = 0; i < n; i++) g.holes.push(Object.fromEntries(['x', 'y', 'r'].map(k => [k, evaluate(group[k], { ...ctx, i })]))); } return g;}function solve(b, p) { const names = Object.keys(b.vars ?? {}), rows = b.constraints ?? [], ev = x => evaluate(x, { p }); for (const name of names) fields(b.vars[name], ['lower','upper','cost'], 'variable'); if (!names.length) { if (rows.length) throw Error('constraints without variables'); return { status: 'optimal', v: {}, lp: false }; } const columns = names.map(() => []), lower = [], upper = []; for (const [i, row] of rows.entries()) { fields(row, ['terms','op','rhs'], 'constraint'); if (!['eq', 'le', 'ge'].includes(row.op)) throw Error('invalid constraint op'); for (const [name, value] of Object.entries(row.terms)) { const j = names.indexOf(name); if (j < 0) throw Error('unknown variable'); columns[j].push([i, ev(value)]); } const rhs = ev(row.rhs); lower.push(row.op === 'le' ? -high.infinity : rhs); upper.push(row.op === 'ge' ? high.infinity : rhs); } const starts = [], indices = [], values = []; for (const col of columns) { starts.push(indices.length); for (const [i, a] of col) { indices.push(i); values.push(a); } } starts.push(indices.length); const bound = (k, field, fallback) => b.vars[k][field] === undefined ? fallback : ev(b.vars[k][field]); const m = high.createModel({ numCols: names.length, numRows: rows.length, colCost: names.map(k => bound(k, 'cost', 0)), colLower: names.map(k => bound(k, 'lower', -high.infinity)), colUpper: names.map(k => bound(k, 'upper', high.infinity)), rowLower: lower, rowUpper: upper, matrix: { format: 'csc', numRows: rows.length, numCols: names.length, starts, indices, values } }); try { m.options.set({ output_flag: false, solver: 'simplex' }); const code = m.run().modelStatus; return code === 7 ? { status: 'optimal', lp: true, v: Object.fromEntries(names.map((k, i) => [k, m.getSolution().colValue[i]])) } : { status: code === 8 ? 'infeasible' : 'unknown', code, lp: true }; } finally { m.dispose(); }}function run(candidate, answer, p) { if (candidate === 'P') { if (Object.keys(answer).some(k => k !== 'source')) throw Error('unsupported program field'); const g = new vm.Script('(' + answer.source + ')(p)').runInNewContext({ p, Math }, { timeout: 100 }); if (g?.status === 'infeasible' || g?.status === 'unknown') { fields(g, ['status','reason'], 'program status'); return { status: g.status, reason: g.reason, branches: 1, lpCalls: 0 }; } return { status: physical(g) ? 'ok' : 'infeasible', g, branches: 1, lpCalls: 0 }; } const expectedKey = candidate === 'F' ? 'variants' : 'branches'; if (Object.keys(answer).some(k => k !== expectedKey)) throw Error('unsupported recipe field'); let attempts = 0, lpCalls = 0; for (const b of answer[expectedKey]) { const allowed = ['when', 'checks', candidate === 'R' ? 'geometry' : 'features', ...(candidate === 'F' ? [] : ['vars', 'constraints'])]; if (Object.keys(b).some(k => !allowed.includes(k))) throw Error('unsupported branch field'); attempts++; if (b.when !== undefined && !booleanExpr(b.when, { p })) continue; const result = candidate === 'F' ? { status: 'optimal', v: {} } : solve(b, p); if (result.lp) lpCalls++; if (result.status === 'infeasible') continue; if (result.status === 'unknown') return { status: 'unknown', branches: attempts, lpCalls }; const ctx = { p, v: result.v }, g = candidate === 'R' ? geometryFromDeclaration(b.geometry, ctx) : geometryFromFeatures(b.features, ctx); if (!physical(g) || !(b.checks ?? []).every(x => booleanExpr(x, { ...ctx, g }))) continue; return { status: 'ok', g, branches: attempts, lpCalls }; } return { status: 'infeasible', branches: attempts, lpCalls };}function oracle(task, p) { const border = 2 * p.edge + p.d, step = p.d + p.web; if (task === 'T1') return { feasible: p.height >= border && p.width >= border + (p.n - 1) * step }; if (task === 'T2') return { feasible: p.height >= border && p.pitch >= step && p.width >= border + (p.n - 1) * p.pitch }; if (task === 'T3') { const row = p.allowed.includes('row') && p.width >= border + 3 * step && p.height >= border; const grid = p.allowed.includes('grid') && p.width >= border + step && p.height >= border + step; return { feasible: row || grid, structure: row ? 'row' : grid ? 'grid' : null }; } if (task === 'T4') { const holes = Array.from({ length: p.n }, (_, i) => ({ x: p.width / 2 + p.rho * Math.cos(p.phase + 2 * Math.PI * i / p.n), y: p.height / 2 + p.rho * Math.sin(p.phase + 2 * Math.PI * i / p.n), r: p.d / 2 })); return { feasible: clearances({ ...p, holes }, p), holes }; } const width = Math.max(p.minWidth, border + (p.n - 1) * p.pitch); return { feasible: p.height >= border && p.pitch >= step && width <= p.maxWidth, width };}function clearances(g, p) { for (const [i, h] of g.holes.entries()) { if (Math.min(h.x, h.y, g.width - h.x, g.height - h.y) - h.r < p.edge - eps) return false; for (const b of g.holes.slice(i + 1)) if (Math.hypot(h.x - b.x, h.y - b.y) - h.r - b.r < p.web - eps) return false; } return true;}function accept(task, p, g, expected) { const near = (x, y) => Math.abs(x - y) < eps, h = g.holes; if (h.length !== p.n || !near(g.height, p.height) || !near(g.thickness, p.thickness) || h.some(x => !near(x.r, p.d / 2)) || !clearances(g, p)) return false; if (!near(g.width, task === 'T5' ? expected.width : p.width)) return false; if (task === 'T4') return expected.holes.every(a => h.some(b => near(a.x, b.x) && near(a.y, b.y))); const x = [...h].sort((a, b) => a.x - b.x), onCentreRow = h.every(a => near(a.y, p.height / 2)); if (task === 'T3' && expected.structure === 'grid') { const unique = values => [...values].sort((a,b)=>a-b).filter((v, i, sorted) => i === 0 || !near(v, sorted[i-1])); const xs = unique(h.map(a => a.x)), ys = unique(h.map(a => a.y)); if (xs.length !== 2 || ys.length !== 2) return false; return near(xs[0] + xs[1], p.width) && near(ys[0] + ys[1], p.height); } if (!onCentreRow) return false; const gaps = x.slice(1).map((a, i) => a.x - x[i].x); if (Math.max(...gaps) - Math.min(...gaps) >= eps) return false; if (task === 'T1') return near(x[0].x - p.d / 2, p.edge) && near(g.width - x.at(-1).x - p.d / 2, p.edge); if (task === 'T3') return true; if (!near(x[0].x + x.at(-1).x, g.width)) return false; return gaps.every(a => near(a, p.pitch));}const requested = process.argv.find(x => x.startsWith('--candidate='))?.split('=')[1];const candidates = requested ? [requested] : ['F', 'P', 'R', 'H'], results = [], artifacts = {};for (const candidate of candidates) { const path = folder + 'answers-' + candidate + '.json', bytes = fs.readFileSync(path), answers = JSON.parse(bytes); artifacts[candidate] = { file: path, sha256: hash(bytes), utf8Bytes: bytes.length }; for (const input of cases) { const expected = oracle(input.task, input.p), t = performance.now(); let emitted, actual, outcome, error; try { emitted = run(candidate, answers[input.task], structuredClone(input.p)); if (emitted.status === 'unknown') outcome = 'unknown'; else if (emitted.status === 'infeasible') outcome = expected.feasible ? 'false-reject' : 'correct-reject'; else { const g = emitted.g, checkParams = { width: g.width, height: g.height, thickness: g.thickness, n: input.p.n, radius: input.p.d / 2 }, shape = native.build(checkParams, g.holes); try { const measured = native.inspect(shape, checkParams, 'unused'); const measuredGeometry = { width: measured.boundsVector[3] - measured.boundsVector[0], height: measured.boundsVector[4] - measured.boundsVector[1], thickness: measured.boundsVector[5] - measured.boundsVector[2], holes: measured.cylinders.map(c => ({ x: c.x, y: c.y, r: c.radius })) }; actual = { geometry: measured.geometry, requirements: accept(input.task, input.p, measuredGeometry, expected), measuredGeometry }; outcome = expected.feasible && actual.geometry && actual.requirements ? 'pass' : 'wrong-geometry-or-intent'; } finally { shape.delete(); } } } catch (e) { error = String(e); outcome = 'execution-error'; } results.push({ candidate, ...input, expected, outcome, emitted, actual, error, diagnosticMs: performance.now() - t }); }}const summary = Object.fromEntries(candidates.map(c => [c, Object.fromEntries(['pass', 'correct-reject', 'false-reject', 'wrong-geometry-or-intent', 'execution-error', 'unknown'].map(k => [k, results.filter(r => r.candidate === c && r.outcome === k).length]))]));const report = { timestamp: new Date().toISOString(), node: process.version, protocolSha256: hash(fs.readFileSync(lockPath)), evaluatorSha256: hash(fs.readFileSync(new URL(import.meta.url))), geometrySourceSha256: hash(previous), transformedGeometrySha256: hash(geometrySource), occtWasmSha256: hash(wasm), highsVersion: high.version, artifacts, summary, results };const output = folder + 'results' + (requested ? '-' + requested : '') + '.json'; fs.writeFileSync(output, JSON.stringify(report, null, 2));console.log(JSON.stringify({ output, summary, failures: results.filter(r => !['pass', 'correct-reject'].includes(r.outcome)).map(r => ({ candidate: r.candidate, id: r.id, outcome: r.outcome, error: r.error, p: r.p })) }, null, 2));