0xray 4.0.1 → 4.0.3

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 (59) hide show
  1. package/.xray/features.json +1 -1
  2. package/AGENTS-consumer.md +4 -4
  3. package/AGENTS.md +3 -3
  4. package/README.md +1 -1
  5. package/SKILLS.md +1 -1
  6. package/dist/AGENTS.md +3 -3
  7. package/dist/CHANGELOG.md +43 -0
  8. package/dist/README.md +1 -1
  9. package/dist/SKILLS.md +1 -1
  10. package/dist/cli/commands/foundry-mint-wear.d.ts +3 -0
  11. package/dist/cli/commands/foundry-mint-wear.js +17 -0
  12. package/dist/cli/commands/hermes-install.js +2 -0
  13. package/dist/cli/commands/openclaw-install.js +2 -0
  14. package/dist/cli/commands/opencode-install.js +10 -2
  15. package/dist/cli/commands/skill-install.js +4 -0
  16. package/dist/enforcement/enforcer-tools.d.ts +7 -0
  17. package/dist/enforcement/enforcer-tools.js +18 -109
  18. package/dist/integrations/grok/grok-cli.js +2 -0
  19. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  20. package/dist/processors/implementations/version-compliance-processor.d.ts +3 -34
  21. package/dist/processors/implementations/version-compliance-processor.js +8 -135
  22. package/package.json +15 -14
  23. package/scripts/foundry/CHANGELOG.md +38 -0
  24. package/scripts/foundry/LICENSE +21 -0
  25. package/scripts/foundry/README.md +69 -0
  26. package/scripts/foundry/ci-monitor.mjs +115 -0
  27. package/scripts/foundry/cli.js +2 -0
  28. package/scripts/foundry/cli.mjs +55 -0
  29. package/scripts/foundry/docs-build.mjs +38 -0
  30. package/scripts/foundry/hooks.mjs +36 -0
  31. package/scripts/foundry/mill-root.mjs +62 -0
  32. package/scripts/foundry/mint-suit.cjs +397 -0
  33. package/scripts/foundry/mint.mjs +33 -0
  34. package/scripts/foundry/package.json +54 -0
  35. package/scripts/foundry/plant/agents/mill.yml +5 -0
  36. package/scripts/foundry/plant/skills/mill/SKILL.md +22 -0
  37. package/scripts/foundry/reconcile-version.mjs +150 -0
  38. package/scripts/foundry/release-gate.mjs +100 -0
  39. package/scripts/foundry/release.mjs +266 -0
  40. package/scripts/foundry/validate-release-docs.mjs +316 -0
  41. package/scripts/foundry/version-manager.mjs +444 -0
  42. package/scripts/node/ci-cd-auto-fix.cjs +12 -257
  43. package/scripts/node/consumer-install-smoke.mjs +17 -0
  44. package/scripts/node/enforce-version-compliance.sh +5 -20
  45. package/scripts/node/enforce-version-compliance.ts +13 -113
  46. package/scripts/node/foundry-shim.mjs +19 -0
  47. package/scripts/node/github-actions-monitor.cjs +13 -18
  48. package/scripts/node/install-bridges.cjs +43 -29
  49. package/scripts/node/postinstall.cjs +36 -1
  50. package/scripts/node/reconcile-version.mjs +3 -142
  51. package/scripts/node/release-gate.mjs +3 -74
  52. package/scripts/node/release.mjs +3 -171
  53. package/scripts/node/validate-release-docs.mjs +3 -285
  54. package/scripts/node/version-manager.mjs +3 -738
  55. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  56. package/xray/features.json +1 -1
  57. package/scripts/node/release.js +0 -17
  58. package/scripts/node/sync-versions.mjs +0 -18
  59. package/scripts/node/universal-version-manager.js +0 -1043
@@ -8,6 +8,15 @@ const {
8
8
  isConsumerInstall,
9
9
  } = require("./install-bridges.cjs");
10
10
  const { applyConsumerGitignore } = require("./consumer-gitignore.cjs");
11
+ const {
12
+ overlayConsumerTree,
13
+ mintConsumerFromSsot,
14
+ mintConsumerSuit,
15
+ listConsumerSkillNames,
16
+ listConsumerAgentFiles,
17
+ loadFoundryParams,
18
+ readPackageIdentity,
19
+ } = require("../foundry/mint-suit.cjs");
11
20
 
12
21
  function structuredLog(component, action, status, details) {
13
22
  const ts = new Date().toISOString();
@@ -17,6 +26,16 @@ function structuredLog(component, action, status, details) {
17
26
 
18
27
  const XRAY_MANAGED_AGENTS_MARKER = "<!-- 0xray-managed -->";
19
28
 
29
+ function fillConsumerPlaceholders(content, consumer) {
30
+ const name = consumer.name || "this project";
31
+ const versionParen = consumer.version ? ` (${consumer.version})` : "";
32
+ return content
33
+ .split("{{CONSUMER_NAME}}")
34
+ .join(name)
35
+ .split("{{CONSUMER_VERSION_PAREN}}")
36
+ .join(versionParen);
37
+ }
38
+
20
39
  function deployManagedAgents(packageRoot, targetDir, log) {
21
40
  const agentsConsumer = path.join(packageRoot, "AGENTS-consumer.md");
22
41
  const agentsDest = path.join(targetDir, "AGENTS.md");
@@ -26,6 +45,8 @@ function deployManagedAgents(packageRoot, targetDir, log) {
26
45
  fs.readFileSync(agentsDest, "utf8").includes(XRAY_MANAGED_AGENTS_MARKER);
27
46
  if (shouldDeployAgents) {
28
47
  let content = fs.readFileSync(agentsConsumer, "utf8");
48
+ const consumer = readPackageIdentity(path.join(targetDir, "package.json"));
49
+ content = fillConsumerPlaceholders(content, consumer);
29
50
  if (!content.includes(XRAY_MANAGED_AGENTS_MARKER)) {
30
51
  content = `${content.trimEnd()}\n\n${XRAY_MANAGED_AGENTS_MARKER}\n`;
31
52
  }
@@ -65,6 +86,9 @@ function runPostinstall(packageRoot, targetDir, log) {
65
86
  packageRoot: resolvedPackage,
66
87
  log: logFn,
67
88
  });
89
+ if (consumer) {
90
+ mintConsumerSuit(resolvedPackage, resolvedTarget, logFn);
91
+ }
68
92
  } catch (e) {
69
93
  logFn("postinstall", "Bridge install failed", "error", { error: e.message });
70
94
  throw e;
@@ -81,7 +105,18 @@ function runPostinstall(packageRoot, targetDir, log) {
81
105
  }
82
106
  }
83
107
 
84
- module.exports = { runPostinstall };
108
+ module.exports = {
109
+ runPostinstall,
110
+ mintConsumerFromSsot,
111
+ mintConsumerSuit,
112
+ overlayConsumerTree,
113
+ listConsumerSkillNames,
114
+ listConsumerAgentFiles,
115
+ loadFoundryParams,
116
+ fillConsumerPlaceholders,
117
+ readPackageIdentity,
118
+ deployManagedAgents,
119
+ };
85
120
 
86
121
  if (require.main === module) {
87
122
  const packageRoot = path.join(__dirname, "..", "..");
@@ -1,143 +1,4 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * reconcile-version.mjs — Single version truth before bump/tag/publish.
4
- *
5
- * Sources: npm registry, package.json, latest git tag.
6
- *
7
- * Usage:
8
- * node scripts/node/reconcile-version.mjs # report
9
- * node scripts/node/reconcile-version.mjs --check # fail if not publish-ready
10
- * node scripts/node/reconcile-version.mjs patch # print next patch target
11
- * node scripts/node/reconcile-version.mjs patch --apply # write package.json
12
- */
13
-
14
- import { execSync } from "child_process";
15
- import fs from "fs";
16
- import path from "path";
17
- import { fileURLToPath } from "url";
18
-
19
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
20
- const rootDir = path.resolve(__dirname, "../..");
21
- const pkgPath = path.join(rootDir, "package.json");
22
-
23
- const args = process.argv.slice(2);
24
- const checkMode = args.includes("--check");
25
- const applyMode = args.includes("--apply");
26
- const printTarget = args.includes("--print-target");
27
- const bumpType = args.find((a) => ["major", "minor", "patch"].includes(a)) || null;
28
-
29
- function run(cmd) {
30
- try {
31
- return execSync(cmd, { cwd: rootDir, encoding: "utf-8" }).trim();
32
- } catch {
33
- return null;
34
- }
35
- }
36
-
37
- function readLocalVersion() {
38
- return JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version;
39
- }
40
-
41
- function readPublishedVersion() {
42
- const v = run("npm view 0xray version");
43
- return v || "0.0.0";
44
- }
45
-
46
- function readLatestTag() {
47
- const tag = run('git describe --tags --abbrev=0 2>/dev/null');
48
- if (!tag) return null;
49
- return tag.replace(/^v/, "");
50
- }
51
-
52
- function parseVersion(version) {
53
- const [major, minor, patch] = version.split(".").map((n) => parseInt(n, 10));
54
- return { major, minor, patch };
55
- }
56
-
57
- function bumpVersion(version, type) {
58
- const v = parseVersion(version);
59
- switch (type) {
60
- case "major":
61
- return `${v.major + 1}.0.0`;
62
- case "minor":
63
- return `${v.major}.${v.minor + 1}.0`;
64
- case "patch":
65
- return `${v.major}.${v.minor}.${v.patch + 1}`;
66
- default:
67
- return version;
68
- }
69
- }
70
-
71
- function compare(a, b) {
72
- const va = parseVersion(a);
73
- const vb = parseVersion(b);
74
- if (va.major !== vb.major) return va.major - vb.major;
75
- if (va.minor !== vb.minor) return va.minor - vb.minor;
76
- return va.patch - vb.patch;
77
- }
78
-
79
- function maxVersion(...versions) {
80
- return versions.reduce((best, cur) => (compare(cur, best) > 0 ? cur : best));
81
- }
82
-
83
- function fail(msg) {
84
- console.error(`❌ ${msg}`);
85
- process.exit(1);
86
- }
87
-
88
- function main() {
89
- const local = readLocalVersion();
90
- const npm = readPublishedVersion();
91
- const tag = readLatestTag();
92
-
93
- const baseline = maxVersion(npm, tag || "0.0.0");
94
- const target = bumpType ? bumpVersion(baseline, bumpType) : local;
95
-
96
- if (printTarget && bumpType) {
97
- console.log(target);
98
- return;
99
- }
100
-
101
- console.log("\n=== Version Reconcile ===\n");
102
- console.log(` npm registry : ${npm}`);
103
- console.log(` package.json : ${local}`);
104
- console.log(` latest tag : ${tag ? `v${tag}` : "(none)"}`);
105
- if (bumpType) {
106
- console.log(` bump ${bumpType} : ${target} (from baseline ${baseline})`);
107
- }
108
-
109
- if (applyMode && bumpType) {
110
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
111
- pkg.version = target;
112
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
113
- console.log(`\n✅ Updated package.json → ${target}`);
114
- }
115
-
116
- if (!checkMode) {
117
- if (compare(local, npm) <= 0 && !bumpType) {
118
- console.log("\n⚠️ Local version is not ahead of npm — bump before publishing.");
119
- } else {
120
- console.log("\n✅ Reconcile report complete.");
121
- }
122
- return;
123
- }
124
-
125
- // Strict checks for release gate / pre-tag
126
- if (compare(local, npm) <= 0) {
127
- fail(`package.json (${local}) must be > npm (${npm}). Run: node scripts/node/reconcile-version.mjs patch --apply`);
128
- }
129
-
130
- if (tag && compare(local, tag) < 0) {
131
- fail(`package.json (${local}) is behind latest tag v${tag}`);
132
- }
133
-
134
- if (tag && compare(local, tag) > 0 && compare(npm, tag) === 0) {
135
- console.log(`✅ Ready to tag v${local} (npm at ${npm})`);
136
- } else if (compare(local, npm) > 0) {
137
- console.log(`✅ Ready to publish ${local} (npm at ${npm})`);
138
- } else {
139
- console.log("✅ Version reconcile OK");
140
- }
141
- }
142
-
143
- main();
2
+ export * from "../foundry/reconcile-version.mjs";
3
+ import { millMain } from "./foundry-shim.mjs";
4
+ millMain(import.meta.url, "reconcile-version.mjs");
@@ -1,75 +1,4 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * release-gate.mjs — Single release checkpoint.
4
- *
5
- * Modes:
6
- * (default) build + test + consumer smoke (fresh + upgrade merge)
7
- * --verify-only git + reconcile + release docs + consumer smoke — after push, before publish
8
- * --skip-smoke skip consumer install smoke
9
- * --skip-docs skip release docs validation (not recommended for publish)
10
- *
11
- * Usage:
12
- * node scripts/node/release-gate.mjs
13
- * node scripts/node/release-gate.mjs --verify-only
14
- */
15
-
16
- import { execSync } from "child_process";
17
- import path from "path";
18
- import { fileURLToPath } from "url";
19
-
20
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
21
- const rootDir = path.resolve(__dirname, "../..");
22
- const verifyOnly = process.argv.includes("--verify-only");
23
- const skipSmoke = process.argv.includes("--skip-smoke");
24
- const skipDocs = process.argv.includes("--skip-docs");
25
-
26
- function step(label, cmd) {
27
- console.log(`\n${"─".repeat(60)}\n🔄 ${label}\n${"─".repeat(60)}\n`);
28
- execSync(cmd, { cwd: rootDir, stdio: "inherit" });
29
- }
30
-
31
- function main() {
32
- const mode = verifyOnly ? "verify" : "full";
33
- console.log("\n╔════════════════════════════════════════════════════════╗");
34
- console.log(`║ 🛡️ 0xRay Release Gate (${mode})`.padEnd(57) + "║");
35
- console.log("╚════════════════════════════════════════════════════════╝");
36
-
37
- try {
38
- if (verifyOnly) {
39
- step("1/5 Git + reconcile", "node scripts/node/pre-publish-guard.js --verify-only");
40
- if (!skipDocs) {
41
- step("2/5 Release docs", "node scripts/node/validate-release-docs.mjs");
42
- }
43
- step(
44
- "3/5 Plugin infrastructure",
45
- "node scripts/test/validate-plugins-e2e.cjs --structural-only",
46
- );
47
- if (!skipSmoke) {
48
- step("4/5 Consumer install smoke", "node scripts/node/consumer-install-smoke.mjs");
49
- }
50
- } else {
51
- step("1/6 Build", "npm run build");
52
- step("2/6 Tests", "npm test");
53
- step(
54
- "3/6 Consumer hook verifiers",
55
- "npm run verify:pre-commit-diff && npm run verify:pre-push-diff && node scripts/mjs/verify-delegation-gate-core.mjs --host=grok && node scripts/mjs/verify-delegation-gate-core.mjs --host=hermes && node scripts/mjs/verify-delegation-gate-core.mjs --host=opencode && node scripts/mjs/verify-hermes-session-start.mjs && node scripts/mjs/verify-confer-core.mjs && npm run verify:user-aside && npm run build && node scripts/mjs/verify-pipeline-facets.mjs --package-only",
56
- );
57
- step(
58
- "4/6 Plugin infrastructure",
59
- "node scripts/test/validate-plugins-e2e.cjs --structural-only",
60
- );
61
- if (!skipSmoke) {
62
- step("5/6 Consumer install smoke (fresh + upgrade)", "node scripts/node/consumer-install-smoke.mjs");
63
- }
64
- }
65
-
66
- console.log("\n╔════════════════════════════════════════════════════════╗");
67
- console.log("║ ✅ RELEASE GATE PASSED ║");
68
- console.log("╚════════════════════════════════════════════════════════╝\n");
69
- } catch {
70
- console.error("\n❌ RELEASE GATE FAILED — do not tag or publish\n");
71
- process.exit(1);
72
- }
73
- }
74
-
75
- main();
2
+ export * from "../foundry/release-gate.mjs";
3
+ import { millMain } from "./foundry-shim.mjs";
4
+ millMain(import.meta.url, "release-gate.mjs");
@@ -1,172 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
- /**
4
- * Canonical 0xRay release script.
5
- *
6
- * 1. Bump version from npm registry baseline (reconcile-version)
7
- * 2. Release artifacts (CHANGELOG / README / AGENTS / docs) — before gate so docs tests pass
8
- * 3. Release gate (build + test + consumer smoke)
9
- * 4. Commit release artifacts → push
10
- * 5. Verify gate (reconcile + git + release docs + smoke)
11
- * 6. npm publish (idempotent — skip if version already on registry)
12
- * 7. Tag → push tag (only after successful publish)
13
- *
14
- * Usage:
15
- * npm run release:patch
16
- * node scripts/node/release.mjs patch --dry-run
17
- */
18
-
19
- import { execSync } from "child_process";
20
- import fs from "fs";
21
- import path from "path";
22
- import { getReleaseArtifactPaths } from "./version-manager.mjs";
23
-
24
- const rootDir = process.cwd();
25
- const args = process.argv.slice(2);
26
- const dryRun = args.includes("--dry-run");
27
- const releaseType = args.find((a) => ["major", "minor", "patch"].includes(a));
28
-
29
- function run(cmd, label) {
30
- console.log(`\n> ${cmd}`);
31
- if (dryRun) {
32
- console.log(` (dry-run skip: ${label})`);
33
- return;
34
- }
35
- execSync(cmd, { cwd: rootDir, stdio: "inherit", encoding: "utf-8" });
36
- }
37
-
38
- function readVersion() {
39
- return JSON.parse(fs.readFileSync(path.join(rootDir, "package.json"), "utf-8")).version;
40
- }
41
-
42
- function currentBranch() {
43
- return execSync("git rev-parse --abbrev-ref HEAD", { cwd: rootDir, encoding: "utf-8" }).trim();
44
- }
45
-
46
- function npmVersionPublished(version) {
47
- try {
48
- const out = execSync(`npm view 0xray@${version} version`, {
49
- cwd: rootDir,
50
- encoding: "utf-8",
51
- stdio: ["pipe", "pipe", "pipe"],
52
- }).trim();
53
- return out === version;
54
- } catch {
55
- return false;
56
- }
57
- }
58
-
59
- function publishIdempotent(version) {
60
- if (dryRun) {
61
- console.log(` would: npm publish --access public (check 0xray@${version} first)`);
62
- return;
63
- }
64
- if (npmVersionPublished(version)) {
65
- console.log(`ℹ️ 0xray@${version} already on npm — skipping publish`);
66
- return;
67
- }
68
- execSync("npm publish --access public", { cwd: rootDir, stdio: "inherit", encoding: "utf-8" });
69
- console.log(`✅ Published 0xray@${version}`);
70
- }
71
-
72
- async function main() {
73
- if (!releaseType || !["major", "minor", "patch"].includes(releaseType)) {
74
- console.error("Usage: node scripts/node/release.mjs [patch|minor|major] [--dry-run]");
75
- process.exit(1);
76
- }
77
-
78
- console.log("╔════════════════════════════════════════════════════════╗");
79
- console.log("║ 🚀 0xRay Release (canonical) ║");
80
- console.log("╚════════════════════════════════════════════════════════╝");
81
- if (dryRun) console.log("\n⚠️ DRY RUN — no writes, commits, tags, or publish\n");
82
-
83
- // 1. Version bump from npm SSOT
84
- console.log(`\n📦 Step 1: Bump ${releaseType} from npm baseline`);
85
- if (dryRun) {
86
- execSync(`node scripts/node/reconcile-version.mjs ${releaseType}`, { cwd: rootDir, stdio: "inherit" });
87
- } else {
88
- run(`node scripts/node/reconcile-version.mjs ${releaseType} --apply`, "version bump");
89
- }
90
- const newVersion = dryRun
91
- ? execSync(`node scripts/node/reconcile-version.mjs ${releaseType} --print-target`, {
92
- cwd: rootDir,
93
- encoding: "utf-8",
94
- }).trim()
95
- : readVersion();
96
- console.log(`📌 Release version: ${newVersion}`);
97
-
98
- // 2. Artifacts BEFORE gate (docs vitest matches package.json version)
99
- console.log("\n📦 Step 2: Release artifacts (CHANGELOG, README, AGENTS, docs)");
100
- run("node scripts/node/version-manager.mjs --artifacts-only", "release artifacts");
101
-
102
- // 3. Gate
103
- console.log("\n📦 Step 3: Release gate (build + test + smoke)");
104
- run("node scripts/node/release-gate.mjs", "release gate");
105
-
106
- // 4. Commit + push
107
- console.log("\n📦 Step 4: Commit & push");
108
- const releaseFiles = getReleaseArtifactPaths();
109
- if (!dryRun) {
110
- run(`git add ${releaseFiles.join(" ")}`, "git add");
111
- try {
112
- execSync(`git commit --no-verify -m "release: v${newVersion}"`, { cwd: rootDir, stdio: "inherit" });
113
- } catch (e) {
114
- const out = String(e.stdout || e.stderr || "");
115
- if (!out.includes("nothing to commit")) throw e;
116
- console.log("ℹ️ Nothing to commit (release files unchanged)");
117
- }
118
- } else {
119
- console.log(` would: git add ${releaseFiles.join(" ")} && git commit -m "release: v${newVersion}"`);
120
- }
121
-
122
- const branch = currentBranch();
123
- run(`git push origin ${branch}`, "git push");
124
-
125
- // 5. Post-push verify before publish
126
- console.log("\n📦 Step 5: Verify gate (reconcile + git + docs + smoke)");
127
- run("node scripts/node/release-gate.mjs --verify-only", "verify gate");
128
-
129
- // 6. Publish (idempotent)
130
- console.log("\n📦 Step 6: npm publish");
131
- publishIdempotent(newVersion);
132
-
133
- // 7. Tag after publish
134
- console.log("\n📦 Step 7: Tag");
135
- if (!dryRun) {
136
- try {
137
- execSync(`git tag -a v${newVersion} -m "Release v${newVersion}"`, { cwd: rootDir, stdio: "inherit" });
138
- console.log(`✅ Created tag v${newVersion}`);
139
- } catch (e) {
140
- const msg = String(e.stderr || e.message || "");
141
- if (msg.includes("already exists")) {
142
- console.log(`ℹ️ Tag v${newVersion} already exists`);
143
- } else {
144
- throw e;
145
- }
146
- }
147
- } else {
148
- console.log(` would: git tag -a v${newVersion}`);
149
- }
150
- run(`git push origin v${newVersion}`, "push tag");
151
-
152
- console.log("\n╔════════════════════════════════════════════════════════╗");
153
- console.log("║ ✅ Release Complete! ║");
154
- console.log("╚════════════════════════════════════════════════════════╝");
155
- if (!dryRun) {
156
- console.log(`\n📦 0xray@${newVersion} 🏷 v${newVersion}\n`);
157
- const tweetPath = path.join(rootDir, "tweets", `v${newVersion}.md`);
158
- if (!fs.existsSync(tweetPath)) {
159
- fs.mkdirSync(path.join(rootDir, "tweets"), { recursive: true });
160
- fs.writeFileSync(
161
- tweetPath,
162
- `🎉 0xRay v${newVersion} is LIVE - consumer-safe upgrades!\n...\n\`\`\`\nnpm install 0xray@latest\n\`\`\`\n`,
163
- );
164
- console.log(`📝 Tweet template: tweets/v${newVersion}.md`);
165
- }
166
- }
167
- }
168
-
169
- main().catch((err) => {
170
- console.error("\n❌ Release failed:", err.message);
171
- process.exit(1);
172
- });
2
+ export * from "../foundry/release.mjs";
3
+ import { millMain } from "./foundry-shim.mjs";
4
+ millMain(import.meta.url, "release.mjs");