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.
@@ -0,0 +1,242 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * pack-tmp-suit-proof.mjs — Clean-room pack → tmp install → mill fasten → hangar plant → inspect.
4
+ *
5
+ * Asserts (Task B):
6
+ * 1. `npm install` of the packed 0xray tgz works
7
+ * 2. `foundry mint --skip-live` fastens mill+inspect (not 45/42 costume)
8
+ * 3. groover-hangar factory shops + inspect do not costume-dump
9
+ *
10
+ * Usage:
11
+ * node scripts/node/pack-tmp-suit-proof.mjs
12
+ * npm run pack:tmp-proof
13
+ *
14
+ * Playwright / UI: n/a (mill CLI).
15
+ */
16
+
17
+ import { execSync, spawnSync } from "node:child_process";
18
+ import fs from "node:fs";
19
+ import os from "node:os";
20
+ import path from "node:path";
21
+ import { fileURLToPath } from "node:url";
22
+
23
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
+ const repoRoot = path.resolve(__dirname, "../..");
25
+
26
+ export const FACTORY_SHOP_SKILLS = ["shop-extract", "shop-witness", "shop-pin"];
27
+ export const MILL_PLANT_SKILLS = ["mill", "inspect"];
28
+
29
+ function run(cmd, cwd, { inherit = false } = {}) {
30
+ const result = execSync(cmd, {
31
+ cwd,
32
+ encoding: inherit ? undefined : "utf-8",
33
+ stdio: inherit ? "inherit" : "pipe",
34
+ });
35
+ return inherit ? "" : String(result).trim();
36
+ }
37
+
38
+ export function foundryCliPath(millRoot) {
39
+ return path.join(millRoot, "cli.js");
40
+ }
41
+
42
+ export function runFoundryCli(millRoot, consumerRoot, args) {
43
+ const isolatedHome = path.join(consumerRoot, ".proof-home");
44
+ fs.mkdirSync(isolatedHome, { recursive: true });
45
+ return spawnSync(process.execPath, [foundryCliPath(millRoot), ...args], {
46
+ cwd: consumerRoot,
47
+ encoding: "utf8",
48
+ env: {
49
+ ...process.env,
50
+ FOUNDRY_ROOT: consumerRoot,
51
+ HOME: isolatedHome,
52
+ },
53
+ });
54
+ }
55
+
56
+ export function lastJsonObject(text) {
57
+ const src = String(text || "");
58
+ for (let end = src.length - 1; end >= 0; end -= 1) {
59
+ if (src[end] !== "}") continue;
60
+ let depth = 0;
61
+ for (let start = end; start >= 0; start -= 1) {
62
+ const ch = src[start];
63
+ if (ch === "}") depth += 1;
64
+ else if (ch === "{") {
65
+ depth -= 1;
66
+ if (depth === 0) {
67
+ try {
68
+ return JSON.parse(src.slice(start, end + 1));
69
+ } catch {
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ return null;
77
+ }
78
+
79
+ export function plantHangarFactoryShops(consumerRoot) {
80
+ for (const name of FACTORY_SHOP_SKILLS) {
81
+ const dir = path.join(consumerRoot, ".opencode", "skills", name);
82
+ fs.mkdirSync(dir, { recursive: true });
83
+ fs.writeFileSync(path.join(dir, "SKILL.md"), `groover-hangar plant ${name}\n`);
84
+ }
85
+ }
86
+
87
+ export function wornSkillNames(consumerRoot) {
88
+ const skillsDir = path.join(consumerRoot, ".opencode", "skills");
89
+ if (!fs.existsSync(skillsDir)) return [];
90
+ return fs.readdirSync(skillsDir).filter((name) =>
91
+ fs.existsSync(path.join(skillsDir, name, "SKILL.md")),
92
+ );
93
+ }
94
+
95
+ export function assertFastenedMillPlant(consumerRoot) {
96
+ const inventoryPath = path.join(consumerRoot, ".xray", "foundry-inventory.json");
97
+ if (!fs.existsSync(inventoryPath)) {
98
+ throw new Error("foundry-inventory.json missing — mill did not fasten");
99
+ }
100
+ const inventory = JSON.parse(fs.readFileSync(inventoryPath, "utf8"));
101
+ if (inventory.costume === true) {
102
+ throw new Error("inventory.costume is true — costume dump is not default mill plant");
103
+ }
104
+ const millSkills = inventory.millPlant?.skills || [];
105
+ for (const name of MILL_PLANT_SKILLS) {
106
+ if (!millSkills.includes(name)) {
107
+ throw new Error(`mill plant missing ${name} (got ${millSkills.join(",")})`);
108
+ }
109
+ if (!fs.existsSync(path.join(consumerRoot, ".opencode", "skills", name, "SKILL.md"))) {
110
+ throw new Error(`worn mill plant missing ${name}`);
111
+ }
112
+ }
113
+ const foundry = path.join(consumerRoot, "foundry.json");
114
+ if (fs.existsSync(foundry)) {
115
+ const extra = JSON.parse(fs.readFileSync(foundry, "utf8"));
116
+ if (extra.costume === true) {
117
+ throw new Error("foundry.json costume:true is not the mill+inspect path");
118
+ }
119
+ }
120
+ const worn = wornSkillNames(consumerRoot);
121
+ const extras = worn.filter(
122
+ (name) => !MILL_PLANT_SKILLS.includes(name) && !FACTORY_SHOP_SKILLS.includes(name),
123
+ );
124
+ if (extras.length > 0) {
125
+ throw new Error(`costume dump extras before hangar plant: ${extras.join(",")}`);
126
+ }
127
+ return inventory;
128
+ }
129
+
130
+ export function proveSuitAfterInstall(consumerRoot, millRoot) {
131
+ if (!fs.existsSync(foundryCliPath(millRoot))) {
132
+ throw new Error(`foundry CLI missing at ${foundryCliPath(millRoot)}`);
133
+ }
134
+
135
+ console.log(" ⚒️ foundry mint --skip-live (fasten mill+inspect)...");
136
+ const mint = runFoundryCli(millRoot, consumerRoot, ["mint", "--skip-live"]);
137
+ if (mint.status !== 0) {
138
+ throw new Error(`foundry mint --skip-live failed:\n${mint.stdout}\n${mint.stderr}`);
139
+ }
140
+ const inventory = assertFastenedMillPlant(consumerRoot);
141
+ if (inventory.suit !== "fastened" && inventory.suit !== "overlay") {
142
+ throw new Error(`expected fastened/overlay suit, got ${inventory.suit}`);
143
+ }
144
+ console.log(` ✅ mint fastened mill+inspect (suit=${inventory.suit}, costume=${inventory.costume === true})`);
145
+
146
+ console.log(" 🏭 groover-hangar plant factory shops (not costume)...");
147
+ plantHangarFactoryShops(consumerRoot);
148
+ for (const name of FACTORY_SHOP_SKILLS) {
149
+ if (!fs.existsSync(path.join(consumerRoot, ".opencode", "skills", name, "SKILL.md"))) {
150
+ throw new Error(`hangar plant missing ${name}`);
151
+ }
152
+ }
153
+
154
+ console.log(" 🔍 foundry inspect --skip-live (shop plant must not costume-dump)...");
155
+ const inspect = runFoundryCli(millRoot, consumerRoot, ["inspect", "--skip-live"]);
156
+ const report = lastJsonObject(inspect.stdout);
157
+ if (inspect.status !== 0 || !report?.ok) {
158
+ throw new Error(
159
+ `inspect failed after hangar plant (costume dump?):\n${inspect.stdout}\n${inspect.stderr}`,
160
+ );
161
+ }
162
+ const plantVsWorn = (report.checks || []).find((c) => c.id === "plant-vs-worn");
163
+ if (!plantVsWorn?.ok) {
164
+ throw new Error(`plant-vs-worn failed: ${JSON.stringify(plantVsWorn)}`);
165
+ }
166
+ const shopPlant = plantVsWorn.shopPlant || [];
167
+ for (const name of FACTORY_SHOP_SKILLS) {
168
+ if (!shopPlant.includes(name)) {
169
+ throw new Error(`inspect shopPlant missing ${name} (got ${shopPlant.join(",")})`);
170
+ }
171
+ }
172
+ if (Array.isArray(plantVsWorn.extraSkills) && plantVsWorn.extraSkills.length > 0) {
173
+ throw new Error(`inspect extraSkills after hangar plant: ${plantVsWorn.extraSkills.join(",")}`);
174
+ }
175
+ const after = assertFastenedMillPlant(consumerRoot);
176
+ if (after.costume === true) {
177
+ throw new Error("costume flipped true after hangar plant");
178
+ }
179
+ console.log(" ✅ hangar factory shops + inspect OK (costume false, no dump)");
180
+ return { inventory: after, report };
181
+ }
182
+
183
+ export function packXrayTgz(xrayRoot = repoRoot) {
184
+ const packOut = run("npm pack --silent", xrayRoot);
185
+ const tarball = packOut.split("\n").filter(Boolean).pop();
186
+ const tarballPath = path.join(xrayRoot, tarball);
187
+ if (!fs.existsSync(tarballPath)) {
188
+ throw new Error(`Tarball not found: ${tarballPath}`);
189
+ }
190
+ return tarballPath;
191
+ }
192
+
193
+ export function writeBareConsumerManifest(tmpRoot) {
194
+ fs.writeFileSync(
195
+ path.join(tmpRoot, "package.json"),
196
+ `${JSON.stringify({ name: "xray-pack-tmp-proof", version: "0.0.1", private: true }, null, 2)}\n`,
197
+ );
198
+ }
199
+
200
+ export function runPackTmpProof(xrayRoot = repoRoot) {
201
+ console.log("\n=== Pack → tmp suit proof ===\n");
202
+ const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "0xray-pack-tmp-proof-"));
203
+ let tarballPath = null;
204
+ try {
205
+ console.log("📦 npm pack...");
206
+ tarballPath = packXrayTgz(xrayRoot);
207
+ writeBareConsumerManifest(tmpRoot);
208
+ console.log("📥 npm install tgz into clean tmp...");
209
+ run(`npm install ${JSON.stringify(tarballPath)}`, tmpRoot, { inherit: true });
210
+ const millRoot = path.join(tmpRoot, "node_modules", "0xray", "scripts", "foundry");
211
+ proveSuitAfterInstall(tmpRoot, millRoot);
212
+ console.log("\n✅ Pack → tmp suit proof passed (Playwright n/a — mill CLI)\n");
213
+ return { tmpRoot, tarballPath };
214
+ } catch (err) {
215
+ console.error(`\n❌ Pack → tmp suit proof failed: ${err.message}\n`);
216
+ throw err;
217
+ } finally {
218
+ if (tarballPath) {
219
+ try {
220
+ fs.unlinkSync(tarballPath);
221
+ } catch {
222
+ /* best-effort */
223
+ }
224
+ }
225
+ try {
226
+ fs.rmSync(tmpRoot, { recursive: true, force: true });
227
+ } catch {
228
+ /* best-effort */
229
+ }
230
+ }
231
+ }
232
+
233
+ const isMain =
234
+ process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
235
+
236
+ if (isMain) {
237
+ try {
238
+ runPackTmpProof();
239
+ } catch {
240
+ process.exit(1);
241
+ }
242
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * wear-vendored-repertoire.cjs — Materialize @0xray/repertoire from the
3
+ * packed vendor tree. Published 0xray must not ship a `file:` dependency:
4
+ * npm --install-links, pnpm, and yarn resolve that path from the consumer
5
+ * root (ENOENT on vendor/@0xray/repertoire), not from node_modules/0xray.
6
+ */
7
+
8
+ const fs = require("fs");
9
+ const path = require("path");
10
+
11
+ function resolveVendoredRepertoire(packageRoot) {
12
+ const vendor = path.join(packageRoot, "vendor", "@0xray", "repertoire");
13
+ if (fs.existsSync(path.join(vendor, "package.json"))) return vendor;
14
+ return null;
15
+ }
16
+
17
+ function repertoirePackageName(dir) {
18
+ try {
19
+ const pkg = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf8"));
20
+ return pkg.name || null;
21
+ } catch {
22
+ return null;
23
+ }
24
+ }
25
+
26
+ function destAlreadyWorn(dest, vendor) {
27
+ try {
28
+ if (!fs.existsSync(path.join(dest, "package.json"))) return false;
29
+ if (repertoirePackageName(dest) !== "@0xray/repertoire") return false;
30
+ return fs.realpathSync(dest) === fs.realpathSync(vendor);
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ function destIsUsableRepertoire(dest) {
37
+ return repertoirePackageName(dest) === "@0xray/repertoire";
38
+ }
39
+
40
+ function removeBrokenDest(dest) {
41
+ try {
42
+ const st = fs.lstatSync(dest);
43
+ if (st.isSymbolicLink() && !fs.existsSync(dest)) {
44
+ fs.unlinkSync(dest);
45
+ }
46
+ } catch {
47
+ /* dest absent */
48
+ }
49
+ }
50
+
51
+ function wearOne(vendor, dest, log) {
52
+ removeBrokenDest(dest);
53
+ if (destAlreadyWorn(dest, vendor)) return true;
54
+ if (fs.existsSync(dest) && destIsUsableRepertoire(dest)) return true;
55
+
56
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
57
+ const rel = path.relative(path.dirname(dest), vendor);
58
+ const linkType = process.platform === "win32" ? "junction" : "dir";
59
+ try {
60
+ fs.symlinkSync(rel, dest, linkType);
61
+ return true;
62
+ } catch (linkErr) {
63
+ try {
64
+ fs.cpSync(vendor, dest, { recursive: true });
65
+ return true;
66
+ } catch (copyErr) {
67
+ if (typeof log === "function") {
68
+ log("wear-repertoire", "failed to wear vendored organ", "warning", {
69
+ dest,
70
+ linkError: linkErr.message,
71
+ copyError: copyErr.message,
72
+ });
73
+ }
74
+ return false;
75
+ }
76
+ }
77
+ }
78
+
79
+ function wearDestinations(packageRoot, targetDir) {
80
+ const dests = [path.join(packageRoot, "node_modules", "@0xray", "repertoire")];
81
+ if (targetDir && path.resolve(targetDir) !== path.resolve(packageRoot)) {
82
+ dests.push(path.join(targetDir, "node_modules", "@0xray", "repertoire"));
83
+ }
84
+ return dests;
85
+ }
86
+
87
+ function wearVendoredRepertoire(packageRoot, targetDir, log) {
88
+ const vendor = resolveVendoredRepertoire(packageRoot);
89
+ if (!vendor) return { worn: [], vendor: null };
90
+
91
+ const worn = [];
92
+ for (const dest of wearDestinations(packageRoot, targetDir)) {
93
+ if (wearOne(vendor, dest, log)) worn.push(dest);
94
+ }
95
+ if (worn.length && typeof log === "function") {
96
+ log("wear-repertoire", "vendored @0xray/repertoire worn", "info", {
97
+ vendor,
98
+ dests: worn,
99
+ });
100
+ }
101
+ return { worn, vendor };
102
+ }
103
+
104
+ function hasFileProtocolDependency(pkg) {
105
+ const buckets = [pkg.dependencies, pkg.optionalDependencies, pkg.peerDependencies];
106
+ for (const bucket of buckets) {
107
+ if (!bucket || typeof bucket !== "object") continue;
108
+ for (const spec of Object.values(bucket)) {
109
+ if (String(spec).startsWith("file:")) return true;
110
+ }
111
+ }
112
+ return false;
113
+ }
114
+
115
+ module.exports = {
116
+ resolveVendoredRepertoire,
117
+ wearVendoredRepertoire,
118
+ wearDestinations,
119
+ hasFileProtocolDependency,
120
+ };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray-pre-tool",
3
- "version": "4.0.9",
3
+ "version": "4.0.11",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./features.schema.json",
3
- "version": "4.0.9",
3
+ "version": "4.0.11",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",