ruvnet-brain 4.3.3 โ 4.3.8
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 +1 -1
- package/bin/install.mjs +8 -7
- package/data/model-catalog.json +3 -3
- package/package.json +2 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/scripts/learn-flush.mjs +1 -1
- package/plugin/skills/release-proof/SKILL.md +19 -10
- package/plugin/skills/release-proof/references/receipt-contract.md +18 -8
- package/scripts/candidate-host-evidence.mjs +9 -2
- package/scripts/execution-policy.mjs +49 -4
- package/scripts/execution-preflight.mjs +18 -0
- package/scripts/host-install-matrix.mjs +247 -40
- package/scripts/integration-evidence.mjs +73 -0
- package/scripts/nightly-wrapper.sh +4 -3
- package/scripts/onboarding-console.mjs +3 -3
- package/scripts/prepublication-evidence.mjs +174 -0
- package/scripts/protected-release-invocation.mjs +32 -4
- package/scripts/public-verification-aggregate.mjs +24 -53
- package/scripts/qa-runner.mjs +1 -0
- package/scripts/refresh-model-catalog.mjs +32 -3
- package/scripts/release-authority.mjs +19 -7
- package/scripts/release-convergence-watchdog.mjs +10 -22
- package/scripts/release-transaction.mjs +1 -1
- package/scripts/release.mjs +4 -5
- package/scripts/source-coverage.mjs +11 -2
- package/scripts/staged-host-verifier.mjs +2 -2
- package/scripts/wired-check.mjs +1 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
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
|
|
package/bin/install.mjs
CHANGED
|
@@ -2245,16 +2245,17 @@ async function doctor() {
|
|
|
2245
2245
|
hookResult = await runSelfCheck({ installState: { repos: v.repos, reader: v.reader, mcp: v.mcp } });
|
|
2246
2246
|
}
|
|
2247
2247
|
|
|
2248
|
-
// โโ THE PERSISTED GROUNDING VERDICT (ADR-058 ยงD8) โ
|
|
2249
|
-
//
|
|
2250
|
-
//
|
|
2251
|
-
//
|
|
2252
|
-
//
|
|
2253
|
-
// (the live smoke result printed above already updates the SAME file the next real install or
|
|
2254
|
-
// search_ruvnet touches; this just reads back whatever the most recent real attempt recorded).
|
|
2248
|
+
// โโ THE PERSISTED GROUNDING VERDICT (ADR-058 ยงD8) โ synchronize stronger live proof first โโโโโโโ
|
|
2249
|
+
// A failed install smoke stays non-fatal there. `--doctor` is different: it is the command someone
|
|
2250
|
+
// runs SPECIFICALLY TO ASK whether the install is healthy, so this is the one place an unresolved
|
|
2251
|
+
// "unproven" verdict DOES gate the exit code. Its successful live citation proof above must clear
|
|
2252
|
+
// an older failure before this read; otherwise one invocation can print both PROVEN and UNPROVEN.
|
|
2255
2253
|
let groundingUnprovenPersisted = false;
|
|
2256
2254
|
try {
|
|
2257
2255
|
const mod = await import(new URL('../scripts/selfcheck.mjs', import.meta.url).href);
|
|
2256
|
+
if (smoke.grounded === true) {
|
|
2257
|
+
mod.writeInstallState({ grounding: 'proven', reason: null, clearedBy: 'doctor-live-proof' });
|
|
2258
|
+
}
|
|
2258
2259
|
groundingUnprovenPersisted = mod.groundingUnproven(mod.readInstallState());
|
|
2259
2260
|
if (groundingUnprovenPersisted) {
|
|
2260
2261
|
console.log(` ${c.yellow('! Grounding UNPROVEN')} (recorded at ${c.bold(mod.installStatePath())}).`);
|
package/data/model-catalog.json
CHANGED
|
@@ -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-
|
|
7
|
+
"prices": "OpenRouter /api/v1/models live catalog, pulled 2026-09-04 (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.",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
],
|
|
56
56
|
"frontier": {
|
|
57
57
|
"model": "openai/gpt-5.6-sol",
|
|
58
|
-
"in": 2
|
|
59
|
-
"out":
|
|
58
|
+
"in": 2,
|
|
59
|
+
"out": 10,
|
|
60
60
|
"released": "2026-07-09",
|
|
61
61
|
"rank": "AA Intelligence #2 (59) ยท AA Coding Index leader (80) ยท Terminal-Bench 2.1 SOTA ยท ~1/3 Fable 5's cost/task",
|
|
62
62
|
"source": "independent (AA)"
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ruvnet-brain",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.8",
|
|
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": {
|
|
7
7
|
"ruvnet-brain": "bin/install.mjs"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
+
"prepublishOnly": "node scripts/protected-release-invocation.mjs --prepublish-only",
|
|
10
11
|
"test": "node plugin/test/run-tests.mjs",
|
|
11
12
|
"release:proof": "node scripts/release-proof.mjs",
|
|
12
13
|
"benchmark:brain50": "node scripts/brain-latency-50.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 an enforced UserPromptSubmit retrieve-and-inject grounding hook that sharply reduces drift.",
|
|
4
|
-
"version": "4.3.
|
|
4
|
+
"version": "4.3.8",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Stuart Kerr"
|
|
7
7
|
},
|
|
@@ -29,7 +29,7 @@ const HOME = os.homedir();
|
|
|
29
29
|
// SAME CLAUDE_PROJECT_DIR-with-containment rule #85/#107 already fixed for the receipt/Console
|
|
30
30
|
// agreement โ reused here rather than trusting the variable unconditionally, which would reopen the
|
|
31
31
|
// class of bug #107 was: an unrelated declared root overruling a cwd it does not actually contain.
|
|
32
|
-
const PROJECT = process.env.RUVNET_BRAIN_PROJECT_DIR || projectDirectory();
|
|
32
|
+
const PROJECT = process.env.RUVNET_BRAIN_PROJECT_DIR || projectDirectory({ env: process.env });
|
|
33
33
|
// ISSUE #139 โ this WRITER resolved scope correctly while two READERS hardcoded it, so they agreed
|
|
34
34
|
// only by coincidence. The resolution moved into runtime-preferences.mjs and all three now call it;
|
|
35
35
|
// a future scope is one edit, not three. Behaviour here is unchanged by design.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: release-proof
|
|
3
|
-
description: Fail-closed exact-artifact release and deployment authority. Use before saying a release is ready, pushing a release commit, publishing npm packages, creating GitHub releases, deploying production, closing release-blocking issues, or claiming all gates are green. Requires clean immutable lineage, zero
|
|
3
|
+
description: Fail-closed exact-artifact release and deployment authority. Use before saying a release is ready, pushing a release commit, publishing npm packages, creating GitHub releases, deploying production, closing release-blocking issues, or claiming all gates are green. Requires clean immutable lineage, zero labeled release blockers, exact-SHA GitHub success, nonzero no-skip QE, packed-artifact host tests, installed Brain/RVF proof, and post-publication byte verification.
|
|
4
|
+
updated: 2026-09-04
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Release Proof
|
|
@@ -12,10 +13,12 @@ green.
|
|
|
12
13
|
## Non-bypassable rules
|
|
13
14
|
|
|
14
15
|
1. Use the exact source SHA and one packed-artifact SHA-256 everywhere.
|
|
15
|
-
2. Require zero open GitHub issues
|
|
16
|
-
3.
|
|
16
|
+
2. Require zero open GitHub issues labeled `release-blocker`. Unlabeled backlog is not release authority; a local fix does not clear a labeled blocker.
|
|
17
|
+
3. Run CI, integration, UX, and stranger qualification once in
|
|
18
|
+
`.github/workflows/release-candidate-preflight.yml` on `release/**`. Require its exact-SHA,
|
|
19
|
+
source-bound package and aggregate before that unchanged SHA reaches `main`.
|
|
17
20
|
4. Reject any test/QE result with zero tests, skips, todos, unknowns, pending jobs, or failures.
|
|
18
|
-
5.
|
|
21
|
+
5. When the candidate changes architecture or the retrieval oracle, require the accepted Fable 5 and GPT-5.6-Sol design-review receipts for that change. Routine releases do not manufacture caller-supplied reviewer keys; bundled public keys are integrity material, not an independent trust anchor.
|
|
19
22
|
6. Install the sealed artifact into virgin Claude Code and Codex homes; test their real entrypoints.
|
|
20
23
|
7. Require the source package, Claude manifest, Codex manifest, packed npm version, bundle
|
|
21
24
|
`brainVersion`/`releaseTag`, and both installed host versions to identify one exact generation.
|
|
@@ -29,12 +32,18 @@ green.
|
|
|
29
32
|
|
|
30
33
|
## Candidate seal
|
|
31
34
|
|
|
32
|
-
Generate the receipt
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
`release-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
Generate the candidate receipt in `.github/workflows/release-candidate-preflight.yml`; do not
|
|
36
|
+
hand-author it. The preflight runs the long CI, integration, UX, and stranger lanes once on
|
|
37
|
+
`release/**`, then emits the source-bound package and aggregate as
|
|
38
|
+
`release-candidate-<exact SHA>`. Fast-forward that unchanged SHA to `main`.
|
|
39
|
+
|
|
40
|
+
Dispatch `.github/workflows/protected-release.yml` only after the fast-forward. It is the sole
|
|
41
|
+
publication controller: it proves current `origin/main` is the preflight SHA, selects the artifact
|
|
42
|
+
by its deterministic name rather than a caller-supplied run ID, revalidates every receipt,
|
|
43
|
+
payload/source binding, and digest, then signs and publishes once. The same protected run downloads
|
|
44
|
+
the public bytes, executes the three-OS by three-host-mode matrix, and appends `install-verified`.
|
|
45
|
+
It does not rerun the long preflight lanes. Conditional architecture/retrieval-oracle reviews are
|
|
46
|
+
candidate inputs only when the governed surfaces changed; they do not authorize publication.
|
|
38
47
|
Validate it from the repository with:
|
|
39
48
|
|
|
40
49
|
```bash
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Receipt contract
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Updated: 2026-09-04
|
|
4
|
+
|
|
5
|
+
The authority accepts only typed receipt schemas. The candidate receipts are emitted by
|
|
6
|
+
`release-candidate-preflight` and imported by `protected-release`; publication receipts are emitted
|
|
7
|
+
inside that protected run. All are append-only evidence artifacts, never editable status documents.
|
|
5
8
|
|
|
6
9
|
## Candidate receipt
|
|
7
10
|
|
|
@@ -11,17 +14,20 @@ Required bindings:
|
|
|
11
14
|
- `version`, `tag`, and exact-equal `sourceVersions.package`, `sourceVersions.claudePlugin`, and
|
|
12
15
|
`sourceVersions.codexPlugin`
|
|
13
16
|
- `artifact.path`, `artifact.sha256`, `artifact.sourceSha`
|
|
17
|
+
- artifact name exactly `release-candidate-<sha>`; selection is by name and exact source SHA, never
|
|
18
|
+
by a caller-supplied workflow run ID
|
|
14
19
|
- exact-equal `artifact.version`, `artifact.bundle.brainVersion`, and
|
|
15
20
|
`artifact.bundle.releaseTag`
|
|
16
21
|
- exact-SHA release-vector verdict with zero unknown/skipped
|
|
17
22
|
- aggregate tests with nonzero total, all passed, zero failed/skipped/todo
|
|
18
23
|
- fresh coverage floor and zero critical/high security findings
|
|
19
|
-
- zero open GitHub issues
|
|
24
|
+
- zero open GitHub issues labeled `release-blocker`
|
|
20
25
|
- required GitHub workflow results on the same SHA
|
|
21
26
|
- virgin-home Claude and Codex results on the same artifact digest and exact candidate version
|
|
22
27
|
- installed Brain self-RVF plus narrow, broad, and concurrent cited search timings
|
|
23
28
|
- nonzero Agentic QE totals with zero failed/skipped
|
|
24
|
-
-
|
|
29
|
+
- when architecture or retrieval-oracle surfaces changed, accepted Fable 5 and GPT-5.6-Sol review
|
|
30
|
+
receipts bound to that change; no per-release caller-supplied key can create independent authority
|
|
25
31
|
|
|
26
32
|
## Publication receipt
|
|
27
33
|
|
|
@@ -35,10 +41,14 @@ Required bindings:
|
|
|
35
41
|
- installed Brain self-RVF and broad search within 80 percent of deadline
|
|
36
42
|
- successful exact-SHA `published-surface-probe`
|
|
37
43
|
|
|
44
|
+
Before provider mutation, `protected-release` revalidates the imported candidate receipt, package
|
|
45
|
+
payload, source binding, and digest against current `origin/main`. It consumes the long-lane proof;
|
|
46
|
+
it does not rerun CI, integration, UX, or stranger qualification.
|
|
47
|
+
|
|
38
48
|
## Failure semantics
|
|
39
49
|
|
|
40
|
-
Any missing field, split version identity, malformed digest, mismatched SHA, dirty tree, open
|
|
50
|
+
Any missing field, split version identity, malformed digest, mismatched SHA, dirty tree, open labeled release blocker, absent/pending/red
|
|
41
51
|
workflow, skipped/todo/zero-test result, missing RVF store, uncited search, deadline-margin breach,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
missing required change-triggered design review, or public byte mismatch is `FAIL`. There is no
|
|
53
|
+
warning state and no score average. Preflight owns candidate qualification; one `protected-release`
|
|
54
|
+
run owns import revalidation, publication, public verification, and the terminal receipt.
|
|
@@ -25,7 +25,12 @@ if (result.verdict !== 'PASS') throw new Error(`candidate host matrix failed: ${
|
|
|
25
25
|
const modeNames = { claude: 'claude-only', codex: 'codex-only', dual: 'dual-host' };
|
|
26
26
|
const leaves = Object.entries(modeNames).map(([mode, name]) => {
|
|
27
27
|
const fixture = result.fixtures?.[mode];
|
|
28
|
-
|
|
28
|
+
const grounding = fixture?.grounding;
|
|
29
|
+
const grounded = grounding && ['repo', 'path', 'file', 'storedPath']
|
|
30
|
+
.every((field) => typeof grounding[field] === 'string' && grounding[field].trim());
|
|
31
|
+
if (fixture?.status !== 'PASS' || fixture?.process?.status !== 0 || !grounded) {
|
|
32
|
+
throw new Error(`${name} did not produce a clean installed-search grounding receipt`);
|
|
33
|
+
}
|
|
29
34
|
return {
|
|
30
35
|
name,
|
|
31
36
|
sha: manifest.candidateSha,
|
|
@@ -35,7 +40,9 @@ const leaves = Object.entries(modeNames).map(([mode, name]) => {
|
|
|
35
40
|
verdict: 'PASS',
|
|
36
41
|
source: 'candidate-host-evidence',
|
|
37
42
|
mode,
|
|
38
|
-
|
|
43
|
+
functionalSearch: true,
|
|
44
|
+
searchExit: fixture.process.status,
|
|
45
|
+
grounding,
|
|
39
46
|
artifactSha256: sha256(packagePath),
|
|
40
47
|
};
|
|
41
48
|
});
|
|
@@ -5,6 +5,40 @@
|
|
|
5
5
|
const NATIVE_HOSTS = new Set(['claude', 'codex']);
|
|
6
6
|
const API_EXECUTORS = new Set(['agent_execute', 'sdk', 'openrouter', 'api']);
|
|
7
7
|
const ARCHITECTURE_TERMS = /\b(adr|ddd|architecture|release|deploy|qa|security|schema|migration)\b/i;
|
|
8
|
+
const CONSEQUENTIAL_ACTIONS = new Set(['delegate', 'write', 'release', 'external']);
|
|
9
|
+
const FRESHNESS_MS = 30 * 60 * 1000;
|
|
10
|
+
|
|
11
|
+
const hex64 = (value) => /^[a-f0-9]{64}$/i.test(String(value || ''));
|
|
12
|
+
const fresh = (value, now = Date.now()) => {
|
|
13
|
+
const time = Date.parse(String(value || ''));
|
|
14
|
+
return Number.isFinite(time) && time <= now && now - time <= FRESHNESS_MS;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The classifier used to trust caller-supplied routing fields. That made a correct memory lesson
|
|
19
|
+
* advisory: a caller could omit the live search and AgentDB read and still receive ALLOW. This is
|
|
20
|
+
* the evidence boundary used by the executable preflight. Receipts are intentionally structural;
|
|
21
|
+
* the producers (search_ruvnet and ruflo memory retrieve) own their contents and identities.
|
|
22
|
+
*/
|
|
23
|
+
export function validateEvidence(input = {}, now = Date.now()) {
|
|
24
|
+
const failures = [];
|
|
25
|
+
const grounding = input.groundingReceipt;
|
|
26
|
+
const memory = input.memoryReceipt;
|
|
27
|
+
if (!grounding || grounding.status !== 'success' || !fresh(grounding.observedAt, now)) {
|
|
28
|
+
failures.push('fresh successful search_ruvnet receipt is required');
|
|
29
|
+
} else if (!(Array.isArray(grounding.sources) && grounding.sources.length > 0)
|
|
30
|
+
&& !hex64(grounding.sourceIdentity)) {
|
|
31
|
+
failures.push('grounding receipt must bind a source list or source identity');
|
|
32
|
+
}
|
|
33
|
+
if (!memory || memory.status !== 'retrieved' || !fresh(memory.observedAt, now)) {
|
|
34
|
+
failures.push('fresh exact AgentDB checkpoint retrieval is required');
|
|
35
|
+
} else {
|
|
36
|
+
if (!String(memory.path || '').endsWith('/.swarm/memory.db')) failures.push('memory receipt must use the project .swarm/memory.db');
|
|
37
|
+
if (!/^project-state-current-\d+$/.test(String(memory.key || ''))) failures.push('memory receipt must retrieve an append-only project-state-current key');
|
|
38
|
+
if (!hex64(memory.valueDigest)) failures.push('memory receipt must bind the retrieved value digest');
|
|
39
|
+
}
|
|
40
|
+
return { valid: failures.length === 0, failures };
|
|
41
|
+
}
|
|
8
42
|
|
|
9
43
|
export function classifyExecutionPolicy(input = {}) {
|
|
10
44
|
const action = String(input.action || 'read');
|
|
@@ -24,10 +58,21 @@ export function classifyExecutionPolicy(input = {}) {
|
|
|
24
58
|
? 'architecture-or-consequential-action'
|
|
25
59
|
: 'single-sequential-surface';
|
|
26
60
|
|
|
61
|
+
const evidence = CONSEQUENTIAL_ACTIONS.has(action) && input.enforceEvidence === true
|
|
62
|
+
? validateEvidence(input, input.now ?? Date.now())
|
|
63
|
+
: { valid: true, failures: [] };
|
|
64
|
+
if (!evidence.valid) {
|
|
65
|
+
return {
|
|
66
|
+
schema: 'ruvnet-brain.execution-policy.v1',
|
|
67
|
+
verdict: 'REFUSE', action, swarmRequired, swarmReason,
|
|
68
|
+
executor: 'unknown', reason: 'live-evidence-preflight-failed', evidence,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
27
72
|
if (action !== 'delegate') {
|
|
28
73
|
return {
|
|
29
74
|
schema: 'ruvnet-brain.execution-policy.v1',
|
|
30
|
-
verdict: 'ALLOW', action, swarmRequired, swarmReason,
|
|
75
|
+
verdict: 'ALLOW', action, swarmRequired, swarmReason, evidence,
|
|
31
76
|
executor: 'current-agent', reason: 'delegation-not-requested',
|
|
32
77
|
};
|
|
33
78
|
}
|
|
@@ -37,7 +82,7 @@ export function classifyExecutionPolicy(input = {}) {
|
|
|
37
82
|
if (API_EXECUTORS.has(requestedExecutor)) {
|
|
38
83
|
return {
|
|
39
84
|
schema: 'ruvnet-brain.execution-policy.v1',
|
|
40
|
-
verdict: nativeHost ? 'REFUSE' : 'DEGRADED', action, swarmRequired, swarmReason,
|
|
85
|
+
verdict: nativeHost ? 'REFUSE' : 'DEGRADED', action, swarmRequired, swarmReason, evidence,
|
|
41
86
|
executor: nativeHost ? `native:${nativeHost}` : 'unknown',
|
|
42
87
|
reason: nativeHost
|
|
43
88
|
? 'api-backed-executor-is-not-the-native-subscription-route'
|
|
@@ -47,13 +92,13 @@ export function classifyExecutionPolicy(input = {}) {
|
|
|
47
92
|
if (!nativeHost) {
|
|
48
93
|
return {
|
|
49
94
|
schema: 'ruvnet-brain.execution-policy.v1',
|
|
50
|
-
verdict: 'DEGRADED', action, swarmRequired, swarmReason, executor: 'unknown',
|
|
95
|
+
verdict: 'DEGRADED', action, swarmRequired, swarmReason, executor: 'unknown', evidence,
|
|
51
96
|
reason: 'no-authenticated-native-host-is-available',
|
|
52
97
|
};
|
|
53
98
|
}
|
|
54
99
|
return {
|
|
55
100
|
schema: 'ruvnet-brain.execution-policy.v1',
|
|
56
|
-
verdict: 'ALLOW', action, swarmRequired, swarmReason,
|
|
101
|
+
verdict: 'ALLOW', action, swarmRequired, swarmReason, evidence,
|
|
57
102
|
executor: `native:${nativeHost}`, reason: 'native-subscription-route-selected',
|
|
58
103
|
};
|
|
59
104
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Enforced knowledge-to-execution boundary. The caller must provide receipts produced by the
|
|
3
|
+
// live Brain search and exact project AgentDB retrieval; prose, memory, and guessed host state do
|
|
4
|
+
// not satisfy this command.
|
|
5
|
+
import { classifyExecutionPolicy } from './execution-policy.mjs';
|
|
6
|
+
|
|
7
|
+
export function runExecutionPreflight(input = {}) {
|
|
8
|
+
return classifyExecutionPolicy({ ...input, enforceEvidence: true });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
12
|
+
let input;
|
|
13
|
+
try { input = JSON.parse(process.argv[2] || '{}'); }
|
|
14
|
+
catch { process.stderr.write('execution-preflight: input must be JSON\n'); process.exit(2); }
|
|
15
|
+
const result = runExecutionPreflight(input);
|
|
16
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
17
|
+
process.exit(result.verdict === 'ALLOW' ? 0 : 2);
|
|
18
|
+
}
|