ruvnet-brain 4.3.25 → 4.3.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +2 -2
  2. package/bin/install.mjs +19 -4
  3. package/console/app.js +48 -0
  4. package/console/index.html +19 -0
  5. package/console/style.css +26 -0
  6. package/data/model-catalog.json +1 -1
  7. package/docs/RELEASE-NOTES-4.0.md +4 -3
  8. package/kb/capability-only.mjs +27 -0
  9. package/kb/capability-summaries/cognitum-ruos/CAPABILITIES.md +26 -0
  10. package/kb/verify-citation.mjs +16 -4
  11. package/package.json +5 -1
  12. package/plugin/.claude-plugin/plugin.json +1 -1
  13. package/plugin/.codex-plugin/plugin.json +1 -1
  14. package/plugin/docs/RELEASE-NOTES-4.0.md +4 -3
  15. package/plugin/hooks/codex-hooks.json +6 -1
  16. package/plugin/hooks/hook-contracts.json +24 -2
  17. package/plugin/hooks/hooks.json +6 -1
  18. package/plugin/scripts/capacity-aware-parallel-work.mjs +200 -0
  19. package/plugin/scripts/codex-hook-adapter.mjs +37 -0
  20. package/plugin/scripts/continuity-hook-policy.mjs +4 -0
  21. package/plugin/scripts/coverage-integrity.mjs +17 -0
  22. package/plugin/scripts/hook-shim.mjs +1 -0
  23. package/plugin/scripts/lesson-gate.mjs +4 -1
  24. package/plugin/scripts/project-progression-reader.mjs +12 -1
  25. package/plugin/scripts/project-progression-session-start.mjs +24 -6
  26. package/plugin/scripts/project-progression-store.mjs +76 -4
  27. package/plugin/skills/release-proof/SKILL.md +28 -4
  28. package/plugin/skills/release-proof/scripts/release-proof.mjs +48 -24
  29. package/scripts/brain-novice-50.mjs +14 -16
  30. package/scripts/build-bundle.mjs +2 -0
  31. package/scripts/corpus-dispatch-receipt.mjs +22 -0
  32. package/scripts/corpus-reconcile.mjs +26 -4
  33. package/scripts/doc-currency.mjs +12 -4
  34. package/scripts/eval-brain.mjs +7 -5
  35. package/scripts/gist-git-transport.mjs +218 -0
  36. package/scripts/gist-receipts.mjs +168 -38
  37. package/scripts/ingest-gists.mjs +5 -2
  38. package/scripts/installed-brain-health.mjs +99 -0
  39. package/scripts/onboarding-console.mjs +45 -1
  40. package/scripts/public-inputs.mjs +2 -1
  41. package/scripts/public-verification-inputs.mjs +14 -6
  42. package/scripts/refresh-capability-only-store.mjs +143 -0
  43. package/scripts/release-transaction-provider.mjs +25 -5
  44. package/scripts/release-transaction.mjs +40 -11
  45. package/scripts/release-vector.mjs +44 -20
  46. package/scripts/run-operational-benchmark.mjs +151 -0
  47. package/scripts/run-operational-benchmark.v3.mjs +194 -0
  48. package/scripts/self-update.mjs +2 -0
  49. package/scripts/source-coverage.mjs +6 -1
  50. package/scripts/sync-version.mjs +10 -2
  51. package/scripts/wired-check.mjs +73 -45
package/README.md CHANGED
@@ -7,7 +7,7 @@ Created: 2026-06-29 22:36:38 EDT
7
7
 
8
8
  # 🧠 RuvNet Brain
9
9
 
10
- ### 🧠 RuvNet Brain — [![RuvNet Brain version 4.3.25 — updated 2026-07-30 03:24 EDT](https://img.shields.io/badge/version_4.3.25-updated_2026--07--30_03:24_EDT-1E90FF?style=for-the-badge&labelColor=0757BA)](https://github.com/stuinfla/ruvnet-brain/blob/main/plugin/.claude-plugin/plugin.json)
10
+ ### 🧠 RuvNet Brain — [![RuvNet Brain version 4.3.27 — updated 2026-07-30 03:24 EDT](https://img.shields.io/badge/version_4.3.27-updated_2026--07--30_03:24_EDT-1E90FF?style=for-the-badge&labelColor=0757BA)](https://github.com/stuinfla/ruvnet-brain/blob/main/plugin/.claude-plugin/plugin.json)
11
11
 
12
12
  **A portable, source-grounded brain over Reuven Cohen's (rUv's) RuvNet stack — delivered as a Claude Code plugin that makes Claude _use_ the stack instead of fighting it.**
13
13
 
@@ -562,7 +562,7 @@ node forge-ask-all.mjs --dir . --q "How does RuVector implement HNSW vector sear
562
562
 
563
563
  This project versions in the open (see the live badge up top for the exact plugin version; the downloadable knowledge bundle is a separate track) — we don't claim “done,” “complete,” or “zero hallucinations.” Where it stands:
564
564
 
565
- - ✅ **The grounding brain is real and proven** — 182 public stores · 143,719 public source chunks, dual embeddings, cross-encoder rerank, plugin (MCP tool + explicit skills; automatic hooks retired), all re-runnable.
565
+ - ✅ **The grounding brain is real and proven** — 182 public stores · 143,682 public source chunks, dual embeddings, cross-encoder rerank, plugin (MCP tool + explicit skills; automatic hooks retired), all re-runnable.
566
566
  - ✅ **Code-level depth** — the code-rich repos are indexed to full function bodies; “how is it implemented?” returns the implementation. Verified in the shipped bundle (clean-room 3/3).
567
567
  - ✅ **Routing holds** — named 47/48, described 26/28, scenario 7/8; behavioral L1–L3 all pass (**L4 downgraded — it measures that the brain spoke, not that anything listened**); private stores fenced out of the public bundle (zero-leak verified).
568
568
  - ⚠️ **Two routing residuals** (above) — surfaced, not hidden.
package/bin/install.mjs CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  } from '../kb/model-requirements.mjs';
31
31
  import { applyManagedCatalogUpdate } from '../scripts/model-router-catalog.mjs';
32
32
  import { cmpVersion } from '../scripts/stack-sync.mjs';
33
+ import { inspectInstalledBrain, classifySmokeEvidence, DOCTOR_SMOKE_QUERY, doctorSmokeArgs } from '../scripts/installed-brain-health.mjs';
33
34
  import { validateCoverageDirectory } from '../plugin/scripts/coverage-integrity.mjs';
34
35
  import {
35
36
  continuityContractIds,
@@ -2402,9 +2403,9 @@ async function smokeQuery(cacheDir) {
2402
2403
  if (!fs.existsSync(ask)) return { ran: false };
2403
2404
  step(
2404
2405
  'Asking the brain a real question',
2405
- 'this warms the local model so your first real answer is instant — and proves grounding works end to end',
2406
+ 'this warms the local model and checks that retrieval returns usable, cited evidence',
2406
2407
  );
2407
- const Q = 'How should I store embeddings in this project without running a server?';
2408
+ const Q = DOCTOR_SMOKE_QUERY;
2408
2409
  info(`Q: ${c.cyan(`"${Q}"`)}`);
2409
2410
  info(c.dim('(first run downloads a small local model once — this can take a minute)'));
2410
2411
  const started = Date.now();
@@ -2415,7 +2416,7 @@ async function smokeQuery(cacheDir) {
2415
2416
  // absolute path via spawnSync (no shell involved) that identity check silently fails on this
2416
2417
  // machine, so main() never runs — exit 0, zero stdout, zero stderr, no exception. Looks like a
2417
2418
  // clean success; is actually a total no-op. Verified: switching to a relative name + cwd fixes it.
2418
- r = spawnSync('node', ['forge-ask-all.mjs', '--dir', cacheDir, '--q', Q, '--k', '3'], {
2419
+ r = spawnSync('node', doctorSmokeArgs(cacheDir), {
2419
2420
  cwd: cacheDir,
2420
2421
  encoding: 'utf8',
2421
2422
  timeout: 240000,
@@ -2476,6 +2477,11 @@ async function smokeQuery(cacheDir) {
2476
2477
  }
2477
2478
 
2478
2479
  const v = await verifier.verifyGrounding(out, cacheDir);
2480
+ const evidence = classifySmokeEvidence(v, out);
2481
+ if (v.grounded && !evidence.usable) {
2482
+ warn(`the citation resolves, but the question was not answered with sufficient evidence (${evidence.reason})`);
2483
+ return { ran: true, grounded: false, citationResolved: true, reason: evidence.reason, secs };
2484
+ }
2479
2485
  if (v.grounded) {
2480
2486
  ok(`grounded in rUv's real source — verified in ${secs}s, not guessed ✦`);
2481
2487
  console.log(` ${c.dim('cited:')} ${c.bold(v.receipt.path)}`);
@@ -2693,6 +2699,13 @@ async function doctor() {
2693
2699
  // Two independent version streams (KB bundle vs plugin wrapper) — see checkVersionDrift()'s
2694
2700
  // header comment for the full story. Silent unless they've genuinely diverged.
2695
2701
  reportVersionDrift(cacheDir);
2702
+ const installedIdentity = inspectInstalledBrain(cacheDir, PACKAGE_VERSION);
2703
+ info(`installed identities: package ${installedIdentity.packageVersion || 'unknown'}; search engine ${installedIdentity.searchVersion || 'unknown'}; validator ${installedIdentity.validatorVersion || 'unknown'}`);
2704
+ if (installedIdentity.corpusTag) info(`corpus generation: ${installedIdentity.corpusTag}`);
2705
+ if (!installedIdentity.healthy) {
2706
+ for (const issue of installedIdentity.issues) warn(`installed identity: ${issue}`);
2707
+ info(`Repair the installed generation: ${c.bold('npx ruvnet-brain@latest --update')}`);
2708
+ }
2696
2709
  // Extraction no longer needs an external binary at all — kb/zip-extract.mjs does it with node:zlib
2697
2710
  // (see unzipInto()). So this reports the file's PRESENCE, not a PATH lookup: if it is missing from
2698
2711
  // the install, extraction on Windows silently loses its primary method, which is exactly the class
@@ -2883,6 +2896,8 @@ async function doctor() {
2883
2896
  const codexWiringFailed = Boolean(cx.host && !cx.wired);
2884
2897
  const codexReadinessFailed = Boolean(codexMcp?.blocking);
2885
2898
  const failed = (hookResult ? hookResult.exitCode !== 0 : !allGreen)
2899
+ || !installedIdentity.healthy
2900
+ || smoke.grounded !== true
2886
2901
  || groundingUnprovenPersisted
2887
2902
  || (codexLifecycleFailed && !codexTrustBypassed)
2888
2903
  || codexWiringFailed
@@ -3056,7 +3071,7 @@ function reportVersionDrift(cacheDir) {
3056
3071
  const state = checkVersionDrift(cacheDir);
3057
3072
  if (!state.drift) return state;
3058
3073
  warn(`the brain (${c.bold(state.kb)}) and the Claude Code plugin (${c.bold(state.wrapper)}) have drifted apart —`);
3059
- info(`that's normal (they update on separate schedules) and neither one is broken. To bring the`);
3074
+ info(`they update on separate schedules; this comparison does not prove either is healthy. To bring the`);
3060
3075
  info(`plugin up to date: ${c.bold('claude plugin marketplace update ruvnet-brain')} ${c.dim('(body updates go live without a restart; boot-surface changes are called out)')}`);
3061
3076
  return state;
3062
3077
  }
package/console/app.js CHANGED
@@ -2973,6 +2973,53 @@ function bpField(bp) {
2973
2973
  return (bp && Array.isArray(bp.schema) && bp.schema[0]) || null;
2974
2974
  }
2975
2975
 
2976
+ /* ------------------------------------------------------------ inventory */
2977
+
2978
+ // Renders /api/state's `inventory` section: the installed brain's stores BY NAME, joined with their
2979
+ // upstream repo and build commit. Ranked by recency (server-side) — never alphabetical. Read-only.
2980
+ function renderInventory(inv) {
2981
+ const body = $('#body-inventory');
2982
+ if (!body) return;
2983
+ if (!inv || inv.available !== true) {
2984
+ setChips('chips-inventory', [chip('can’t read the manifest', 'nt')]);
2985
+ body.replaceChildren(el('p', { class: 'muted' },
2986
+ inv && inv.reason ? inv.reason : 'The console could not read RVF-GENERATIONS.json from the installed brain, so it is not guessing a list.'));
2987
+ return;
2988
+ }
2989
+ const chips = [chip(`${fmtInt(inv.count)} repositories`, 'green')];
2990
+ if (inv.privateCount > 0) chips.push(chip(`${fmtInt(inv.privateCount)} private`, 'cyan', 'Fenced private stores — never leave this machine'));
2991
+ if (inv.releaseTag) chips.push(chip(`generation ${inv.releaseTag}`, 'grey'));
2992
+ setChips('chips-inventory', chips);
2993
+
2994
+ const mb = inv.totalBytes ? `${(inv.totalBytes / 1e6).toFixed(0)} MB on disk` : null;
2995
+ const summary = el('p', { class: 'muted' },
2996
+ `${fmtInt(inv.count)} searchable stores`,
2997
+ inv.withProvenance != null ? `, ${fmtInt(inv.withProvenance)} with a recorded upstream commit` : '',
2998
+ mb ? `, ${mb}.` : '.');
2999
+
3000
+ const rows = (inv.stores || []).map((s) => el('li', { class: 'inv-row', 'data-name': s.name.toLowerCase() },
3001
+ el('span', { class: 'mono inv-name' }, s.name),
3002
+ s.private ? chip('private', 'cyan') : null,
3003
+ s.sourceRepo && /^https?:\/\//.test(s.sourceRepo)
3004
+ ? el('a', { class: 'inv-src', href: s.sourceRepo, target: '_blank', rel: 'noopener noreferrer' }, s.sourceRepo.replace(/^https?:\/\/(www\.)?github\.com\//, ''))
3005
+ : el('span', { class: 'muted inv-src' }, s.sourceRepo || '—'),
3006
+ el('span', { class: 'mono muted inv-meta' },
3007
+ s.sourceCommit ? `@${s.sourceCommit}` : '', s.builtUtc ? ` · built ${String(s.builtUtc).slice(0, 10)}` : ''),
3008
+ ));
3009
+ const list = el('ul', { class: 'inv-list', 'aria-label': 'Repositories in the brain' }, ...rows);
3010
+ const filter = el('input', {
3011
+ class: 'inv-filter', type: 'search', placeholder: 'Filter by name…', 'aria-label': 'Filter repositories by name',
3012
+ oninput: (e) => {
3013
+ const q = String(e.target.value || '').trim().toLowerCase();
3014
+ let shown = 0;
3015
+ for (const li of list.children) { const hit = !q || li.dataset.name.includes(q); li.hidden = !hit; if (hit) shown += 1; }
3016
+ count.textContent = q ? `${fmtInt(shown)} of ${fmtInt(inv.count)} match` : '';
3017
+ },
3018
+ });
3019
+ const count = el('span', { class: 'muted inv-count', 'aria-live': 'polite' });
3020
+ body.replaceChildren(summary, el('div', { class: 'inv-tools' }, filter, count), list);
3021
+ }
3022
+
2976
3023
  function renderBrainPower(bp) {
2977
3024
  const body = $('#body-brain');
2978
3025
  if (!body) return;
@@ -3663,6 +3710,7 @@ async function loadState({ landed = false } = {}) {
3663
3710
  renderHost(state.host, state.generatedAt);
3664
3711
  const s = state.sections || {};
3665
3712
  renderBrainPower(s.brainPower);
3713
+ renderInventory(s.inventory);
3666
3714
  renderWiring(s.wiring);
3667
3715
  lastMemory = s.memory;
3668
3716
  renderMemory(s.memory);
@@ -108,6 +108,25 @@
108
108
  </div>
109
109
  </section>
110
110
 
111
+ <!-- The one thing this page never showed: WHICH repositories are in the brain, by name. It always
112
+ carried the count and never the list. Read-only mirror of the installed manifest. -->
113
+ <section class="card rail-mirror" id="card-inventory" aria-labelledby="card-inventory-h">
114
+ <div class="qgroup-head">
115
+ <span class="card-ic ic-mirror" aria-hidden="true">
116
+ <svg viewBox="0 0 24 24"><path d="M4 6h16"/><path d="M4 12h16"/><path d="M4 18h10"/></svg>
117
+ </span>
118
+ <span class="card-head">
119
+ <span class="stage st-mirror">Mirror</span>
120
+ <h2 id="card-inventory-h">What’s in your brain</h2>
121
+ <span class="q">Every repository the brain can search right now, by name — where it came from and when it was built.</span>
122
+ </span>
123
+ <span class="chips" id="chips-inventory"><span class="chip tone-wait">counting…</span></span>
124
+ </div>
125
+ <div class="body" id="body-inventory">
126
+ <div class="skeleton" aria-hidden="true"><div class="sk-bar w40"></div><div class="sk-bar w75"></div></div>
127
+ </div>
128
+ </section>
129
+
111
130
  <!-- ======================================================= HERO -->
112
131
  <section class="intro">
113
132
  <div class="intro-grid">
package/console/style.css CHANGED
@@ -2147,3 +2147,29 @@ details.sub .sub-body > *:first-child { margin-top: 4px; }
2147
2147
  #body-brain .fn-path {
2148
2148
  font-family: var(--mono); font-size: 0.86em; color: var(--faint); overflow-wrap: anywhere;
2149
2149
  }
2150
+
2151
+ /* ------------------------------------------------------------ inventory card
2152
+ The repository list, by name. Same row language as .cap-row (hairline separators, quiet meta),
2153
+ with a type-to-filter above it because 200+ names need a way in. Long upstream URLs wrap rather
2154
+ than overflow the card. */
2155
+ .inv-tools { display: flex; align-items: center; gap: 12px; margin: 10px 0 8px; flex-wrap: wrap; }
2156
+ .inv-filter {
2157
+ flex: 1 1 220px; min-width: 0; padding: 7px 10px; font: inherit; font-size: 13.5px;
2158
+ color: var(--ink); background: var(--panel-2, transparent);
2159
+ border: 1px solid var(--hair-strong); border-radius: 8px;
2160
+ }
2161
+ .inv-filter:focus { outline: 2px solid var(--cyan); outline-offset: 1px; }
2162
+ .inv-count { font-size: 12.5px; }
2163
+ .inv-list { list-style: none; margin: 0; padding: 0; max-height: 28rem; overflow: auto; border-top: 1px solid var(--hair); }
2164
+ .inv-row {
2165
+ display: grid; grid-template-columns: minmax(10ch, 16ch) auto 1fr auto; align-items: baseline; gap: 6px 12px;
2166
+ padding: 7px 4px; border-bottom: 1px solid var(--hair); font-size: 13.5px;
2167
+ }
2168
+ .inv-row[hidden] { display: none; }
2169
+ .inv-name { font-size: 13px; overflow-wrap: anywhere; }
2170
+ .inv-src { min-width: 0; overflow-wrap: anywhere; font-size: 12.5px; }
2171
+ .inv-meta { font-size: 12px; white-space: nowrap; }
2172
+ @media (max-width: 640px) {
2173
+ .inv-row { grid-template-columns: 1fr auto; }
2174
+ .inv-src, .inv-meta { grid-column: 1 / -1; white-space: normal; }
2175
+ }
@@ -4,7 +4,7 @@
4
4
  "generated": "2026-07-15",
5
5
  "schema_version": 1,
6
6
  "sources": {
7
- "prices": "OpenRouter /api/v1/models live catalog, pulled 2026-09-04 (in/out USD per Mtok).",
7
+ "prices": "OpenRouter /api/v1/models live catalog, pulled 2026-09-19 (in/out USD per Mtok).",
8
8
  "rankings": "Artificial Analysis Intelligence Index (artificialanalysis.ai) + Arena/LMArena (arena.ai) — the ONLY independent evaluators carrying current-generation models as of 2026-07-15; each figure cross-verified twice.",
9
9
  "provenance_rule": "rUv ADR-206: vendor-reported scores are optimistic and harness-confounded — trust independent (AA/Arena) numbers, treat vendor self-scaffold SWE-bench/LiveCodeBench figures as noisy features, never as truth.",
10
10
  "benchmark_lag": "The canonical hard coding benchmarks (SWE-bench Verified standardized harness, LiveCodeBench, Aider polyglot) were ALL months stale on 2026-07-15 and carry NONE of these models. The '88.6% / 95% SWE-bench' figures in the press are vendor self-scaffold scores, not the standardized harness — excluded here.",
@@ -1,6 +1,6 @@
1
1
  # RuvNet-Brain 4.0 line — what's new (the major-release highlights)
2
2
 
3
- Updated: 2026-08-01
3
+ Updated: 2026-09-20
4
4
 
5
5
  > **Source of truth** for the `/whats-new` command and the first-run upgrade message. Curated, honest,
6
6
  > major-only — not the point-release churn. If a claim here isn't true of the shipping build, it does not
@@ -19,10 +19,11 @@ it's landing now.
19
19
 
20
20
  ### Release proof is fail-closed
21
21
  The 4.0 release path now separates a clean candidate seal from a post-publication seal. Dirty
22
- lineage, zero/skipped/todo tests, open issues, red or pending exact-SHA workflows, a missing
22
+ lineage, zero/skipped/todo tests, open `release-blocker` issues, red or pending exact-SHA workflows, a missing
23
23
  `ruvnet-brain` self-RVF store, weak query-deadline margin, missing independent graders,
24
24
  host/artifact mismatches, and public-byte drift are release failures rather than warnings.
25
- `npm run release:proof -- --status --quick` shows the current live blockers.
25
+ The local `release:proof --status --quick` command is only a diagnostic and cannot qualify a
26
+ candidate; use the exact-SHA preflight receipt and protected publisher evidence.
26
27
 
27
28
  ### 1. The Console is the front door
28
29
  Type `/rvbc` and your whole RuvNet stack is on one live local page: what's installed, what the AI has
@@ -0,0 +1,27 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export const isCapabilityOnly = name => String(name).toLowerCase() === 'cognitum-ruos';
5
+ export const CAPABILITY_RETIRED_SUFFIXES = [
6
+ '-primer.md', '.symbols.json', '.rvf', '.rvf.idmap.json', '.rvf.embed.json', '.big.passages.jsonl', '.big.meta.json',
7
+ ];
8
+
9
+ // Reject historical source-bearing stores at the final packaging boundary, even
10
+ // when their upstream SHA and signed generation receipt are otherwise current.
11
+ export function assertCapabilityOnlyStore(dir, name) {
12
+ if (!isCapabilityOnly(name)) return;
13
+ const expected = fs.readFileSync(new URL('./capability-summaries/cognitum-ruos/CAPABILITIES.md', import.meta.url), 'utf8');
14
+ const rows = fs.readFileSync(path.join(dir, `${name}.passages.jsonl`), 'utf8')
15
+ .trim().split('\n').map(line => JSON.parse(line));
16
+ if (rows.length !== 1 || rows[0].path !== 'CAPABILITIES.md' || rows[0].text !== expected) {
17
+ throw new Error(`${name}: capability-only policy requires the current curated summary, without source passages`);
18
+ }
19
+ const meta = JSON.parse(fs.readFileSync(path.join(dir, `${name}.meta.json`), 'utf8'));
20
+ const entries = Object.values(meta.entries || {});
21
+ if (entries.length !== 1 || entries[0].path !== 'CAPABILITIES.md' || entries[0].kind !== 'doc') {
22
+ throw new Error(`${name}: capability-only metadata contains unexpected source paths`);
23
+ }
24
+ if (CAPABILITY_RETIRED_SUFFIXES.some(suffix => fs.existsSync(path.join(dir, `${name}${suffix}`)))) {
25
+ throw new Error(`${name}: capability-only store must not carry a symbol index or legacy source sidecar`);
26
+ }
27
+ }
@@ -0,0 +1,26 @@
1
+ Updated: 2026-09-19 | Version 1.0.0
2
+ Created: 2026-09-19
3
+
4
+ # Cognitum ruOS capabilities
5
+
6
+ Cognitum ruOS is an agentic operating system for AI workstations. It is designed
7
+ to observe workstation conditions, reason about what needs attention, and take
8
+ appropriate actions with less manual intervention.
9
+
10
+ Its documented capabilities include:
11
+
12
+ - Workstation health monitoring and recovery from service failures.
13
+ - Adapting performance profiles to workload and user context.
14
+ - Local AI assistance and persistent knowledge for workstation tasks.
15
+ - Learning from prior sessions and evaluating knowledge quality.
16
+ - Backup, recovery, and software updates.
17
+ - Voice interaction and optional sensing with user consent.
18
+ - Security checks around AI interactions.
19
+
20
+ It is relevant when a user wants a workstation that helps maintain itself and
21
+ supports ongoing AI-assisted work. These are documented capabilities, not a claim
22
+ that ruOS is installed, provisioned, or independently benchmarked on this machine.
23
+
24
+ This Brain entry intentionally covers capabilities and use cases only. Proprietary
25
+ source code, internal architecture, algorithms, configuration, and implementation
26
+ instructions are outside its published knowledge scope.
@@ -42,7 +42,7 @@ import readline from 'node:readline';
42
42
  export function parseCitations(stdout) {
43
43
  const out = [];
44
44
  const text = String(stdout ?? '');
45
- const blockRe = /^#(\d+)\s+repo=(\S+)(?:\s+ce=(-?[\d.]+))?(?:\s+vec=(-?[\d.]+))?(?:\s+kind=(\S+))?/gm;
45
+ const blockRe = /^#(\d+)[ \t]+repo=(\S+)([^\r\n]*)/gm;
46
46
  const nextHeaderRe = /^#\d+\s+repo=\S+/gm;
47
47
  let m;
48
48
  let expectedRank = 1;
@@ -63,15 +63,27 @@ export function parseCitations(stdout) {
63
63
  if (!pathM) continue;
64
64
  expectedRank = rank + 1;
65
65
  const repo = m[2];
66
+ // Metadata comes only from the header, never from a retrieved document body.
67
+ // A proof label is descriptive; consumers must independently validate its evidence.
68
+ const field = (name) => new RegExp(`(?:^|[ \\t])${name}=([^ \\t]+)`).exec(m[3])?.[1] ?? null;
69
+ const score = (name) => {
70
+ const value = field(name);
71
+ return value !== null && /^-?\d+(?:\.\d+)?$/.test(value) ? Number(value) : null;
72
+ };
66
73
  const fullPath = pathM[1].trim();
67
74
  // Strip the repo prefix the reader adds, so the remainder can be matched against the store.
68
75
  const docPath = fullPath.startsWith(`${repo}/`) ? fullPath.slice(repo.length + 1) : fullPath;
76
+ // Retain only the reader's bounded document body. Missing/truncated delimiters fail
77
+ // closed, so evaluators cannot borrow claims from headers, diagnostics, or later hits.
78
+ const body = /^----- full document -----\r?\n([\s\S]*?)\r?\n={67}(?:\r?\n|$)/m.exec(block);
69
79
  out.push({
70
80
  rank,
71
81
  repo,
72
- ce: m[3] !== undefined ? Number(m[3]) : null,
73
- vec: m[4] !== undefined ? Number(m[4]) : null,
74
- kind: m[5] ?? null,
82
+ ce: score('ce'),
83
+ vec: score('vec'),
84
+ kind: field('kind'),
85
+ proofMethod: field('proof'),
86
+ returnedText: body ? body[1] : null,
75
87
  fullPath,
76
88
  docPath,
77
89
  title: titleM ? titleM[1].trim() : null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvnet-brain",
3
- "version": "4.3.25",
3
+ "version": "4.3.27",
4
4
  "description": "One-command installer for RuvNet Brain — a portable, source-grounded brain over rUv's RuvNet building blocks, delivered as a Claude Code plugin so Claude uses the stack instead of fighting it.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,6 +12,8 @@
12
12
  "release:proof": "node scripts/release-proof.mjs",
13
13
  "benchmark:brain50": "node scripts/brain-latency-50.mjs",
14
14
  "benchmark:novice50": "node scripts/brain-novice-50.mjs",
15
+ "benchmark:operational": "node scripts/run-operational-benchmark.v3.mjs",
16
+ "benchmark:operational:v2": "node scripts/run-operational-benchmark.mjs",
15
17
  "version:check": "node scripts/sync-version.mjs --check",
16
18
  "version:set": "node scripts/set-version.mjs",
17
19
  "qa:pr": "node scripts/qa-runner.mjs",
@@ -94,6 +96,8 @@
94
96
  "kb/verify-citation.mjs",
95
97
  "kb/retrieval-result.mjs",
96
98
  "kb/corpus-release-identity.mjs",
99
+ "kb/capability-only.mjs",
100
+ "kb/capability-summaries/",
97
101
  "kb/zip-extract.mjs",
98
102
  "kb/brain-profile.mjs",
99
103
  "kb/lifecycle-evidence-retention.mjs",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ruvnet-brain",
3
3
  "description": "RuvNet brain transplant for Claude Code — grounds every RuvNet decision in real source across 77 rUv repositories, prefers Ruflo / RuVector-RVF / AgentDB over training-prior defaults (pgvector, Pinecone, hand-rolled cosine), and can pull in any RuvNet repo on demand. Ships a UserPromptSubmit retrieve-and-inject grounding hook and a PreToolUse write gate that refuses ungrounded rUv-product code until search_ruvnet has been consulted (ADR-0012 / ADR-067).",
4
- "version": "4.3.25",
4
+ "version": "4.3.27",
5
5
  "author": {
6
6
  "name": "Stuart Kerr"
7
7
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvnet-brain",
3
- "version": "4.3.25",
3
+ "version": "4.3.27",
4
4
  "description": "Source-grounded RuvNet knowledge, lifecycle enforcement, and learning for Codex.",
5
5
  "author": {
6
6
  "name": "Stuart Kerr"
@@ -1,6 +1,6 @@
1
1
  # RuvNet-Brain 4.0 line — what's new (the major-release highlights)
2
2
 
3
- Updated: 2026-08-01
3
+ Updated: 2026-09-20
4
4
 
5
5
  > **Source of truth** for the `/whats-new` command and the first-run upgrade message. Curated, honest,
6
6
  > major-only — not the point-release churn. If a claim here isn't true of the shipping build, it does not
@@ -19,10 +19,11 @@ it's landing now.
19
19
 
20
20
  ### Release proof is fail-closed
21
21
  The 4.0 release path now separates a clean candidate seal from a post-publication seal. Dirty
22
- lineage, zero/skipped/todo tests, open issues, red or pending exact-SHA workflows, a missing
22
+ lineage, zero/skipped/todo tests, open `release-blocker` issues, red or pending exact-SHA workflows, a missing
23
23
  `ruvnet-brain` self-RVF store, weak query-deadline margin, missing independent graders,
24
24
  host/artifact mismatches, and public-byte drift are release failures rather than warnings.
25
- `npm run release:proof -- --status --quick` shows the current live blockers.
25
+ The local `release:proof --status --quick` command is only a diagnostic and cannot qualify a
26
+ candidate; use the exact-SHA preflight receipt and protected publisher evidence.
26
27
 
27
28
  ### 1. The Console is the front door
28
29
  Type `/rvbc` and your whole RuvNet stack is on one live local page: what's installed, what the AI has
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "RuvNet Brain continuity plane for Codex. Broad legacy automatic gates remain retired. Registrations here are MEASURED, not assumed: a probe hook was registered on all twelve event names the installed codex-cli 0.154.0 binary declares and a real `codex exec` run was observed (2026-09-11). SessionStart, UserPromptSubmit and SessionEnd FIRED and carry handlers. Stop keeps only the pre-existing, project-scoped continuation gate. PreCompact is DECLARED ABSENT here: the binary declares the event but the probe never observed it, and a capture registered on an unobserved event would look symmetrical while capturing nothing. All handlers are bounded and fail open. Amended 2026-09-11: UserPromptSubmit also runs ground-ruvnet (grounding injection, ADR-040 §Amendment). Amended 2026-09-12: the 2026-09-11 PreToolUse/PostToolUse \"not observed\" note was measured with a prompt (`codex exec \"reply OK\"`) that never invoked a tool, so neither event had anything to fire on — that was an untested path, not a failing one. Re-probed with prompts that actually call a tool: a real apply_patch write fired PreToolUse/PostToolUse with tool_name \"apply_patch\", and a real MCP call to this repo's own search_ruvnet server fired both with tool_name \"mcp__ruvnet_brain__search_ruvnet\". Both are now registered below: decision-gate's write route (matcher includes apply_patch, Codex's raw write-tool name) and grounding-stamp (unchanged matcher already recognizes the mcp__..__search_ruvnet shape). The bash route (exec_command) remains unregistered — today's measurement covered a write and an MCP call, not exec_command, and extending on that evidence would be the same unproven leap this note replaces. Also added 2026-09-12: grounding-turn-mark (UserPromptSubmit) and grounding-turn-gate (Stop), the \"answered without searching\" pair — a prompt-level grounding directive is advisory, so this records whether it fired and forces continuation at Stop if no search_ruvnet call was recorded since (reusing grounding-stamp's own stamp evidence). Both are registered on Codex identically to Claude: the Stop-block contract (hookSpecificOutput.additionalContext) already has a proven Codex translation via codex-hook-adapter.mjs's Stop branch (see tests/unit/codex-lifecycle-hooks.test.mjs), the same path continuation-gate already uses.",
2
+ "description": "RuvNet Brain continuity plane for Codex. Broad legacy automatic gates remain retired. Registrations here are MEASURED, not assumed: a probe hook was registered on all twelve event names the installed codex-cli 0.154.0 binary declares and a real `codex exec` run was observed (2026-09-11). SessionStart, UserPromptSubmit and SessionEnd FIRED and carry handlers. Stop keeps only the pre-existing, project-scoped continuation gate. PreCompact is DECLARED ABSENT here: the binary declares the event but the probe never observed it, and a capture registered on an unobserved event would look symmetrical while capturing nothing. All handlers are bounded and fail open. Amended 2026-09-11: UserPromptSubmit also runs ground-ruvnet (grounding injection, ADR-040 §Amendment). Amended 2026-09-12: the 2026-09-11 PreToolUse/PostToolUse \"not observed\" note was measured with a prompt (`codex exec \"reply OK\"`) that never invoked a tool, so neither event had anything to fire on — that was an untested path, not a failing one. Re-probed with prompts that actually call a tool: a real apply_patch write fired PreToolUse/PostToolUse with tool_name \"apply_patch\", and a real MCP call to this repo's own search_ruvnet server fired both with tool_name \"mcp__ruvnet_brain__search_ruvnet\". Both are now registered below: decision-gate's write route (matcher includes apply_patch, Codex's raw write-tool name) and grounding-stamp (unchanged matcher already recognizes the mcp__..__search_ruvnet shape). The bash route (exec_command) remains unregistered — today's measurement covered a write and an MCP call, not exec_command, and extending on that evidence would be the same unproven leap this note replaces. Also added 2026-09-12: grounding-turn-mark (UserPromptSubmit) and grounding-turn-gate (Stop), the \"answered without searching\" pair — a prompt-level grounding directive is advisory, so this records whether it fired and forces continuation at Stop if no search_ruvnet call was recorded since (reusing grounding-stamp's own stamp evidence). Both are registered on Codex identically to Claude: the Stop-block contract (hookSpecificOutput.additionalContext) already has a proven Codex translation via codex-hook-adapter.mjs's Stop branch (see tests/unit/codex-lifecycle-hooks.test.mjs), the same path continuation-gate already uses. Capacity-aware parallel-work guidance is also registered at UserPromptSubmit: it advises the coordinator to launch only real independent workers within sampled resource headroom and the live runtime/tool cap; it never spawns workers or claims execution.",
3
3
  "hooks": {
4
4
  "SessionStart": [
5
5
  {
@@ -68,6 +68,11 @@
68
68
  "command": "node -e \"const f=require('node:fs'),o=require('node:os'),p=require('node:path'),c=require('node:child_process'),d=process.env.CODEX_HOME||p.join(o.homedir(),'.codex'),b=process.env.RUVNET_BRAIN_HOME||p.join(p.dirname(d),'.cache','ruvnet-brain'),w=p.join(b,'codex-hook.mjs');let s;try{s=f.statSync(w)}catch{}if(!s?.isFile())process.exit(0);const r=c.spawnSync(process.execPath,[w,...process.argv.slice(2)],{stdio:['inherit','pipe','pipe'],encoding:'utf8',env:process.env,timeout:Number(process.argv[1]),killSignal:'SIGKILL'});if(r.status===0||r.status===2){if(r.stdout)process.stdout.write(r.stdout);if(r.stderr)process.stderr.write(r.stderr)}process.exit(r.status===2?2:0)\" 9000 ground-ruvnet",
69
69
  "timeout": 10
70
70
  },
71
+ {
72
+ "type": "command",
73
+ "command": "node -e \"const f=require('node:fs'),o=require('node:os'),p=require('node:path'),c=require('node:child_process'),d=process.env.CODEX_HOME||p.join(o.homedir(),'.codex'),b=process.env.RUVNET_BRAIN_HOME||p.join(p.dirname(d),'.cache','ruvnet-brain'),w=p.join(b,'codex-hook.mjs');let s;try{s=f.statSync(w)}catch{}if(!s?.isFile())process.exit(0);const r=c.spawnSync(process.execPath,[w,...process.argv.slice(2)],{stdio:['inherit','pipe','pipe'],encoding:'utf8',env:process.env,timeout:Number(process.argv[1]),killSignal:'SIGKILL'});if(r.status===0||r.status===2){if(r.stdout)process.stdout.write(r.stdout);if(r.stderr)process.stderr.write(r.stderr)}process.exit(r.status===2?2:0)\" 1500 capacity-aware-parallel-work",
74
+ "timeout": 2
75
+ },
71
76
  {
72
77
  "type": "command",
73
78
  "command": "node -e \"const f=require('node:fs'),o=require('node:os'),p=require('node:path'),c=require('node:child_process'),d=process.env.CODEX_HOME||p.join(o.homedir(),'.codex'),b=process.env.RUVNET_BRAIN_HOME||p.join(p.dirname(d),'.cache','ruvnet-brain'),w=p.join(b,'codex-hook.mjs');let s;try{s=f.statSync(w)}catch{}if(!s?.isFile())process.exit(0);const r=c.spawnSync(process.execPath,[w,...process.argv.slice(2)],{stdio:['inherit','pipe','pipe'],encoding:'utf8',env:process.env,timeout:Number(process.argv[1]),killSignal:'SIGKILL'});if(r.status===0||r.status===2){if(r.stdout)process.stdout.write(r.stdout);if(r.stderr)process.stderr.write(r.stderr)}process.exit(r.status===2?2:0)\" 4500 grounding-turn-mark",
@@ -1,6 +1,6 @@
1
1
  {
2
- "_note": "The legacy automatic gate collection remains retired. What is permitted is the continuity plane below and nothing else: SessionStart restores the canonical project checkpoint; UserPromptSubmit runs the single unprompted-speech chokepoint; Stop may nudge one explicitly authorized project-scoped objective AND capture a project snapshot; PreCompact and SessionEnd capture a project snapshot. Version 3 of this file permitted exactly two handlers, which was not a safety property but a contradiction: it demanded a restore while forbidding any event that could WRITE the journal the restore reads, so the canonical store held zero progression rows. Adding to this list is still a deliberate act that must pass `npm run hooks:check`; what changed is that the shape can now express the plane that actually works. Amended 2026-09-11 (Stuart): the continuity-only charter had retired the ONLY enforcement of ADR-0012 — never write rUv-product code the brain has not seen — and the failure it exists to prevent recurred the day it was measured absent. The plane now also carries three grounding registrations: ground-ruvnet (UserPromptSubmit, grounding injection — a second owner of that event, scoped by ADR-040 §Amendment 2026-09-11 to directives rather than speech), decision-gate’s write route (PreToolUse, the one refuser, ADR-067), and grounding-stamp (PostToolUse on a successful search_ruvnet, the receipt that opens the write gate). Amended 2026-09-12: the 2026-09-11 claim that Codex PreToolUse/PostToolUse delivery had never been observed was measured with a prompt that never invoked a tool (`codex exec \"reply OK\"`), so it was an untested path, not a failing one. Re-measured with prompts that actually call a tool (a real apply_patch write, a real MCP search_ruvnet call against this repo's own server): both events FIRED on codex-cli 0.154.0 with real payloads. decision-gate's write route and grounding-stamp are now dual-host (see _codexCapture and contracts below); the bash route (exec_command) remains Claude-only — today's measurement did not exercise it. Also amended 2026-09-12: added grounding-turn-mark (UserPromptSubmit) and grounding-turn-gate (Stop), the \"answered without searching\" pair — ground-ruvnet's Gate 1 directive is advisory, so nothing previously checked whether the model complied before the turn ended. grounding-turn-mark records that Gate 1 fired for a turn; grounding-turn-gate forces continuation at Stop if grounding-stamp's own evidence shows no search_ruvnet call happened since. Both dual-host from the start (the Stop-block contract is already proven on Codex via continuation-gate).",
3
- "_version": 7,
2
+ "_note": "The legacy automatic gate collection remains retired. What is permitted is the continuity plane below and nothing else: SessionStart restores the canonical project checkpoint; UserPromptSubmit runs the single unprompted-speech chokepoint; Stop may nudge one explicitly authorized project-scoped objective AND capture a project snapshot; PreCompact and SessionEnd capture a project snapshot. Version 3 of this file permitted exactly two handlers, which was not a safety property but a contradiction: it demanded a restore while forbidding any event that could WRITE the journal the restore reads, so the canonical store held zero progression rows. Adding to this list is still a deliberate act that must pass `npm run hooks:check`; what changed is that the shape can now express the plane that actually works. Amended 2026-09-11 (Stuart): the continuity-only charter had retired the ONLY enforcement of ADR-0012 — never write rUv-product code the brain has not seen — and the failure it exists to prevent recurred the day it was measured absent. The plane now also carries three grounding registrations: ground-ruvnet (UserPromptSubmit, grounding injection — a second owner of that event, scoped by ADR-040 §Amendment 2026-09-11 to directives rather than speech), decision-gate’s write route (PreToolUse, the one refuser, ADR-067), and grounding-stamp (PostToolUse on a successful search_ruvnet, the receipt that opens the write gate). Amended 2026-09-12: the 2026-09-11 claim that Codex PreToolUse/PostToolUse delivery had never been observed was measured with a prompt that never invoked a tool (`codex exec \"reply OK\"`), so it was an untested path, not a failing one. Re-measured with prompts that actually call a tool (a real apply_patch write, a real MCP search_ruvnet call against this repo's own server): both events FIRED on codex-cli 0.154.0 with real payloads. decision-gate's write route and grounding-stamp are now dual-host (see _codexCapture and contracts below); the bash route (exec_command) remains Claude-only — today's measurement did not exercise it. Also amended 2026-09-12: added grounding-turn-mark (UserPromptSubmit) and grounding-turn-gate (Stop), the \"answered without searching\" pair — ground-ruvnet's Gate 1 directive is advisory, so nothing previously checked whether the model complied before the turn ended. grounding-turn-mark records that Gate 1 fired for a turn; grounding-turn-gate forces continuation at Stop if grounding-stamp's own evidence shows no search_ruvnet call happened since. Both dual-host from the start (the Stop-block contract is already proven on Codex via continuation-gate). Added capacity-aware-parallel-work at UserPromptSubmit on both measured hosts: it is context-only, resource-bounded, and requires the coordinator to check actual tool/runtime slots; it does not spawn or claim workers.",
3
+ "_version": 8,
4
4
  "_eventOwners": [
5
5
  {
6
6
  "event": "SessionStart",
@@ -70,6 +70,16 @@
70
70
  ],
71
71
  "responsibility": "Injects a grounding directive into the model’s context when the prompt names the rUv stack, reaches for a classical default, or asks to build: call search_ruvnet before you assert. Not speech — emits no advocacy, promotion, lesson or alarm and reads no dial; silenced by the brain switch (ADR-054); scoped by ADR-040 §Amendment 2026-09-11."
72
72
  },
73
+ {
74
+ "event": "UserPromptSubmit",
75
+ "owner": "capacity-aware-parallel-work",
76
+ "class": "capacity-aware coordination guidance",
77
+ "hosts": [
78
+ "claude",
79
+ "codex"
80
+ ],
81
+ "responsibility": "For clearly substantial, independently splittable work, adds context-only guidance based on bounded memory-pressure, swap, compression, and normalized-load signals. It never creates workers, claims they are running, or overrides the coordinator’s live agent-tool/runtime cap; unknown capacity recommends serial execution."
82
+ },
73
83
  {
74
84
  "event": "PreToolUse",
75
85
  "owner": "decision-gate",
@@ -228,6 +238,18 @@
228
238
  "matcher": "*",
229
239
  "timeout": 10
230
240
  },
241
+ {
242
+ "id": "capacity-aware-parallel-work",
243
+ "event": "UserPromptSubmit",
244
+ "hosts": [
245
+ "claude",
246
+ "codex"
247
+ ],
248
+ "mode": "advisory",
249
+ "offBehavior": "run",
250
+ "matcher": "*",
251
+ "timeout": 2
252
+ },
231
253
  {
232
254
  "id": "decision-gate",
233
255
  "event": "PreToolUse",
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "RuvNet Brain lifecycle plane. The broad legacy routing, learning, and release interceptors remain retired. What is automatic is exactly: SessionStart restores the canonical project checkpoint; UserPromptSubmit runs the single unprompted-speech chokepoint AND the ground-ruvnet grounding injection (a directive to the model, not speech — ADR-040 §Amendment 2026-09-11); PreToolUse runs decision-gate's write route, the ONE process that may refuse a Write/Edit/MultiEdit/NotebookEdit/apply_patch (ADR-067, composing ground-before-write per ADR-0012) — apply_patch is Codex's own write tool name, added 2026-09-12 once a real apply_patch call was measured to fire this event live (codex-hooks.json carries the matching Codex registration; this is a dead branch on Claude, which never names a tool apply_patch); PostToolUse on a successful search_ruvnet mints the grounding stamp that opens that gate; grounding-turn-mark (UserPromptSubmit) records that the grounding directive fired this turn, and grounding-turn-gate (Stop) forces continuation if no search_ruvnet call was recorded since — the \"answered without searching\" gate, added 2026-09-12 (a directive alone is advisory; nothing previously checked whether the model actually complied); Stop also runs the ledger-scoped continuation handler and captures a project snapshot; PreCompact and SessionEnd capture a project snapshot. Every capture is bounded and fails open; only decision-gate may block on exit code, and it fails open on its own errors — grounding-turn-gate and continuation-gate force continuation via the Stop stdout envelope instead, which is advisory in the shim's own mode table but still keeps the agent working.",
2
+ "description": "RuvNet Brain lifecycle plane. The broad legacy routing, learning, and release interceptors remain retired. What is automatic is exactly: SessionStart restores the canonical project checkpoint; UserPromptSubmit runs the single unprompted-speech chokepoint, ground-ruvnet grounding injection, and a capacity-aware context hint for clearly large independent work. The capacity hook uses bounded CPU/memory-pressure evidence, never starts agents, and tells the coordinator to check live tools and clamp to the runtime cap; it is not user-facing speech. ground-ruvnet remains a directive to the model, not speech — ADR-040 §Amendment 2026-09-11. PreToolUse runs decision-gate's write route, the ONE process that may refuse a Write/Edit/MultiEdit/NotebookEdit/apply_patch (ADR-067, composing ground-before-write per ADR-0012); PostToolUse on a successful search_ruvnet mints the grounding stamp that opens that gate. grounding-turn-mark (UserPromptSubmit) records that the grounding directive fired this turn, and grounding-turn-gate (Stop) forces continuation if no search_ruvnet call was recorded since. Stop also runs the ledger-scoped continuation handler and captures a project snapshot; PreCompact and SessionEnd capture a project snapshot. Every capture is bounded and fails open; only decision-gate may block on exit code, and it fails open on its own errors — the Stop stdout envelopes are advisory at the shim boundary but keep the agent working.",
3
3
  "hooks": {
4
4
  "SessionStart": [
5
5
  {
@@ -27,6 +27,11 @@
27
27
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" ground-ruvnet || true",
28
28
  "timeout": 10
29
29
  },
30
+ {
31
+ "type": "command",
32
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" capacity-aware-parallel-work || true",
33
+ "timeout": 2
34
+ },
30
35
  {
31
36
  "type": "command",
32
37
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" grounding-turn-mark || true",