0xray 4.0.6 → 4.0.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./features.schema.json",
3
- "version": "4.0.1",
3
+ "version": "4.0.8",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",
package/dist/CHANGELOG.md CHANGED
@@ -30,6 +30,25 @@ The format is based on [Conventional Commits](https://www.conventionalcommits.or
30
30
  - Mill plant fastens **inspect** (inspect AI work) plus `mill`. Not empty. Mill 0.1.6.
31
31
  - Nested mill **0.1.7**: inspect organ, four floors, passwd HOME, mill CI receipt. 4.0.5.
32
32
  - Nested mill **0.1.8**: isolated Hermes/OpenClaw, consumer tarball GET, CLI mint inspects. 4.0.6.
33
+ - Nested mill **0.1.9**: inventory DNA for Groover 0xray-suit pack. 4.0.7.
34
+
35
+ ---
36
+
37
+ ## [4.0.8] - 2026-09-11
38
+
39
+ ### 🔄 Changes
40
+
41
+ ### 🔎 Other Changes
42
+ - fix(foundry): mill release gate uses test:comprehensive like mill CI (bd980ea3f)
43
+ - fix(confer): allow undefined on optional local vote fields (e4436af8f)
44
+ - fix(confer): abstain locally; do not rubber-stamp analyze_proposal (0f6c61cbe)
45
+ - fix(confer): local vote when nested LLM is not configured (eb6004b07)
46
+
47
+ ---
48
+
49
+ ## [4.0.7] - 2026-09-09
50
+
51
+ 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.
33
52
 
34
53
  ---
35
54
 
@@ -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
+ }
@@ -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.6",
3
+ "version": "4.0.8",
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",
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.9] - 2026-09-09
4
+
5
+ Inventory writes `dna` (keccak256 of canonical JSON without `mintedAt`). Inspect receipt echoes `dna` + pack `0xray-suit` for Groover GRVR. Mill does not mint on chain. Not an 8th MCP. Not 5.0.
6
+
3
7
  ## [0.1.8] - 2026-09-09
4
8
 
5
9
  Isolated HOME skips machine `~/.hermes` and `~/.openclaw` (passwd home, same gate as Grok). Inspect GETs a public consumer tarball (`@0xray/review-suit`). CLI `mint` runs inspect after overlay; postinstall does not. Not an 8th MCP. Not 5.0.
@@ -119,6 +119,8 @@ function checkReceipt(root) {
119
119
  suit: inventory.suit,
120
120
  mill: inventory.mill,
121
121
  millPlant: millPlantSkills,
122
+ dna: typeof inventory.dna === "string" ? inventory.dna : null,
123
+ pack: "0xray-suit",
122
124
  detail: ok ? null : "millPlant.skills must include mill and inspect",
123
125
  };
124
126
  }
@@ -273,10 +275,13 @@ export async function inspectSuit(root, opts = {}) {
273
275
  checks.push(checkIsolatedHome(env, machineHome));
274
276
 
275
277
  const failed = checks.filter((c) => c.ok === false);
278
+ const receipt = checks.find((c) => c.id === "receipt") || {};
276
279
  return {
277
280
  ok: failed.length === 0,
278
281
  failed: failed.map((c) => c.id),
279
282
  checks,
283
+ dna: receipt.dna || null,
284
+ pack: "0xray-suit",
280
285
  };
281
286
  }
282
287
 
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Canonical mill DNA for Groover GRVR. keccak256 of inventory without mintedAt/dna.
3
+ * Not a chain client. Not an 8th MCP.
4
+ */
5
+ "use strict";
6
+
7
+ const { keccak_256 } = require("./mill-keccak.cjs");
8
+
9
+ function isPlainObject(value) {
10
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
11
+ }
12
+
13
+ function canonicalJson(value) {
14
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
15
+ if (Array.isArray(value)) {
16
+ return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
17
+ }
18
+ const keys = Object.keys(value).sort();
19
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
20
+ }
21
+
22
+ function dnaPayload(inventory) {
23
+ if (!isPlainObject(inventory)) {
24
+ throw new Error("inventory object required for mill DNA");
25
+ }
26
+ const payload = { ...inventory };
27
+ delete payload.mintedAt;
28
+ delete payload.dna;
29
+ return payload;
30
+ }
31
+
32
+ function inventoryDna(inventory) {
33
+ const json = canonicalJson(dnaPayload(inventory));
34
+ const digest = keccak_256(Buffer.from(json, "utf8"));
35
+ return `0x${Buffer.from(digest).toString("hex")}`;
36
+ }
37
+
38
+ function attachInventoryDna(inventory) {
39
+ if (!isPlainObject(inventory)) return inventory;
40
+ const next = { ...inventory };
41
+ next.dna = inventoryDna(next);
42
+ return next;
43
+ }
44
+
45
+ module.exports = {
46
+ canonicalJson,
47
+ dnaPayload,
48
+ inventoryDna,
49
+ attachInventoryDna,
50
+ };
@@ -0,0 +1,306 @@
1
+ /* vendored @noble/hashes keccak_256 — mill DNA. Not an 8th MCP. */
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // <stdin>
21
+ var stdin_exports = {};
22
+ __export(stdin_exports, {
23
+ keccak_256: () => keccak_256
24
+ });
25
+ module.exports = __toCommonJS(stdin_exports);
26
+
27
+ // node_modules/@noble/hashes/esm/_u64.js
28
+ var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
29
+ var _32n = /* @__PURE__ */ BigInt(32);
30
+ function fromBig(n, le = false) {
31
+ if (le)
32
+ return { h: Number(n & U32_MASK64), l: Number(n >> _32n & U32_MASK64) };
33
+ return { h: Number(n >> _32n & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
34
+ }
35
+ function split(lst, le = false) {
36
+ const len = lst.length;
37
+ let Ah = new Uint32Array(len);
38
+ let Al = new Uint32Array(len);
39
+ for (let i = 0; i < len; i++) {
40
+ const { h, l } = fromBig(lst[i], le);
41
+ [Ah[i], Al[i]] = [h, l];
42
+ }
43
+ return [Ah, Al];
44
+ }
45
+ var rotlSH = (h, l, s) => h << s | l >>> 32 - s;
46
+ var rotlSL = (h, l, s) => l << s | h >>> 32 - s;
47
+ var rotlBH = (h, l, s) => l << s - 32 | h >>> 64 - s;
48
+ var rotlBL = (h, l, s) => h << s - 32 | l >>> 64 - s;
49
+
50
+ // node_modules/@noble/hashes/esm/utils.js
51
+ function isBytes(a) {
52
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
53
+ }
54
+ function anumber(n) {
55
+ if (!Number.isSafeInteger(n) || n < 0)
56
+ throw new Error("positive integer expected, got " + n);
57
+ }
58
+ function abytes(b, ...lengths) {
59
+ if (!isBytes(b))
60
+ throw new Error("Uint8Array expected");
61
+ if (lengths.length > 0 && !lengths.includes(b.length))
62
+ throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
63
+ }
64
+ function aexists(instance, checkFinished = true) {
65
+ if (instance.destroyed)
66
+ throw new Error("Hash instance has been destroyed");
67
+ if (checkFinished && instance.finished)
68
+ throw new Error("Hash#digest() has already been called");
69
+ }
70
+ function aoutput(out, instance) {
71
+ abytes(out);
72
+ const min = instance.outputLen;
73
+ if (out.length < min) {
74
+ throw new Error("digestInto() expects output buffer of length at least " + min);
75
+ }
76
+ }
77
+ function u32(arr) {
78
+ return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
79
+ }
80
+ function clean(...arrays) {
81
+ for (let i = 0; i < arrays.length; i++) {
82
+ arrays[i].fill(0);
83
+ }
84
+ }
85
+ var isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68)();
86
+ function byteSwap(word) {
87
+ return word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255;
88
+ }
89
+ function byteSwap32(arr) {
90
+ for (let i = 0; i < arr.length; i++) {
91
+ arr[i] = byteSwap(arr[i]);
92
+ }
93
+ return arr;
94
+ }
95
+ var swap32IfBE = isLE ? (u) => u : byteSwap32;
96
+ function utf8ToBytes(str) {
97
+ if (typeof str !== "string")
98
+ throw new Error("string expected");
99
+ return new Uint8Array(new TextEncoder().encode(str));
100
+ }
101
+ function toBytes(data) {
102
+ if (typeof data === "string")
103
+ data = utf8ToBytes(data);
104
+ abytes(data);
105
+ return data;
106
+ }
107
+ var Hash = class {
108
+ };
109
+ function createHasher(hashCons) {
110
+ const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
111
+ const tmp = hashCons();
112
+ hashC.outputLen = tmp.outputLen;
113
+ hashC.blockLen = tmp.blockLen;
114
+ hashC.create = () => hashCons();
115
+ return hashC;
116
+ }
117
+
118
+ // node_modules/@noble/hashes/esm/sha3.js
119
+ var _0n = BigInt(0);
120
+ var _1n = BigInt(1);
121
+ var _2n = BigInt(2);
122
+ var _7n = BigInt(7);
123
+ var _256n = BigInt(256);
124
+ var _0x71n = BigInt(113);
125
+ var SHA3_PI = [];
126
+ var SHA3_ROTL = [];
127
+ var _SHA3_IOTA = [];
128
+ for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
129
+ [x, y] = [y, (2 * x + 3 * y) % 5];
130
+ SHA3_PI.push(2 * (5 * y + x));
131
+ SHA3_ROTL.push((round + 1) * (round + 2) / 2 % 64);
132
+ let t = _0n;
133
+ for (let j = 0; j < 7; j++) {
134
+ R = (R << _1n ^ (R >> _7n) * _0x71n) % _256n;
135
+ if (R & _2n)
136
+ t ^= _1n << (_1n << /* @__PURE__ */ BigInt(j)) - _1n;
137
+ }
138
+ _SHA3_IOTA.push(t);
139
+ }
140
+ var IOTAS = split(_SHA3_IOTA, true);
141
+ var SHA3_IOTA_H = IOTAS[0];
142
+ var SHA3_IOTA_L = IOTAS[1];
143
+ var rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s);
144
+ var rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s);
145
+ function keccakP(s, rounds = 24) {
146
+ const B = new Uint32Array(5 * 2);
147
+ for (let round = 24 - rounds; round < 24; round++) {
148
+ for (let x = 0; x < 10; x++)
149
+ B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
150
+ for (let x = 0; x < 10; x += 2) {
151
+ const idx1 = (x + 8) % 10;
152
+ const idx0 = (x + 2) % 10;
153
+ const B0 = B[idx0];
154
+ const B1 = B[idx0 + 1];
155
+ const Th = rotlH(B0, B1, 1) ^ B[idx1];
156
+ const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
157
+ for (let y = 0; y < 50; y += 10) {
158
+ s[x + y] ^= Th;
159
+ s[x + y + 1] ^= Tl;
160
+ }
161
+ }
162
+ let curH = s[2];
163
+ let curL = s[3];
164
+ for (let t = 0; t < 24; t++) {
165
+ const shift = SHA3_ROTL[t];
166
+ const Th = rotlH(curH, curL, shift);
167
+ const Tl = rotlL(curH, curL, shift);
168
+ const PI = SHA3_PI[t];
169
+ curH = s[PI];
170
+ curL = s[PI + 1];
171
+ s[PI] = Th;
172
+ s[PI + 1] = Tl;
173
+ }
174
+ for (let y = 0; y < 50; y += 10) {
175
+ for (let x = 0; x < 10; x++)
176
+ B[x] = s[y + x];
177
+ for (let x = 0; x < 10; x++)
178
+ s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
179
+ }
180
+ s[0] ^= SHA3_IOTA_H[round];
181
+ s[1] ^= SHA3_IOTA_L[round];
182
+ }
183
+ clean(B);
184
+ }
185
+ var Keccak = class _Keccak extends Hash {
186
+ // NOTE: we accept arguments in bytes instead of bits here.
187
+ constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
188
+ super();
189
+ this.pos = 0;
190
+ this.posOut = 0;
191
+ this.finished = false;
192
+ this.destroyed = false;
193
+ this.enableXOF = false;
194
+ this.blockLen = blockLen;
195
+ this.suffix = suffix;
196
+ this.outputLen = outputLen;
197
+ this.enableXOF = enableXOF;
198
+ this.rounds = rounds;
199
+ anumber(outputLen);
200
+ if (!(0 < blockLen && blockLen < 200))
201
+ throw new Error("only keccak-f1600 function is supported");
202
+ this.state = new Uint8Array(200);
203
+ this.state32 = u32(this.state);
204
+ }
205
+ clone() {
206
+ return this._cloneInto();
207
+ }
208
+ keccak() {
209
+ swap32IfBE(this.state32);
210
+ keccakP(this.state32, this.rounds);
211
+ swap32IfBE(this.state32);
212
+ this.posOut = 0;
213
+ this.pos = 0;
214
+ }
215
+ update(data) {
216
+ aexists(this);
217
+ data = toBytes(data);
218
+ abytes(data);
219
+ const { blockLen, state } = this;
220
+ const len = data.length;
221
+ for (let pos = 0; pos < len; ) {
222
+ const take = Math.min(blockLen - this.pos, len - pos);
223
+ for (let i = 0; i < take; i++)
224
+ state[this.pos++] ^= data[pos++];
225
+ if (this.pos === blockLen)
226
+ this.keccak();
227
+ }
228
+ return this;
229
+ }
230
+ finish() {
231
+ if (this.finished)
232
+ return;
233
+ this.finished = true;
234
+ const { state, suffix, pos, blockLen } = this;
235
+ state[pos] ^= suffix;
236
+ if ((suffix & 128) !== 0 && pos === blockLen - 1)
237
+ this.keccak();
238
+ state[blockLen - 1] ^= 128;
239
+ this.keccak();
240
+ }
241
+ writeInto(out) {
242
+ aexists(this, false);
243
+ abytes(out);
244
+ this.finish();
245
+ const bufferOut = this.state;
246
+ const { blockLen } = this;
247
+ for (let pos = 0, len = out.length; pos < len; ) {
248
+ if (this.posOut >= blockLen)
249
+ this.keccak();
250
+ const take = Math.min(blockLen - this.posOut, len - pos);
251
+ out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
252
+ this.posOut += take;
253
+ pos += take;
254
+ }
255
+ return out;
256
+ }
257
+ xofInto(out) {
258
+ if (!this.enableXOF)
259
+ throw new Error("XOF is not possible for this instance");
260
+ return this.writeInto(out);
261
+ }
262
+ xof(bytes) {
263
+ anumber(bytes);
264
+ return this.xofInto(new Uint8Array(bytes));
265
+ }
266
+ digestInto(out) {
267
+ aoutput(out, this);
268
+ if (this.finished)
269
+ throw new Error("digest() was already called");
270
+ this.writeInto(out);
271
+ this.destroy();
272
+ return out;
273
+ }
274
+ digest() {
275
+ return this.digestInto(new Uint8Array(this.outputLen));
276
+ }
277
+ destroy() {
278
+ this.destroyed = true;
279
+ clean(this.state);
280
+ }
281
+ _cloneInto(to) {
282
+ const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
283
+ to || (to = new _Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
284
+ to.state32.set(this.state32);
285
+ to.pos = this.pos;
286
+ to.posOut = this.posOut;
287
+ to.finished = this.finished;
288
+ to.rounds = rounds;
289
+ to.suffix = suffix;
290
+ to.outputLen = outputLen;
291
+ to.enableXOF = enableXOF;
292
+ to.destroyed = this.destroyed;
293
+ return to;
294
+ }
295
+ };
296
+ var gen = (suffix, blockLen, outputLen) => createHasher(() => new Keccak(blockLen, suffix, outputLen));
297
+ var keccak_256 = /* @__PURE__ */ (() => gen(1, 136, 256 / 8))();
298
+ // Annotate the CommonJS export names for ESM import in node:
299
+ 0 && (module.exports = {
300
+ keccak_256
301
+ });
302
+ /*! Bundled license information:
303
+
304
+ @noble/hashes/esm/utils.js:
305
+ (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
306
+ */
@@ -10,6 +10,8 @@ const fs = require("fs");
10
10
  const os = require("os");
11
11
  const path = require("path");
12
12
 
13
+ const { attachInventoryDna, inventoryDna } = require("./mill-dna.cjs");
14
+
13
15
  const DEFAULT_PARAMS = {
14
16
  codex: "xray/codex.json",
15
17
  features: "xray/features.json",
@@ -436,20 +438,22 @@ function mintConsumerFromSsot(packageRoot, targetDir, log, tree) {
436
438
  },
437
439
  mintedAt: new Date().toISOString(),
438
440
  };
441
+ const withDna = attachInventoryDna(inventory);
439
442
  const xrayDir = path.join(targetDir, ".xray");
440
443
  if (!fs.existsSync(xrayDir)) fs.mkdirSync(xrayDir, { recursive: true });
441
444
  fs.writeFileSync(
442
445
  path.join(xrayDir, "foundry-inventory.json"),
443
- `${JSON.stringify(inventory, null, 2)}\n`,
446
+ `${JSON.stringify(withDna, null, 2)}\n`,
444
447
  );
445
448
  if (log) {
446
449
  log("foundry-mint", "Minted foundry-inventory from consumer mill SSOT", "info", {
447
450
  consumer: consumer.name,
448
451
  version: consumer.version,
449
452
  suit,
453
+ dna: withDna.dna,
450
454
  });
451
455
  }
452
- return inventory;
456
+ return withDna;
453
457
  }
454
458
 
455
459
  function mintConsumerSuit(millPackageRoot, targetDir, log) {
@@ -504,6 +508,8 @@ module.exports = {
504
508
  listProjectSkillDirs,
505
509
  mintConsumerFromSsot,
506
510
  mintConsumerSuit,
511
+ attachInventoryDna,
512
+ inventoryDna,
507
513
  isDogfood,
508
514
  readPackageIdentity,
509
515
  wornSkillNames,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xray/foundry",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "0xRay mill: mint their suit params, stamp, gate, publish, CI report, git hooks. Not the worn exo.",
@@ -1,5 +1,5 @@
1
1
  name: inspect
2
2
  skill: inspect
3
3
  description: "Inspect AI work: diffs, traces, mill receipts, CI. Fastened mill plant."
4
- version: "0.1.8"
4
+ version: "0.1.9"
5
5
  mode: subagent
@@ -1,5 +1,5 @@
1
1
  name: mill
2
2
  skill: mill
3
3
  description: "Fasten their plant as the suit. Factory Repertoire. Inspect is the mill discipline."
4
- version: "0.1.8"
4
+ version: "0.1.9"
5
5
  mode: subagent
@@ -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
  }
@@ -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.8",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",