0xray 4.0.5 → 4.0.6

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/dist/CHANGELOG.md CHANGED
@@ -29,6 +29,13 @@ The format is based on [Conventional Commits](https://www.conventionalcommits.or
29
29
  - Empty garment: mill plant (`mill` skill) is the hanger. Not 45/42 costume unless `foundry.json` `"costume": true`. Mill 0.1.5.
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
+ - Nested mill **0.1.8**: isolated Hermes/OpenClaw, consumer tarball GET, CLI mint inspects. 4.0.6.
33
+
34
+ ---
35
+
36
+ ## [4.0.6] - 2026-09-09
37
+
38
+ Nested mill **0.1.8**. Isolated HOME skips machine Hermes/OpenClaw. Inspect GETs public consumer `.tgz`. CLI `mint` runs inspect (chat is not done). Postinstall does not inspect. Not 5.0.0.
32
39
 
33
40
  ---
34
41
 
@@ -1,6 +1,5 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { homedir } from 'os';
4
3
  import { createRequire } from 'module';
5
4
  import { frameworkLogger } from '../../core/framework-logger.js';
6
5
  import { syncBuiltinSkills } from './skill-install.js';
@@ -8,6 +7,7 @@ import { mintAfterWear } from './foundry-mint-wear.js';
8
7
  const __dirname = path.dirname(new URL(import.meta.url).pathname);
9
8
  const require = createRequire(import.meta.url);
10
9
  const packageRoot = path.join(__dirname, '..', '..', '..');
10
+ const millSuit = require(path.join(packageRoot, 'scripts', 'foundry', 'mint-suit.cjs'));
11
11
  const wiring = require(path.join(packageRoot, 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
12
12
  export function registerHermesCommands(hermesCmd) {
13
13
  hermesCmd
@@ -21,8 +21,10 @@ export function registerHermesCommands(hermesCmd) {
21
21
  }
22
22
  async function installForHermes(options = {}) {
23
23
  frameworkLogger.log('hermes-integration', 'install-start', 'info', { options });
24
- const home = homedir();
25
- const targetPluginDir = path.join(home, '.hermes/plugins/xray-hermes');
24
+ const isolated = millSuit.isIsolatedHome();
25
+ const targetPluginDir = isolated
26
+ ? path.join(process.cwd(), '.hermes/plugins/xray-hermes')
27
+ : path.join(millSuit.machineHome(), '.hermes/plugins/xray-hermes');
26
28
  const possibleSources = [
27
29
  path.join(__dirname, '..', '..', '..', 'dist/integrations/hermes-agent'),
28
30
  path.join(__dirname, '..', '..', '..', 'src/integrations/hermes-agent'),
@@ -65,10 +67,10 @@ async function installForHermes(options = {}) {
65
67
  frameworkLogger.log('hermes-integration', 'skills-synced', 'info', { count: skillsCopied });
66
68
  }
67
69
  wiring.copyHermesFindProjectRootHelper(packageRoot, targetPluginDir);
68
- if (wiring.copyHermesHookRuntimes(packageRoot)) {
70
+ if (!isolated && wiring.copyHermesHookRuntimes(packageRoot)) {
69
71
  frameworkLogger.log('hermes-integration', 'hooks-copied', 'info', {});
70
72
  }
71
- const wired = wiring.wireHermesBridge(targetDir);
73
+ const wired = isolated ? { count: 0 } : wiring.wireHermesBridge(targetDir);
72
74
  mintAfterWear(targetDir);
73
75
  console.log(`\x1b[32m✓ Wired Hermes mcp_servers (${wired.count} servers)\x1b[0m`);
74
76
  console.log(`\x1b[32m✓ Consumer root → ${targetDir}\x1b[0m`);
@@ -1,6 +1,5 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { homedir } from 'os';
4
3
  import { createRequire } from 'module';
5
4
  import { frameworkLogger } from '../../core/framework-logger.js';
6
5
  import { syncBuiltinSkills } from './skill-install.js';
@@ -9,6 +8,7 @@ import { OpenClawConfigLoader } from '../../integrations/openclaw/config.js';
9
8
  import { writeSuitSessionBoot } from '../../nucleus/suit-temperament.js';
10
9
  const __dirname = path.dirname(new URL(import.meta.url).pathname);
11
10
  const require = createRequire(import.meta.url);
11
+ const millSuit = require(path.join(__dirname, '..', '..', '..', 'scripts', 'foundry', 'mint-suit.cjs'));
12
12
  const wiring = require(path.join(__dirname, '..', '..', '..', 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
13
13
  export function registerOpenClawCommands(openclawCmd) {
14
14
  openclawCmd
@@ -40,14 +40,19 @@ async function installForOpenClaw(options = {}) {
40
40
  const relative = path.relative(process.cwd(), configPath);
41
41
  console.log(`\x1b[32m✓ Created OpenClaw config at ${relative}\x1b[0m`);
42
42
  }
43
- const openclawSkillsDir = path.join(homedir(), '.openclaw', 'skills');
43
+ const isolated = millSuit.isIsolatedHome();
44
+ const openclawSkillsDir = isolated
45
+ ? path.join(targetDir, '.openclaw', 'skills')
46
+ : path.join(millSuit.machineHome(), '.openclaw', 'skills');
44
47
  const skillsCopied = syncBuiltinSkills(openclawSkillsDir);
45
48
  if (skillsCopied > 0) {
46
49
  console.log(`\x1b[32m✓ Synced ${skillsCopied} builtin skills to ~/.openclaw/skills/\x1b[0m`);
47
50
  }
48
51
  frameworkLogger.log('openclaw-integration', 'skills-synced', 'info', { count: skillsCopied });
49
52
  mintAfterWear(targetDir);
50
- const wired = wiring.wireOpenClawBridge(targetDir);
53
+ const wired = isolated
54
+ ? { count: 0, path: configPath, method: 'skipped-isolated-home' }
55
+ : wiring.wireOpenClawBridge(targetDir);
51
56
  console.log(`\x1b[32m✓ Wired OpenClaw MCP servers (${wired.count} via ${wired.method}) → ${wired.path}\x1b[0m`);
52
57
  console.log(`\x1b[32m✓ Consumer root → ${targetDir}\x1b[0m`);
53
58
  try {
@@ -57,8 +62,8 @@ async function installForOpenClaw(options = {}) {
57
62
  /* session-boot is best-effort */
58
63
  }
59
64
  const packageRoot = path.resolve(__dirname, '..', '..', '..');
60
- const hookInstalled = wiring.installOpenClawHostWear(packageRoot);
61
- const cliBackend = wiring.maybeWriteOpenClawCliBackend();
65
+ const hookInstalled = isolated ? null : wiring.installOpenClawHostWear(packageRoot);
66
+ const cliBackend = isolated ? false : wiring.maybeWriteOpenClawCliBackend();
62
67
  frameworkLogger.log('openclaw-integration', 'cli-backend', 'info', { written: cliBackend });
63
68
  if (hookInstalled) {
64
69
  console.log(`\x1b[32m✓ OpenClaw PreToolUse hook → ${hookInstalled}\x1b[0m`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "4.0.5",
3
+ "version": "4.0.6",
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.8] - 2026-09-09
4
+
5
+ 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.
6
+
3
7
  ## [0.1.7] - 2026-09-04
4
8
 
5
9
  Inspect is mill flesh: `npx @0xray/foundry inspect` runs diff, plant vs worn (mint fails costume dump), mill receipt, CI, GET the `.tgz` (HTTP 200), isolated HOME vs passwd home. Four project skill floors created on fasten (OpenCode, Grok, Hermes, OpenClaw). CI report is `.xray/foundry-ci-report.json`. Not an 8th MCP. Not 5.0.
@@ -26,7 +26,7 @@ const HELP =
26
26
  "\n" +
27
27
  "Mill, not exo. FOUNDRY_ROOT overrides cwd (the repo being milled).\n" +
28
28
  "release bumps/commits/pushes/publishes the milled cwd — pass --dry-run or --i-mean-it (or FOUNDRY_RELEASE=1).\n" +
29
- "Mint fastens mill plant then overlays their plant (mill-fill JSON). PPE stays worn.\n" +
29
+ "Mint fastens mill plant then overlays their plant (mill-fill JSON), then runs inspect. PPE stays worn.\n" +
30
30
  "inspect runs the six mill checks (diff, plant vs worn, receipt, CI, live tarball GET, isolated HOME). Not an 8th MCP.\n" +
31
31
  "gate is build+test. docs-build is Docusaurus on the 0xray exo. ci reports GitHub Actions (no auto-push). hooks installs git pre/post hooks.\n";
32
32
 
@@ -179,7 +179,7 @@ export async function checkLivePut(packages, fetchFn = fetch) {
179
179
  return results;
180
180
  }
181
181
 
182
- function packagesToProbe(root) {
182
+ export function packagesToProbe(root) {
183
183
  const pkgs = [];
184
184
  const inventory = readJson(path.join(root, ".xray", "foundry-inventory.json"));
185
185
  if (inventory?.mill?.name && inventory?.mill?.version) {
@@ -193,6 +193,17 @@ function packagesToProbe(root) {
193
193
  if (self?.name === "0xray" && self?.version) {
194
194
  pkgs.push({ name: "0xray", version: self.version });
195
195
  }
196
+ if (
197
+ self &&
198
+ self.private !== true &&
199
+ inventory?.consumer?.name &&
200
+ inventory?.consumer?.version
201
+ ) {
202
+ pkgs.push({
203
+ name: inventory.consumer.name,
204
+ version: inventory.consumer.version,
205
+ });
206
+ }
196
207
  const seen = new Set();
197
208
  return pkgs.filter((p) => {
198
209
  const key = `${p.name}@${p.version}`;
@@ -8,13 +8,15 @@ import { createRequire } from "node:module";
8
8
  import path from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
  import { millPackageDir, resolveMillRoot } from "./mill-root.mjs";
11
+ import { inspectSuit } from "./inspect.mjs";
11
12
 
12
13
  const require = createRequire(import.meta.url);
13
14
  const { mintConsumerSuit } = require("./mint-suit.cjs");
14
15
 
15
- function main() {
16
+ async function main() {
16
17
  const target = resolveMillRoot();
17
18
  const millRoot = millPackageDir();
19
+ const skipLive = process.argv.includes("--skip-live");
18
20
  let inventory;
19
21
  try {
20
22
  inventory = mintConsumerSuit(millRoot, target, (component, action, status) => {
@@ -29,6 +31,9 @@ function main() {
29
31
  process.exit(0);
30
32
  }
31
33
  process.stdout.write(`${JSON.stringify(inventory, null, 2)}\n`);
34
+ const report = await inspectSuit(target, { millRoot, skipLive });
35
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
36
+ if (!report.ok) process.exit(1);
32
37
  }
33
38
 
34
39
  const isMain =
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xray/foundry",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
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.7"
4
+ version: "0.1.8"
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.7"
4
+ version: "0.1.8"
5
5
  mode: subagent
@@ -30,3 +30,5 @@ npx @0xray/foundry mint
30
30
  npx @0xray/foundry inspect
31
31
  npx @0xray/foundry ci --report
32
32
  ```
33
+
34
+ CLI `mint` runs inspect after overlay (exit 1 if inspect fails). Postinstall mint does not; `--skip-live` skips the tarball GET. Chat is not a receipt.
@@ -230,12 +230,13 @@ function isIsolatedHome(env = process.env, machine = millSuit.machineHome()) {
230
230
  }
231
231
 
232
232
  function copyHermesHookRuntimes(packageRoot) {
233
+ if (millSuit.isIsolatedHome()) return false;
233
234
  const hooksSrc = [
234
235
  path.join(packageRoot, "dist", "integrations", "hooks"),
235
236
  path.join(packageRoot, "src", "integrations", "hooks"),
236
237
  ].find((p) => fs.existsSync(p));
237
238
  if (!hooksSrc) return false;
238
- const hooksDst = path.join(os.homedir(), ".hermes", "plugins", "hooks");
239
+ const hooksDst = path.join(millSuit.machineHome(), ".hermes", "plugins", "hooks");
239
240
  fs.mkdirSync(hooksDst, { recursive: true });
240
241
  fs.cpSync(hooksSrc, hooksDst, { recursive: true, force: true });
241
242
  return true;
@@ -428,10 +429,11 @@ function resolveOpenClawPluginDir(packageRoot) {
428
429
  }
429
430
 
430
431
  function installOpenClawHostWear(packageRoot) {
432
+ if (millSuit.isIsolatedHome()) return null;
431
433
  const source = resolveOpenClawPreToolHookSource(packageRoot);
432
434
  if (!source) return null;
433
435
 
434
- const hookDir = path.join(os.homedir(), ".openclaw", "hooks");
436
+ const hookDir = path.join(millSuit.machineHome(), ".openclaw", "hooks");
435
437
  fs.mkdirSync(hookDir, { recursive: true });
436
438
  const dest = path.join(hookDir, "xray-pre-tool.mjs");
437
439
  fs.copyFileSync(source, dest);
@@ -423,7 +423,16 @@ function installHermesBridge(targetDir, packageRoot, log) {
423
423
  return;
424
424
  }
425
425
 
426
- const targetPluginDir = path.join(os.homedir(), ".hermes", "plugins", "xray-hermes");
426
+ const ephemeral = isEphemeralInstallRoot(targetDir);
427
+ const isolated = isIsolatedHome();
428
+ const machine = machineHome();
429
+ const targetPluginDir =
430
+ ephemeral || isolated
431
+ ? path.join(targetDir, ".hermes", "plugins", "xray-hermes")
432
+ : path.join(machine, ".hermes", "plugins", "xray-hermes");
433
+ if (isolated) {
434
+ log("hermes-bridge", "skip machine ~/.hermes plugin — isolated HOME", "info");
435
+ }
427
436
  fs.mkdirSync(targetPluginDir, { recursive: true });
428
437
  for (const entry of fs.readdirSync(sourceDir)) {
429
438
  const src = path.join(sourceDir, entry);
@@ -435,10 +444,15 @@ function installHermesBridge(targetDir, packageRoot, log) {
435
444
  }
436
445
  }
437
446
  copyHermesFindProjectRootHelper(packageRoot, targetPluginDir);
438
- if (copyHermesHookRuntimes(packageRoot)) {
447
+ if (!ephemeral && !isolated && copyHermesHookRuntimes(packageRoot)) {
439
448
  log("hermes-bridge", "hook runtimes copied", "info", { path: "~/.hermes/plugins/hooks" });
440
449
  }
441
- log("hermes-bridge", "plugin copied", "info", { path: "~/.hermes/plugins/xray-hermes" });
450
+ log(
451
+ "hermes-bridge",
452
+ "plugin copied",
453
+ "info",
454
+ { path: ephemeral || isolated ? path.relative(targetDir, targetPluginDir) : "~/.hermes/plugins/xray-hermes" },
455
+ );
442
456
 
443
457
  writePluginMcpJson(targetPluginDir, targetDir, log, "hermes-bridge");
444
458
 
@@ -453,11 +467,13 @@ function installHermesBridge(targetDir, packageRoot, log) {
453
467
  log("hermes-bridge", "skip machine consumer marker — ephemeral consumer", "info");
454
468
  }
455
469
 
456
- try {
457
- const result = wireHermesBridge(targetDir);
458
- log("hermes-bridge", `mcp_servers wired (${result.count} servers)`, "info");
459
- } catch (e) {
460
- log("hermes-bridge", "mcp_servers wire failed", "warn", { error: e.message });
470
+ if (!ephemeral && !isolated) {
471
+ try {
472
+ const result = wireHermesBridge(targetDir);
473
+ log("hermes-bridge", `mcp_servers wired (${result.count} servers)`, "info");
474
+ } catch (e) {
475
+ log("hermes-bridge", "mcp_servers wire failed", "warn", { error: e.message });
476
+ }
461
477
  }
462
478
  }
463
479
 
@@ -494,26 +510,52 @@ function installOpenclawBridge(targetDir, packageRoot, log) {
494
510
  log("openclaw-bridge", "config created", "info", { path: ".xray/config/openclaw.json" });
495
511
  }
496
512
 
497
- const copied = syncCostumeSkills(path.join(os.homedir(), ".openclaw", "skills"), packageRoot, targetDir);
498
- if (copied > 0) log("openclaw-bridge", `skills synced (${copied})`, "info", { path: "~/.openclaw/skills/" });
513
+ const ephemeralOpenclaw = isEphemeralInstallRoot(targetDir);
514
+ const isolatedOpenclaw = isIsolatedHome();
515
+ if (!ephemeralOpenclaw && !isolatedOpenclaw) {
516
+ const copied = syncCostumeSkills(
517
+ path.join(machineHome(), ".openclaw", "skills"),
518
+ packageRoot,
519
+ targetDir,
520
+ );
521
+ if (copied > 0) {
522
+ log("openclaw-bridge", `skills synced (${copied})`, "info", { path: "~/.openclaw/skills/" });
523
+ }
524
+ } else {
525
+ log(
526
+ "openclaw-bridge",
527
+ isolatedOpenclaw
528
+ ? "skip machine ~/.openclaw skills — isolated HOME"
529
+ : "skip machine ~/.openclaw skills — ephemeral consumer",
530
+ "info",
531
+ );
532
+ }
499
533
 
500
- try {
501
- const result = wireOpenClawBridge(targetDir);
502
- log("openclaw-bridge", `openclaw.json mcp wired (${result.count} servers)`, "info", {
503
- method: result.method,
504
- });
505
- } catch (e) {
506
- log("openclaw-bridge", "openclaw.json mcp wire failed", "warn", { error: e.message });
534
+ if (!ephemeralOpenclaw && !isolatedOpenclaw) {
535
+ try {
536
+ const result = wireOpenClawBridge(targetDir);
537
+ log("openclaw-bridge", `openclaw.json mcp wired (${result.count} servers)`, "info", {
538
+ method: result.method,
539
+ });
540
+ } catch (e) {
541
+ log("openclaw-bridge", "openclaw.json mcp wire failed", "warn", { error: e.message });
542
+ }
507
543
  }
508
544
 
509
- if (!isEphemeralInstallRoot(targetDir)) {
545
+ if (!ephemeralOpenclaw && !isolatedOpenclaw) {
510
546
  const hook = installOpenClawHostWear(packageRoot);
511
547
  if (hook) log("openclaw-bridge", "PreToolUse hook installed", "info", { path: hook });
512
548
  if (maybeWriteOpenClawCliBackend()) {
513
549
  log("openclaw-bridge", "opencode-cli backend written", "info");
514
550
  }
515
551
  } else {
516
- log("openclaw-bridge", "skip machine PreToolUse wear — ephemeral consumer", "info");
552
+ log(
553
+ "openclaw-bridge",
554
+ isolatedOpenclaw
555
+ ? "skip machine PreToolUse wear — isolated HOME"
556
+ : "skip machine PreToolUse wear — ephemeral consumer",
557
+ "info",
558
+ );
517
559
  }
518
560
  }
519
561