0xray 4.0.7 → 4.0.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./features.schema.json",
3
- "version": "4.0.1",
3
+ "version": "4.0.9",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",
package/README.md CHANGED
@@ -50,6 +50,7 @@ Docs: [guides/autonomy-command](docs-site/docs/guides/autonomy-command.md) · Sk
50
50
 
51
51
  | Version | Highlights |
52
52
  |---------|------------|
53
+ | **4.0.9** | Mill target: postinstall does not mill npm global prefix or `_npx` as a consumer. Isolated HOME skips machine `~/.grok`. |
53
54
  | **4.0.0** | Exo + temperament. Constitution always on; ceremony by host. Repertoire organ on (vendored 0.2). Station card survives compact/host-swap. **On npm.** [vision](docs-site/docs/architecture/v4-vision.md) · [now](docs-site/docs/architecture/v4-now.md) |
54
55
  | **3.4.1** | Unified `install-bridges.cjs` on postinstall — OpenCode, Grok, Hermes, OpenClaw in one pass. All 7 MCPs servers via `npx -y 0xray mcp <cmd>` (no `dist/` paths). Canonical `release.mjs` pipeline. |
55
56
  | **3.3.1** | Orchestrator confidence gate wired into execution planning. |
@@ -60,7 +61,7 @@ Docs: [guides/autonomy-command](docs-site/docs/guides/autonomy-command.md) · Sk
60
61
 
61
62
  ### Consolidations
62
63
 
63
- - **One consumer install path** — `postinstall.cjs` → `installAllBridges()` replaces scattered per-platform setup.
64
+ - **One consumer install path** — `postinstall.cjs` → `installAllBridges()` replaces scattered per-platform setup. **4.0.9:** does not mill npm global prefix or `_npx`.
64
65
  - **7-server MCP surface** — `.mcp.json` SSOT; Grok plugin and all bridges share `XRAY_MCP_SERVERS`.
65
66
  - **Dev vs consumer AGENTS** — `AGENTS.md` (framework) vs `AGENTS-consumer.md` (copied to consumer projects on install).
66
67
  - **Release pipeline** — `npm run release:patch|minor|major` → reconcile → gate → artifacts → tag → publish.
package/dist/CHANGELOG.md CHANGED
@@ -34,6 +34,26 @@ The format is based on [Conventional Commits](https://www.conventionalcommits.or
34
34
 
35
35
  ---
36
36
 
37
+ ## [4.0.9] - 2026-09-11
38
+
39
+ Postinstall does **not** mill npm global prefix or npx cache as a consumer. `resolveConsumerTargetDir` treats `_npx` and a prefix without `package.json` as an install prefix: mill `INIT_CWD` if it is a real project, else mill the 0xray package (dogfood skip). Isolated HOME still skips machine `~/.grok`. Mill plant stays `mill` + `inspect`. Not 45/42 costume. Nested mill stays **0.1.9**. Not 5.0.0.
40
+
41
+ - fix(foundry): do not mill npm global prefix or npx cache as a consumer (b08b19612)
42
+
43
+ ---
44
+
45
+ ## [4.0.8] - 2026-09-11
46
+
47
+ ### 🔄 Changes
48
+
49
+ ### 🔎 Other Changes
50
+ - fix(foundry): mill release gate uses test:comprehensive like mill CI (bd980ea3f)
51
+ - fix(confer): allow undefined on optional local vote fields (e4436af8f)
52
+ - fix(confer): abstain locally; do not rubber-stamp analyze_proposal (0f6c61cbe)
53
+ - fix(confer): local vote when nested LLM is not configured (eb6004b07)
54
+
55
+ ---
56
+
37
57
  ## [4.0.7] - 2026-09-09
38
58
 
39
59
  Nested mill **0.1.9**. Inventory writes `dna` (keccak256 of canonical JSON without `mintedAt`). Inspect echoes dna + pack `0xray-suit`. Mill does not mint on chain. Not 5.0.0.
package/dist/README.md CHANGED
@@ -50,6 +50,7 @@ Docs: [guides/autonomy-command](docs-site/docs/guides/autonomy-command.md) · Sk
50
50
 
51
51
  | Version | Highlights |
52
52
  |---------|------------|
53
+ | **4.0.9** | Mill target: postinstall does not mill npm global prefix or `_npx` as a consumer. Isolated HOME skips machine `~/.grok`. |
53
54
  | **4.0.0** | Exo + temperament. Constitution always on; ceremony by host. Repertoire organ on (vendored 0.2). Station card survives compact/host-swap. **On npm.** [vision](docs-site/docs/architecture/v4-vision.md) · [now](docs-site/docs/architecture/v4-now.md) |
54
55
  | **3.4.1** | Unified `install-bridges.cjs` on postinstall — OpenCode, Grok, Hermes, OpenClaw in one pass. All 7 MCPs servers via `npx -y 0xray mcp <cmd>` (no `dist/` paths). Canonical `release.mjs` pipeline. |
55
56
  | **3.3.1** | Orchestrator confidence gate wired into execution planning. |
@@ -60,7 +61,7 @@ Docs: [guides/autonomy-command](docs-site/docs/guides/autonomy-command.md) · Sk
60
61
 
61
62
  ### Consolidations
62
63
 
63
- - **One consumer install path** — `postinstall.cjs` → `installAllBridges()` replaces scattered per-platform setup.
64
+ - **One consumer install path** — `postinstall.cjs` → `installAllBridges()` replaces scattered per-platform setup. **4.0.9:** does not mill npm global prefix or `_npx`.
64
65
  - **7-server MCP surface** — `.mcp.json` SSOT; Grok plugin and all bridges share `XRAY_MCP_SERVERS`.
65
66
  - **Dev vs consumer AGENTS** — `AGENTS.md` (framework) vs `AGENTS-consumer.md` (copied to consumer projects on install).
66
67
  - **Release pipeline** — `npm run release:patch|minor|major` → reconcile → gate → artifacts → tag → publish.
@@ -5,6 +5,7 @@ export interface GovernanceVote {
5
5
  reasoning: string;
6
6
  }
7
7
  export declare function resolveHermesBin(): string;
8
+ export declare function isGovernanceLlmConfigured(): boolean;
8
9
  export declare function hermesCliAvailable(): boolean;
9
10
  export declare function tryLLMGovernance(role: GovernanceRole, proposalTitle: string, proposalDescription: string, evidence: string[], proposalType: string): Promise<GovernanceVote | null>;
10
11
  export declare function checkHermesOAuthStatus(): {
@@ -94,6 +94,9 @@ function getConfig() {
94
94
  }
95
95
  return null;
96
96
  }
97
+ export function isGovernanceLlmConfigured() {
98
+ return getConfig() !== null;
99
+ }
97
100
  export function hermesCliAvailable() {
98
101
  try {
99
102
  execFileSync(resolveHermesBin(), ["--version"], {
@@ -0,0 +1,10 @@
1
+ import type { GovernanceRole, GovernanceVote } from "./llm-governance-provider.js";
2
+ export type LocalConferInput = {
3
+ role: GovernanceRole;
4
+ highConfidenceTrapPresent?: boolean | undefined;
5
+ recommendedAgent?: string | null | undefined;
6
+ llmConfigured?: boolean | undefined;
7
+ };
8
+ /** Receipt when nested LLM is absent or returned no vote. Never approve — analyze_proposal feeds mergeVotes. */
9
+ export declare function localConferVote(input: LocalConferInput): GovernanceVote;
10
+ export declare function formatGovernanceVoteText(vote: GovernanceVote, extra?: string): string;
@@ -0,0 +1,27 @@
1
+ /** Receipt when nested LLM is absent or returned no vote. Never approve — analyze_proposal feeds mergeVotes. */
2
+ export function localConferVote(input) {
3
+ const role = input.role;
4
+ if (input.llmConfigured) {
5
+ return {
6
+ decision: "abstain",
7
+ confidence: 0.5,
8
+ reasoning: `Local confer (${role}); nested LLM configured but returned no vote.`,
9
+ };
10
+ }
11
+ if (input.highConfidenceTrapPresent) {
12
+ const agent = input.recommendedAgent?.trim() || "architect";
13
+ return {
14
+ decision: "abstain",
15
+ confidence: 0.62,
16
+ reasoning: `Local confer (${role}); nested LLM not configured. Repertoire high-confidence ontological trap — route to ${agent} before implementation.`,
17
+ };
18
+ }
19
+ return {
20
+ decision: "abstain",
21
+ confidence: 0.58,
22
+ reasoning: `Local confer (${role}); nested LLM not configured.`,
23
+ };
24
+ }
25
+ export function formatGovernanceVoteText(vote, extra = "") {
26
+ return `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}${extra}`;
27
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray-pre-tool",
3
- "version": "4.0.4",
3
+ "version": "4.0.9",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
@@ -7,7 +7,8 @@
7
7
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
8
8
  import * as fs from "fs";
9
9
  import * as path from "path";
10
- import { tryLLMGovernance } from "../../governance/llm-governance-provider.js";
10
+ import { isGovernanceLlmConfigured, tryLLMGovernance, } from "../../governance/llm-governance-provider.js";
11
+ import { formatGovernanceVoteText, localConferVote } from "../../governance/local-confer.js";
11
12
  class XrayCodeReviewServer extends XrayKnowledgeSkillBase {
12
13
  constructor() {
13
14
  super("code-review", "3.1.0");
@@ -315,22 +316,16 @@ class XrayCodeReviewServer extends XrayKnowledgeSkillBase {
315
316
  */
316
317
  async analyzeProposal(args) {
317
318
  const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args;
318
- const vote = await tryLLMGovernance("code-review", proposalTitle, proposalDescription, evidence, proposalType);
319
- if (!vote) {
320
- return {
321
- content: [
322
- {
323
- type: "text",
324
- text: "DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: No LLM governance provider configured. Install Hermes on PATH (hermes -z) with xai-oauth, or set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT.",
325
- },
326
- ],
327
- };
328
- }
319
+ const vote = (await tryLLMGovernance("code-review", proposalTitle, proposalDescription, evidence, proposalType)) ??
320
+ localConferVote({
321
+ role: "code-review",
322
+ llmConfigured: isGovernanceLlmConfigured(),
323
+ });
329
324
  return {
330
325
  content: [
331
326
  {
332
327
  type: "text",
333
- text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
328
+ text: formatGovernanceVoteText(vote),
334
329
  },
335
330
  ],
336
331
  };
@@ -7,7 +7,8 @@
7
7
  import * as fs from "fs";
8
8
  import * as path from "path";
9
9
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
10
- import { tryLLMGovernance } from "../../governance/llm-governance-provider.js";
10
+ import { isGovernanceLlmConfigured, tryLLMGovernance, } from "../../governance/llm-governance-provider.js";
11
+ import { formatGovernanceVoteText, localConferVote } from "../../governance/local-confer.js";
11
12
  class XraySecurityAuditServer extends XrayKnowledgeSkillBase {
12
13
  constructor() {
13
14
  super("security-audit", "3.1.0");
@@ -660,22 +661,16 @@ class XraySecurityAuditServer extends XrayKnowledgeSkillBase {
660
661
  */
661
662
  async analyzeProposal(args) {
662
663
  const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args;
663
- const vote = await tryLLMGovernance("security-audit", proposalTitle, proposalDescription, evidence, proposalType);
664
- if (!vote) {
665
- return {
666
- content: [
667
- {
668
- type: "text",
669
- text: "DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: No LLM governance provider configured. Install Hermes on PATH (hermes -z) with xai-oauth, or set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT.",
670
- },
671
- ],
672
- };
673
- }
664
+ const vote = (await tryLLMGovernance("security-audit", proposalTitle, proposalDescription, evidence, proposalType)) ??
665
+ localConferVote({
666
+ role: "security-audit",
667
+ llmConfigured: isGovernanceLlmConfigured(),
668
+ });
674
669
  return {
675
670
  content: [
676
671
  {
677
672
  type: "text",
678
- text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
673
+ text: formatGovernanceVoteText(vote),
679
674
  },
680
675
  ],
681
676
  };
@@ -10,7 +10,8 @@
10
10
  import * as fs from "fs";
11
11
  import * as path from "path";
12
12
  import { frameworkLogger } from "../core/framework-logger.js";
13
- import { tryLLMGovernance } from "../governance/llm-governance-provider.js";
13
+ import { isGovernanceLlmConfigured, tryLLMGovernance, } from "../governance/llm-governance-provider.js";
14
+ import { formatGovernanceVoteText, localConferVote } from "../governance/local-confer.js";
14
15
  import { initializeMemoryRouting } from "../memory-routing/index.js";
15
16
  import { buildMemoryRoutingEvidence, formatMemoryRoutingBlock, resolveResearcherMemoryContext, } from "./researcher-confidence.js";
16
17
  import { XrayKnowledgeSkillBase } from "./shared/knowledge-skill-base.js";
@@ -390,28 +391,21 @@ class XrayLibrarianServer extends XrayKnowledgeSkillBase {
390
391
  if (memoryContext?.confidence.highConfidenceTrapPresent) {
391
392
  enrichedEvidence.push(...buildMemoryRoutingEvidence(memoryContext));
392
393
  }
393
- const vote = await tryLLMGovernance("researcher", proposalTitle || "", proposalDescription || "", enrichedEvidence, proposalType || "");
394
+ const vote = (await tryLLMGovernance("researcher", proposalTitle || "", proposalDescription || "", enrichedEvidence, proposalType || "")) ??
395
+ localConferVote({
396
+ role: "researcher",
397
+ llmConfigured: isGovernanceLlmConfigured(),
398
+ highConfidenceTrapPresent: memoryContext?.confidence.highConfidenceTrapPresent,
399
+ recommendedAgent: memoryContext?.recommendedAgent,
400
+ });
394
401
  const memoryRoutingBlock = memoryContext?.confidence.highConfidenceTrapPresent
395
402
  ? `\n${formatMemoryRoutingBlock(memoryContext)}`
396
403
  : "";
397
- if (!vote) {
398
- const abstainReason = memoryContext?.confidence.highConfidenceTrapPresent
399
- ? "No LLM governance provider configured. Repertoire detected a high-confidence ontological trap — route to the recommended agent before proceeding."
400
- : "No LLM governance provider configured. Install Hermes on PATH (hermes -z) with xai-oauth, or set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT.";
401
- return {
402
- content: [
403
- {
404
- type: "text",
405
- text: `DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: ${abstainReason}${memoryRoutingBlock}`,
406
- },
407
- ],
408
- };
409
- }
410
404
  return {
411
405
  content: [
412
406
  {
413
407
  type: "text",
414
- text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}${memoryRoutingBlock}`,
408
+ text: formatGovernanceVoteText(vote, memoryRoutingBlock),
415
409
  },
416
410
  ],
417
411
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "4.0.7",
3
+ "version": "4.0.9",
4
4
  "description": "Multi-agent orchestration and Codex governance for OpenCode, Hermes, Grok Build, and OpenClaw",
5
5
  "readme": "README.md",
6
6
  "license": "MIT",
@@ -55,6 +55,8 @@ After mill plant is fastened, overlay their plant (defaults; remap in `foundry.j
55
55
 
56
56
  **Default mill plant:** `mill` + `inspect` (inspect AI work). Fastens a suit, not an empty one. Not 45/42 costume. `foundry.json` `"costume": true` copies that dump. Factory Repertoire still enable-when-resolves. PPE stays worn.
57
57
 
58
+ **4.0.9 mill target (0xray postinstall, not this mill package):** `install-bridges.cjs` does not mill npm global prefix or npx `_npx` as a consumer. Isolated HOME skips machine `~/.grok`. Nested mill stays **0.1.9**.
59
+
58
60
  ## Publish this mill
59
61
 
60
62
  From **this directory**, not the 0xray repo root:
@@ -66,7 +66,7 @@ function main() {
66
66
  }
67
67
  } else {
68
68
  step("1/7 Build", "npm run build");
69
- step("2/7 Tests", "npm test");
69
+ step("2/7 Tests", "npm run test:comprehensive");
70
70
  if (!skipDocs) {
71
71
  step("3/7 Release docs", docsCheckCmd());
72
72
  }
@@ -27,23 +27,44 @@ const SKIP_DIRS = new Set(["node_modules", "logs"]);
27
27
  const MERGE_FILES = new Set(["enforcer-config.json"]);
28
28
  const KEEP_IF_EXISTS = new Set([".yml", ".yaml", ".md"]);
29
29
 
30
+ function isInstallPrefixTarget(dir) {
31
+ const n = path.resolve(dir);
32
+ const norm = n.replace(/\\/g, "/");
33
+ if (norm.includes("/_npx/") || norm.endsWith("/_npx")) return true;
34
+ if (!fs.existsSync(path.join(n, "package.json"))) return true;
35
+ return false;
36
+ }
37
+
30
38
  function resolveConsumerTargetDir(packageRoot, fallbackDir) {
31
39
  const resolved = path.resolve(packageRoot);
40
+ const fallback = path.resolve(
41
+ fallbackDir || process.env.INIT_CWD || process.env.PWD || process.cwd(),
42
+ );
32
43
  const inNodeModules =
33
44
  resolved.includes(`${path.sep}node_modules${path.sep}`) ||
34
45
  resolved.endsWith(`${path.sep}node_modules`);
35
46
 
47
+ let candidate;
36
48
  if (!inNodeModules) {
37
- return fallbackDir || process.env.PWD || process.cwd();
49
+ candidate = fallback;
50
+ } else {
51
+ let current = resolved;
52
+ while (path.basename(current) !== "node_modules") {
53
+ const parent = path.dirname(current);
54
+ if (parent === current) {
55
+ candidate = fallback;
56
+ break;
57
+ }
58
+ current = parent;
59
+ }
60
+ if (!candidate) candidate = path.dirname(current);
38
61
  }
39
62
 
40
- let current = resolved;
41
- while (path.basename(current) !== "node_modules") {
42
- const parent = path.dirname(current);
43
- if (parent === current) return fallbackDir || process.cwd();
44
- current = parent;
63
+ if (isInstallPrefixTarget(candidate)) {
64
+ if (!isInstallPrefixTarget(fallback)) return fallback;
65
+ return resolved;
45
66
  }
46
- return path.dirname(current);
67
+ return candidate;
47
68
  }
48
69
 
49
70
  function isConsumerInstall(packageRoot, targetDir) {
@@ -744,6 +765,7 @@ function installAllBridges(opts) {
744
765
  module.exports = {
745
766
  installAllBridges,
746
767
  resolveConsumerTargetDir,
768
+ isInstallPrefixTarget,
747
769
  syncBuiltinSkills,
748
770
  isConsumerInstall,
749
771
  deployXrayConfig,
@@ -120,7 +120,10 @@ module.exports = {
120
120
 
121
121
  if (require.main === module) {
122
122
  const packageRoot = path.join(__dirname, "..", "..");
123
- const targetDir = resolveConsumerTargetDir(packageRoot, process.env.PWD || process.cwd());
123
+ const targetDir = resolveConsumerTargetDir(
124
+ packageRoot,
125
+ process.env.INIT_CWD || process.env.PWD || process.cwd(),
126
+ );
124
127
  try {
125
128
  runPostinstall(packageRoot, targetDir);
126
129
  } catch {
@@ -11,7 +11,10 @@ const {
11
11
  isConsumerInstall,
12
12
  deployXrayConfig,
13
13
  } = require("./install-bridges.cjs");
14
- let targetDir = resolveConsumerTargetDir(packageRoot, process.env.PWD || process.cwd());
14
+ let targetDir = resolveConsumerTargetDir(
15
+ packageRoot,
16
+ process.env.INIT_CWD || process.env.PWD || process.cwd(),
17
+ );
15
18
 
16
19
  const resolvedPackage = path.resolve(packageRoot);
17
20
  const resolvedTarget = path.resolve(targetDir);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray-pre-tool",
3
- "version": "4.0.4",
3
+ "version": "4.0.9",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
@@ -9,7 +9,11 @@ import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
9
9
  import * as fs from "fs";
10
10
  import * as path from "path";
11
11
  import { createGracefulShutdown } from "../../utils/shutdown-handler.js";
12
- import { tryLLMGovernance } from "../../governance/llm-governance-provider.js";
12
+ import {
13
+ isGovernanceLlmConfigured,
14
+ tryLLMGovernance,
15
+ } from "../../governance/llm-governance-provider.js";
16
+ import { formatGovernanceVoteText, localConferVote } from "../../governance/local-confer.js";
13
17
 
14
18
  interface CodeReviewResult {
15
19
  file: string;
@@ -435,30 +439,24 @@ class XrayCodeReviewServer extends XrayKnowledgeSkillBase {
435
439
  async analyzeProposal(args: AnalyzeProposalArgs) {
436
440
  const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args;
437
441
 
438
- const vote = await tryLLMGovernance(
439
- "code-review",
440
- proposalTitle,
441
- proposalDescription,
442
- evidence,
443
- proposalType,
444
- );
445
-
446
- if (!vote) {
447
- return {
448
- content: [
449
- {
450
- type: "text",
451
- text: "DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: No LLM governance provider configured. Install Hermes on PATH (hermes -z) with xai-oauth, or set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT.",
452
- },
453
- ],
454
- };
455
- }
442
+ const vote =
443
+ (await tryLLMGovernance(
444
+ "code-review",
445
+ proposalTitle,
446
+ proposalDescription,
447
+ evidence,
448
+ proposalType,
449
+ )) ??
450
+ localConferVote({
451
+ role: "code-review",
452
+ llmConfigured: isGovernanceLlmConfigured(),
453
+ });
456
454
 
457
455
  return {
458
456
  content: [
459
457
  {
460
458
  type: "text",
461
- text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
459
+ text: formatGovernanceVoteText(vote),
462
460
  },
463
461
  ],
464
462
  };
@@ -8,7 +8,11 @@
8
8
  import * as fs from "fs";
9
9
  import * as path from "path";
10
10
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
11
- import { tryLLMGovernance } from "../../governance/llm-governance-provider.js";
11
+ import {
12
+ isGovernanceLlmConfigured,
13
+ tryLLMGovernance,
14
+ } from "../../governance/llm-governance-provider.js";
15
+ import { formatGovernanceVoteText, localConferVote } from "../../governance/local-confer.js";
12
16
 
13
17
  interface SecurityVulnerability {
14
18
  id: string;
@@ -995,30 +999,24 @@ class XraySecurityAuditServer extends XrayKnowledgeSkillBase {
995
999
  async analyzeProposal(args: AnalyzeProposalArgs) {
996
1000
  const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args;
997
1001
 
998
- const vote = await tryLLMGovernance(
999
- "security-audit",
1000
- proposalTitle,
1001
- proposalDescription,
1002
- evidence,
1003
- proposalType,
1004
- );
1005
-
1006
- if (!vote) {
1007
- return {
1008
- content: [
1009
- {
1010
- type: "text",
1011
- text: "DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: No LLM governance provider configured. Install Hermes on PATH (hermes -z) with xai-oauth, or set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT.",
1012
- },
1013
- ],
1014
- };
1015
- }
1002
+ const vote =
1003
+ (await tryLLMGovernance(
1004
+ "security-audit",
1005
+ proposalTitle,
1006
+ proposalDescription,
1007
+ evidence,
1008
+ proposalType,
1009
+ )) ??
1010
+ localConferVote({
1011
+ role: "security-audit",
1012
+ llmConfigured: isGovernanceLlmConfigured(),
1013
+ });
1016
1014
 
1017
1015
  return {
1018
1016
  content: [
1019
1017
  {
1020
1018
  type: "text",
1021
- text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
1019
+ text: formatGovernanceVoteText(vote),
1022
1020
  },
1023
1021
  ],
1024
1022
  };
@@ -12,7 +12,11 @@ import { type CallToolResult } from "@modelcontextprotocol/sdk/types.js";
12
12
  import * as fs from "fs";
13
13
  import * as path from "path";
14
14
  import { frameworkLogger } from "../core/framework-logger.js";
15
- import { tryLLMGovernance } from "../governance/llm-governance-provider.js";
15
+ import {
16
+ isGovernanceLlmConfigured,
17
+ tryLLMGovernance,
18
+ } from "../governance/llm-governance-provider.js";
19
+ import { formatGovernanceVoteText, localConferVote } from "../governance/local-confer.js";
16
20
  import { initializeMemoryRouting } from "../memory-routing/index.js";
17
21
  import {
18
22
  buildMemoryRoutingEvidence,
@@ -472,39 +476,31 @@ class XrayLibrarianServer extends XrayKnowledgeSkillBase {
472
476
  enrichedEvidence.push(...buildMemoryRoutingEvidence(memoryContext));
473
477
  }
474
478
 
475
- const vote = await tryLLMGovernance(
476
- "researcher",
477
- proposalTitle || "",
478
- proposalDescription || "",
479
- enrichedEvidence,
480
- proposalType || "",
481
- );
479
+ const vote =
480
+ (await tryLLMGovernance(
481
+ "researcher",
482
+ proposalTitle || "",
483
+ proposalDescription || "",
484
+ enrichedEvidence,
485
+ proposalType || "",
486
+ )) ??
487
+ localConferVote({
488
+ role: "researcher",
489
+ llmConfigured: isGovernanceLlmConfigured(),
490
+ highConfidenceTrapPresent: memoryContext?.confidence.highConfidenceTrapPresent,
491
+ recommendedAgent: memoryContext?.recommendedAgent,
492
+ });
482
493
 
483
494
  const memoryRoutingBlock =
484
495
  memoryContext?.confidence.highConfidenceTrapPresent
485
496
  ? `\n${formatMemoryRoutingBlock(memoryContext)}`
486
497
  : "";
487
498
 
488
- if (!vote) {
489
- const abstainReason = memoryContext?.confidence.highConfidenceTrapPresent
490
- ? "No LLM governance provider configured. Repertoire detected a high-confidence ontological trap — route to the recommended agent before proceeding."
491
- : "No LLM governance provider configured. Install Hermes on PATH (hermes -z) with xai-oauth, or set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT.";
492
-
493
- return {
494
- content: [
495
- {
496
- type: "text",
497
- text: `DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: ${abstainReason}${memoryRoutingBlock}`,
498
- },
499
- ],
500
- };
501
- }
502
-
503
499
  return {
504
500
  content: [
505
501
  {
506
502
  type: "text",
507
- text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}${memoryRoutingBlock}`,
503
+ text: formatGovernanceVoteText(vote, memoryRoutingBlock),
508
504
  },
509
505
  ],
510
506
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./features.schema.json",
3
- "version": "4.0.1",
3
+ "version": "4.0.9",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",