0xray 3.5.4 → 4.0.0

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 (266) hide show
  1. package/.mcp.json +51 -7
  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 +32 -6
  39. package/.xray/features.schema.json +87 -0
  40. package/AGENTS-consumer.md +16 -6
  41. package/AGENTS.md +21 -3
  42. package/README.md +13 -10
  43. package/SKILLS.md +1 -1
  44. package/dist/AGENTS.md +21 -3
  45. package/dist/CHANGELOG.md +98 -0
  46. package/dist/README.md +13 -10
  47. package/dist/SKILLS.md +1 -1
  48. package/dist/cli/commands/hermes-install.js +6 -1
  49. package/dist/cli/commands/openclaw-install.js +14 -0
  50. package/dist/cli/index.js +0 -0
  51. package/dist/core/features-config.d.ts +30 -2
  52. package/dist/governance/governance-service.d.ts +1 -0
  53. package/dist/governance/governance-service.js +81 -6
  54. package/dist/infrastructure/schemas/cloud-schemas.d.ts +1 -1
  55. package/dist/integrations/enforcement-gate.js +15 -5
  56. package/dist/integrations/grok/grok-cli.d.ts +3 -0
  57. package/dist/integrations/grok/grok-cli.js +92 -13
  58. package/dist/integrations/grok/hooks/grok-hook-utils.js +99 -9
  59. package/dist/integrations/grok/hooks/post-tool-use.js +68 -25
  60. package/dist/integrations/grok/hooks/pre-tool-use.js +17 -14
  61. package/dist/integrations/grok/hooks/session-start.js +114 -4
  62. package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
  63. package/dist/integrations/hermes-agent/__init__.py +11 -1
  64. package/dist/integrations/hermes-agent/__pycache__/__init__.cpython-313.pyc +0 -0
  65. package/dist/integrations/hermes-agent/__pycache__/schemas.cpython-313.pyc +0 -0
  66. package/dist/integrations/hermes-agent/__pycache__/tools.cpython-313.pyc +0 -0
  67. package/dist/integrations/hermes-agent/bridge.mjs +92 -11
  68. package/dist/integrations/hooks/confer-hook-runtime.mjs +49 -0
  69. package/dist/integrations/hooks/delegation-gate-runtime.mjs +32 -3
  70. package/dist/integrations/hooks/pipeline-hook-runtime.mjs +211 -0
  71. package/dist/integrations/hooks/plan-hook-runtime.mjs +68 -0
  72. package/dist/integrations/hooks/station-hook-runtime.cjs +421 -0
  73. package/dist/integrations/hooks/station-hook-runtime.mjs +24 -0
  74. package/dist/integrations/hooks/station-memory-ingest.mjs +45 -0
  75. package/dist/integrations/hooks/station-memory-match.mjs +47 -0
  76. package/dist/integrations/hooks/user-aside-hook-runtime.mjs +49 -0
  77. package/dist/integrations/openclaw/client.d.ts +5 -1
  78. package/dist/integrations/openclaw/client.js +17 -9
  79. package/dist/integrations/openclaw/config.js +0 -1
  80. package/dist/integrations/openclaw/hooks/pre-tool-gate-runtime.mjs +102 -0
  81. package/dist/integrations/openclaw/index.js +17 -0
  82. package/dist/integrations/openclaw/plugin/xray-pre-tool/index.js +75 -0
  83. package/dist/integrations/openclaw/plugin/xray-pre-tool/openclaw.plugin.json +10 -0
  84. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +10 -0
  85. package/dist/integrations/openclaw/pre-tool-gate.d.ts +19 -0
  86. package/dist/integrations/openclaw/pre-tool-gate.js +39 -0
  87. package/dist/mcps/architect-tools.server.js +6 -1
  88. package/dist/mcps/orchestrator/handlers/complexity-handler.d.ts +7 -0
  89. package/dist/mcps/orchestrator/handlers/complexity-handler.js +107 -8
  90. package/dist/mcps/orchestrator/handlers/task-handler.d.ts +6 -0
  91. package/dist/mcps/orchestrator/handlers/task-handler.js +75 -0
  92. package/dist/mcps/orchestrator/server.js +54 -5
  93. package/dist/memory-routing/index.d.ts +1 -1
  94. package/dist/memory-routing/index.js +1 -1
  95. package/dist/memory-routing/provider-loader.d.ts +4 -0
  96. package/dist/memory-routing/provider-loader.js +74 -4
  97. package/dist/memory-routing/provider-registry.js +3 -2
  98. package/dist/nucleus/aside-worktree.d.ts +41 -0
  99. package/dist/nucleus/aside-worktree.js +164 -0
  100. package/dist/nucleus/autonomy-kernel.d.ts +2 -2
  101. package/dist/nucleus/autonomy-kernel.js +17 -6
  102. package/dist/nucleus/confer.d.ts +57 -0
  103. package/dist/nucleus/confer.js +322 -0
  104. package/dist/nucleus/delegation-gate.d.ts +18 -8
  105. package/dist/nucleus/delegation-gate.js +234 -20
  106. package/dist/nucleus/lead-dev-plan-persistence.d.ts +27 -3
  107. package/dist/nucleus/lead-dev-plan-persistence.js +201 -19
  108. package/dist/nucleus/spawn-plan-resolution.d.ts +20 -0
  109. package/dist/nucleus/spawn-plan-resolution.js +42 -0
  110. package/dist/nucleus/suit-temperament.d.ts +40 -0
  111. package/dist/nucleus/suit-temperament.js +157 -0
  112. package/dist/nucleus/synthesis-consult-receipt.js +18 -2
  113. package/dist/nucleus/synthesis-context.js +1 -1
  114. package/dist/nucleus/user-aside.d.ts +70 -0
  115. package/dist/nucleus/user-aside.js +393 -0
  116. package/dist/plugin/xray-codex-injection.js +14 -3
  117. package/dist/postprocessor/PostProcessor.d.ts +1 -0
  118. package/dist/postprocessor/PostProcessor.js +11 -0
  119. package/dist/postprocessor/triggers/GitHookTrigger.js +11 -5
  120. package/dist/processors/implementations/session-summary-processor.d.ts +1 -1
  121. package/dist/processors/implementations/session-summary-processor.js +9 -6
  122. package/opencode.json +88 -0
  123. package/package.json +25 -6
  124. package/scripts/hooks/install-hooks.cjs +21 -6
  125. package/scripts/hooks/run-hook.js +237 -88
  126. package/scripts/mjs/run-repertoire-mcp.mjs +39 -0
  127. package/scripts/mjs/verify-confer-core.mjs +103 -0
  128. package/scripts/mjs/verify-delegation-gate-core.mjs +76 -3
  129. package/scripts/mjs/verify-four-floor-compact.mjs +524 -0
  130. package/scripts/mjs/verify-hermes-session-start.mjs +137 -0
  131. package/scripts/mjs/verify-pipeline-facets.mjs +215 -0
  132. package/scripts/mjs/verify-pre-push-diff-core.mjs +87 -0
  133. package/scripts/mjs/verify-temperament-live.mjs +261 -0
  134. package/scripts/mjs/verify-user-aside-core.mjs +137 -0
  135. package/scripts/node/bridge-mcp-wiring.cjs +287 -29
  136. package/scripts/node/install-bridges.cjs +198 -44
  137. package/scripts/node/load-reflection-config.mjs +2 -2
  138. package/scripts/node/postinstall.cjs +50 -27
  139. package/scripts/node/release-gate.mjs +8 -4
  140. package/scripts/node/release.mjs +2 -2
  141. package/scripts/node/validate-release-docs.mjs +20 -33
  142. package/scripts/node/version-manager.mjs +25 -10
  143. package/src/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
  144. package/src/integrations/openclaw/README.md +134 -0
  145. package/src/integrations/openclaw/plugin/xray-pre-tool/index.js +75 -0
  146. package/src/integrations/openclaw/plugin/xray-pre-tool/openclaw.plugin.json +10 -0
  147. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +10 -0
  148. package/src/mcps/architect-tools.server.ts +6 -1
  149. package/src/mcps/orchestrator/handlers/complexity-handler.ts +180 -21
  150. package/src/mcps/orchestrator/handlers/task-handler.ts +99 -0
  151. package/src/mcps/orchestrator/server.ts +56 -5
  152. package/vendor/@0xray/repertoire/AGENTS.md +163 -0
  153. package/vendor/@0xray/repertoire/LICENSE +21 -0
  154. package/vendor/@0xray/repertoire/README.md +120 -0
  155. package/vendor/@0xray/repertoire/data/curated_signals.json +208 -0
  156. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts +78 -0
  157. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +1 -0
  158. package/vendor/@0xray/repertoire/dist/RepertoireService.js +153 -0
  159. package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +1 -0
  160. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts +39 -0
  161. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts.map +1 -0
  162. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js +60 -0
  163. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js.map +1 -0
  164. package/vendor/@0xray/repertoire/dist/index.d.ts +14 -0
  165. package/vendor/@0xray/repertoire/dist/index.d.ts.map +1 -0
  166. package/vendor/@0xray/repertoire/dist/index.js +14 -0
  167. package/vendor/@0xray/repertoire/dist/index.js.map +1 -0
  168. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts +26 -0
  169. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +1 -0
  170. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js +109 -0
  171. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +1 -0
  172. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts +18 -0
  173. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts.map +1 -0
  174. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js +94 -0
  175. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js.map +1 -0
  176. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts +7 -0
  177. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts.map +1 -0
  178. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js +18 -0
  179. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js.map +1 -0
  180. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts +31 -0
  181. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +1 -0
  182. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js +83 -0
  183. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +1 -0
  184. package/vendor/@0xray/repertoire/dist/mcp/server.d.ts +6 -0
  185. package/vendor/@0xray/repertoire/dist/mcp/server.d.ts.map +1 -0
  186. package/vendor/@0xray/repertoire/dist/mcp/server.js +173 -0
  187. package/vendor/@0xray/repertoire/dist/mcp/server.js.map +1 -0
  188. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts +27 -0
  189. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts.map +1 -0
  190. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js +107 -0
  191. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js.map +1 -0
  192. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts +11 -0
  193. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts.map +1 -0
  194. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js +32 -0
  195. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js.map +1 -0
  196. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts +9 -0
  197. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +1 -0
  198. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js +72 -0
  199. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +1 -0
  200. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts +5 -0
  201. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts.map +1 -0
  202. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js +18 -0
  203. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js.map +1 -0
  204. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts +31 -0
  205. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +1 -0
  206. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js +218 -0
  207. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +1 -0
  208. package/vendor/@0xray/repertoire/dist/paths.d.ts +24 -0
  209. package/vendor/@0xray/repertoire/dist/paths.d.ts.map +1 -0
  210. package/vendor/@0xray/repertoire/dist/paths.js +74 -0
  211. package/vendor/@0xray/repertoire/dist/paths.js.map +1 -0
  212. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts +141 -0
  213. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +1 -0
  214. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js +210 -0
  215. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +1 -0
  216. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts +48 -0
  217. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +1 -0
  218. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js +221 -0
  219. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +1 -0
  220. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts +11 -0
  221. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +1 -0
  222. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js +43 -0
  223. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +1 -0
  224. package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts +15 -0
  225. package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts.map +1 -0
  226. package/vendor/@0xray/repertoire/dist/registry/signal-prune.js +35 -0
  227. package/vendor/@0xray/repertoire/dist/registry/signal-prune.js.map +1 -0
  228. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts +3 -0
  229. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts.map +1 -0
  230. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js +24 -0
  231. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js.map +1 -0
  232. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts +24 -0
  233. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +1 -0
  234. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js +148 -0
  235. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +1 -0
  236. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts +4 -0
  237. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts.map +1 -0
  238. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js +44 -0
  239. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js.map +1 -0
  240. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts +22 -0
  241. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts.map +1 -0
  242. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js +66 -0
  243. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js.map +1 -0
  244. package/vendor/@0xray/repertoire/dist/types.d.ts +210 -0
  245. package/vendor/@0xray/repertoire/dist/types.d.ts.map +1 -0
  246. package/vendor/@0xray/repertoire/dist/types.js +2 -0
  247. package/vendor/@0xray/repertoire/dist/types.js.map +1 -0
  248. package/vendor/@0xray/repertoire/docs/MEMORY-ROUTING-PROVIDER.md +54 -0
  249. package/vendor/@0xray/repertoire/hermes-mcp.example.json +20 -0
  250. package/vendor/@0xray/repertoire/mcp-config.example.json +11 -0
  251. package/vendor/@0xray/repertoire/package.json +124 -0
  252. package/vendor/@0xray/repertoire/schemas/curated-signal.schema.json +68 -0
  253. package/vendor/@0xray/repertoire/schemas/inference-log.schema.json +82 -0
  254. package/vendor/@0xray/repertoire/scripts/confirm-suit-all.mjs +253 -0
  255. package/vendor/@0xray/repertoire/scripts/confirm-suit-harness.mjs +220 -0
  256. package/vendor/@0xray/repertoire/scripts/run-live-synthesis-checkpoint.mjs +215 -0
  257. package/vendor/@0xray/repertoire/scripts/suit-bridge-shared.mjs +139 -0
  258. package/vendor/@0xray/repertoire/scripts/verify-grok-suit.mjs +304 -0
  259. package/vendor/@0xray/repertoire/scripts/verify-hermes-suit.mjs +163 -0
  260. package/vendor/@0xray/repertoire/scripts/verify-openclaw-suit.mjs +125 -0
  261. package/vendor/@0xray/repertoire/scripts/verify-opencode-suit.mjs +127 -0
  262. package/vendor/@0xray/repertoire/scripts/verify-synthesis-dogfood.mjs +207 -0
  263. package/vendor/@0xray/repertoire/skills/repertoire-trap-handling/SKILL.md +206 -0
  264. package/xray/codex.json +12 -3
  265. package/xray/features.json +32 -6
  266. package/xray/features.schema.json +87 -0
@@ -11,7 +11,6 @@ import {
11
11
  import {
12
12
  checkCodexPatterns,
13
13
  checkFullTestSuite,
14
- checkSurfaceArea,
15
14
  ensureSessionBoot,
16
15
  isShellTool,
17
16
  isWriteTool,
@@ -46,10 +45,10 @@ async function main() {
46
45
  ensureSessionBoot(eventRoot, '0xray/grok-pre-tool-use-boot');
47
46
 
48
47
  const features = loadFeatures(eventRoot);
49
- const gateFeatures = loadDelegationGateFeatures(eventRoot);
48
+ const gateFeatures = loadDelegationGateFeatures(eventRoot, 'grok');
50
49
  const ctx = extractFromEvent(event);
51
50
  toolName = ctx.toolName;
52
- const { paths, content, cmd, toolInput } = ctx;
51
+ const { content, cmd, toolInput } = ctx;
53
52
  const sessionId = resolveSessionId(event);
54
53
 
55
54
  const gateBlock = evaluatePreToolGate(toolName, toolInput, {
@@ -69,25 +68,29 @@ async function main() {
69
68
  );
70
69
  }
71
70
 
72
- if (features.no_new_surface && isWriteTool(toolName) && paths.length) {
73
- const surfaceBlock = checkSurfaceArea(paths, eventRoot);
74
- if (surfaceBlock) finish(eventRoot, 'deny', surfaceBlock, null, toolName);
75
- }
76
-
71
+ // Constitution (11/29/69 + destructive shell) is in evaluatePreToolGate.
72
+ // Grok extra: Codex 2/7 (TODO/FIXME/STUB, console.log).
77
73
  if (isWriteTool(toolName) && content) {
78
- const codexBlock = checkCodexPatterns(content);
79
- if (codexBlock) finish(eventRoot, 'deny', codexBlock, null, toolName);
74
+ const extraBlock = checkCodexPatterns(content, { terms: [2, 7] });
75
+ if (extraBlock) finish(eventRoot, 'deny', extraBlock, null, toolName);
80
76
  }
81
77
 
82
78
  if (isShellTool(toolName) && cmd) {
83
- const destructive =
84
- /\brm\s+-rf\s+\/\b|\bmkfs\b|\bdd\s+if=|:()\s*\{\s*:\|&\s*\}\s*;:/i.test(cmd);
85
- if (destructive) finish(eventRoot, 'deny', 'Blocked destructive shell command', null, toolName);
86
-
87
79
  const testHint = checkFullTestSuite(cmd, features);
88
80
  if (testHint) finish(eventRoot, 'allow', null, testHint, toolName);
89
81
  }
90
82
 
83
+ if (gateBlock.reason) {
84
+ finish(
85
+ eventRoot,
86
+ 'allow',
87
+ gateBlock.reason,
88
+ gateBlock.hint,
89
+ toolName,
90
+ { gate: gateBlock.gate, warn: true },
91
+ );
92
+ }
93
+
91
94
  finish(eventRoot, 'allow', null, null, toolName);
92
95
  } catch (err) {
93
96
  appendHookActivity(root, 'grok-pre-tool-use', 'hook-error', 'error', {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Grok SessionStart / UserPromptSubmit — writes session-boot.json + activity.log.
4
- * Stdout is ignored by Grok for these events; side effects are the suit contract.
3
+ * Grok SessionStart / UserPromptSubmit / PreCompact / PostCompact.
4
+ * Grok ignores stdout here; station heat is session-boot.json + STATION.md.
5
5
  */
6
6
 
7
7
  import {
@@ -15,22 +15,100 @@ import {
15
15
  } from './grok-hook-utils.js';
16
16
  import { appendHookActivity } from './grok-hook-activity.js';
17
17
  import { recordSynthesisTurnSlice } from '../../hooks/synthesis-hook-runtime.mjs';
18
+ import { archiveStaleLeadDevPlan } from '../../hooks/plan-hook-runtime.mjs';
19
+ import {
20
+ maybeRunReflectionStub,
21
+ scheduleAutonomousReportingMarker,
22
+ runInferenceImprovementLight,
23
+ } from '../../hooks/pipeline-hook-runtime.mjs';
18
24
 
19
25
  function resolveHookEvent(event) {
20
26
  if (process.env.GROK_HOOK_EVENT) return process.env.GROK_HOOK_EVENT;
21
27
  const flag = process.argv.find((a) => a.startsWith('--hook-event='));
22
28
  if (flag) return flag.slice('--hook-event='.length);
29
+ const named = event.hookEventName || event.hook;
30
+ if (named === 'PreCompact' || named === 'pre_compact') return 'pre_compact';
31
+ if (named === 'PostCompact' || named === 'post_compact') return 'post_compact';
23
32
  if (
24
33
  event.prompt != null ||
25
34
  event.userMessage != null ||
26
35
  event.user_prompt != null ||
27
- event.hook === 'UserPromptSubmit'
36
+ named === 'UserPromptSubmit' ||
37
+ named === 'user_prompt_submit'
28
38
  ) {
29
39
  return 'user_prompt_submit';
30
40
  }
31
41
  return 'session_start';
32
42
  }
33
43
 
44
+ function extractIntent(event) {
45
+ return event.prompt || event.userMessage || event.user_prompt || event.compactContext || null;
46
+ }
47
+
48
+ async function loadStationProvider(root) {
49
+ const { loadMemoryRoutingProvider } = await import('../../../memory-routing/index.js');
50
+ const { readFileSync, existsSync } = await import('node:fs');
51
+ const { join } = await import('node:path');
52
+ let routing = { enabled: false, provider: 'null' };
53
+ const featuresPath = join(root, '.xray', 'features.json');
54
+ if (existsSync(featuresPath)) {
55
+ try {
56
+ routing = JSON.parse(readFileSync(featuresPath, 'utf8')).memory_routing || routing;
57
+ } catch {
58
+ /* leftover default */
59
+ }
60
+ }
61
+ return loadMemoryRoutingProvider(routing, root);
62
+ }
63
+
64
+ async function matchStationSignals(root, intent) {
65
+ if (!intent) return [];
66
+ try {
67
+ const provider = await loadStationProvider(root);
68
+ if (!provider || provider.id === 'null' || typeof provider.getTaskConfidence !== 'function') {
69
+ return [];
70
+ }
71
+ const conf = provider.getTaskConfidence({
72
+ id: 'station',
73
+ description: String(intent),
74
+ type: 'station',
75
+ });
76
+ const names = Array.isArray(conf.matchedSignals) ? conf.matchedSignals : [];
77
+ const safe = [];
78
+ for (const signalName of names) {
79
+ const name = String(signalName || '').trim();
80
+ if (!name || name.toLowerCase().startsWith('bedrock-')) continue;
81
+ safe.push(name);
82
+ if (safe.length >= 4) break;
83
+ }
84
+ return safe;
85
+ } catch {
86
+ return [];
87
+ }
88
+ }
89
+
90
+ const COMPACT_EVENTS = new Set(['pre_compact', 'post_compact']);
91
+
92
+ async function ingestStationFeedback(root, sessionId, hookEvent, matchedSignals) {
93
+ if (!COMPACT_EVENTS.has(hookEvent) || !matchedSignals.length) return;
94
+ try {
95
+ const provider = await loadStationProvider(root);
96
+ if (!provider || typeof provider.ingestFeedback !== 'function') return;
97
+ provider.ingestFeedback({
98
+ timestamp: new Date().toISOString(),
99
+ sessionId: sessionId || 'station',
100
+ taskId: `station-${hookEvent}`,
101
+ assignedAgent: 'station',
102
+ memorySignals: matchedSignals,
103
+ complexity: 0,
104
+ success: true,
105
+ durationMs: 0,
106
+ });
107
+ } catch {
108
+ /* working-state file is the session memory; registry ingest is best-effort */
109
+ }
110
+ }
111
+
34
112
  async function main() {
35
113
  const root = workspaceRoot();
36
114
  let HOOK_EVENT = 'session_start';
@@ -47,24 +125,56 @@ async function main() {
47
125
  sessionId,
48
126
  });
49
127
  }
128
+
129
+ try {
130
+ const archived = archiveStaleLeadDevPlan(eventRoot);
131
+ if (archived.archived) {
132
+ appendHookActivity(eventRoot, 'grok-session-start', 'stale-plan-archived', 'info', {
133
+ archivePath: archived.archivePath,
134
+ reason: archived.reason,
135
+ });
136
+ }
137
+ } catch {
138
+ /* non-blocking */
139
+ }
50
140
  const source =
51
141
  HOOK_EVENT === 'user_prompt_submit'
52
142
  ? '0xray/grok-user-prompt-submit'
53
- : '0xray/grok-session-start';
143
+ : HOOK_EVENT === 'pre_compact' || HOOK_EVENT === 'post_compact'
144
+ ? '0xray/grok-compact'
145
+ : '0xray/grok-session-start';
54
146
 
147
+ const intent = extractIntent(event);
148
+ const matchedSignals = await matchStationSignals(eventRoot, intent);
55
149
  const payload = buildSessionBootPayload(eventRoot, source, {
56
150
  hookEvent: HOOK_EVENT,
57
151
  sessionId: event.sessionId || process.env.GROK_SESSION_ID || null,
152
+ ...(intent ? { intent } : {}),
153
+ ...(matchedSignals.length ? { matchedSignals } : {}),
58
154
  });
59
155
 
60
156
  const bootPath = writeSessionBoot(eventRoot, payload) || ensureSessionBoot(eventRoot, source);
157
+ await ingestStationFeedback(eventRoot, sessionId, HOOK_EVENT, matchedSignals);
61
158
 
62
159
  appendHookActivity(eventRoot, 'grok-session-start', 'session-boot-written', 'success', {
63
160
  bootPath,
64
161
  hookEvent: HOOK_EVENT,
65
162
  lead_dev_mode: payload.lead_dev_mode,
163
+ repertoireResume: payload.repertoireResume,
164
+ stationLine: payload.stationLine,
165
+ hotSwap: payload.hotSwap || null,
66
166
  });
67
167
 
168
+ try {
169
+ scheduleAutonomousReportingMarker(eventRoot);
170
+ if (HOOK_EVENT === 'session_start') {
171
+ maybeRunReflectionStub(eventRoot);
172
+ runInferenceImprovementLight(eventRoot);
173
+ }
174
+ } catch {
175
+ /* non-blocking pipeline facets */
176
+ }
177
+
68
178
  console.log(JSON.stringify(payload));
69
179
  process.exit(0);
70
180
  } catch (err) {
@@ -2,15 +2,11 @@
2
2
  "hooks": {
3
3
  "PreToolUse": [
4
4
  {
5
- "matcher": ".*",
6
5
  "hooks": [
7
6
  {
8
7
  "type": "command",
9
- "command": "node",
10
- "args": [
11
- "${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/pre-tool-use.js"
12
- ],
13
- "timeout": 30000
8
+ "command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/pre-tool-use.js\"",
9
+ "timeout": 30
14
10
  }
15
11
  ]
16
12
  }
@@ -20,11 +16,8 @@
20
16
  "hooks": [
21
17
  {
22
18
  "type": "command",
23
- "command": "node",
24
- "args": [
25
- "${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js"
26
- ],
27
- "timeout": 15000
19
+ "command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js\"",
20
+ "timeout": 30
28
21
  }
29
22
  ]
30
23
  }
@@ -34,30 +27,44 @@
34
27
  "hooks": [
35
28
  {
36
29
  "type": "command",
37
- "command": "node",
38
- "args": [
39
- "${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js",
40
- "--hook-event=user_prompt_submit"
41
- ],
42
- "timeout": 15000
30
+ "command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js\" --hook-event=user_prompt_submit",
31
+ "timeout": 30
43
32
  }
44
33
  ]
45
34
  }
46
35
  ],
47
36
  "PostToolUse": [
48
37
  {
49
- "matcher": ".*",
50
38
  "hooks": [
51
39
  {
52
40
  "type": "command",
53
- "command": "node",
54
- "args": [
55
- "${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/post-tool-use.js"
56
- ],
57
- "timeout": 15000
41
+ "command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/post-tool-use.js\"",
42
+ "timeout": 30
43
+ }
44
+ ]
45
+ }
46
+ ],
47
+ "PreCompact": [
48
+ {
49
+ "hooks": [
50
+ {
51
+ "type": "command",
52
+ "command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js\" --hook-event=pre_compact",
53
+ "timeout": 30
54
+ }
55
+ ]
56
+ }
57
+ ],
58
+ "PostCompact": [
59
+ {
60
+ "hooks": [
61
+ {
62
+ "type": "command",
63
+ "command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js\" --hook-event=post_compact",
64
+ "timeout": 30
58
65
  }
59
66
  ]
60
67
  }
61
68
  ]
62
69
  }
63
- }
70
+ }
@@ -206,6 +206,10 @@ def _delegation_gate_block(tool_name: str, args: dict, task_id: str, **kwargs):
206
206
  },
207
207
  timeout=10,
208
208
  )
209
+ if bridge_result.get("error") and bridge_result.get("allow") is not False:
210
+ err = bridge_result.get("error", "delegation-gate bridge error")
211
+ _log_to_file("activity.log", f"[delegation-gate] bridge-error tool={tool_name} {err}")
212
+ return {"action": "block", "message": err}
209
213
  if bridge_result.get("allow") is False:
210
214
  reason = bridge_result.get("reason", "Delegation gate blocked this tool")
211
215
  gate = bridge_result.get("gate", "delegation-gate")
@@ -376,6 +380,8 @@ def _on_post_tool_call(tool_name: str, args: dict, result, task_id: str, **kwarg
376
380
  "args": args or {},
377
381
  "sessionId": session_id,
378
382
  "host": "hermes",
383
+ "toolOutput": result,
384
+ "result": result,
379
385
  },
380
386
  timeout=10,
381
387
  )
@@ -452,6 +458,10 @@ def _on_session_start(session_id: str, platform: str, **kwargs):
452
458
  _ensure_log_dir()
453
459
  _log_to_file("activity.log",
454
460
  f"[session-start] session={session_id} platform={platform}")
461
+ try:
462
+ _call_bridge({"command": "session-start", "sessionId": session_id}, timeout=10)
463
+ except Exception as e:
464
+ logger.debug("[xray] session-start bridge skipped: %s", e)
455
465
  logger.info("[xray] Session %s started on %s", session_id, platform)
456
466
 
457
467
 
@@ -771,7 +781,7 @@ def register(ctx):
771
781
 
772
782
  # Log session-start since on_session_start may not fire in oneshot mode
773
783
  _log_to_file("activity.log",
774
- f"[session-start] session={session_id}")
784
+ "[session-start] session=bootstrap source=plugin-load")
775
785
 
776
786
  logger.info(
777
787
  "[xray] Plugin v2.2 loaded: 6 tools, 2 hooks, "
@@ -15,6 +15,7 @@
15
15
  * codex-check - Check code against codex rules
16
16
  * stats - Return bridge/framework statistics
17
17
  * hooks - Manage git hooks (install, uninstall, list, status)
18
+ * session-start - Session boot: archive stale lead-dev plans (synthesis exempt)
18
19
  * govern - Govern inference proposals through weighted voting
19
20
  * apply - Govern + apply approved inference proposals
20
21
  *
@@ -36,13 +37,42 @@ import {
36
37
  unlinkSync,
37
38
  renameSync,
38
39
  } from "fs";
39
- import { join, dirname, relative } from "path";
40
- import { fileURLToPath } from "url";
40
+ import { join, dirname, relative, resolve } from "path";
41
+ import { fileURLToPath, pathToFileURL } from "url";
41
42
  import { homedir } from "os";
42
- import { findProjectRoot } from "../../../scripts/helpers/find-project-root.mjs";
43
43
 
44
44
  const __dirname = dirname(fileURLToPath(import.meta.url));
45
45
 
46
+ /** Resolve find-project-root from plugin install, dist layout, or consumer node_modules. */
47
+ function resolveFindProjectRootPath() {
48
+ const candidates = [];
49
+ const marker = join(__dirname, "xray-consumer-root.txt");
50
+ if (existsSync(marker)) {
51
+ try {
52
+ const marked = readFileSync(marker, "utf-8").trim();
53
+ if (marked) {
54
+ candidates.push(
55
+ join(marked, "node_modules", "0xray", "scripts", "helpers", "find-project-root.mjs"),
56
+ );
57
+ }
58
+ } catch {
59
+ /* fall through */
60
+ }
61
+ }
62
+ candidates.push(
63
+ join(__dirname, "scripts", "helpers", "find-project-root.mjs"),
64
+ join(__dirname, "..", "..", "..", "scripts", "helpers", "find-project-root.mjs"),
65
+ join(__dirname, "../../../scripts/helpers/find-project-root.mjs"),
66
+ );
67
+ for (const candidate of candidates) {
68
+ const abs = resolve(candidate);
69
+ if (existsSync(abs)) return abs;
70
+ }
71
+ throw new Error("find-project-root.mjs not found — re-run: npx 0xray hermes install --force");
72
+ }
73
+
74
+ const { findProjectRoot } = await import(pathToFileURL(resolveFindProjectRootPath()).href);
75
+
46
76
  // ── Framework components (lazy-loaded) ───────────────────────
47
77
  let ProcessorManager = null;
48
78
  let XrayStateManager = null;
@@ -389,6 +419,45 @@ async function handleHealth(input) {
389
419
  };
390
420
  }
391
421
 
422
+ async function handleSessionStart(input, projectRoot, logDir) {
423
+ const sessionId = input.sessionId || `bridge-${Date.now()}`;
424
+ let planArchive = { archived: false };
425
+
426
+ try {
427
+ const { archiveStaleLeadDevPlan } = await import('../hooks/plan-hook-runtime.mjs');
428
+ planArchive = archiveStaleLeadDevPlan(projectRoot);
429
+ if (planArchive.archived) {
430
+ logToActivity(
431
+ logDir,
432
+ `session-start: stale-plan-archived path=${planArchive.archivePath ?? 'unknown'}`,
433
+ );
434
+ }
435
+ } catch {
436
+ /* non-blocking — dist may be absent during dev */
437
+ }
438
+
439
+ try {
440
+ const gate = await import('../hooks/delegation-gate-runtime.mjs');
441
+ if (typeof gate.writeSuitSessionBoot === 'function') {
442
+ const compact =
443
+ input.compact === true ||
444
+ input.hookEvent === 'pre_compact' ||
445
+ input.hookEvent === 'post_compact';
446
+ gate.writeSuitSessionBoot(projectRoot, 'hermes', {
447
+ source: compact ? '0xray/hermes-compact' : '0xray/hermes-session-start',
448
+ sessionId,
449
+ hookEvent: compact ? 'post_compact' : 'session_start',
450
+ ...(input.intent ? { intent: input.intent } : {}),
451
+ });
452
+ }
453
+ } catch {
454
+ /* dist may be absent during dev */
455
+ }
456
+
457
+ logToActivity(logDir, `session-start: session=${sessionId} source=bridge`);
458
+ return { ok: true, sessionId, planArchive };
459
+ }
460
+
392
461
  async function handlePreProcess(input, projectRoot, logDir) {
393
462
  const { tool, args } = input;
394
463
  const startTime = Date.now();
@@ -766,7 +835,7 @@ async function handleApply(input, projectRoot, logDir) {
766
835
  // ── Known commands for positional-arg mode ──────────────────
767
836
  const KNOWN_COMMANDS = new Set([
768
837
  "health", "stats", "pre-process", "post-process", "validate", "codex-check", "hooks", "govern", "apply",
769
- "skill-install", "skill-registry", "delegation-gate",
838
+ "skill-install", "skill-registry", "delegation-gate", "session-start",
770
839
  ]);
771
840
 
772
841
  async function recordHermesSynthesisTurn(projectRoot, sessionId) {
@@ -792,7 +861,12 @@ async function handleDelegationGate(command, projectRoot, logDir) {
792
861
  if (!gate.isSubagentTool(tool)) {
793
862
  return { allow: true, phase: "post", skipped: true };
794
863
  }
795
- const result = gate.evaluatePostToolSpawn(tool, args, projectRoot);
864
+ const toolOutput =
865
+ command.toolOutput ?? command.result ?? command.output ?? args?.result ?? null;
866
+ const result = gate.evaluatePostToolSpawn(tool, args, projectRoot, {
867
+ sessionId,
868
+ toolOutput,
869
+ });
796
870
  if (result.satisfied.length > 0) {
797
871
  logToActivity(
798
872
  logDir,
@@ -806,7 +880,7 @@ async function handleDelegationGate(command, projectRoot, logDir) {
806
880
  await recordHermesSynthesisTurn(projectRoot, sessionId);
807
881
  }
808
882
 
809
- const features = gate.loadDelegationGateFeatures(projectRoot);
883
+ const features = gate.loadDelegationGateFeatures(projectRoot, host);
810
884
  const outcome = gate.evaluatePreToolGate(tool, args, {
811
885
  projectRoot,
812
886
  sessionId,
@@ -823,7 +897,15 @@ async function handleDelegationGate(command, projectRoot, logDir) {
823
897
 
824
898
  return { phase: "pre", ...outcome };
825
899
  } catch (error) {
826
- return { error: `delegation-gate failed: ${error.message || error}` };
900
+ const message = `delegation-gate failed: ${error.message || error}`;
901
+ logToActivity(logDir, `[delegation-gate] error ${message}`);
902
+ return {
903
+ allow: false,
904
+ phase: "pre",
905
+ gate: "delegation-gate-error",
906
+ reason: message,
907
+ error: message,
908
+ };
827
909
  }
828
910
  }
829
911
 
@@ -910,10 +992,6 @@ async function main() {
910
992
  const projectRoot = resolveBridgeProjectRoot();
911
993
  const logDir = ensureLogDir(projectRoot);
912
994
 
913
- // Log session start for test verification
914
- const sessionId = `bridge-${Date.now()}`;
915
- logToActivity(logDir, `session-start: session=${sessionId} source=bridge`);
916
-
917
995
  // Lazy-load framework on first call
918
996
  if (!frameworkReady && !frameworkLoadAttempted) {
919
997
  await loadFramework(projectRoot);
@@ -956,6 +1034,9 @@ async function main() {
956
1034
  case "skill-registry":
957
1035
  response = await handleSkillRegistry(command, projectRoot, logDir);
958
1036
  break;
1037
+ case "session-start":
1038
+ response = await handleSessionStart(command, projectRoot, logDir);
1039
+ break;
959
1040
  case "delegation-gate":
960
1041
  response = await handleDelegationGate(command, projectRoot, logDir);
961
1042
  break;
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Lazy-load confer SSOT for Grok session-boot hints.
4
+ */
5
+ import { createRequire } from 'node:module';
6
+ import { existsSync } from 'node:fs';
7
+ import { dirname, join, resolve } from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+
12
+ function resolvePackageRoot() {
13
+ let dir = __dirname;
14
+ for (let i = 0; i < 10; i++) {
15
+ const pkg = join(dir, 'package.json');
16
+ if (existsSync(pkg)) {
17
+ try {
18
+ const require = createRequire(join(dir, 'package.json'));
19
+ if (require('./package.json').name === '0xray') return dir;
20
+ } catch {
21
+ /* continue */
22
+ }
23
+ }
24
+ const nm = join(dir, 'node_modules', '0xray', 'package.json');
25
+ if (existsSync(nm)) return dirname(nm);
26
+ const parent = dirname(dir);
27
+ if (parent === dir) break;
28
+ dir = parent;
29
+ }
30
+ return resolve(__dirname, '../../..');
31
+ }
32
+
33
+ function loadConfer() {
34
+ const root = resolvePackageRoot();
35
+ const candidates = [
36
+ join(__dirname, '../../nucleus/confer.js'),
37
+ join(root, 'dist/nucleus/confer.js'),
38
+ join(process.cwd(), 'node_modules/0xray/dist/nucleus/confer.js'),
39
+ ];
40
+ const found = candidates.find((p) => existsSync(p));
41
+ if (!found) return null;
42
+ return createRequire(import.meta.url)(found);
43
+ }
44
+
45
+ export function isConferPendingForSession(projectRoot, sessionId = null) {
46
+ const mod = loadConfer();
47
+ if (!mod?.isConferPending) return false;
48
+ return mod.isConferPending(projectRoot, sessionId);
49
+ }
@@ -4,7 +4,8 @@
4
4
  * Used by Grok hooks, Hermes bridge, and verify fixtures.
5
5
  */
6
6
  import { createRequire } from 'node:module';
7
- import { existsSync } from 'node:fs';
7
+ import { existsSync, readFileSync } from 'node:fs';
8
+ import { homedir } from 'node:os';
8
9
  import { dirname, join, resolve } from 'node:path';
9
10
  import { fileURLToPath } from 'node:url';
10
11
 
@@ -35,17 +36,40 @@ function resolvePackageRoot() {
35
36
  return resolve(__dirname, '../../..');
36
37
  }
37
38
 
39
+ function markedRoots() {
40
+ const files = [
41
+ join(homedir(), '.hermes', 'plugins', 'xray-hermes', 'xray-consumer-root.txt'),
42
+ join(homedir(), '.openclaw', 'xray-consumer-root.txt'),
43
+ ];
44
+ const roots = [];
45
+ for (const file of files) {
46
+ if (!existsSync(file)) continue;
47
+ try {
48
+ const marked = readFileSync(file, 'utf8').trim();
49
+ if (marked) {
50
+ roots.push(marked, join(marked, 'node_modules', '0xray'));
51
+ }
52
+ } catch {
53
+ /* ignore unreadable marker */
54
+ }
55
+ }
56
+ return roots;
57
+ }
58
+
38
59
  function loadDelegationGate() {
39
60
  const root = resolvePackageRoot();
61
+ const envRoot = process.env.XRAY_AI_PATH || '';
40
62
  const candidates = [
41
63
  join(__dirname, '../../nucleus/delegation-gate.js'),
42
64
  join(root, 'dist/nucleus/delegation-gate.js'),
65
+ envRoot ? join(envRoot, 'dist/nucleus/delegation-gate.js') : '',
66
+ ...markedRoots().map((r) => join(r, 'dist/nucleus/delegation-gate.js')),
43
67
  join(process.cwd(), 'node_modules/0xray/dist/nucleus/delegation-gate.js'),
44
- ];
68
+ ].filter(Boolean);
45
69
  const found = candidates.find((p) => existsSync(p));
46
70
  if (!found) {
47
71
  throw new Error(
48
- 'delegation-gate.js missing — run npm run build in 0xray or npm install 0xray@^3.5.1',
72
+ 'delegation-gate.js missing — run npm run build in 0xray or npm install 0xray',
49
73
  );
50
74
  }
51
75
  return createRequire(import.meta.url)(found);
@@ -53,6 +77,9 @@ function loadDelegationGate() {
53
77
 
54
78
  const gate = loadDelegationGate();
55
79
 
80
+ export const writeSuitSessionBoot = gate.writeSuitSessionBoot;
81
+ export const maybeHeatHostStation = gate.maybeHeatHostStation;
82
+
56
83
  export const {
57
84
  loadDelegationGateFeatures,
58
85
  normalizeHostToolInput,
@@ -78,4 +105,6 @@ export const {
78
105
  buildReceiptFromConsultOutput,
79
106
  parseConsultVerdictFromText,
80
107
  isSynthesisConsultTodoId,
108
+ archiveStaleLeadDevPlan,
109
+ findRecentStalePlanArchive,
81
110
  } = gate;