0xray 3.5.5 → 4.0.1

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 (233) hide show
  1. package/.mcp.json +18 -14
  2. package/.opencode/skills/api-design/SKILL.md +1 -1
  3. package/.opencode/skills/architect-tools/SKILL.md +1 -1
  4. package/.opencode/skills/architecture-patterns/SKILL.md +1 -1
  5. package/.opencode/skills/auto-format/SKILL.md +1 -1
  6. package/.opencode/skills/boot-orchestrator/SKILL.md +2 -6
  7. package/.opencode/skills/bug-triage/SKILL.md +1 -1
  8. package/.opencode/skills/code-analyzer/SKILL.md +1 -1
  9. package/.opencode/skills/code-review/SKILL.md +1 -1
  10. package/.opencode/skills/enforcer/SKILL.md +1 -1
  11. package/.opencode/skills/framework-compliance-audit/SKILL.md +1 -1
  12. package/.opencode/skills/git-workflow/SKILL.md +1 -1
  13. package/.opencode/skills/hermes-agent/SKILL.md +36 -36
  14. package/.opencode/skills/inference-improve/SKILL.md +1 -1
  15. package/.opencode/skills/lint/SKILL.md +1 -1
  16. package/.opencode/skills/log-monitor/SKILL.md +1 -1
  17. package/.opencode/skills/model-health-check/SKILL.md +1 -1
  18. package/.opencode/skills/multimodal-looker/SKILL.md +1 -1
  19. package/.opencode/skills/orchestrator/SKILL.md +38 -14
  20. package/.opencode/skills/performance-analysis/SKILL.md +1 -1
  21. package/.opencode/skills/performance-optimization/SKILL.md +1 -1
  22. package/.opencode/skills/processor-pipeline/SKILL.md +1 -1
  23. package/.opencode/skills/project-analysis/SKILL.md +1 -1
  24. package/.opencode/skills/refactoring-strategies/SKILL.md +1 -1
  25. package/.opencode/skills/registry.json +65 -0
  26. package/.opencode/skills/researcher/SKILL.md +18 -5
  27. package/.opencode/skills/security-audit/SKILL.md +1 -1
  28. package/.opencode/skills/security-scan/SKILL.md +1 -1
  29. package/.opencode/skills/session-management/SKILL.md +1 -1
  30. package/.opencode/skills/state-manager/SKILL.md +1 -1
  31. package/.opencode/skills/storyteller/SKILL.md +1 -1
  32. package/.opencode/skills/strategist/SKILL.md +12 -0
  33. package/.opencode/skills/testing-best-practices/SKILL.md +37 -0
  34. package/.opencode/skills/testing-strategy/SKILL.md +14 -3
  35. package/.opencode/skills/ui-ux-design/SKILL.md +1 -1
  36. package/.opencode/skills/xray-orchestrator/index.ts +267 -0
  37. package/.xray/codex.json +12 -3
  38. package/.xray/features.json +28 -6
  39. package/.xray/features.schema.json +31 -0
  40. package/AGENTS-consumer.md +17 -7
  41. package/AGENTS.md +18 -10
  42. package/README.md +30 -27
  43. package/SKILLS.md +2 -2
  44. package/dist/AGENTS.md +18 -10
  45. package/dist/CHANGELOG.md +81 -11
  46. package/dist/README.md +30 -27
  47. package/dist/SKILLS.md +2 -2
  48. package/dist/cli/commands/hermes-install.js +3 -0
  49. package/dist/cli/commands/openclaw-install.js +14 -0
  50. package/dist/cli/index.js +10 -1
  51. package/dist/core/features-config.d.ts +15 -2
  52. package/dist/infrastructure/schemas/cloud-schemas.d.ts +1 -1
  53. package/dist/integrations/grok/grok-cli.d.ts +3 -0
  54. package/dist/integrations/grok/grok-cli.js +92 -4
  55. package/dist/integrations/grok/hooks/grok-hook-utils.js +53 -7
  56. package/dist/integrations/grok/hooks/post-tool-use.js +68 -46
  57. package/dist/integrations/grok/hooks/pre-tool-use.js +14 -31
  58. package/dist/integrations/grok/hooks/session-start.js +86 -4
  59. package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
  60. package/dist/integrations/hermes-agent/bridge.mjs +26 -1
  61. package/dist/integrations/hooks/delegation-gate-runtime.mjs +32 -3
  62. package/dist/integrations/hooks/pipeline-hook-runtime.mjs +1 -1
  63. package/dist/integrations/hooks/station-hook-runtime.cjs +421 -0
  64. package/dist/integrations/hooks/station-hook-runtime.mjs +24 -0
  65. package/dist/integrations/hooks/station-memory-ingest.mjs +45 -0
  66. package/dist/integrations/hooks/station-memory-match.mjs +47 -0
  67. package/dist/integrations/openclaw/client.d.ts +5 -1
  68. package/dist/integrations/openclaw/client.js +17 -9
  69. package/dist/integrations/openclaw/config.js +0 -1
  70. package/dist/integrations/openclaw/hooks/pre-tool-gate-runtime.mjs +102 -0
  71. package/dist/integrations/openclaw/index.js +17 -0
  72. package/dist/integrations/openclaw/plugin/xray-pre-tool/index.js +75 -0
  73. package/dist/integrations/openclaw/plugin/xray-pre-tool/openclaw.plugin.json +10 -0
  74. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +12 -0
  75. package/dist/integrations/openclaw/pre-tool-gate.d.ts +19 -0
  76. package/dist/integrations/openclaw/pre-tool-gate.js +39 -0
  77. package/dist/mcps/orchestrator/handlers/complexity-handler.js +2 -2
  78. package/dist/memory-routing/index.d.ts +1 -1
  79. package/dist/memory-routing/index.js +1 -1
  80. package/dist/memory-routing/provider-loader.d.ts +4 -0
  81. package/dist/memory-routing/provider-loader.js +44 -2
  82. package/dist/memory-routing/provider-registry.js +3 -2
  83. package/dist/nucleus/autonomy-kernel.d.ts +2 -2
  84. package/dist/nucleus/autonomy-kernel.js +17 -6
  85. package/dist/nucleus/confer.js +17 -3
  86. package/dist/nucleus/delegation-gate.d.ts +14 -8
  87. package/dist/nucleus/delegation-gate.js +151 -16
  88. package/dist/nucleus/suit-temperament.d.ts +40 -0
  89. package/dist/nucleus/suit-temperament.js +157 -0
  90. package/dist/nucleus/user-aside.js +1 -1
  91. package/dist/plugin/xray-codex-injection.js +14 -3
  92. package/dist/postprocessor/triggers/GitHookTrigger.js +11 -5
  93. package/opencode.json +80 -0
  94. package/package.json +15 -5
  95. package/scripts/hooks/install-hooks.cjs +18 -3
  96. package/scripts/hooks/run-hook.js +67 -3
  97. package/scripts/mjs/run-repertoire-mcp.mjs +39 -0
  98. package/scripts/mjs/verify-confer-core.mjs +1 -1
  99. package/scripts/mjs/verify-delegation-gate-core.mjs +29 -2
  100. package/scripts/mjs/verify-four-floor-compact.mjs +524 -0
  101. package/scripts/mjs/verify-pipeline-facets.mjs +215 -0
  102. package/scripts/mjs/verify-temperament-live.mjs +261 -0
  103. package/scripts/node/bridge-mcp-wiring.cjs +277 -29
  104. package/scripts/node/consumer-install-smoke.mjs +55 -2
  105. package/scripts/node/install-bridges.cjs +195 -33
  106. package/scripts/node/postinstall.cjs +50 -27
  107. package/scripts/node/reconcile-version.mjs +0 -4
  108. package/scripts/node/release-gate.mjs +1 -1
  109. package/scripts/node/release.mjs +2 -2
  110. package/scripts/node/universal-version-manager.js +1 -1
  111. package/scripts/node/validate-release-docs.mjs +20 -33
  112. package/scripts/node/version-manager.mjs +63 -18
  113. package/src/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
  114. package/src/integrations/openclaw/README.md +134 -0
  115. package/src/integrations/openclaw/plugin/xray-pre-tool/index.js +75 -0
  116. package/src/integrations/openclaw/plugin/xray-pre-tool/openclaw.plugin.json +10 -0
  117. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +12 -0
  118. package/src/mcps/orchestrator/handlers/complexity-handler.ts +2 -1
  119. package/vendor/@0xray/repertoire/AGENTS.md +163 -0
  120. package/vendor/@0xray/repertoire/LICENSE +21 -0
  121. package/vendor/@0xray/repertoire/README.md +120 -0
  122. package/vendor/@0xray/repertoire/data/curated_signals.json +208 -0
  123. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts +78 -0
  124. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +1 -0
  125. package/vendor/@0xray/repertoire/dist/RepertoireService.js +153 -0
  126. package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +1 -0
  127. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts +39 -0
  128. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts.map +1 -0
  129. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js +60 -0
  130. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js.map +1 -0
  131. package/vendor/@0xray/repertoire/dist/index.d.ts +14 -0
  132. package/vendor/@0xray/repertoire/dist/index.d.ts.map +1 -0
  133. package/vendor/@0xray/repertoire/dist/index.js +14 -0
  134. package/vendor/@0xray/repertoire/dist/index.js.map +1 -0
  135. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts +26 -0
  136. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +1 -0
  137. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js +109 -0
  138. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +1 -0
  139. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts +18 -0
  140. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts.map +1 -0
  141. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js +94 -0
  142. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js.map +1 -0
  143. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts +7 -0
  144. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts.map +1 -0
  145. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js +18 -0
  146. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js.map +1 -0
  147. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts +31 -0
  148. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +1 -0
  149. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js +83 -0
  150. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +1 -0
  151. package/vendor/@0xray/repertoire/dist/mcp/server.d.ts +6 -0
  152. package/vendor/@0xray/repertoire/dist/mcp/server.d.ts.map +1 -0
  153. package/vendor/@0xray/repertoire/dist/mcp/server.js +173 -0
  154. package/vendor/@0xray/repertoire/dist/mcp/server.js.map +1 -0
  155. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts +27 -0
  156. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts.map +1 -0
  157. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js +107 -0
  158. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js.map +1 -0
  159. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts +11 -0
  160. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts.map +1 -0
  161. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js +32 -0
  162. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js.map +1 -0
  163. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts +9 -0
  164. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +1 -0
  165. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js +72 -0
  166. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +1 -0
  167. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts +5 -0
  168. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts.map +1 -0
  169. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js +18 -0
  170. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js.map +1 -0
  171. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts +31 -0
  172. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +1 -0
  173. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js +218 -0
  174. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +1 -0
  175. package/vendor/@0xray/repertoire/dist/paths.d.ts +24 -0
  176. package/vendor/@0xray/repertoire/dist/paths.d.ts.map +1 -0
  177. package/vendor/@0xray/repertoire/dist/paths.js +74 -0
  178. package/vendor/@0xray/repertoire/dist/paths.js.map +1 -0
  179. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts +141 -0
  180. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +1 -0
  181. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js +210 -0
  182. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +1 -0
  183. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts +48 -0
  184. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +1 -0
  185. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js +221 -0
  186. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +1 -0
  187. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts +11 -0
  188. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +1 -0
  189. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js +43 -0
  190. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +1 -0
  191. package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts +15 -0
  192. package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts.map +1 -0
  193. package/vendor/@0xray/repertoire/dist/registry/signal-prune.js +35 -0
  194. package/vendor/@0xray/repertoire/dist/registry/signal-prune.js.map +1 -0
  195. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts +3 -0
  196. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts.map +1 -0
  197. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js +24 -0
  198. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js.map +1 -0
  199. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts +24 -0
  200. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +1 -0
  201. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js +148 -0
  202. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +1 -0
  203. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts +4 -0
  204. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts.map +1 -0
  205. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js +44 -0
  206. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js.map +1 -0
  207. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts +22 -0
  208. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts.map +1 -0
  209. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js +66 -0
  210. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js.map +1 -0
  211. package/vendor/@0xray/repertoire/dist/types.d.ts +210 -0
  212. package/vendor/@0xray/repertoire/dist/types.d.ts.map +1 -0
  213. package/vendor/@0xray/repertoire/dist/types.js +2 -0
  214. package/vendor/@0xray/repertoire/dist/types.js.map +1 -0
  215. package/vendor/@0xray/repertoire/docs/MEMORY-ROUTING-PROVIDER.md +54 -0
  216. package/vendor/@0xray/repertoire/hermes-mcp.example.json +20 -0
  217. package/vendor/@0xray/repertoire/mcp-config.example.json +11 -0
  218. package/vendor/@0xray/repertoire/package.json +124 -0
  219. package/vendor/@0xray/repertoire/schemas/curated-signal.schema.json +68 -0
  220. package/vendor/@0xray/repertoire/schemas/inference-log.schema.json +82 -0
  221. package/vendor/@0xray/repertoire/scripts/confirm-suit-all.mjs +253 -0
  222. package/vendor/@0xray/repertoire/scripts/confirm-suit-harness.mjs +220 -0
  223. package/vendor/@0xray/repertoire/scripts/run-live-synthesis-checkpoint.mjs +215 -0
  224. package/vendor/@0xray/repertoire/scripts/suit-bridge-shared.mjs +139 -0
  225. package/vendor/@0xray/repertoire/scripts/verify-grok-suit.mjs +304 -0
  226. package/vendor/@0xray/repertoire/scripts/verify-hermes-suit.mjs +163 -0
  227. package/vendor/@0xray/repertoire/scripts/verify-openclaw-suit.mjs +125 -0
  228. package/vendor/@0xray/repertoire/scripts/verify-opencode-suit.mjs +127 -0
  229. package/vendor/@0xray/repertoire/scripts/verify-synthesis-dogfood.mjs +207 -0
  230. package/vendor/@0xray/repertoire/skills/repertoire-trap-handling/SKILL.md +206 -0
  231. package/xray/codex.json +12 -3
  232. package/xray/features.json +28 -6
  233. package/xray/features.schema.json +31 -0
@@ -6,7 +6,7 @@
6
6
  const fs = require("fs");
7
7
  const path = require("path");
8
8
  const os = require("os");
9
- const { execSync } = require("child_process");
9
+ const { execFileSync, execSync } = require("child_process");
10
10
 
11
11
  /** Canonical 7-server MCP surface */
12
12
  const XRAY_MCP_SERVERS = [
@@ -24,31 +24,118 @@ const HERMES_PLUGIN_DIR = path.join(os.homedir(), ".hermes", "plugins", "xray-he
24
24
  const OPENCLAW_CONFIG_PATH = path.join(os.homedir(), ".openclaw", "openclaw.json");
25
25
  const OPENCLAW_STATE_DIR = path.join(os.homedir(), ".openclaw");
26
26
 
27
+ function isRepertoirePackageRoot(dir) {
28
+ try {
29
+ const pkg = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf8"));
30
+ return pkg.name === "@0xray/repertoire" || pkg.name === "repertoire";
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ function resolveRepertoireMcp(targetDir) {
37
+ const selfRoot = targetDir;
38
+ const siblingRoot = path.join(targetDir, "..", "repertoire");
39
+ const candidates = [
40
+ path.join(targetDir, "node_modules", "@0xray", "repertoire", "dist", "mcp", "server.js"),
41
+ path.join(targetDir, "vendor", "@0xray", "repertoire", "dist", "mcp", "server.js"),
42
+ isRepertoirePackageRoot(selfRoot) ? path.join(selfRoot, "dist", "mcp", "server.js") : null,
43
+ isRepertoirePackageRoot(siblingRoot) ? path.join(siblingRoot, "dist", "mcp", "server.js") : null,
44
+ ];
45
+ return candidates.find((p) => p && fs.existsSync(p)) || null;
46
+ }
47
+
48
+ function resolveRepertoireProvider(targetDir) {
49
+ const siblingRoot = path.join(targetDir, "..", "repertoire");
50
+ const siblingProvider = path.join(siblingRoot, "dist", "provider", "memory-routing-provider.js");
51
+ const nmProvider = path.join(
52
+ targetDir,
53
+ "node_modules",
54
+ "@0xray",
55
+ "repertoire",
56
+ "dist",
57
+ "provider",
58
+ "memory-routing-provider.js",
59
+ );
60
+ const vendorProvider = path.join(
61
+ targetDir,
62
+ "vendor",
63
+ "@0xray",
64
+ "repertoire",
65
+ "dist",
66
+ "provider",
67
+ "memory-routing-provider.js",
68
+ );
69
+ if (fs.existsSync(nmProvider)) return nmProvider;
70
+ if (fs.existsSync(vendorProvider)) return vendorProvider;
71
+ if (isRepertoirePackageRoot(siblingRoot) && fs.existsSync(siblingProvider)) return siblingProvider;
72
+ return null;
73
+ }
74
+
75
+ function isDefaultMemoryRoutingOff(mr) {
76
+ if (!mr || typeof mr !== "object") return true;
77
+ if (mr.enabled === true) return false;
78
+ const provider = mr.provider == null || mr.provider === "" ? "null" : mr.provider;
79
+ return provider === "null";
80
+ }
81
+
82
+ function enableMemoryRoutingIfResolves(features, targetDir) {
83
+ const modulePath = resolveRepertoireProvider(targetDir);
84
+ if (!modulePath) return { features, changed: false };
85
+ const mr = (features && features.memory_routing) || {};
86
+ if (!isDefaultMemoryRoutingOff(mr)) return { features, changed: false };
87
+
88
+ const siblingRel = "../repertoire/dist/provider/memory-routing-provider.js";
89
+ const siblingAbs = path.join(targetDir, "..", "repertoire", "dist", "provider", "memory-routing-provider.js");
90
+ const useSibling = path.resolve(modulePath) === path.resolve(siblingAbs);
91
+ const repertoireRoot = path.resolve(modulePath, "..", "..", "..");
92
+ const signalsAbs = path.join(repertoireRoot, "data", "curated_signals.json");
93
+ const config = { ...(mr.config || {}) };
94
+ if (!config.signalsPath && fs.existsSync(signalsAbs)) {
95
+ config.signalsPath = useSibling ? "../repertoire/data/curated_signals.json" : signalsAbs;
96
+ }
97
+ if (!config.statePath) {
98
+ config.statePath = ".xray/state/repertoire/inference-state.json";
99
+ }
100
+ if (!config.feedbackDir) {
101
+ config.feedbackDir = ".xray/state/repertoire/feedback";
102
+ }
103
+
104
+ return {
105
+ features: {
106
+ ...features,
107
+ memory_routing: {
108
+ ...mr,
109
+ enabled: true,
110
+ provider: "repertoire",
111
+ module_path: useSibling ? siblingRel : modulePath,
112
+ config,
113
+ },
114
+ },
115
+ changed: true,
116
+ };
117
+ }
118
+
27
119
  function detectConsumerExtraMcpServers(targetDir) {
28
120
  const extras = { hermes: {}, opencode: {}, openclaw: {} };
29
121
  try {
30
- const pkgPath = path.join(targetDir, "package.json");
31
- if (!fs.existsSync(pkgPath)) return extras;
32
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
33
- const localRepertoireMcp = path.join(targetDir, "dist", "mcp", "server.js");
34
- if (pkg.name === "@0xray/repertoire" && fs.existsSync(localRepertoireMcp)) {
35
- extras.hermes.repertoire = {
36
- command: "node",
37
- args: [localRepertoireMcp],
38
- env: { XRAY_ROOT: targetDir },
39
- };
40
- extras.opencode.repertoire = {
41
- type: "local",
42
- command: ["node", "dist/mcp/server.js"],
43
- enabled: true,
44
- cwd: ".",
45
- };
46
- extras.openclaw.repertoire = {
47
- command: "node",
48
- args: [localRepertoireMcp],
49
- env: { XRAY_ROOT: targetDir },
50
- };
51
- }
122
+ const repertoireMcp = resolveRepertoireMcp(targetDir);
123
+ if (!repertoireMcp) return extras;
124
+ extras.hermes.repertoire = {
125
+ command: "node",
126
+ args: [repertoireMcp],
127
+ env: { XRAY_ROOT: targetDir },
128
+ };
129
+ extras.opencode.repertoire = {
130
+ type: "local",
131
+ command: ["node", repertoireMcp],
132
+ enabled: true,
133
+ };
134
+ extras.openclaw.repertoire = {
135
+ command: "node",
136
+ args: [repertoireMcp],
137
+ env: { XRAY_ROOT: targetDir },
138
+ };
52
139
  } catch {
53
140
  // best-effort
54
141
  }
@@ -130,13 +217,31 @@ function copyHermesFindProjectRootHelper(packageRoot, targetPluginDir) {
130
217
  return true;
131
218
  }
132
219
 
220
+ function isEphemeralInstallRoot(targetDir) {
221
+ const normalized = String(targetDir || "").replace(/\\/g, "/");
222
+ return /\/T\/|\/tmp\/|\/var\/folders\/|\/Temp\//i.test(normalized);
223
+ }
224
+
225
+ function copyHermesHookRuntimes(packageRoot) {
226
+ const hooksSrc = [
227
+ path.join(packageRoot, "dist", "integrations", "hooks"),
228
+ path.join(packageRoot, "src", "integrations", "hooks"),
229
+ ].find((p) => fs.existsSync(p));
230
+ if (!hooksSrc) return false;
231
+ const hooksDst = path.join(os.homedir(), ".hermes", "plugins", "hooks");
232
+ fs.mkdirSync(hooksDst, { recursive: true });
233
+ fs.cpSync(hooksSrc, hooksDst, { recursive: true, force: true });
234
+ return true;
235
+ }
236
+
133
237
  function writeHermesPluginArtifacts(targetDir) {
134
238
  if (!fs.existsSync(HERMES_PLUGIN_DIR)) return false;
135
- fs.writeFileSync(path.join(HERMES_PLUGIN_DIR, "xray-consumer-root.txt"), `${targetDir}\n`);
136
239
  fs.writeFileSync(
137
240
  path.join(HERMES_PLUGIN_DIR, ".mcp.json"),
138
241
  `${JSON.stringify(buildPluginMcpJson(targetDir), null, 2)}\n`
139
242
  );
243
+ if (isEphemeralInstallRoot(targetDir)) return true;
244
+ fs.writeFileSync(path.join(HERMES_PLUGIN_DIR, "xray-consumer-root.txt"), `${targetDir}\n`);
140
245
  return true;
141
246
  }
142
247
 
@@ -192,11 +297,13 @@ function deployPortableProjectMcpJson(targetDir) {
192
297
  existing = { mcpServers: {} };
193
298
  }
194
299
  }
300
+ const extras = detectConsumerExtraMcpServers(targetDir);
195
301
  const merged = {
196
302
  ...existing,
197
303
  mcpServers: {
198
304
  ...(existing.mcpServers || {}),
199
305
  ...portable.mcpServers,
306
+ ...(extras.openclaw || {}),
200
307
  },
201
308
  };
202
309
  fs.writeFileSync(destPath, `${JSON.stringify(merged, null, 2)}\n`);
@@ -204,10 +311,20 @@ function deployPortableProjectMcpJson(targetDir) {
204
311
 
205
312
  function enableHermesPluginBestEffort() {
206
313
  try {
207
- execSync("hermes plugins enable 0xray-hermes", { stdio: "pipe", encoding: "utf8" });
314
+ execSync("hermes plugins enable xray-hermes", { stdio: "pipe", encoding: "utf8" });
315
+ try {
316
+ execSync("hermes plugins disable 0xray-hermes", { stdio: "pipe", encoding: "utf8" });
317
+ } catch {
318
+ /* stale id may be absent */
319
+ }
208
320
  return true;
209
321
  } catch {
210
- return false;
322
+ try {
323
+ execSync("hermes plugins enable 0xray-hermes", { stdio: "pipe", encoding: "utf8" });
324
+ return true;
325
+ } catch {
326
+ return false;
327
+ }
211
328
  }
212
329
  }
213
330
 
@@ -269,10 +386,12 @@ function syncOpenClawMcpRegistry(targetDir) {
269
386
  }
270
387
 
271
388
  function writeOpenClawConsumerArtifacts(targetDir) {
272
- if (!fs.existsSync(OPENCLAW_STATE_DIR)) {
273
- fs.mkdirSync(OPENCLAW_STATE_DIR, { recursive: true });
389
+ if (!isEphemeralInstallRoot(targetDir)) {
390
+ if (!fs.existsSync(OPENCLAW_STATE_DIR)) {
391
+ fs.mkdirSync(OPENCLAW_STATE_DIR, { recursive: true });
392
+ }
393
+ fs.writeFileSync(path.join(OPENCLAW_STATE_DIR, "xray-consumer-root.txt"), `${targetDir}\n`);
274
394
  }
275
- fs.writeFileSync(path.join(OPENCLAW_STATE_DIR, "xray-consumer-root.txt"), `${targetDir}\n`);
276
395
 
277
396
  const consumerConfigPath = path.join(targetDir, ".xray", "config", "openclaw.json");
278
397
  if (fs.existsSync(consumerConfigPath)) {
@@ -287,6 +406,124 @@ function writeOpenClawConsumerArtifacts(targetDir) {
287
406
  return true;
288
407
  }
289
408
 
409
+ function resolveOpenClawPreToolHookSource(packageRoot) {
410
+ return [
411
+ path.join(packageRoot, "dist", "integrations", "openclaw", "hooks", "pre-tool-gate-runtime.mjs"),
412
+ path.join(packageRoot, "src", "integrations", "openclaw", "hooks", "pre-tool-gate-runtime.mjs"),
413
+ ].find((p) => fs.existsSync(p)) || null;
414
+ }
415
+
416
+ function resolveOpenClawPluginDir(packageRoot) {
417
+ return [
418
+ path.join(packageRoot, "dist", "integrations", "openclaw", "plugin", "xray-pre-tool"),
419
+ path.join(packageRoot, "src", "integrations", "openclaw", "plugin", "xray-pre-tool"),
420
+ ].find((p) => fs.existsSync(path.join(p, "index.js"))) || null;
421
+ }
422
+
423
+ function installOpenClawHostWear(packageRoot) {
424
+ const source = resolveOpenClawPreToolHookSource(packageRoot);
425
+ if (!source) return null;
426
+
427
+ const hookDir = path.join(os.homedir(), ".openclaw", "hooks");
428
+ fs.mkdirSync(hookDir, { recursive: true });
429
+ const dest = path.join(hookDir, "xray-pre-tool.mjs");
430
+ fs.copyFileSync(source, dest);
431
+ fs.writeFileSync(
432
+ path.join(hookDir, "xray-pre-tool.json"),
433
+ `${JSON.stringify(
434
+ {
435
+ name: "xray-pre-tool",
436
+ command: "node",
437
+ args: [dest],
438
+ stdin: "json",
439
+ blockExitCode: 2,
440
+ env: { XRAY_AI_PATH: packageRoot },
441
+ },
442
+ null,
443
+ 2,
444
+ )}\n`,
445
+ );
446
+
447
+ const pluginSrc = resolveOpenClawPluginDir(packageRoot);
448
+ if (pluginSrc) {
449
+ try {
450
+ execFileSync("openclaw", ["plugins", "install", "-l", pluginSrc], {
451
+ stdio: "pipe",
452
+ encoding: "utf8",
453
+ timeout: 60000,
454
+ });
455
+ } catch {
456
+ /* link is best-effort — stdin runtime is still installed */
457
+ }
458
+ try {
459
+ execFileSync("openclaw", ["config", "set", "plugins.entries.xray-pre-tool.enabled", "true"], {
460
+ stdio: "pipe",
461
+ encoding: "utf8",
462
+ timeout: 20000,
463
+ });
464
+ } catch {
465
+ /* enable is best-effort */
466
+ }
467
+ }
468
+ return dest;
469
+ }
470
+
471
+ function resolveOpencodeBin() {
472
+ try {
473
+ const found = execSync("command -v opencode", { encoding: "utf8" }).trim();
474
+ return found || null;
475
+ } catch {
476
+ return null;
477
+ }
478
+ }
479
+
480
+ function maybeWriteOpenClawCliBackend() {
481
+ const bin = resolveOpencodeBin();
482
+ if (!bin) return false;
483
+ const configPath = resolveOpenClawConfigPath();
484
+ if (!fs.existsSync(configPath)) return false;
485
+ let config;
486
+ try {
487
+ config = JSON.parse(fs.readFileSync(configPath, "utf8"));
488
+ } catch {
489
+ return false;
490
+ }
491
+ if (!config.agents || typeof config.agents !== "object") config.agents = {};
492
+ if (!config.agents.defaults || typeof config.agents.defaults !== "object") {
493
+ config.agents.defaults = {};
494
+ }
495
+ const defaults = config.agents.defaults;
496
+ if (!defaults.cliBackends || typeof defaults.cliBackends !== "object") {
497
+ defaults.cliBackends = {};
498
+ }
499
+ defaults.cliBackends["opencode-cli"] = {
500
+ command: bin,
501
+ args: ["run", "--pure"],
502
+ output: "text",
503
+ input: "arg",
504
+ modelArg: "--model",
505
+ modelAliases: { "big-pickle": "opencode/big-pickle" },
506
+ sessionMode: "none",
507
+ };
508
+ if (!defaults.models || typeof defaults.models !== "object") defaults.models = {};
509
+ defaults.models["opencode-cli/big-pickle"] = {};
510
+ const model = defaults.model && typeof defaults.model === "object" ? defaults.model : {};
511
+ const primary = model.primary;
512
+ if (!primary || primary === "opencode/big-pickle") {
513
+ const fallbacks = Array.isArray(model.fallbacks) ? model.fallbacks.slice() : [];
514
+ if (primary === "opencode/big-pickle" && !fallbacks.includes("opencode/big-pickle")) {
515
+ fallbacks.unshift("opencode/big-pickle");
516
+ }
517
+ defaults.model = {
518
+ ...model,
519
+ primary: "opencode-cli/big-pickle",
520
+ fallbacks,
521
+ };
522
+ }
523
+ fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
524
+ return true;
525
+ }
526
+
290
527
  function wireOpenClawBridge(targetDir) {
291
528
  writeOpenClawConsumerArtifacts(targetDir);
292
529
  return syncOpenClawMcpRegistry(targetDir);
@@ -317,4 +554,15 @@ module.exports = {
317
554
  writeOpenClawConsumerArtifacts,
318
555
  resolveOpenClawConfigPath,
319
556
  detectConsumerExtraMcpServers,
557
+ isRepertoirePackageRoot,
558
+ resolveRepertoireMcp,
559
+ resolveRepertoireProvider,
560
+ isDefaultMemoryRoutingOff,
561
+ enableMemoryRoutingIfResolves,
562
+ isEphemeralInstallRoot,
563
+ copyHermesHookRuntimes,
564
+ resolveOpenClawPreToolHookSource,
565
+ resolveOpenClawPluginDir,
566
+ installOpenClawHostWear,
567
+ maybeWriteOpenClawCliBackend,
320
568
  };
@@ -48,9 +48,14 @@ function assertFreshInstallDefaults(tmpRoot, version) {
48
48
  if (!features.memory_routing) {
49
49
  throw new Error("Deployed features.json missing memory_routing block");
50
50
  }
51
- if (features.memory_routing.enabled !== false) {
51
+ if (features.memory_routing.enabled !== true) {
52
52
  throw new Error(
53
- `Fresh install must default memory_routing.enabled=false (got ${features.memory_routing.enabled})`,
53
+ `Fresh 4.0 install must ship memory_routing.enabled=true with the vendored organ (got ${features.memory_routing.enabled})`,
54
+ );
55
+ }
56
+ if (features.memory_routing.provider !== "repertoire") {
57
+ throw new Error(
58
+ `Fresh install memory_routing.provider must be repertoire (got ${features.memory_routing.provider})`,
54
59
  );
55
60
  }
56
61
  if (!features.inference_governance) {
@@ -59,6 +64,33 @@ function assertFreshInstallDefaults(tmpRoot, version) {
59
64
  if (features.inference_governance.enabled !== false) {
60
65
  throw new Error("Fresh install must default inference_governance.enabled=false");
61
66
  }
67
+ const organHoisted = path.join(tmpRoot, "node_modules", "@0xray", "repertoire", "package.json");
68
+ const organNested = path.join(
69
+ tmpRoot,
70
+ "node_modules",
71
+ "0xray",
72
+ "node_modules",
73
+ "@0xray",
74
+ "repertoire",
75
+ "package.json",
76
+ );
77
+ const organVendor = path.join(
78
+ tmpRoot,
79
+ "node_modules",
80
+ "0xray",
81
+ "vendor",
82
+ "@0xray",
83
+ "repertoire",
84
+ "package.json",
85
+ );
86
+ const organPkg = [organNested, organHoisted, organVendor].find((p) => fs.existsSync(p));
87
+ if (!organPkg) {
88
+ throw new Error("vendored @0xray/repertoire missing from fresh tarball install");
89
+ }
90
+ const organ = JSON.parse(fs.readFileSync(organPkg, "utf-8"));
91
+ if (organ.version !== "0.2.0") {
92
+ throw new Error(`expected organ 0.2.0, got ${organ.version}`);
93
+ }
62
94
  console.log(" ✅ .xray/features.json fresh-install defaults (opt-in off)");
63
95
  return { consumerFeaturesPath, features };
64
96
  }
@@ -114,6 +146,27 @@ function runUpgradeMergeSmoke(tmpRoot, nmRoot, version) {
114
146
  if (shippedMarker && !merged[shippedMarker]) {
115
147
  throw new Error(`Upgrade merge missing shipped template key: ${shippedMarker}`);
116
148
  }
149
+ fs.writeFileSync(
150
+ consumerFeaturesPath,
151
+ `${JSON.stringify(
152
+ {
153
+ version: "3.5.5",
154
+ memory_routing: { enabled: false, provider: "repertoire" },
155
+ },
156
+ null,
157
+ 2,
158
+ )}\n`,
159
+ );
160
+ deployXrayConfig(tmpRoot, nmRoot, () => {});
161
+ const optedOut = JSON.parse(fs.readFileSync(consumerFeaturesPath, "utf-8"));
162
+ if (optedOut.memory_routing?.enabled !== false) {
163
+ throw new Error(
164
+ `Upgrade merge must keep explicit memory_routing opt-out (got ${optedOut.memory_routing?.enabled})`,
165
+ );
166
+ }
167
+ if (optedOut.memory_routing?.provider !== "repertoire") {
168
+ throw new Error("Upgrade merge dropped memory_routing.provider on opt-out");
169
+ }
117
170
 
118
171
  console.log(" ✅ upgrade merge preserves opt-ins + bumps features.version");
119
172
  }