0xray 4.0.9 → 4.0.11

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.
@@ -21,6 +21,9 @@ const DEFAULT_PARAMS = {
21
21
  agentsCard: "xray/AGENTS.md",
22
22
  };
23
23
 
24
+ /** Factory shop plant. First-class with mill plant. Not 45/42 costume. */
25
+ const FACTORY_SHOP_SKILLS = ["shop-extract", "shop-witness", "shop-pin"];
26
+
24
27
  function deepMerge(src, dest) {
25
28
  if (typeof src !== "object" || src === null) return dest !== undefined ? dest : src;
26
29
  if (Array.isArray(src)) return Array.isArray(dest) ? dest : src;
@@ -298,13 +301,59 @@ function wornAgentFiles(targetDir) {
298
301
  return listAgentFilesAt(path.join(targetDir, ".opencode", "agents"));
299
302
  }
300
303
 
304
+ function normalizeNameList(value) {
305
+ if (!Array.isArray(value)) return [];
306
+ const names = [];
307
+ for (const item of value) {
308
+ if (typeof item !== "string") continue;
309
+ const name = item.trim();
310
+ if (name) names.push(name);
311
+ }
312
+ return names;
313
+ }
314
+
315
+ function shopPlantFromDir(targetDir, rel) {
316
+ const resolved = resolveInside(targetDir, rel);
317
+ if (!resolved || !isDirectory(resolved)) return [];
318
+ const nested = path.join(resolved, "skills");
319
+ return listSkillNamesAt(isDirectory(nested) ? nested : resolved);
320
+ }
321
+
322
+ function declaredShopPlant(targetDir) {
323
+ const raw = loadFoundryExtra(targetDir).shopPlant;
324
+ const names = [];
325
+ if (Array.isArray(raw)) {
326
+ names.push(...normalizeNameList(raw));
327
+ } else if (typeof raw === "string" && raw.trim()) {
328
+ names.push(...shopPlantFromDir(targetDir, raw.trim()));
329
+ } else if (raw && typeof raw === "object") {
330
+ names.push(...normalizeNameList(raw.skills));
331
+ if (typeof raw.dir === "string" && raw.dir.trim()) {
332
+ names.push(...shopPlantFromDir(targetDir, raw.dir.trim()));
333
+ }
334
+ }
335
+ return names;
336
+ }
337
+
338
+ /** Factory shop names plus foundry.json shopPlant. Not costume. */
339
+ function loadShopPlant(targetDir) {
340
+ return [...new Set([...FACTORY_SHOP_SKILLS, ...declaredShopPlant(targetDir)])];
341
+ }
342
+
301
343
  function previousTreeAllowlist(targetDir) {
302
344
  const file = path.join(targetDir, ".xray", "foundry-inventory.json");
303
345
  if (!fs.existsSync(file)) return { skills: [], agents: [] };
304
346
  try {
305
347
  const inventory = JSON.parse(fs.readFileSync(file, "utf8"));
348
+ const shopFromInv = inventory?.shopPlant;
349
+ const shopSkills = Array.isArray(shopFromInv)
350
+ ? normalizeNameList(shopFromInv)
351
+ : normalizeNameList(shopFromInv?.skills);
306
352
  return {
307
- skills: Array.isArray(inventory?.tree?.skills) ? inventory.tree.skills : [],
353
+ skills: [
354
+ ...(Array.isArray(inventory?.tree?.skills) ? inventory.tree.skills : []),
355
+ ...shopSkills,
356
+ ],
308
357
  agents: Array.isArray(inventory?.tree?.agents) ? inventory.tree.agents : [],
309
358
  };
310
359
  } catch {
@@ -312,13 +361,15 @@ function previousTreeAllowlist(targetDir) {
312
361
  }
313
362
  }
314
363
 
315
- /** Extra worn names that are neither mill plant, their plant, nor a prior overlay. */
364
+ /** Extra worn names that are neither mill plant, their plant, shop plant, nor a prior overlay. */
316
365
  function costumeDumpExtras(targetDir, millPlant, tree) {
317
366
  const prior = previousTreeAllowlist(targetDir);
367
+ const shopPlant = loadShopPlant(targetDir);
318
368
  const allowedSkills = new Set([
319
369
  ...(Array.isArray(millPlant?.skills) ? millPlant.skills : []),
320
370
  ...(Array.isArray(tree?.skills) ? tree.skills : []),
321
371
  ...prior.skills,
372
+ ...shopPlant,
322
373
  ]);
323
374
  const allowedAgents = new Set([
324
375
  ...(Array.isArray(millPlant?.agents) ? millPlant.agents : []),
@@ -427,6 +478,9 @@ function mintConsumerFromSsot(packageRoot, targetDir, log, tree) {
427
478
  skills: Array.isArray(tree?.millPlantSkills) ? tree.millPlantSkills : [],
428
479
  agents: Array.isArray(tree?.millPlantAgents) ? tree.millPlantAgents : [],
429
480
  },
481
+ shopPlant: {
482
+ skills: Array.isArray(tree?.shopPlantSkills) ? tree.shopPlantSkills : loadShopPlant(targetDir),
483
+ },
430
484
  costume,
431
485
  facets: {
432
486
  constitution,
@@ -465,6 +519,7 @@ function mintConsumerSuit(millPackageRoot, targetDir, log) {
465
519
  const tree = overlayConsumerTree(targetDir, log, params);
466
520
  tree.millPlantSkills = millPlant.skills;
467
521
  tree.millPlantAgents = millPlant.agents;
522
+ tree.shopPlantSkills = loadShopPlant(targetDir);
468
523
  tree.codex = overlayJsonFacet(
469
524
  resolveInside(targetDir, params.codex),
470
525
  path.join(targetDir, ".xray", "codex.json"),
@@ -491,9 +546,12 @@ function mintConsumerSuit(millPackageRoot, targetDir, log) {
491
546
 
492
547
  module.exports = {
493
548
  DEFAULT_PARAMS,
549
+ FACTORY_SHOP_SKILLS,
494
550
  deepMerge,
495
551
  loadFoundryParams,
496
552
  loadFoundryExtra,
553
+ loadShopPlant,
554
+ declaredShopPlant,
497
555
  wantsCostume,
498
556
  millPlantDir,
499
557
  listSkillNamesAt,
@@ -12,7 +12,7 @@ Mill **does** these checks (`npx @0xray/foundry inspect`). Mint fails on a costu
12
12
  ## What mill inspects
13
13
 
14
14
  1. **Diff.** `git status` / `git diff --stat` of the milled cwd. Ignore the agent's summary if the diff disagrees.
15
- 2. **Plant vs worn.** `src/skills`, `src/opencode/agents` vs `.opencode/skills`, `.opencode/agents`. Same name: plant wins. Costume dump (worn names they did not plant and mill did not fasten) fails mint unless `foundry.json` has `"costume": true`.
15
+ 2. **Plant vs worn.** `src/skills`, `src/opencode/agents` vs `.opencode/skills`, `.opencode/agents`. Same name: plant wins. Shop plant (`shop-extract`, `shop-witness`, `shop-pin`, plus `foundry.json` `shopPlant`) is first-class with mill plant. Costume dump (worn names they did not plant, mill did not fasten, and shop plant did not name) fails mint unless `foundry.json` has `"costume": true`.
16
16
  3. **Mill receipt.** `.xray/foundry-inventory.json` — mill name/version, `suit` (`fastened` / `overlay` / `costume`), `millPlant.skills` must include `mill` and `inspect`.
17
17
  4. **CI.** GitHub mill CI report (`.opencode/logs/ci-cd-monitor-report.json`), not a green check in chat. No token is a skip, not a pass invented.
18
18
  5. **Live PUT.** HTTP 200 on the npm `.tgz`. Metadata without a tarball is not shipped.
@@ -2,8 +2,8 @@
2
2
  /**
3
3
  * validate-release-docs.mjs — Blocking guard for release doc freshness.
4
4
  *
5
- * Ensures README, AGENTS, SKILLS, CHANGELOG, Docusaurus headers, and required
6
- * guides match package.json version and live framework counts before tag/publish.
5
+ * Ensures README, AGENTS, SKILLS, llms.txt, CHANGELOG, Docusaurus headers, and
6
+ * required guides match package.json version and mill law before tag/publish.
7
7
  *
8
8
  * Usage:
9
9
  * npx @0xray/foundry docs-check
@@ -42,6 +42,24 @@ const REQUIRED_GUIDES = [
42
42
  'docs-site/docs/agents/README.md',
43
43
  ];
44
44
 
45
+ function millLawLagErrors(content) {
46
+ const errors = [];
47
+ if (/Syncs \*\*45 framework skills\*\*/.test(content) || /syncs all 45 skills/i.test(content)) {
48
+ errors.push('lags mill law: default plant is mill+inspect, not 45-skill sync');
49
+ }
50
+ if (/SKILLS\.md \+ 45 skills → platform skill directories/.test(content)) {
51
+ errors.push('lags mill law: postinstall must not sync 45 skills as default plant');
52
+ }
53
+ return errors;
54
+ }
55
+
56
+ function millPlantMentionErrors(content) {
57
+ if (!content.includes('mill') || !content.includes('inspect')) {
58
+ return ['missing mill+inspect plant'];
59
+ }
60
+ return [];
61
+ }
62
+
45
63
  const ROOT_DOC_CHECKS = [
46
64
  {
47
65
  rel: 'README.md',
@@ -62,6 +80,14 @@ const ROOT_DOC_CHECKS = [
62
80
  if (!content.includes('install-bridges') && !content.includes('installAllBridges')) {
63
81
  errors.push('missing install-bridges / installAllBridges reference');
64
82
  }
83
+ if (!content.includes('llms.txt')) {
84
+ errors.push('missing llms.txt agent-map reference');
85
+ }
86
+ if (!content.includes('shopPlant') && !content.includes('shop-extract')) {
87
+ errors.push('missing shop plant / shopPlant');
88
+ }
89
+ errors.push(...millPlantMentionErrors(content));
90
+ errors.push(...millLawLagErrors(content));
65
91
  return errors;
66
92
  },
67
93
  },
@@ -81,6 +107,11 @@ const ROOT_DOC_CHECKS = [
81
107
  if (!content.includes('SKILLS.md')) {
82
108
  errors.push('missing SKILLS.md link');
83
109
  }
110
+ if (!content.includes('llms.txt')) {
111
+ errors.push('missing llms.txt agent-map reference');
112
+ }
113
+ errors.push(...millPlantMentionErrors(content));
114
+ errors.push(...millLawLagErrors(content));
84
115
  return errors;
85
116
  },
86
117
  },
@@ -100,6 +131,11 @@ const ROOT_DOC_CHECKS = [
100
131
  if (!content.includes('AsideContext')) {
101
132
  errors.push('missing AsideContext section');
102
133
  }
134
+ if (!content.includes('shopPlant') && !content.includes('shop-extract')) {
135
+ errors.push('missing shop plant / shopPlant');
136
+ }
137
+ errors.push(...millPlantMentionErrors(content));
138
+ errors.push(...millLawLagErrors(content));
103
139
  return errors;
104
140
  },
105
141
  },
@@ -113,6 +149,37 @@ const ROOT_DOC_CHECKS = [
113
149
  if (!content.includes(`**${counts.skills} skills**`)) {
114
150
  errors.push(`skill count stale (expected **${counts.skills} skills**)`);
115
151
  }
152
+ errors.push(...millPlantMentionErrors(content));
153
+ errors.push(...millLawLagErrors(content));
154
+ return errors;
155
+ },
156
+ },
157
+ {
158
+ rel: 'llms.txt',
159
+ validate: (content) => {
160
+ const errors = [];
161
+ if (kernelLineHasPatchStamp(content)) {
162
+ errors.push('kernel header must be era (major.minor), not a patch stamp');
163
+ }
164
+ if (!content.includes('mill') || !content.includes('inspect')) {
165
+ errors.push('missing mill+inspect plant');
166
+ }
167
+ if (!content.includes('shopPlant') && !content.includes('shop-extract')) {
168
+ errors.push('missing hangar / shopPlant coexistence');
169
+ }
170
+ if (!content.includes('69')) {
171
+ errors.push('missing Codex 69');
172
+ }
173
+ if (!content.includes('xray-governance') || !content.includes('xray-orchestrator')) {
174
+ errors.push('missing 7 MCP agent map');
175
+ }
176
+ if (!content.toLowerCase().includes('costume')) {
177
+ errors.push('missing no-costume-dump law');
178
+ }
179
+ if (/^## Complete catalog/m.test(content) || content.includes('`api-design` · `architect-tools`')) {
180
+ errors.push('llms.txt must not costume-dump the 45-skill catalog');
181
+ }
182
+ errors.push(...millLawLagErrors(content));
116
183
  return errors;
117
184
  },
118
185
  },
@@ -348,6 +348,7 @@ export function getReleaseArtifactPaths(baseDir = resolveMillRoot()) {
348
348
  'AGENTS.md',
349
349
  'AGENTS-consumer.md',
350
350
  'SKILLS.md',
351
+ 'llms.txt',
351
352
  '.grok-plugin/plugin.json',
352
353
  'docs/README.md',
353
354
  'docs-site/docs/index.md',
@@ -366,6 +367,9 @@ export function getReleaseArtifactPaths(baseDir = resolveMillRoot()) {
366
367
  'docs-site/docs/architecture/GROK_GUIDE.md',
367
368
  'docs-site/sidebars.ts',
368
369
  'xray/features.json',
370
+ '.xray/features.json',
371
+ 'docs/PIPELINE-FACET-SNAPSHOT.json',
372
+ 'src/integrations/openclaw/plugin/xray-pre-tool/package.json',
369
373
  ];
370
374
  return candidates.filter((rel) => fs.existsSync(path.join(baseDir, rel)));
371
375
  }
@@ -39,6 +39,17 @@ function resolveRepertoireMcp(targetDir) {
39
39
  const candidates = [
40
40
  path.join(targetDir, "node_modules", "@0xray", "repertoire", "dist", "mcp", "server.js"),
41
41
  path.join(targetDir, "vendor", "@0xray", "repertoire", "dist", "mcp", "server.js"),
42
+ path.join(
43
+ targetDir,
44
+ "node_modules",
45
+ "0xray",
46
+ "vendor",
47
+ "@0xray",
48
+ "repertoire",
49
+ "dist",
50
+ "mcp",
51
+ "server.js",
52
+ ),
42
53
  isRepertoirePackageRoot(selfRoot) ? path.join(selfRoot, "dist", "mcp", "server.js") : null,
43
54
  isRepertoirePackageRoot(siblingRoot) ? path.join(siblingRoot, "dist", "mcp", "server.js") : null,
44
55
  ];
@@ -66,8 +77,20 @@ function resolveRepertoireProvider(targetDir) {
66
77
  "provider",
67
78
  "memory-routing-provider.js",
68
79
  );
80
+ const packedVendorProvider = path.join(
81
+ targetDir,
82
+ "node_modules",
83
+ "0xray",
84
+ "vendor",
85
+ "@0xray",
86
+ "repertoire",
87
+ "dist",
88
+ "provider",
89
+ "memory-routing-provider.js",
90
+ );
69
91
  if (fs.existsSync(nmProvider)) return nmProvider;
70
92
  if (fs.existsSync(vendorProvider)) return vendorProvider;
93
+ if (fs.existsSync(packedVendorProvider)) return packedVendorProvider;
71
94
  if (isRepertoirePackageRoot(siblingRoot) && fs.existsSync(siblingProvider)) return siblingProvider;
72
95
  return null;
73
96
  }
@@ -15,6 +15,7 @@ import os from "os";
15
15
  import path from "path";
16
16
  import { fileURLToPath } from "url";
17
17
  import { createRequire } from "module";
18
+ import { proveSuitAfterInstall } from "./pack-tmp-suit-proof.mjs";
18
19
 
19
20
  const require = createRequire(import.meta.url);
20
21
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -39,6 +40,64 @@ function run(cmd, cwd, { inherit = false } = {}) {
39
40
  return inherit ? "" : String(result).trim();
40
41
  }
41
42
 
43
+ function assertPackedPackageHasNoFileDeps(tarballPath) {
44
+ const packedJson = run(`tar -xOf ${JSON.stringify(tarballPath)} package/package.json`);
45
+ const packed = JSON.parse(packedJson);
46
+ const buckets = ["dependencies", "optionalDependencies", "peerDependencies"];
47
+ for (const bucket of buckets) {
48
+ const entries = packed[bucket] || {};
49
+ for (const [name, spec] of Object.entries(entries)) {
50
+ if (String(spec).startsWith("file:")) {
51
+ throw new Error(
52
+ `packed package.json must not ship file: ${bucket} ${name}=${spec} (consumers resolve file: from their root)`,
53
+ );
54
+ }
55
+ }
56
+ }
57
+ if (!String(packedJson).includes("vendor/@0xray/repertoire/")) {
58
+ const listing = run(`tar -tzf ${JSON.stringify(tarballPath)}`);
59
+ if (!listing.includes("package/vendor/@0xray/repertoire/package.json")) {
60
+ throw new Error("packed tarball missing vendor/@0xray/repertoire/package.json");
61
+ }
62
+ }
63
+ console.log(" ✅ packed package.json has no file: deps; vendor organ is in the tarball");
64
+ }
65
+
66
+ function assertOrganRequire(tmpRoot) {
67
+ const consumerRequire = createRequire(path.join(tmpRoot, "package.json"));
68
+ let organPkg;
69
+ try {
70
+ organPkg = consumerRequire("@0xray/repertoire/package.json");
71
+ } catch (err) {
72
+ throw new Error(`require('@0xray/repertoire') failed: ${err.message}`);
73
+ }
74
+ if (organPkg.name !== "@0xray/repertoire") {
75
+ throw new Error(`required organ name ${organPkg.name}`);
76
+ }
77
+ if (organPkg.version !== "0.2.0") {
78
+ throw new Error(`required organ version ${organPkg.version}`);
79
+ }
80
+ if (fs.existsSync(path.join(tmpRoot, "vendor"))) {
81
+ throw new Error("consumer install must not create or require a consumer-root vendor/ tree");
82
+ }
83
+ console.log(" ✅ require('@0xray/repertoire') from consumer cwd (no consumer vendor/)");
84
+ }
85
+
86
+ function writeBareConsumerManifest(tmpRoot) {
87
+ fs.writeFileSync(
88
+ path.join(tmpRoot, "package.json"),
89
+ `${JSON.stringify(
90
+ {
91
+ name: "xray-consumer-test",
92
+ version: "0.0.1",
93
+ private: true,
94
+ },
95
+ null,
96
+ 2,
97
+ )}\n`,
98
+ );
99
+ }
100
+
42
101
  function assertFreshInstallDefaults(tmpRoot, version) {
43
102
  const consumerFeaturesPath = path.join(tmpRoot, ".xray", "features.json");
44
103
  if (!fs.existsSync(consumerFeaturesPath)) {
@@ -188,25 +247,30 @@ function main() {
188
247
  throw new Error(`Tarball not found: ${tarballPath}`);
189
248
  }
190
249
 
191
- const consumerPkg = {
192
- name: "0xray-smoke-consumer",
193
- private: true,
194
- version: "1.0.0",
195
- dependencies: {
196
- "0xray": `file:${tarballPath}`,
197
- },
198
- };
199
- fs.writeFileSync(
200
- path.join(tmpRoot, "package.json"),
201
- JSON.stringify(consumerPkg, null, 2) + "\n",
202
- );
250
+ assertPackedPackageHasNoFileDeps(tarballPath);
251
+
252
+ writeBareConsumerManifest(tmpRoot);
203
253
 
204
- console.log("📥 npm install (runs postinstall)...");
205
- run("npm install", tmpRoot, { inherit: true });
254
+ console.log("📥 npm install tarball into bare consumer (exact ENOENT repro)...");
255
+ run(`npm install ${JSON.stringify(tarballPath)}`, tmpRoot, { inherit: true });
256
+
257
+ const installLinksRoot = fs.mkdtempSync(path.join(os.tmpdir(), "0xray-smoke-links-"));
258
+ writeBareConsumerManifest(installLinksRoot);
259
+ console.log("📥 npm install tarball --install-links (file: ENOENT path)...");
260
+ run(`npm install ${JSON.stringify(tarballPath)} --install-links`, installLinksRoot, {
261
+ inherit: true,
262
+ });
263
+ assertOrganRequire(installLinksRoot);
264
+ try {
265
+ fs.rmSync(installLinksRoot, { recursive: true, force: true });
266
+ } catch {
267
+ /* best-effort */
268
+ }
206
269
 
207
270
  const nmRoot = path.join(tmpRoot, "node_modules", "0xray");
208
271
  const requiredFiles = [
209
272
  "scripts/node/install-bridges.cjs",
273
+ "scripts/node/wear-vendored-repertoire.cjs",
210
274
  "scripts/node/postinstall.cjs",
211
275
  "scripts/foundry/mint-suit.cjs",
212
276
  "scripts/foundry/hooks.mjs",
@@ -274,6 +338,7 @@ function main() {
274
338
  console.log(` ✅ .mcp.json has ${XRAY_MCP_NAMES.length} npx MCP servers`);
275
339
 
276
340
  assertFreshInstallDefaults(tmpRoot, version);
341
+ assertOrganRequire(tmpRoot);
277
342
 
278
343
  const schemaInPackage = path.join(nmRoot, "xray", "features.schema.json");
279
344
  if (!fs.existsSync(schemaInPackage)) {
@@ -283,6 +348,9 @@ function main() {
283
348
 
284
349
  runUpgradeMergeSmoke(tmpRoot, nmRoot, version);
285
350
 
351
+ console.log("\n📋 Pack → tmp mill fasten + hangar shop plant (not costume)...");
352
+ proveSuitAfterInstall(tmpRoot, path.join(nmRoot, "scripts", "foundry"));
353
+
286
354
  console.log("\n✅ Consumer install smoke passed\n");
287
355
  } catch (err) {
288
356
  console.error(`\n❌ Consumer smoke failed: ${err.message}\n`);
@@ -9,6 +9,7 @@ const path = require("path");
9
9
  const os = require("os");
10
10
  const { execSync } = require("child_process");
11
11
  const { wantsCostume, isIsolatedHome, machineHome } = require("../foundry/mint-suit.cjs");
12
+ const { wearVendoredRepertoire } = require("./wear-vendored-repertoire.cjs");
12
13
  const {
13
14
  wireHermesBridge,
14
15
  wireOpencodeBridge,
@@ -742,6 +743,8 @@ function installAllBridges(opts) {
742
743
  /* noop */
743
744
  });
744
745
 
746
+ wearVendoredRepertoire(packageRoot, targetDir, log);
747
+
745
748
  if (!isConsumerInstall(packageRoot, targetDir)) {
746
749
  log("install-bridges", "framework dogfood wear", "info");
747
750
  installFrameworkDogfoodWear(packageRoot, log);
@@ -779,4 +782,5 @@ module.exports = {
779
782
  isEphemeralInstallRoot,
780
783
  isIsolatedHome,
781
784
  installFrameworkDogfoodWear,
785
+ wearVendoredRepertoire,
782
786
  };