ruvnet-brain 4.7.13 → 4.7.15
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
CHANGED
|
@@ -9,7 +9,7 @@ Created: 2026-06-29 22:36:38 EDT
|
|
|
9
9
|
|
|
10
10
|
### Discover the stack. Read the source. Build with confidence.
|
|
11
11
|
|
|
12
|
-
[](plugin/.claude-plugin/plugin.json)
|
|
13
13
|
|
|
14
14
|
**A source-grounded companion for Claude Code and Codex that helps you find and use Reuven Cohen's (rUv's) RuvNet ecosystem.**
|
|
15
15
|
|
|
@@ -255,7 +255,7 @@ uses the protected release workflow; a consumer update downloads an available ge
|
|
|
255
255
|
does not rebuild upstream knowledge. Check `--doctor`, `SOURCE.json` and refresh receipts
|
|
256
256
|
before treating an installation as current.
|
|
257
257
|
|
|
258
|
-
The **4.6.0 published-corpus baseline** is **203 public stores · 164,
|
|
258
|
+
The **4.6.0 published-corpus baseline** is **203 public stores · 164,668 public source chunks**.
|
|
259
259
|
Those are bundle census values, not a claim that every upstream repository is fresh today.
|
|
260
260
|
Later corpus publication may advance the knowledge generation independently of code changes.
|
|
261
261
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ruvnet-brain",
|
|
3
|
-
"version": "4.7.
|
|
3
|
+
"version": "4.7.15",
|
|
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": {
|
|
@@ -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.7.
|
|
4
|
+
"version": "4.7.15",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Stuart Kerr"
|
|
7
7
|
},
|
|
@@ -286,7 +286,7 @@ export async function synchronizePlugins(run, dryRun, notes, { home, prefix, sco
|
|
|
286
286
|
if (JSON.stringify(flags) !== JSON.stringify(pluginFlags(writable, home))) throw Error('Codex plugin enablement changed');
|
|
287
287
|
return { before, after, steps, provider };
|
|
288
288
|
}
|
|
289
|
-
function knowledge(run, dryRun, runId, { brainHome, root, node }) {
|
|
289
|
+
export function knowledge(run, dryRun, runId, { brainHome, root, node }) {
|
|
290
290
|
const kb = path.join(brainHome, 'kb'), updater = path.join(kb, 'forge-update.mjs');
|
|
291
291
|
if (!exists(updater)) throw Error('existing Brain KB updater absent; fresh install refused');
|
|
292
292
|
const file = path.join(brainHome, `nightly-suite-corpus-${runId}.json`);
|
|
@@ -299,7 +299,10 @@ function knowledge(run, dryRun, runId, { brainHome, root, node }) {
|
|
|
299
299
|
}
|
|
300
300
|
const before = check();
|
|
301
301
|
if (before.currencyVerdict === 'CURRENT' || before.currencyVerdict === 'REFUSED') return { before, after: before, state: before.currencyVerdict === 'CURRENT' ? 'current' : 'ahead-preserved' };
|
|
302
|
-
|
|
302
|
+
// UNKNOWN is what a tree installed from a code release reports (no corpus generation stamp): forge-update
|
|
303
|
+
// documents it as apply-allowed, exactly like UPDATE_AVAILABLE, and the check after the apply must reach
|
|
304
|
+
// CURRENT or REFUSED. Throwing here failed every scheduled night until someone ran --update by hand.
|
|
305
|
+
if (before.currencyVerdict !== 'UPDATE_AVAILABLE' && before.currencyVerdict !== 'UNKNOWN') throw Error(`corpus currency unverified: ${before.currencyVerdict}`);
|
|
303
306
|
if (dryRun) return { before, state: 'update-available' };
|
|
304
307
|
const installer = path.join(root, 'ruvnet-brain/bin/install.mjs');
|
|
305
308
|
if (!exists(installer)) throw Error('existing Brain installer absent');
|
|
@@ -315,10 +315,28 @@ function runUpdater({ kbDir, env, resultFile }) {
|
|
|
315
315
|
});
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
318
|
+
// An anonymous GitHub API read from a shared runner address is sometimes refused (403/429) or fails (5xx)
|
|
319
|
+
// for a moment; one such blip must not fail the night. The same call is retried after a short wait.
|
|
320
|
+
const TRANSIENT_HTTP = new Set([403, 429, 500, 502, 503, 504]);
|
|
321
|
+
async function fetchJson(url, what, { retryDelayMs = 15_000, maxAttempts = 4 } = {}) {
|
|
322
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
323
|
+
let status = null;
|
|
324
|
+
try {
|
|
325
|
+
const response = await fetch(url, { headers: { accept: 'application/vnd.github+json' } });
|
|
326
|
+
if (response.ok) return await response.json();
|
|
327
|
+
status = response.status;
|
|
328
|
+
if (!TRANSIENT_HTTP.has(status)) throw new Error(`${what} returned HTTP ${status}`);
|
|
329
|
+
} catch (error) {
|
|
330
|
+
if (status !== null && !TRANSIENT_HTTP.has(status)) throw error;
|
|
331
|
+
if (status === null && attempt >= maxAttempts) throw error;
|
|
332
|
+
}
|
|
333
|
+
if (attempt >= maxAttempts) throw new Error(`${what} returned HTTP ${status}`);
|
|
334
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs * attempt));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async function fetchRelease({ apiBase, repo, tag, retryDelayMs }) {
|
|
339
|
+
return fetchJson(candidateManifestUrl({ apiBase, repo, tag }), `release ${tag}`, { retryDelayMs });
|
|
322
340
|
}
|
|
323
341
|
|
|
324
342
|
/**
|
|
@@ -340,10 +358,8 @@ export const CANARY_CASES = Object.freeze({
|
|
|
340
358
|
'older-runtime': Object.freeze({ runtime: 'N-1', door: 'installer', overlay: false }),
|
|
341
359
|
});
|
|
342
360
|
|
|
343
|
-
async function fetchReleaseList({ apiBase, repo }) {
|
|
344
|
-
|
|
345
|
-
if (!response.ok) throw new Error(`release list returned HTTP ${response.status}`);
|
|
346
|
-
return response.json();
|
|
361
|
+
async function fetchReleaseList({ apiBase, repo, retryDelayMs }) {
|
|
362
|
+
return fetchJson(`${apiBase}/repos/${repo}/releases?per_page=100`, 'release list', { retryDelayMs });
|
|
347
363
|
}
|
|
348
364
|
|
|
349
365
|
/** The footprint of a customer HOME after one update (plugin/scripts/brain-footprint.mjs, never restated). */
|
|
@@ -372,7 +388,7 @@ async function runCase({ name, spec, repo, tag, approvedVersion, release, work,
|
|
|
372
388
|
retryDelayMs, maxAttempts, log, writerRoot, approvedInstaller, footprintUpdates = false }) {
|
|
373
389
|
fs.mkdirSync(home, { recursive: true });
|
|
374
390
|
let runtime = approvedVersion;
|
|
375
|
-
if (spec.runtime !== 'approved') runtime = resolveRuntime(spec.runtime, { candidateTag: `v${approvedVersion}`, releases: await fetchReleaseList({ apiBase, repo }) });
|
|
391
|
+
if (spec.runtime !== 'approved') runtime = resolveRuntime(spec.runtime, { candidateTag: `v${approvedVersion}`, releases: await fetchReleaseList({ apiBase, repo, retryDelayMs }) });
|
|
376
392
|
const installed = await install({ approvedVersion: runtime, work, home, log });
|
|
377
393
|
const { kbDir } = installed;
|
|
378
394
|
home = installed.home || home;
|
|
@@ -465,7 +481,7 @@ export async function runCanary({
|
|
|
465
481
|
throw new Error(`--cases must start with clean and name only: ${Object.keys(CANARY_CASES).join(', ')}`);
|
|
466
482
|
}
|
|
467
483
|
const started = now();
|
|
468
|
-
const release = await fetchRelease({ apiBase, repo, tag });
|
|
484
|
+
const release = await fetchRelease({ apiBase, repo, tag, retryDelayMs });
|
|
469
485
|
// The approved package's installer — what `npx ruvnet-brain@latest` runs — fetched once, on demand.
|
|
470
486
|
let installerPath = null;
|
|
471
487
|
const resolveInstaller = approvedInstaller || (async () => {
|