0xray 4.0.14 → 4.0.16

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.
Files changed (73) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.opencode/init.sh +14 -4
  3. package/.opencode/skills/orchestrator/SKILL.md +20 -1
  4. package/.xray/features.json +2 -2
  5. package/AGENTS-consumer.md +10 -5
  6. package/AGENTS.md +10 -7
  7. package/README.md +8 -7
  8. package/SKILLS.md +3 -2
  9. package/dist/AGENTS.md +10 -7
  10. package/dist/CHANGELOG.md +71 -0
  11. package/dist/README.md +8 -7
  12. package/dist/SKILLS.md +3 -2
  13. package/dist/cli/commands/hermes-install.js +2 -1
  14. package/dist/cli/commands/openclaw-install.js +2 -1
  15. package/dist/cli/commands/opencode-install.js +2 -1
  16. package/dist/cli/commands/validate.d.ts +26 -0
  17. package/dist/cli/commands/validate.js +164 -0
  18. package/dist/cli/index.js +6 -13
  19. package/dist/integrations/cursor/hooks/cursor-hook-utils.js +11 -0
  20. package/dist/integrations/grok/grok-cli.js +2 -1
  21. package/dist/integrations/hooks/station-hook-runtime.cjs +23 -2
  22. package/dist/integrations/hooks/station-hook-runtime.mjs +2 -0
  23. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  24. package/dist/reporting/log-parser.js +2 -2
  25. package/dist/skills/orchestrator/SKILL.md +20 -1
  26. package/llms.txt +8 -7
  27. package/package.json +2 -1
  28. package/scripts/foundry/CHANGELOG.md +33 -1
  29. package/scripts/foundry/README.md +12 -5
  30. package/scripts/foundry/assert-packed-dist-cli.mjs +6 -0
  31. package/scripts/foundry/blip-kapow.cjs +2 -0
  32. package/scripts/foundry/blip-looker.cjs +2 -0
  33. package/scripts/foundry/blip-render.cjs +2 -1237
  34. package/scripts/foundry/blip-rippel-organs.cjs +2 -0
  35. package/scripts/foundry/blip-rippel.cjs +2 -1963
  36. package/scripts/foundry/blip-scene.cjs +2 -0
  37. package/scripts/foundry/blip-stroke.cjs +2 -0
  38. package/scripts/foundry/blip-vibe.cjs +2 -0
  39. package/scripts/foundry/blip.mjs +23 -97
  40. package/scripts/foundry/cli.mjs +2 -2
  41. package/scripts/foundry/inspect.mjs +62 -19
  42. package/scripts/foundry/mill-plant.cjs +598 -0
  43. package/scripts/foundry/mint-suit.cjs +189 -99
  44. package/scripts/foundry/package.json +12 -1
  45. package/scripts/foundry/plant/agents/blip-inspect.yml +1 -1
  46. package/scripts/foundry/plant/agents/blip-looker.yml +5 -0
  47. package/scripts/foundry/plant/agents/blip-vibe.yml +5 -0
  48. package/scripts/foundry/plant/agents/blip.yml +1 -1
  49. package/scripts/foundry/plant/agents/inspect.yml +1 -1
  50. package/scripts/foundry/plant/agents/mill.yml +1 -1
  51. package/scripts/foundry/plant/agents/sound-inspect.yml +1 -1
  52. package/scripts/foundry/plant/agents/sound-mixer.yml +5 -0
  53. package/scripts/foundry/plant/agents/sound.yml +1 -1
  54. package/scripts/foundry/plant/motions/MOTION-REGISTRY.md +15 -9
  55. package/scripts/foundry/plant/motions/registry.json +5 -4
  56. package/scripts/foundry/plant/skills/blip/SKILL.md +4 -4
  57. package/scripts/foundry/plant/skills/blip-inspect/SKILL.md +2 -2
  58. package/scripts/foundry/plant/skills/blip-looker/SKILL.md +30 -0
  59. package/scripts/foundry/plant/skills/blip-vibe/SKILL.md +30 -0
  60. package/scripts/foundry/plant/skills/inspect/SKILL.md +2 -2
  61. package/scripts/foundry/plant/skills/sound/SKILL.md +3 -1
  62. package/scripts/foundry/plant/skills/sound-inspect/SKILL.md +1 -1
  63. package/scripts/foundry/plant/skills/sound-mixer/SKILL.md +28 -0
  64. package/scripts/foundry/sound-bed.cjs +2 -454
  65. package/scripts/foundry/sound-mixer.cjs +2 -0
  66. package/scripts/foundry/sound-rippel.cjs +2 -1434
  67. package/scripts/foundry/sound-taste.cjs +2 -0
  68. package/scripts/foundry/sound-voice.cjs +2 -0
  69. package/scripts/foundry/sound.mjs +23 -81
  70. package/scripts/node/install-bridges.cjs +39 -4
  71. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  72. package/src/skills/orchestrator/SKILL.md +20 -1
  73. package/xray/features.json +2 -2
@@ -0,0 +1,2 @@
1
+ /** Shim — mill drawers live in @0xray/blip. */
2
+ module.exports = require("@0xray/blip/blip-scene");
@@ -0,0 +1,2 @@
1
+ /** Shim — mill drawers live in @0xray/blip. */
2
+ module.exports = require("@0xray/blip/blip-stroke");
@@ -0,0 +1,2 @@
1
+ /** Shim — mill drawers live in @0xray/blip. */
2
+ module.exports = require("@0xray/blip/blip-vibe");
@@ -1,109 +1,35 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Factory-blip CLI — sibling plant to mill + sound, not a mill bolt-on.
4
- * npx @0xray/foundry blip render --brief TEXT --mode still|motion:<id> [--look focus|cage] [--bed PATH] [--engine rippel|wireframe] [--out FILE]
5
- * npx @0xray/foundry blip inspect
3
+ * Shim: product mill lives in @0xray/blip.
4
+ * npx @0xray/foundry blip render|inspect|vibe|look [...]
6
5
  */
7
-
6
+ import { spawnSync } from "node:child_process";
8
7
  import { createRequire } from "node:module";
9
8
  import path from "node:path";
10
- import { fileURLToPath } from "node:url";
11
- import { resolveMillRoot } from "./mill-root.mjs";
12
-
13
- const require = createRequire(import.meta.url);
14
- const blip = require("./blip-render.cjs");
9
+ import { pathToFileURL } from "node:url";
15
10
 
16
- const HELP =
17
- "Usage: npx @0xray/foundry blip <render|inspect> [...args]\n" +
18
- "\n" +
19
- "Factory-blip plant, sibling to mill + sound. FOUNDRY_ROOT overrides cwd.\n" +
20
- "render: brief → checksum seed → still|motion:<id> → 4.44s mp4 + audio bed → receipt.\n" +
21
- "v0 ids: still, orb, swirl, snap, waves, spark (Rippel five are imports).\n" +
22
- "Motions: Rippel VisualConfig.circles at ≥720p (default). --look focus|cage (seed picks if omitted).\n" +
23
- "--engine wireframe is emergency only.\n" +
24
- "Every mp4 muxes a 4.44s bed (--bed PATH or auto sound mill). Silent = inspect FAIL.\n" +
25
- "kapow is a growth stub (FAIL until a renderer ships). Unknown id FAIL.\n" +
26
- "still: Power Plant ident — plate dissolves over 4.44s at ≥720p, not a frozen poster.\n" +
27
- "inspect: last .xray/blip/receipt.json PASS/FAIL (missing is FAIL). Lists live registry ids.\n";
28
-
29
- function argValue(argv, name, fallback) {
30
- const i = argv.indexOf(name);
31
- if (i < 0 || i + 1 >= argv.length) return fallback;
32
- return argv[i + 1];
33
- }
11
+ export { inspectBlip } from "@0xray/blip";
34
12
 
35
- function writeJson(value) {
36
- process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
37
- }
38
-
39
- function inspectBlip(root) {
40
- const motions = blip.listMotionIds();
41
- const receipt = blip.readReceipt(root);
42
- if (!receipt) {
43
- return {
44
- ok: false,
45
- status: "FAIL",
46
- failClosed: true,
47
- plant: "blip",
48
- motions,
49
- detail: "missing .xray/blip/receipt.json",
50
- receipt: null,
51
- };
52
- }
53
- const evaluated = blip.evaluateReceipt(root, receipt);
54
- const status = evaluated.status === "PASS" ? "PASS" : "FAIL";
55
- return {
56
- ok: status === "PASS",
57
- status,
58
- failClosed: true,
59
- plant: "blip",
60
- motions,
61
- mode: evaluated.mode || receipt.motionId || receipt.mode || null,
62
- pictureMode: evaluated.pictureMode || receipt.pictureMode || null,
63
- durationSec: evaluated.durationSec ?? receipt.durationSec ?? null,
64
- receipt,
65
- };
66
- }
67
-
68
- function main() {
69
- const argv = process.argv.slice(2);
70
- const cmd = argv[0];
71
- const rest = argv.slice(1);
72
- const root = resolveMillRoot();
73
-
74
- if (!cmd || cmd === "--help" || cmd === "-h" || cmd === "help") {
75
- process.stdout.write(HELP);
76
- process.exit(cmd ? 0 : 1);
77
- }
78
-
79
- if (cmd === "inspect") {
80
- const report = inspectBlip(root);
81
- writeJson(report);
82
- process.exit(report.ok ? 0 : 1);
83
- }
13
+ const require = createRequire(import.meta.url);
84
14
 
85
- if (cmd === "render") {
86
- const result = blip.renderBlip({
87
- root,
88
- brief: argValue(rest, "--brief", "factory-blip"),
89
- pictureMode: argValue(rest, "--picture-mode", argValue(rest, "--mode", "still")),
90
- lookKind: argValue(rest, "--look", null),
91
- bed: argValue(rest, "--bed", null),
92
- engine: argValue(rest, "--engine", "rippel"),
93
- out: argValue(rest, "--out", null),
94
- });
95
- writeJson(result.receipt);
96
- process.exit(result.receipt.status === "PASS" ? 0 : 1);
15
+ function runCli(args) {
16
+ let cli;
17
+ try {
18
+ cli = require.resolve("@0xray/blip/cli");
19
+ } catch {
20
+ process.stderr.write("Install @0xray/blip — the 4.44s mill moved off the OS foundry.\n");
21
+ process.exit(1);
97
22
  }
98
-
99
- process.stderr.write(HELP);
100
- process.exit(1);
23
+ const result = spawnSync(process.execPath, [cli, ...args], {
24
+ stdio: "inherit",
25
+ cwd: process.env.FOUNDRY_ROOT || process.cwd(),
26
+ env: process.env,
27
+ });
28
+ process.exit(result.status === null ? 1 : result.status);
101
29
  }
102
30
 
103
- export { inspectBlip };
104
-
105
- const isMain =
106
- process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
107
- if (isMain) {
108
- main();
31
+ const invoked =
32
+ process.argv[1] && pathToFileURL(path.resolve(process.argv[1])).href === import.meta.url;
33
+ if (invoked) {
34
+ runCli(process.argv.slice(2));
109
35
  }
@@ -30,8 +30,8 @@ const HELP =
30
30
  "release bumps/commits/pushes/publishes the milled cwd — pass --dry-run or --i-mean-it (or FOUNDRY_RELEASE=1).\n" +
31
31
  "Mint fastens the requested factory plant (default mill; foundry.json plant: sound|blip turns mill off), then inspect.\n" +
32
32
  "inspect runs mill checks plus, on a sound seat, last bed receipt PASS/FAIL; on a blip seat, last blip receipt.\n" +
33
- "sound render|inspect is the factory-sound plant (brief → seed → genre → wav → metrics). Sibling to mill, not a mill copy.\n" +
34
- "blip render|inspect is the factory-blip plant (brief → seed → still|motion:<id> → 4.44s mp4). Sibling to mill + sound.\n" +
33
+ "sound render|inspect|mix is the factory-sound plant (brief → seed → genre → wav → metrics; mix levels every variation). Sibling to mill, not a mill copy.\n" +
34
+ "blip render|inspect|vibe|look is the factory-blip plant (brief → seed → still|motion:<id> → 4.44s mp4; vibe is stamp density, look is the friend hitting replay, ship bar 8). Sibling to mill + sound.\n" +
35
35
  "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";
36
36
 
37
37
  const cmd = process.argv[2];
@@ -14,6 +14,7 @@ import { millPackageDir, resolveMillRoot } from "./mill-root.mjs";
14
14
 
15
15
  const require = createRequire(import.meta.url);
16
16
  const mint = require("./mint-suit.cjs");
17
+ const millProtocol = require("./mill-plant.cjs");
17
18
 
18
19
  export function npmTarballUrl(name, version) {
19
20
  if (typeof name !== "string" || !name || typeof version !== "string" || !version) return null;
@@ -81,20 +82,45 @@ function checkDiff(root) {
81
82
  };
82
83
  }
83
84
 
85
+ function emptyPlantFiles() {
86
+ return { skills: [], agents: [] };
87
+ }
88
+
84
89
  function checkPlantVsWorn(root, millRoot) {
85
- const kinds = mint.loadFactoryPlantKinds(root);
86
- const allow = mint.factoryPlantAllowlist(millRoot, root);
90
+ let seats;
91
+ try {
92
+ seats = millProtocol.resolvePlantSeats(root, millRoot);
93
+ } catch (err) {
94
+ return {
95
+ id: "plant-vs-worn",
96
+ ok: false,
97
+ detail: err instanceof Error ? err.message : String(err),
98
+ };
99
+ }
100
+ const kinds = millProtocol.plantKindsFromSeats(seats);
101
+ const millSeat = seats.find((seat) => seat.kind === "mill");
102
+ const soundSeat = seats.find((seat) => seat.kind === "sound");
103
+ const blipSeat = seats.find((seat) => seat.kind === "blip");
87
104
  const millPlant = {
88
- skills: kinds.includes("mill") ? mint.catalogPlant("mill").skills : [],
89
- agents: kinds.includes("mill") ? mint.catalogPlant("mill").agents : [],
90
- sound: kinds.includes("sound") ? mint.catalogPlant("sound") : { skills: [], agents: [] },
91
- blip: kinds.includes("blip") ? mint.catalogPlant("blip") : { skills: [], agents: [] },
105
+ skills: millSeat ? millSeat.skills : [],
106
+ agents: millSeat ? millSeat.agents : [],
107
+ sound: soundSeat
108
+ ? { skills: soundSeat.skills, agents: soundSeat.agents }
109
+ : emptyPlantFiles(),
110
+ blip: blipSeat ? { skills: blipSeat.skills, agents: blipSeat.agents } : emptyPlantFiles(),
111
+ plants: Object.fromEntries(
112
+ seats
113
+ .filter((seat) => !seat.builtin)
114
+ .map((seat) => [seat.kind, { skills: seat.skills, agents: seat.agents }]),
115
+ ),
92
116
  };
93
117
  const params = mint.loadFoundryParams(root);
94
118
  const tree = {
95
119
  skills: mint.listConsumerSkillNames(root, params.skills),
96
120
  agents: mint.listConsumerAgentFiles(root, params.agents),
97
121
  plantKinds: kinds,
122
+ seats,
123
+ millPackageRoot: millRoot,
98
124
  soundPlantSkills: millPlant.sound.skills,
99
125
  soundPlantAgents: millPlant.sound.agents,
100
126
  sound: millPlant.sound,
@@ -103,6 +129,7 @@ function checkPlantVsWorn(root, millRoot) {
103
129
  blip: millPlant.blip,
104
130
  };
105
131
  const shopPlant = mint.loadShopPlant(root);
132
+ const allow = mint.factoryPlantAllowlist(millRoot, root);
106
133
  try {
107
134
  mint.assertNoCostumeDump(root, millPlant, tree);
108
135
  return {
@@ -132,7 +159,7 @@ function checkPlantVsWorn(root, millRoot) {
132
159
  }
133
160
  }
134
161
 
135
- function checkReceipt(root) {
162
+ function checkReceipt(root, millRoot) {
136
163
  const file = path.join(root, ".xray", "foundry-inventory.json");
137
164
  if (mint.isDogfood(millPackageDir(), root)) {
138
165
  return { id: "receipt", ok: true, skipped: true, detail: "dogfood / exo — no consumer inventory" };
@@ -146,24 +173,40 @@ function checkReceipt(root) {
146
173
  const blipPlantSkills = inventory.blipPlant?.skills || [];
147
174
  const kinds = mint.inventoryPlantKinds(inventory);
148
175
  const needMill = kinds.includes("mill");
149
- const needSound = kinds.includes("sound");
150
- const needBlip = kinds.includes("blip");
151
176
  const millOk = !needMill || (millPlantSkills.includes("mill") && millPlantSkills.includes("inspect"));
152
- const soundOk =
153
- !needSound || (soundPlantSkills.includes("sound") && soundPlantSkills.includes("sound-inspect"));
154
- const blipOk =
155
- !needBlip || (blipPlantSkills.includes("blip") && blipPlantSkills.includes("blip-inspect"));
156
- const ok = millOk && soundOk && blipOk && (needMill || needSound || needBlip);
157
177
  let detail = null;
158
- if (!ok && needMill && !millOk) detail = "millPlant.skills must include mill and inspect";
159
- else if (!ok && needSound && !soundOk) detail = "soundPlant.skills must include sound and sound-inspect";
160
- else if (!ok && needBlip && !blipOk) detail = "blipPlant.skills must include blip and blip-inspect";
161
- else if (!ok) detail = "inventory plant is empty";
178
+ if (needMill && !millOk) detail = "millPlant.skills must include mill and inspect";
179
+ const packageKinds = kinds.filter((kind) => kind !== "mill");
180
+ if (!detail && packageKinds.length > 0) {
181
+ try {
182
+ const declared = millProtocol.declaredReceiptSeats(inventory, root, millRoot);
183
+ for (const seat of declared) {
184
+ if (seat.builtin) continue;
185
+ const have = millProtocol.inventoryFilesForKind(inventory, seat.kind);
186
+ const haveSkills = Array.isArray(have?.skills) ? have.skills : [];
187
+ if (!seat.skills || seat.skills.length === 0) {
188
+ detail = `${seat.kind} plant declared no skills`;
189
+ break;
190
+ }
191
+ const missing = seat.skills.filter((name) => !haveSkills.includes(name));
192
+ if (missing.length > 0) {
193
+ detail = `${seat.kind}Plant.skills must include protocol skills (${missing.join(", ")})`;
194
+ break;
195
+ }
196
+ }
197
+ } catch (err) {
198
+ detail = err instanceof Error ? err.message : String(err);
199
+ }
200
+ }
201
+ const ok = !detail && (needMill || packageKinds.length > 0);
202
+ if (!ok && !detail) detail = "inventory plant is empty";
162
203
  return {
163
204
  id: "receipt",
164
205
  ok,
165
206
  suit: inventory.suit,
166
207
  mill: inventory.mill,
208
+ millPackage: inventory.millPackage || null,
209
+ millProtocol: inventory.millProtocol || null,
167
210
  plant: kinds,
168
211
  millPlant: millPlantSkills,
169
212
  soundPlant: soundPlantSkills,
@@ -373,7 +416,7 @@ export async function inspectSuit(root, opts = {}) {
373
416
  const checks = [];
374
417
  checks.push(checkDiff(root));
375
418
  checks.push(checkPlantVsWorn(root, millRoot));
376
- checks.push(checkReceipt(root));
419
+ checks.push(checkReceipt(root, millRoot));
377
420
  const soundBed = checkSoundBed(root);
378
421
  if (soundBed) checks.push(soundBed);
379
422
  const blip = checkBlip(root);