Files
ruvnet--RuView/harness/ruview/src/brain.js
T
rUv 2b7853b18f feat(ruview): secure community metaharness flywheel (#1467)
* feat(ruview): add secure community metaharness flywheel

* fix(ruview): canonicalize manifest line endings
2026-07-28 23:57:16 -04:00

122 lines
6.2 KiB
JavaScript

// SPDX-License-Identifier: MIT
// Reviewable shared repository knowledge. Canonical records are committed JSONL;
// private vector indexes/transcripts are deliberately outside this package.
import { createHash } from 'node:crypto';
import { existsSync, readFileSync, realpathSync } from 'node:fs';
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
export const CORPUS_PATH = join(ROOT, 'brain', 'corpus', 'core.jsonl');
const SECRET = /(-----BEGIN [A-Z ]*PRIVATE KEY-----|(?:api[_-]?key|token|password|secret)\s*[:=]\s*\S+)/i;
const INJECTION = /\b(ignore (?:all|the|previous)|system prompt|developer message|execute this|run this command)\b/i;
const EVIDENCE = new Set(['REPOSITORY', 'POLICY', 'ADR', 'MEASURED', 'SYNTHETIC']);
function sha256(text) {
return createHash('sha256').update(text).digest('hex');
}
export function validateBrainRecord(record, { canonical = false } = {}) {
const errors = [];
if (!record || typeof record !== 'object' || Array.isArray(record)) return ['record must be an object'];
for (const key of ['id', 'title', 'content', 'evidence']) {
if (typeof record[key] !== 'string' || !record[key].trim()) errors.push(`${key} must be a non-empty string`);
}
if (!/^[a-z0-9][a-z0-9-]{2,63}$/.test(record.id || '')) errors.push('id must be a lowercase slug');
if (!EVIDENCE.has(record.evidence)) errors.push(`unsupported evidence: ${record.evidence}`);
if (!record.source || typeof record.source.path !== 'string' || !Number.isInteger(record.source.line) || record.source.line < 1) {
errors.push('source.path and positive source.line are required');
} else if (isAbsolute(record.source.path) || record.source.path.split(/[\\/]/).includes('..') || /^[A-Za-z]:/.test(record.source.path)) {
errors.push('source.path must be repository-relative without traversal');
}
if (!Array.isArray(record.tags) || record.tags.some((tag) => typeof tag !== 'string')) errors.push('tags must be strings');
if ((record.content || '').length > 8192) errors.push('content exceeds 8192 characters');
if ((record.title || '').length > 200) errors.push('title exceeds 200 characters');
if (canonical && record.reviewed !== true) errors.push('canonical records must be reviewed');
const combined = `${record.title || ''}\n${record.content || ''}`;
if (SECRET.test(combined)) errors.push('record appears to contain a secret');
if (INJECTION.test(combined)) errors.push('record contains instruction-like prompt injection');
return errors;
}
export function loadBrain(path = CORPUS_PATH) {
const raw = readFileSync(path, 'utf8').replace(/\r\n/g, '\n');
if (Buffer.byteLength(raw) > 1_048_576) throw new Error('brain corpus exceeds 1 MiB');
const records = raw.split('\n').filter(Boolean).map((line, index) => {
if (Buffer.byteLength(line) > 16_384) throw new Error(`brain line ${index + 1}: exceeds 16 KiB`);
let record;
try { record = JSON.parse(line); } catch (error) { throw new Error(`brain line ${index + 1}: ${error.message}`); }
const errors = validateBrainRecord(record, { canonical: true });
if (errors.length) throw new Error(`brain line ${index + 1}: ${errors.join('; ')}`);
return Object.freeze(record);
});
if (records.length > 1000) throw new Error('brain corpus exceeds 1000 records');
const ids = new Set();
for (const record of records) {
if (ids.has(record.id)) throw new Error(`duplicate brain id: ${record.id}`);
ids.add(record.id);
}
return { records, digest: sha256(raw), bytes: Buffer.byteLength(raw) };
}
function terms(value) {
return new Set(String(value).toLowerCase().match(/[a-z0-9][a-z0-9_-]{1,}/g) || []);
}
export function searchBrain(query, { limit = 8, path = CORPUS_PATH } = {}) {
const wanted = terms(query);
if (!wanted.size) return [];
const { records, digest } = loadBrain(path);
return records.map((record) => {
const title = terms(record.title);
const body = terms(record.content);
const tags = new Set(record.tags.map((tag) => tag.toLowerCase()));
let score = 0;
for (const term of wanted) score += title.has(term) ? 5 : tags.has(term) ? 3 : body.has(term) ? 1 : 0;
return { ...record, score, citation: `${record.source.path}:${record.source.line}`, corpusDigest: digest };
}).filter((record) => record.score > 0)
.sort((a, b) => b.score - a.score || a.id.localeCompare(b.id))
.slice(0, Math.max(1, Math.min(Number(limit) || 8, 25)));
}
export function verifyBrain({ repo = process.cwd(), path = CORPUS_PATH } = {}) {
const root = resolve(repo);
const { records, digest, bytes } = loadBrain(path);
const findings = [];
for (const record of records) {
const source = resolve(root, record.source.path);
const rel = relative(root, source);
if (isAbsolute(rel) || rel.startsWith('..') || !existsSync(source)) {
findings.push({ id: record.id, reason: 'source_missing', source: record.source.path });
} else {
const real = realpathSync(source);
const realRel = relative(realpathSync(root), real);
if (isAbsolute(realRel) || realRel.startsWith('..')) {
findings.push({ id: record.id, reason: 'source_escape', source: record.source.path });
} else {
const sourceLines = readFileSync(real, 'utf8').split(/\r?\n/);
if (record.source.line > sourceLines.length) {
findings.push({ id: record.id, reason: 'source_line_missing', source: record.source.path, line: record.source.line });
}
}
}
}
return { ok: findings.length === 0, records: records.length, digest, bytes, findings };
}
export function makeProposal(input) {
const record = {
id: String(input.id || '').trim(),
title: String(input.title || '').trim(),
content: String(input.content || '').trim(),
source: { path: String(input.sourcePath || '').trim(), line: Number(input.sourceLine) },
evidence: String(input.evidence || 'REPOSITORY').toUpperCase(),
tags: String(input.tags || '').split(',').map((tag) => tag.trim()).filter(Boolean),
contributor: String(input.contributor || '').trim() || 'unknown',
reviewed: false,
};
const errors = validateBrainRecord(record);
return errors.length ? { ok: false, errors } : { ok: true, proposal: record, jsonl: JSON.stringify(record) };
}