{"record":{"id":"c67300ee7b4dc363","repo":"ruvnet/RuView","slug":"brain-line-index-1-errors-join-c67300","errorCode":null,"errorMessage":"brain line ${index + 1}: ${errors.join('; ')}","messagePattern":"brain line (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"harness/ruview/src/brain.js","lineNumber":51,"sourceCode":"  if (!Array.isArray(record.tags) || record.tags.some((tag) => typeof tag !== 'string')) errors.push('tags must be strings');\n  if ((record.content || '').length > 8192) errors.push('content exceeds 8192 characters');\n  if ((record.title || '').length > 200) errors.push('title exceeds 200 characters');\n  if (canonical && record.reviewed !== true) errors.push('canonical records must be reviewed');\n  const combined = `${record.title || ''}\\n${record.content || ''}`;\n  if (SECRET.test(combined)) errors.push('record appears to contain a secret');\n  if (INJECTION.test(combined)) errors.push('record contains instruction-like prompt injection');\n  return errors;\n}\n\nexport function loadBrain(path = CORPUS_PATH) {\n  const raw = readFileSync(path, 'utf8').replace(/\\r\\n/g, '\\n');\n  if (Buffer.byteLength(raw) > 1_048_576) throw new Error('brain corpus exceeds 1 MiB');\n  const records = raw.split('\\n').filter(Boolean).map((line, index) => {\n    if (Buffer.byteLength(line) > 16_384) throw new Error(`brain line ${index + 1}: exceeds 16 KiB`);\n    let record;\n    try { record = JSON.parse(line); } catch (error) { throw new Error(`brain line ${index + 1}: ${error.message}`); }\n    const errors = validateBrainRecord(record, { canonical: true });\n    if (errors.length) throw new Error(`brain line ${index + 1}: ${errors.join('; ')}`);\n    return Object.freeze(record);\n  });\n  if (records.length > 1000) throw new Error('brain corpus exceeds 1000 records');\n  const ids = new Set();\n  for (const record of records) {\n    if (ids.has(record.id)) throw new Error(`duplicate brain id: ${record.id}`);\n    ids.add(record.id);\n  }\n  return { records, digest: sha256(raw), bytes: Buffer.byteLength(raw) };\n}\n\nfunction terms(value) {\n  return new Set(String(value).toLowerCase().match(/[a-z0-9][a-z0-9_-]{1,}/g) || []);\n}\n\nexport function searchBrain(query, { limit = 8, path = CORPUS_PATH } = {}) {\n  const wanted = terms(query);\n  if (!wanted.size) return [];","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/harness/ruview/src/brain.js#L33-L69","documentation":"Each parsed line must pass validateBrainRecord with canonical:true: non-empty string id/title/content/evidence; id matching /^[a-z0-9][a-z0-9-]{2,63}$/; evidence in {REPOSITORY, POLICY, ADR, MEASURED, SYNTHETIC}; a repository-relative source.path with positive integer source.line; string tags; content <= 8192 chars; title <= 200 chars; reviewed === true; and title+content not matching the SECRET or INJECTION regexes. All violations are joined with '; ' into this message.","triggerScenarios":"Adding a canonical record without \"reviewed\": true, using evidence: \"docs\" instead of an allowed enum, an absolute or ..-traversing source.path, an id like 'My_Record' or shorter than 3 chars, or content containing 'api_key: ...' or 'ignore previous' style phrases.","commonSituations":"Contributors editing brain/corpus/core.jsonl directly instead of using the review flow, records copied from notes without citations, example tokens in content tripping the secret scanner.","solutions":["Fix every field named in the message; the joined list reports all violations for that line at once","Use 'brain propose' to emit unreviewed records for a PR instead of hand-writing canonical entries","Model new records on existing valid lines in core.jsonl"],"exampleFix":"// before\n{\"id\":\"New_Lesson\",\"title\":\"T\",\"content\":\"C\",\"evidence\":\"docs\",\"source\":{\"path\":\"/abs/x.js\",\"line\":0},\"tags\":[\"a\"]}\n\n// after\n{\"id\":\"new-lesson\",\"title\":\"T\",\"content\":\"C\",\"evidence\":\"REPOSITORY\",\"source\":{\"path\":\"src/x.js\",\"line\":1},\"tags\":[\"a\"],\"reviewed\":true}","handlingStrategy":"validation","validationCode":"import { readFileSync } from 'node:fs';\nimport { validateBrainRecord } from './harness/ruview/src/brain.js';\nfunction invalidRecords(path) {\n  return readFileSync(path, 'utf8').split('\\n')\n    .filter((l) => l.trim())\n    .map((line, i) => [i + 1, validateBrainRecord(JSON.parse(line), { canonical: true })])\n    .filter(([, errors]) => errors.length > 0);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const brain = loadBrain(path);\n} catch (error) {\n  if (error.message.includes('must be') || error.message.includes('canonical records')) {\n    console.error(`record validation failed: ${error.message}`);\n    process.exit(1);\n  }\n  throw error;\n}","preventionTips":["Reuse the exported validateBrainRecord() as a pre-commit lint over proposed records","Canonical corpus entries require reviewed:true — route additions through 'brain propose' and review","Check the closed enums: evidence must be REPOSITORY, POLICY, ADR, MEASURED, or SYNTHETIC, and source.path must be repository-relative"],"tags":["validation","schema","jsonl","brain","ruview"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}