ruvnet-brain 4.7.1 → 4.7.3

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
- [![RuvNet Brain version 4.6.2 — README updated 2026-10-10 EDT](https://img.shields.io/badge/version_4.7.1-updated_2026--10--10_EDT-1E90FF?style=for-the-badge&labelColor=0757BA)](plugin/.claude-plugin/plugin.json)
12
+ [![RuvNet Brain version 4.6.2 — README updated 2026-10-10 EDT](https://img.shields.io/badge/version_4.7.3-updated_2026--10--10_EDT-1E90FF?style=for-the-badge&labelColor=0757BA)](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.1",
3
+ "version": "4.7.3",
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.1",
4
+ "version": "4.7.3",
5
5
  "author": {
6
6
  "name": "Stuart Kerr"
7
7
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvnet-brain",
3
- "version": "4.7.1",
3
+ "version": "4.7.3",
4
4
  "description": "Source-grounded RuvNet knowledge, lifecycle enforcement, and learning for Codex.",
5
5
  "author": {
6
6
  "name": "Stuart Kerr"
@@ -17,6 +17,9 @@
17
17
  import { execFileSync } from 'node:child_process';
18
18
 
19
19
  const CODEX_EXEC = /(^|\/)codex(\s+\S+)*\s+exec(\s|$)/;
20
+ // Grok's headless entry points (`grok --help`): -p/--single, --prompt-file, --prompt-json and the `agent` subcommand.
21
+ // Measured 2026-10-13 under `grok -p`: the hook's parent is `grok -p ...` and its env carries GROK_HOOK_EVENT and GROK_SESSION_ID.
22
+ const GROK_HEADLESS = /(^|\/)grok(\s+\S+)*\s+(-p|--single|--prompt-file|--prompt-json|agent)(\s|$)/;
20
23
  const MAX_ANCESTORS = 12;
21
24
 
22
25
  function psRow(pid) {
@@ -28,13 +31,15 @@ function psRow(pid) {
28
31
  /** True when the hook belongs to an automated run. `ps` is injectable for tests. */
29
32
  export function isAutomatedRun({ env = process.env, ppid = process.ppid, ps = psRow } = {}) {
30
33
  if (/^sdk-/.test(env.CLAUDE_CODE_ENTRYPOINT || '')) return true;
31
- if (env.RUVNET_HOOK_HOST !== 'codex') return false;
34
+ const grok = env.RUVNET_HOOK_HOST === 'grok' || Boolean(env.GROK_HOOK_EVENT || env.GROK_SESSION_ID);
35
+ const pattern = env.RUVNET_HOOK_HOST === 'codex' ? CODEX_EXEC : grok ? GROK_HEADLESS : null;
36
+ if (!pattern) return false;
32
37
  try {
33
38
  let pid = ppid;
34
39
  for (let i = 0; i < MAX_ANCESTORS && pid > 1; i++) {
35
40
  const row = ps(pid);
36
41
  if (!row) return false;
37
- if (CODEX_EXEC.test(row.args)) return true;
42
+ if (pattern.test(row.args)) return true;
38
43
  pid = row.ppid;
39
44
  }
40
45
  } catch { /* unknown parent: keep gating */ }
@@ -111,14 +111,20 @@ export function parseCodingAgentEvidence(html, methodology, { url, checkedAt, id
111
111
  }
112
112
  const source = { url, checkedAt, sha256: digest(html), parser: 'aa-coding-agents-flight-v1' };
113
113
  const records = [];
114
+ const skippedIncomplete = [];
114
115
  for (const row of rows.values()) {
116
+ const nativeHost = row.agentName === 'Codex' && row.provider === 'openai' ? 'codex'
117
+ : row.agentName === 'Claude Code' && row.provider === 'anthropic' ? 'claude-code' : null;
115
118
  if (!finite(row.indexScore) || row.indexScore > 1 || !finite(row.mean?.costUsd) || !finite(row.mean?.agentWallTimeSec)
116
119
  || !row.display?.model || !Array.isArray(row.evals) || row.evals.length !== row.indexComponentCount || !row.versions
117
120
  || row.evals.some((e) => !e.datasetIndexName || !finite(e.mean?.reward))) {
118
- throw new Error(`Incomplete coding-agent record: ${row.id}`);
121
+ // A routable (Codex / Claude Code) row must be complete or the whole refresh fails; an incomplete row from a
122
+ // harness we never route to is dropped and disclosed so one third-party null cannot block the weekly review.
123
+ if (nativeHost) throw new Error(`Incomplete coding-agent record: ${row.id}`);
124
+ skippedIncomplete.push({ sourceId: row.id, harness: row.agentName ?? null, provider: row.provider ?? null,
125
+ displayModel: row.display?.model ?? null });
126
+ continue;
119
127
  }
120
- const nativeHost = row.agentName === 'Codex' && row.provider === 'openai' ? 'codex'
121
- : row.agentName === 'Claude Code' && row.provider === 'anthropic' ? 'claude-code' : null;
122
128
  const binding = nativeHost ? identityBindings[row.modelRelease?.slug] : null;
123
129
  if (binding && (!binding.model || !binding.evidence || !binding.checkedAt)) throw new Error('Invalid coding-agent native identity binding');
124
130
  const effort = nativeHost ? row.display.model.match(/\((low|medium|high|xhigh|max|minimal|none)\)/i)?.[1]?.toLowerCase() ?? null : null;
@@ -135,5 +141,6 @@ export function parseCodingAgentEvidence(html, methodology, { url, checkedAt, id
135
141
  }
136
142
  if (!records.length) throw new Error('Coding-agent structured records absent');
137
143
  return { source, records, coverage: { scope: 'public serialized agent/configuration records; native entitlements unverified',
138
- recordCount: records.length, renderedChartSelectionVerified: false }, selectionQualified: false };
144
+ recordCount: records.length, skippedIncompleteCount: skippedIncomplete.length, skippedIncomplete,
145
+ renderedChartSelectionVerified: false }, selectionQualified: false };
139
146
  }