ruvnet-brain 4.7.8 → 4.7.9
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
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ruvnet-brain",
|
|
3
|
-
"version": "4.7.
|
|
3
|
+
"version": "4.7.9",
|
|
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.9",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Stuart Kerr"
|
|
7
7
|
},
|
|
@@ -709,7 +709,9 @@ function securityAlertWork() {
|
|
|
709
709
|
}
|
|
710
710
|
|
|
711
711
|
const observations = [...artifactOpenWork(), ...redCiOpenWork(), ...openPrWork(), ...securityAlertWork()];
|
|
712
|
-
|
|
712
|
+
// Quiet by default (2026-10-15): an observed open issue/PR/CI row is information the user can read on GitHub;
|
|
713
|
+
// printing it on every Stop turned an advisory into per-turn noise. RUVNET_STOP_NUDGES=full restores it.
|
|
714
|
+
if (observations.length && STOP_NUDGES_FULL) console.error(JSON.stringify({ kind: 'continuation-advisory',
|
|
713
715
|
authority: false, items: observations.map(({ text, at }) => ({ text, at })) }));
|
|
714
716
|
// ONE correction per turn: a single item however many claims the answer made; the stop_hook_active
|
|
715
717
|
// exit and the cooldown lock below bound it to one request per stop episode.
|
|
@@ -16,7 +16,20 @@ export function sharedLockStatus({ brainHome, alive = pid => { try { process.kil
|
|
|
16
16
|
export function acquireDeveloperLock({ brainHome, token = process.env.RUVNET_DEVELOPER_UPDATE_TOKEN, pid = process.pid, alive } = {}) {
|
|
17
17
|
const status = sharedLockStatus({ brainHome, alive });
|
|
18
18
|
if (token && status.state === 'running' && status.owner.token === token) return { token, ownerPid: status.owner.pid, inherited: true, release() {} };
|
|
19
|
-
|
|
19
|
+
// A dead owner's lock (dead for 10+ minutes) must not wedge every future update (measured 2026-10-15: a coordinator killed mid-run
|
|
20
|
+
// left `stale` behind and the automatic updater refused with "developer update lock stale" until a person
|
|
21
|
+
// removed the directory). Reclaim it: move the directory aside atomically (so two reclaimers cannot both
|
|
22
|
+
// win), then fall through to the normal atomic mkdir claim. Only a PROVABLY dead pid qualifies; a live,
|
|
23
|
+
// unknown or malformed lock still refuses.
|
|
24
|
+
const STALE_RECLAIM_MS = 10 * 60 * 1000;
|
|
25
|
+
const ageMs = status.state === 'stale' ? Date.now() - Date.parse(status.owner?.startedAt || '') : NaN;
|
|
26
|
+
if (status.state === 'stale' && Number.isFinite(ageMs) && ageMs >= STALE_RECLAIM_MS) {
|
|
27
|
+
const tomb = `${status.directory}.stale-${process.pid}-${Date.now()}`;
|
|
28
|
+
try { fs.renameSync(status.directory, tomb); fs.rmSync(tomb, { recursive: true, force: true }); }
|
|
29
|
+
catch { /* another reclaimer won, or the owner came back: re-read below */ }
|
|
30
|
+
const after = sharedLockStatus({ brainHome, alive });
|
|
31
|
+
if (after.state !== 'idle') throw Error(`developer update lock ${after.state}; ${after.directory}`);
|
|
32
|
+
} else if (status.state !== 'idle') throw Error(`developer update lock ${status.state}; ${status.directory}`);
|
|
20
33
|
fs.mkdirSync(path.dirname(status.directory), { recursive: true });
|
|
21
34
|
fs.mkdirSync(status.directory, { mode: 0o700 }); // atomic claim; racing owners get EEXIST
|
|
22
35
|
const owner = { pid, token: crypto.randomUUID(), startedAt: new Date().toISOString() };
|