ruvnet-brain 3.4.22-dev β 3.6.1-dev
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.
- package/README.md +73 -4
- package/bin/install.mjs +85 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,10 +4,26 @@
|
|
|
4
4
|
|
|
5
5
|
# π§ RuvNet Brain
|
|
6
6
|
|
|
7
|
-
### π§ RuvNet Brain β [](https://github.com/stuinfla/ruvnet-brain/blob/main/plugin/.claude-plugin/plugin.json)
|
|
8
8
|
|
|
9
9
|
**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.**
|
|
10
10
|
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
> ## π§ North Star
|
|
14
|
+
>
|
|
15
|
+
> **rUv has built dozens of genuinely powerful capabilities that are effectively invisible β not undocumented, but _undiscovered_.** Ruflo's own docs call cross-project IPFS pattern transfer *"the substrate plugin's most underused capability."* The author knows people can't find his own work.
|
|
16
|
+
>
|
|
17
|
+
> **This project exists to close that gap** β a CTO on your shoulder that says *"you have this, it's off, here's what turning it on buys you."*
|
|
18
|
+
>
|
|
19
|
+
> **Retrieval was never the product. Proactive capability advocacy is the product.**
|
|
20
|
+
>
|
|
21
|
+
> The test we hold ourselves to: a developer who solves a hard problem with this tool and later learns they'd been sitting on a capability that would have made it trivial β that is a **failure of this project**, not of the user. Knowing which question to ask is the scarce thing; supplying that question is the job.
|
|
22
|
+
>
|
|
23
|
+
> Every feature is judged against this. If a surface can detect something useful and doesn't volunteer it, it is broken β see [ADR-027](docs/adr/0027-capability-advocacy-and-active-signals.md) and [DDD-0004](docs/ddd/0004-advocacy-context.md).
|
|
24
|
+
|
|
25
|
+
<div align="center">
|
|
26
|
+
|
|
11
27
|
[](plugin/.claude-plugin/plugin.json)
|
|
12
28
|
[](https://www.npmjs.com/package/ruvnet-brain)
|
|
13
29
|
[](https://github.com/stuinfla/ruvnet-brain/releases/latest)
|
|
@@ -40,7 +56,58 @@
|
|
|
40
56
|
|
|
41
57
|
---
|
|
42
58
|
|
|
43
|
-
## What's new in 3.
|
|
59
|
+
## What's new in 3.6 β it can finally show you what you own
|
|
60
|
+
|
|
61
|
+
**Shipped 2026-07-22.** 3.5 made the brain speak. 3.6 makes it *legible*: a console panel that
|
|
62
|
+
answers the question the owner has been asking for weeks β **"what is actually turned on?"**
|
|
63
|
+
|
|
64
|
+
- **Eleven capabilities, each ON / OFF / UNKNOWN**, every state *derived* from a real check on your
|
|
65
|
+
machine at render time. `UNKNOWN` is a first-class state and is visually separated from `OFF` in a
|
|
66
|
+
non-colour channel, because collapsing the two is precisely the lie this release exists to kill.
|
|
67
|
+
- **A one-line plain-English "what it buys you"** on every row, and the evidence we observed.
|
|
68
|
+
- **Settings that are conservative by construction.** Each setting declares which of its *values*
|
|
69
|
+
escalate beyond the current project, and `default β escalates` is asserted as a test β so the rule
|
|
70
|
+
holds for settings added later instead of relying on a comment nobody re-reads.
|
|
71
|
+
- **A false alarm found and killed.** 3.5's audit reported *"26 learning hooks installed and every
|
|
72
|
+
one is switched off."* That was wrong: `ruflo hooks list` renders a table column keyed `enabled`
|
|
73
|
+
against a payload that has no such key, so it prints "No" 26 times. The learner had 457
|
|
74
|
+
trajectories and had adapted 106 minutes earlier. We scraped a human-readable table instead of
|
|
75
|
+
reading state, which is the exact mistake this project keeps writing rules about. The detector now
|
|
76
|
+
reads the learner's own state file and **stays silent when it cannot tell** β ADR-028 fixes the
|
|
77
|
+
false-alarm rate at zero and calls it non-negotiable.
|
|
78
|
+
- **Three surfaces that were built and never wired** are now connected. `capability-registry.mjs`
|
|
79
|
+
had zero call sites; the client referenced it only in comments. Built-tested-unwired is this
|
|
80
|
+
project's signature failure, and it happened three times in one night.
|
|
81
|
+
|
|
82
|
+
Honest limit: this is **3.6, not 4.0**. 4.0 requires levels 3β5 of ADR-028's proactivity ladder
|
|
83
|
+
(contextual, anticipatory, compounding) and all three remain unbuilt β see `docs/4.0-READINESS.md`,
|
|
84
|
+
which grades the current state at **L2** with evidence for every mark.
|
|
85
|
+
|
|
86
|
+
<details>
|
|
87
|
+
<summary><b>Earlier — what 3.5 shipped</b> · it stopped waiting to be asked. <i>Expand for the receipts.</i></summary>
|
|
88
|
+
|
|
89
|
+
## 3.5 β it stopped waiting to be asked
|
|
90
|
+
|
|
91
|
+
**Shipped 2026-07-22.** For three weeks this thing had indexed rUv's entire learning stack β ReasoningBank, SONA, MoE, the ADR-174 distillation pipeline β and could have answered any question about any of it. It never once said the only sentence that mattered:
|
|
92
|
+
|
|
93
|
+
> *"Your learning system is installed, and it is switched off."*
|
|
94
|
+
|
|
95
|
+
Stuart found it himself. The measurement: **1,884 captured events sat undelivered** while the learner held 5 trajectories and hadn't trained in six days. Draining the queue took it to 412 in one command. Three weeks of learning had been sitting there, available for the asking, and nobody knew to ask.
|
|
96
|
+
|
|
97
|
+
**That gap is the product.** A brain that waits to be asked is a search box with good manners. 3.5 is the version where it speaks first.
|
|
98
|
+
|
|
99
|
+
- **It now tells you what you own and aren't using.** On the author's machine, unprompted, from a real scan: *"36 project stores are embedded but have never been distilled β 6,858 memories sitting in those stores, teaching nothing."* Every recommendation is built from what was actually **observed on your machine** β never a hardcoded list of cool features, which would rot the week rUv ships again.
|
|
100
|
+
- **Detection without a remedy is now structurally impossible.** The console used to detect a corrupt memory store, score it 49/100, render it into a card, and offer nothing. Stuart's verdict: *"the fact that it didn't recommend a fix is unconscionable."* Every recommendation now carries evidence, a cost, a plain-English impact, and a **real, tested undo** β enforced by a factory that throws, not by a code review that can be skipped.
|
|
101
|
+
- **It stopped lying in four specific ways.** It claimed `ruflo` wasn't installed to anyone whose npm prefix wasn't the author's. It answered *"nothing to undo"* about a database repair for which it held a backup. It reported a distillation that wrote 684 patterns as having done nothing (the check used a read-only connection that can't see another process's WAL). And its installer threw away the stderr that explained every crash β so a missing module and a slow download looked identical. All four found by running the thing rather than trusting it.
|
|
102
|
+
- **Every offered fix is provably runnable and reversible.** The remedy registry makes the idβexecutorβinverse binding a single value, and a closure test drives the real builders to prove nothing can be *offered* that cannot be *run* and *undone*. It found that this ADR's own headline recommendation had **no executor at all** β it rendered as a button that answered "Unknown recommendation id." Proven to fail on both known-bad cases before being trusted.
|
|
103
|
+
- **It stopped writing into your repos** ([#36](https://github.com/stuinfla/ruvnet-brain/issues/36)) and **stopped hiding the error that explains a failure** ([#37](https://github.com/stuinfla/ruvnet-brain/issues/37)) β both reported by users, both fixed at root cause, with an upstream report filed to rUv for the two bugs that turned out to be his.
|
|
104
|
+
|
|
105
|
+
The honest limit: this is **3.5, not 4.0**. The advocacy surface is live and the engine behind it is proven, but score-delta alarms aren't built and ADR-027 has not yet survived its own required adversarial review. A major version marks the release where the product becomes a different thing to the person using it. This is the release where it starts talking.
|
|
106
|
+
|
|
107
|
+
<details>
|
|
108
|
+
<summary><b>Earlier — what 3.4 shipped</b> · the invisible work, made visible and readable. <i>Expand for the receipts.</i></summary>
|
|
109
|
+
|
|
110
|
+
## 3.4 β the invisible work, made visible (and readable)
|
|
44
111
|
|
|
45
112
|
**Shipped 2026-07-17.** 3.3 made every card lead with a point. Then Stuart looked at the two pages meant to *teach* the stack and scored them 55/100: the graphics were mediocre, the one page that should show how the pieces fit was a wall of text, and two diagrams were literally unreadable. 3.4 is the fix β the harness's invisible work, finally drawn, and drawn so you can actually read it.
|
|
46
113
|
|
|
@@ -230,6 +297,8 @@ claude plugin install ruvnet-brain@ruvnet-brain --scope user
|
|
|
230
297
|
|
|
231
298
|
Registers the `search_ruvnet` MCP tool, the grounding skill, and the `UserPromptSubmit` enforcement hook β globally, at user scope. The plugin expects the brain at `~/.cache/ruvnet-brain/kb` (or point `RUVNET_BRAIN_KB` at your own copy). The first install may show a one-time trust prompt for the hook.
|
|
232
299
|
|
|
300
|
+
</details>
|
|
301
|
+
</details>
|
|
233
302
|
</details>
|
|
234
303
|
|
|
235
304
|
**Then just ask.** _βHow does Ruflo orchestrate agent swarms, and what implements it?β_ The hook grounds the turn, Claude calls `search_ruvnet`, and it answers from cited source β down to the function body.
|
|
@@ -271,7 +340,7 @@ Plus: the **βtake the wheelβ behavioral pipeline** (below), a **4-level beha
|
|
|
271
340
|
|
|
272
341
|
## How it works
|
|
273
342
|
|
|
274
|
-
The expensive work happens **once, at build time**: every covered repo is deep-walked (whole files, full function bodies, plus a symbol index), embedded into **two** vector variants (MiniLM-384 for edge/portability, bge-768 for depth) stored on-disk in **RVF / HNSW**, and distilled into a concepts + capability layer of per-repo primers and cards. That's **149,
|
|
343
|
+
The expensive work happens **once, at build time**: every covered repo is deep-walked (whole files, full function bodies, plus a symbol index), embedded into **two** vector variants (MiniLM-384 for edge/portability, bge-768 for depth) stored on-disk in **RVF / HNSW**, and distilled into a concepts + capability layer of per-repo primers and cards. That's **149,720 source chunks**. At **query time**, `search_ruvnet` searches every repo's store at once, pools the hits, and runs them through **one cross-encoder rerank** on a common scale β so the truly relevant file wins regardless of which repo it lives in β then returns whole source files, each labeled by repo and path.
|
|
275
344
|
|
|
276
345
|

|
|
277
346
|
|
|
@@ -381,7 +450,7 @@ node forge-ask-all.mjs --dir . --q "How does RuVector implement HNSW vector sear
|
|
|
381
450
|
|
|
382
451
|
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:
|
|
383
452
|
|
|
384
|
-
- β
**The grounding brain is real and proven** β 54 public stores Β· 149,
|
|
453
|
+
- β
**The grounding brain is real and proven** β 54 public stores Β· 149,720 public source chunks (57 built stores incl. private), dual embeddings, cross-encoder rerank, plugin (MCP tool + enforcement hook + skill), all re-runnable.
|
|
385
454
|
- β
**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).
|
|
386
455
|
- β
**Routing holds** β named 47/48, described 26/28, scenario 7/8; behavioral L1βL4 all pass; private stores fenced out of the public bundle (zero-leak verified).
|
|
387
456
|
- β οΈ **Two routing residuals** (above) β surfaced, not hidden.
|
package/bin/install.mjs
CHANGED
|
@@ -643,7 +643,26 @@ async function smokeQuery(cacheDir) {
|
|
|
643
643
|
const out = `${r.stdout || ''}`;
|
|
644
644
|
if (r.status !== 0 || !out.trim()) {
|
|
645
645
|
warn('no answer came back (first-run model download or offline) β the brain is installed; it\'ll warm on your first real question');
|
|
646
|
-
|
|
646
|
+
// SHOW THE ACTUAL ERROR (issue #37 bug 2, Agentist-Elder, 2026-07-21).
|
|
647
|
+
//
|
|
648
|
+
// This captured stderr and then threw it away, so every hard failure β a crash, a missing
|
|
649
|
+
// module, a bad model path β arrived looking identical to a slow first-run download. That is
|
|
650
|
+
// exactly how a total grounding outage (a static import of a module missing from the bundle,
|
|
651
|
+
// crashing before any model code ran) presented as the reassuring line above and cost the
|
|
652
|
+
// reporter a full debugging session to attribute. Their words, and they are right: this
|
|
653
|
+
// wrapper "will hide the *next* breakage too, whatever it is."
|
|
654
|
+
//
|
|
655
|
+
// A diagnostic that discards the diagnosis is worse than no diagnostic, because it reads as
|
|
656
|
+
// information. Print it. Truncated, because a stack trace is not a friendly install screen β
|
|
657
|
+
// but never hidden.
|
|
658
|
+
const err = `${r.stderr || ''}`.trim();
|
|
659
|
+
if (err) {
|
|
660
|
+
const lines = err.split('\n');
|
|
661
|
+
info(c.dim(' the reader reported:'));
|
|
662
|
+
for (const line of lines.slice(0, 12)) info(c.dim(` ${line.slice(0, 200)}`));
|
|
663
|
+
if (lines.length > 12) info(c.dim(` β¦ ${lines.length - 12} more line(s)`));
|
|
664
|
+
}
|
|
665
|
+
return { ran: true, grounded: false, reason: 'no-answer', stderr: err.slice(0, 4000) };
|
|
647
666
|
}
|
|
648
667
|
|
|
649
668
|
const verifier = await loadCitationVerifier(cacheDir);
|
|
@@ -709,6 +728,12 @@ function runDemo() {
|
|
|
709
728
|
const out = `${r.stdout || ''}`.trim();
|
|
710
729
|
if (r.status !== 0 || !out) {
|
|
711
730
|
warn(`no answer came back β the local model may still be warming up (run this again in a moment)`);
|
|
731
|
+
// Same discarded-diagnosis bug as smokeQuery() β see the note there (issue #37 bug 2).
|
|
732
|
+
const err = `${r.stderr || ''}`.trim();
|
|
733
|
+
if (err) {
|
|
734
|
+
info(c.dim(' the reader reported:'));
|
|
735
|
+
for (const line of err.split('\n').slice(0, 8)) info(c.dim(` ${line.slice(0, 200)}`));
|
|
736
|
+
}
|
|
712
737
|
continue;
|
|
713
738
|
}
|
|
714
739
|
// Show the top hit's actual citation (repo/path/title + the start of its real cited text) β
|
|
@@ -732,14 +757,20 @@ function runDemo() {
|
|
|
732
757
|
}
|
|
733
758
|
|
|
734
759
|
// ββ token meter one-liner for --doctor (ADR-0011 token_cost_efficiency) ββββββββββββββββββββββββββ
|
|
735
|
-
// The hooks + MCP server append one JSON line per fire to
|
|
736
|
-
//
|
|
737
|
-
//
|
|
738
|
-
//
|
|
760
|
+
// The hooks + MCP server append one JSON line per fire to a SINGLE user-level ledger at
|
|
761
|
+
// ~/.cache/ruvnet-brain/token-ledger.jsonl (see scripts/token-report.mjs for the full breakdown).
|
|
762
|
+
// It used to be written per-CWD, which scattered hidden .ruvnet-brain/ directories through users'
|
|
763
|
+
// project trees and dirtied their git status β issue #36. Each line now carries a `cwd` field, so
|
|
764
|
+
// the per-project view survives without writing anything into a project.
|
|
765
|
+
// Fail-silent by design: a meter problem never reddens a checkup.
|
|
739
766
|
function meterSummaryLine() {
|
|
740
767
|
try {
|
|
741
|
-
const
|
|
742
|
-
|
|
768
|
+
const canonical = path.join(process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache'), 'ruvnet-brain', 'token-ledger.jsonl');
|
|
769
|
+
const legacy = path.join(process.cwd(), '.ruvnet-brain', 'token-ledger.jsonl');
|
|
770
|
+
// Read the legacy per-project ledger only if it exists and the canonical one does not β an
|
|
771
|
+
// existing user's measurements should not disappear the day the location changes.
|
|
772
|
+
const ledger = fs.existsSync(canonical) || !fs.existsSync(legacy) ? canonical : legacy;
|
|
773
|
+
if (!fs.existsSync(ledger)) return 'meter: no data yet (appears after the first hook/MCP fire)';
|
|
743
774
|
const since = new Date();
|
|
744
775
|
since.setHours(0, 0, 0, 0);
|
|
745
776
|
since.setDate(since.getDate() - 1); // start of yesterday, local time
|
|
@@ -850,6 +881,33 @@ async function doctor() {
|
|
|
850
881
|
// no env β every field is generic. The user still writes and posts the actual feedback themselves.
|
|
851
882
|
const DISCUSSIONS_URL = `https://github.com/${REPO}/discussions`;
|
|
852
883
|
|
|
884
|
+
/**
|
|
885
|
+
* Compare two release tags. Returns >0 if a is newer, <0 if older, 0 if equal.
|
|
886
|
+
*
|
|
887
|
+
* Local to this file on purpose: bin/install.mjs is the ONLY file that runs before anything is
|
|
888
|
+
* installed, so it may not import from scripts/ (which isn't in the npm `files` list). Duplicating
|
|
889
|
+
* ~10 lines is the correct trade against an installer that cannot run.
|
|
890
|
+
*
|
|
891
|
+
* Prerelease handling matters here because every tag this project ships is `X.Y.Z-dev`. Numeric
|
|
892
|
+
* parts compare numerically (so 3.10.0 > 3.9.0, which a string compare gets backwards), and a
|
|
893
|
+
* release WITHOUT a prerelease suffix outranks the same numbers WITH one, per semver.
|
|
894
|
+
*/
|
|
895
|
+
function cmpTag(a, b) {
|
|
896
|
+
const parse = (v) => {
|
|
897
|
+
const [core, pre = ''] = String(v).replace(/^v/, '').split('-');
|
|
898
|
+
return { nums: core.split('.').map((n) => parseInt(n, 10) || 0), pre };
|
|
899
|
+
};
|
|
900
|
+
const A = parse(a), B = parse(b);
|
|
901
|
+
for (let i = 0; i < Math.max(A.nums.length, B.nums.length); i++) {
|
|
902
|
+
const d = (A.nums[i] || 0) - (B.nums[i] || 0);
|
|
903
|
+
if (d !== 0) return d > 0 ? 1 : -1;
|
|
904
|
+
}
|
|
905
|
+
if (A.pre === B.pre) return 0;
|
|
906
|
+
if (!A.pre) return 1; // 3.5.0 is newer than 3.5.0-dev
|
|
907
|
+
if (!B.pre) return -1;
|
|
908
|
+
return A.pre > B.pre ? 1 : -1;
|
|
909
|
+
}
|
|
910
|
+
|
|
853
911
|
function installedBrainVersion(cacheDir) {
|
|
854
912
|
// Same read the telemetry ping uses: the bundle stamps its Release tag into SOURCE.json.
|
|
855
913
|
// "unknown" is honest for a locally-built or pre-stamping bundle β never guess a tag.
|
|
@@ -2386,6 +2444,7 @@ It is safe to re-run at any time. After installing, restart Claude Code so the g
|
|
|
2386
2444
|
// that is what happened, instead of implying everything is up to date.
|
|
2387
2445
|
const alreadyInstalled = fs.existsSync(path.join(cacheDir, 'forge-mcp-all.mjs'));
|
|
2388
2446
|
let staleSkip = false;
|
|
2447
|
+
let ahead = false;
|
|
2389
2448
|
let installedTag = null;
|
|
2390
2449
|
let latestTag = null;
|
|
2391
2450
|
let resolvedRelease = null; // reused below so the release is resolved at most once
|
|
@@ -2406,12 +2465,28 @@ It is safe to re-run at any time. After installing, restart Claude Code so the g
|
|
|
2406
2465
|
} catch { latestTag = null; }
|
|
2407
2466
|
const norm = (v) => (v == null || v === 'unknown' ? null : String(v).replace(/^v/, ''));
|
|
2408
2467
|
const a = norm(installedTag), b = norm(latestTag);
|
|
2409
|
-
//
|
|
2410
|
-
|
|
2468
|
+
// BEHIND => download. SAME => skip. AHEAD => skip, and say so honestly.
|
|
2469
|
+
//
|
|
2470
|
+
// This was a bare `a !== b`, which treats "newer than the latest release" as staleness. Anyone
|
|
2471
|
+
// running a pre-release or dev build β or who simply updated in the window before a release was
|
|
2472
|
+
// cut β was told "Brain is out of date" and pushed through a 2 GB download that would DOWNGRADE
|
|
2473
|
+
// them. Found 2026-07-22 the moment this repo's own version moved to 3.5.0-dev ahead of the
|
|
2474
|
+
// 3.4.22-dev release: the installer immediately declared its own newest brain stale.
|
|
2475
|
+
//
|
|
2476
|
+
// stack-sync.mjs has modelled AHEAD as legal from the start ("AHEAD is legal and produces NO
|
|
2477
|
+
// recommendation β that modelling choice is what makes the alpha-vs-latest downgrade war
|
|
2478
|
+
// structurally impossible"). The installer never learned the same lesson. It has now.
|
|
2479
|
+
ahead = Boolean(a && b && cmpTag(a, b) > 0);
|
|
2480
|
+
staleSkip = Boolean(b && (a === null || (a !== b && !ahead)));
|
|
2411
2481
|
}
|
|
2412
2482
|
|
|
2413
2483
|
if (alreadyInstalled && !FLAG_FORCE && !staleSkip) {
|
|
2414
|
-
if (latestTag) {
|
|
2484
|
+
if (latestTag && ahead) {
|
|
2485
|
+
// Never silently imply equality when the user is AHEAD β that would be a small lie, and it is
|
|
2486
|
+
// the one that hides a downgrade. Skipping is right; misdescribing why is not.
|
|
2487
|
+
step('Brain already current β skipping the download', `installed ${installedTag} is NEWER than the latest release (${latestTag})`);
|
|
2488
|
+
ok(`found an up-to-date brain at ${cacheDir} β nothing to download, and we will never downgrade you`);
|
|
2489
|
+
} else if (latestTag) {
|
|
2415
2490
|
step('Brain already current β skipping the download', `installed ${installedTag} matches the latest release`);
|
|
2416
2491
|
ok(`found an up-to-date brain at ${cacheDir}`);
|
|
2417
2492
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ruvnet-brain",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.1-dev",
|
|
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": {
|