0xray 3.5.5 → 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 (229) 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 +27 -5
  39. package/.xray/features.schema.json +31 -0
  40. package/AGENTS-consumer.md +16 -6
  41. package/AGENTS.md +11 -3
  42. package/README.md +13 -10
  43. package/SKILLS.md +1 -1
  44. package/dist/AGENTS.md +11 -3
  45. package/dist/CHANGELOG.md +65 -11
  46. package/dist/README.md +13 -10
  47. package/dist/SKILLS.md +1 -1
  48. package/dist/cli/commands/hermes-install.js +3 -0
  49. package/dist/cli/commands/openclaw-install.js +14 -0
  50. package/dist/core/features-config.d.ts +15 -2
  51. package/dist/infrastructure/schemas/cloud-schemas.d.ts +1 -1
  52. package/dist/integrations/grok/grok-cli.d.ts +3 -0
  53. package/dist/integrations/grok/grok-cli.js +92 -4
  54. package/dist/integrations/grok/hooks/grok-hook-utils.js +53 -7
  55. package/dist/integrations/grok/hooks/post-tool-use.js +68 -46
  56. package/dist/integrations/grok/hooks/pre-tool-use.js +14 -31
  57. package/dist/integrations/grok/hooks/session-start.js +86 -4
  58. package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
  59. package/dist/integrations/hermes-agent/bridge.mjs +19 -1
  60. package/dist/integrations/hooks/delegation-gate-runtime.mjs +32 -3
  61. package/dist/integrations/hooks/pipeline-hook-runtime.mjs +1 -1
  62. package/dist/integrations/hooks/station-hook-runtime.cjs +421 -0
  63. package/dist/integrations/hooks/station-hook-runtime.mjs +24 -0
  64. package/dist/integrations/hooks/station-memory-ingest.mjs +45 -0
  65. package/dist/integrations/hooks/station-memory-match.mjs +47 -0
  66. package/dist/integrations/openclaw/client.d.ts +5 -1
  67. package/dist/integrations/openclaw/client.js +17 -9
  68. package/dist/integrations/openclaw/config.js +0 -1
  69. package/dist/integrations/openclaw/hooks/pre-tool-gate-runtime.mjs +102 -0
  70. package/dist/integrations/openclaw/index.js +17 -0
  71. package/dist/integrations/openclaw/plugin/xray-pre-tool/index.js +75 -0
  72. package/dist/integrations/openclaw/plugin/xray-pre-tool/openclaw.plugin.json +10 -0
  73. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +10 -0
  74. package/dist/integrations/openclaw/pre-tool-gate.d.ts +19 -0
  75. package/dist/integrations/openclaw/pre-tool-gate.js +39 -0
  76. package/dist/mcps/orchestrator/handlers/complexity-handler.js +2 -2
  77. package/dist/memory-routing/index.d.ts +1 -1
  78. package/dist/memory-routing/index.js +1 -1
  79. package/dist/memory-routing/provider-loader.d.ts +4 -0
  80. package/dist/memory-routing/provider-loader.js +44 -2
  81. package/dist/memory-routing/provider-registry.js +3 -2
  82. package/dist/nucleus/autonomy-kernel.d.ts +2 -2
  83. package/dist/nucleus/autonomy-kernel.js +17 -6
  84. package/dist/nucleus/confer.js +17 -3
  85. package/dist/nucleus/delegation-gate.d.ts +14 -8
  86. package/dist/nucleus/delegation-gate.js +151 -16
  87. package/dist/nucleus/suit-temperament.d.ts +40 -0
  88. package/dist/nucleus/suit-temperament.js +157 -0
  89. package/dist/nucleus/user-aside.js +1 -1
  90. package/dist/plugin/xray-codex-injection.js +14 -3
  91. package/dist/postprocessor/triggers/GitHookTrigger.js +11 -5
  92. package/opencode.json +88 -0
  93. package/package.json +14 -4
  94. package/scripts/hooks/install-hooks.cjs +18 -3
  95. package/scripts/hooks/run-hook.js +67 -3
  96. package/scripts/mjs/run-repertoire-mcp.mjs +39 -0
  97. package/scripts/mjs/verify-confer-core.mjs +1 -1
  98. package/scripts/mjs/verify-delegation-gate-core.mjs +29 -2
  99. package/scripts/mjs/verify-four-floor-compact.mjs +524 -0
  100. package/scripts/mjs/verify-pipeline-facets.mjs +215 -0
  101. package/scripts/mjs/verify-temperament-live.mjs +261 -0
  102. package/scripts/node/bridge-mcp-wiring.cjs +277 -29
  103. package/scripts/node/install-bridges.cjs +195 -33
  104. package/scripts/node/postinstall.cjs +50 -27
  105. package/scripts/node/release-gate.mjs +1 -1
  106. package/scripts/node/release.mjs +2 -2
  107. package/scripts/node/validate-release-docs.mjs +20 -33
  108. package/scripts/node/version-manager.mjs +25 -10
  109. package/src/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
  110. package/src/integrations/openclaw/README.md +134 -0
  111. package/src/integrations/openclaw/plugin/xray-pre-tool/index.js +75 -0
  112. package/src/integrations/openclaw/plugin/xray-pre-tool/openclaw.plugin.json +10 -0
  113. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +10 -0
  114. package/src/mcps/orchestrator/handlers/complexity-handler.ts +2 -1
  115. package/vendor/@0xray/repertoire/AGENTS.md +163 -0
  116. package/vendor/@0xray/repertoire/LICENSE +21 -0
  117. package/vendor/@0xray/repertoire/README.md +120 -0
  118. package/vendor/@0xray/repertoire/data/curated_signals.json +208 -0
  119. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts +78 -0
  120. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +1 -0
  121. package/vendor/@0xray/repertoire/dist/RepertoireService.js +153 -0
  122. package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +1 -0
  123. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts +39 -0
  124. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts.map +1 -0
  125. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js +60 -0
  126. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js.map +1 -0
  127. package/vendor/@0xray/repertoire/dist/index.d.ts +14 -0
  128. package/vendor/@0xray/repertoire/dist/index.d.ts.map +1 -0
  129. package/vendor/@0xray/repertoire/dist/index.js +14 -0
  130. package/vendor/@0xray/repertoire/dist/index.js.map +1 -0
  131. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts +26 -0
  132. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +1 -0
  133. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js +109 -0
  134. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +1 -0
  135. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts +18 -0
  136. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts.map +1 -0
  137. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js +94 -0
  138. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js.map +1 -0
  139. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts +7 -0
  140. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts.map +1 -0
  141. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js +18 -0
  142. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js.map +1 -0
  143. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts +31 -0
  144. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +1 -0
  145. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js +83 -0
  146. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +1 -0
  147. package/vendor/@0xray/repertoire/dist/mcp/server.d.ts +6 -0
  148. package/vendor/@0xray/repertoire/dist/mcp/server.d.ts.map +1 -0
  149. package/vendor/@0xray/repertoire/dist/mcp/server.js +173 -0
  150. package/vendor/@0xray/repertoire/dist/mcp/server.js.map +1 -0
  151. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts +27 -0
  152. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts.map +1 -0
  153. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js +107 -0
  154. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js.map +1 -0
  155. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts +11 -0
  156. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts.map +1 -0
  157. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js +32 -0
  158. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js.map +1 -0
  159. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts +9 -0
  160. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +1 -0
  161. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js +72 -0
  162. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +1 -0
  163. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts +5 -0
  164. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts.map +1 -0
  165. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js +18 -0
  166. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js.map +1 -0
  167. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts +31 -0
  168. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +1 -0
  169. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js +218 -0
  170. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +1 -0
  171. package/vendor/@0xray/repertoire/dist/paths.d.ts +24 -0
  172. package/vendor/@0xray/repertoire/dist/paths.d.ts.map +1 -0
  173. package/vendor/@0xray/repertoire/dist/paths.js +74 -0
  174. package/vendor/@0xray/repertoire/dist/paths.js.map +1 -0
  175. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts +141 -0
  176. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +1 -0
  177. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js +210 -0
  178. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +1 -0
  179. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts +48 -0
  180. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +1 -0
  181. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js +221 -0
  182. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +1 -0
  183. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts +11 -0
  184. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +1 -0
  185. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js +43 -0
  186. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +1 -0
  187. package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts +15 -0
  188. package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts.map +1 -0
  189. package/vendor/@0xray/repertoire/dist/registry/signal-prune.js +35 -0
  190. package/vendor/@0xray/repertoire/dist/registry/signal-prune.js.map +1 -0
  191. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts +3 -0
  192. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts.map +1 -0
  193. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js +24 -0
  194. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js.map +1 -0
  195. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts +24 -0
  196. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +1 -0
  197. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js +148 -0
  198. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +1 -0
  199. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts +4 -0
  200. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts.map +1 -0
  201. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js +44 -0
  202. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js.map +1 -0
  203. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts +22 -0
  204. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts.map +1 -0
  205. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js +66 -0
  206. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js.map +1 -0
  207. package/vendor/@0xray/repertoire/dist/types.d.ts +210 -0
  208. package/vendor/@0xray/repertoire/dist/types.d.ts.map +1 -0
  209. package/vendor/@0xray/repertoire/dist/types.js +2 -0
  210. package/vendor/@0xray/repertoire/dist/types.js.map +1 -0
  211. package/vendor/@0xray/repertoire/docs/MEMORY-ROUTING-PROVIDER.md +54 -0
  212. package/vendor/@0xray/repertoire/hermes-mcp.example.json +20 -0
  213. package/vendor/@0xray/repertoire/mcp-config.example.json +11 -0
  214. package/vendor/@0xray/repertoire/package.json +124 -0
  215. package/vendor/@0xray/repertoire/schemas/curated-signal.schema.json +68 -0
  216. package/vendor/@0xray/repertoire/schemas/inference-log.schema.json +82 -0
  217. package/vendor/@0xray/repertoire/scripts/confirm-suit-all.mjs +253 -0
  218. package/vendor/@0xray/repertoire/scripts/confirm-suit-harness.mjs +220 -0
  219. package/vendor/@0xray/repertoire/scripts/run-live-synthesis-checkpoint.mjs +215 -0
  220. package/vendor/@0xray/repertoire/scripts/suit-bridge-shared.mjs +139 -0
  221. package/vendor/@0xray/repertoire/scripts/verify-grok-suit.mjs +304 -0
  222. package/vendor/@0xray/repertoire/scripts/verify-hermes-suit.mjs +163 -0
  223. package/vendor/@0xray/repertoire/scripts/verify-openclaw-suit.mjs +125 -0
  224. package/vendor/@0xray/repertoire/scripts/verify-opencode-suit.mjs +127 -0
  225. package/vendor/@0xray/repertoire/scripts/verify-synthesis-dogfood.mjs +207 -0
  226. package/vendor/@0xray/repertoire/skills/repertoire-trap-handling/SKILL.md +206 -0
  227. package/xray/codex.json +12 -3
  228. package/xray/features.json +27 -5
  229. package/xray/features.schema.json +31 -0
@@ -8,6 +8,8 @@ import {
8
8
  extractToolContext,
9
9
  isOrchestrateToolEvent,
10
10
  isSubagentTool,
11
+ isWriteTool,
12
+ loadFeatures,
11
13
  readStdinJson,
12
14
  resolveSessionId,
13
15
  workspaceRoot,
@@ -17,7 +19,7 @@ import {
17
19
  evaluatePostToolSpawn,
18
20
  isOrchestrateToolEvent as gateIsOrchestrateToolEvent,
19
21
  } from '../../hooks/delegation-gate-runtime.mjs';
20
- import { recordRoutingOutcome } from '../../hooks/pipeline-hook-runtime.mjs';
22
+ import { recordRoutingOutcome, runGrokPostprocessorLight } from '../../hooks/pipeline-hook-runtime.mjs';
21
23
 
22
24
  function extractToolOutput(event) {
23
25
  return (
@@ -30,60 +32,77 @@ function extractToolOutput(event) {
30
32
  );
31
33
  }
32
34
 
33
- async function main() {
34
- const root = workspaceRoot();
35
- try {
36
- const event = await readStdinJson();
37
- const eventRoot = event.workspaceRoot || event.cwd || root;
38
- const sessionId = resolveSessionId(event);
39
- const { toolName, toolInput } = extractToolContext(event);
35
+ export function handlePostToolUse(event, root = workspaceRoot()) {
36
+ const eventRoot = event.workspaceRoot || event.cwd || root;
37
+ const sessionId = resolveSessionId(event);
38
+ const { toolName, toolInput } = extractToolContext(event);
40
39
 
41
- if (isOrchestrateToolEvent(toolName, toolInput) || gateIsOrchestrateToolEvent(toolName, toolInput)) {
42
- appendHookActivity(eventRoot, 'grok-post-tool-use', 'auto-chain-pending', 'info', {
40
+ if (isOrchestrateToolEvent(toolName, toolInput) || gateIsOrchestrateToolEvent(toolName, toolInput)) {
41
+ appendHookActivity(eventRoot, 'grok-post-tool-use', 'auto-chain-pending', 'info', {
42
+ tool: toolName,
43
+ sessionId,
44
+ note: 'orchestrate-task completed — pending-delegations.json written by task-handler',
45
+ });
46
+ try {
47
+ recordRoutingOutcome(eventRoot, {
43
48
  tool: toolName,
49
+ agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'orchestrate-task',
50
+ planTodoId: toolInput?.planTodoId ?? null,
44
51
  sessionId,
45
- note: 'orchestrate-task completed — pending-delegations.json written by task-handler',
46
52
  });
47
- try {
48
- recordRoutingOutcome(eventRoot, {
49
- tool: toolName,
50
- agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'orchestrate-task',
51
- planTodoId: toolInput?.planTodoId ?? null,
52
- sessionId,
53
- });
54
- } catch {
55
- /* non-blocking */
56
- }
53
+ } catch {
54
+ /* non-blocking */
57
55
  }
56
+ }
57
+
58
+ const features = loadFeatures(eventRoot);
59
+ if (features.grok_postprocessor_light === true && isWriteTool(toolName)) {
60
+ try {
61
+ const paths = [
62
+ toolInput?.path,
63
+ toolInput?.filePath,
64
+ toolInput?.file_path,
65
+ ].filter(Boolean);
66
+ runGrokPostprocessorLight(eventRoot, { tool: toolName, paths });
67
+ } catch {
68
+ /* non-blocking */
69
+ }
70
+ }
71
+
72
+ if (isSubagentTool(toolName)) {
73
+ const spawnResult = evaluatePostToolSpawn(toolName, toolInput, eventRoot, {
74
+ toolOutput: extractToolOutput(event),
75
+ sessionId,
76
+ });
58
77
 
59
- if (isSubagentTool(toolName)) {
60
- const spawnResult = evaluatePostToolSpawn(toolName, toolInput, eventRoot, {
61
- toolOutput: extractToolOutput(event),
78
+ if (spawnResult.satisfied.length > 0 || spawnResult.expectedTodoId) {
79
+ appendHookActivity(eventRoot, 'grok-post-tool-use', 'auto-chain-cleared', 'success', {
80
+ tool: toolName,
81
+ satisfied: spawnResult.satisfied.map((d) => d.id),
82
+ clearedAll: spawnResult.clearedAll,
83
+ planTodoId: spawnResult.expectedTodoId ?? null,
84
+ receiptRecorded: spawnResult.receiptRecorded ?? false,
85
+ todoCompleted: spawnResult.todoCompleted ?? false,
86
+ });
87
+ }
88
+ try {
89
+ recordRoutingOutcome(eventRoot, {
90
+ tool: toolName,
91
+ agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'subagent',
92
+ planTodoId: toolInput?.planTodoId ?? spawnResult.expectedTodoId ?? null,
62
93
  sessionId,
63
94
  });
64
-
65
- if (spawnResult.satisfied.length > 0 || spawnResult.expectedTodoId) {
66
- appendHookActivity(eventRoot, 'grok-post-tool-use', 'auto-chain-cleared', 'success', {
67
- tool: toolName,
68
- satisfied: spawnResult.satisfied.map((d) => d.id),
69
- clearedAll: spawnResult.clearedAll,
70
- planTodoId: spawnResult.expectedTodoId ?? null,
71
- receiptRecorded: spawnResult.receiptRecorded ?? false,
72
- todoCompleted: spawnResult.todoCompleted ?? false,
73
- });
74
- }
75
- try {
76
- recordRoutingOutcome(eventRoot, {
77
- tool: toolName,
78
- agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'subagent',
79
- planTodoId: toolInput?.planTodoId ?? spawnResult.expectedTodoId ?? null,
80
- sessionId,
81
- });
82
- } catch {
83
- /* non-blocking */
84
- }
95
+ } catch {
96
+ /* non-blocking */
85
97
  }
98
+ }
99
+ }
86
100
 
101
+ async function main() {
102
+ const root = workspaceRoot();
103
+ try {
104
+ const event = await readStdinJson();
105
+ handlePostToolUse(event, root);
87
106
  process.exit(0);
88
107
  } catch (err) {
89
108
  appendHookActivity(root, 'grok-post-tool-use', 'hook-error', 'error', {
@@ -93,4 +112,7 @@ async function main() {
93
112
  }
94
113
  }
95
114
 
96
- main();
115
+ const launchedAsCli = Boolean(process.argv[1] && process.argv[1].endsWith('post-tool-use.js'));
116
+ if (launchedAsCli) {
117
+ main();
118
+ }
@@ -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,
@@ -21,7 +20,6 @@ import {
21
20
  workspaceRoot,
22
21
  } from './grok-hook-utils.js';
23
22
  import { appendHookActivity } from './grok-hook-activity.js';
24
- import { runGrokPostprocessorLight } from '../../hooks/pipeline-hook-runtime.mjs';
25
23
 
26
24
  function finish(root, decision, reason, hint, toolName, extra = {}) {
27
25
  const out = { decision, ...extra };
@@ -47,10 +45,10 @@ async function main() {
47
45
  ensureSessionBoot(eventRoot, '0xray/grok-pre-tool-use-boot');
48
46
 
49
47
  const features = loadFeatures(eventRoot);
50
- const gateFeatures = loadDelegationGateFeatures(eventRoot);
48
+ const gateFeatures = loadDelegationGateFeatures(eventRoot, 'grok');
51
49
  const ctx = extractFromEvent(event);
52
50
  toolName = ctx.toolName;
53
- const { paths, content, cmd, toolInput } = ctx;
51
+ const { content, cmd, toolInput } = ctx;
54
52
  const sessionId = resolveSessionId(event);
55
53
 
56
54
  const gateBlock = evaluatePreToolGate(toolName, toolInput, {
@@ -70,6 +68,18 @@ async function main() {
70
68
  );
71
69
  }
72
70
 
71
+ // Constitution (11/29/69 + destructive shell) is in evaluatePreToolGate.
72
+ // Grok extra: Codex 2/7 (TODO/FIXME/STUB, console.log).
73
+ if (isWriteTool(toolName) && content) {
74
+ const extraBlock = checkCodexPatterns(content, { terms: [2, 7] });
75
+ if (extraBlock) finish(eventRoot, 'deny', extraBlock, null, toolName);
76
+ }
77
+
78
+ if (isShellTool(toolName) && cmd) {
79
+ const testHint = checkFullTestSuite(cmd, features);
80
+ if (testHint) finish(eventRoot, 'allow', null, testHint, toolName);
81
+ }
82
+
73
83
  if (gateBlock.reason) {
74
84
  finish(
75
85
  eventRoot,
@@ -81,33 +91,6 @@ async function main() {
81
91
  );
82
92
  }
83
93
 
84
- if (features.no_new_surface && isWriteTool(toolName) && paths.length) {
85
- const surfaceBlock = checkSurfaceArea(paths, eventRoot);
86
- if (surfaceBlock) finish(eventRoot, 'deny', surfaceBlock, null, toolName);
87
- }
88
-
89
- if (isWriteTool(toolName) && content) {
90
- const codexBlock = checkCodexPatterns(content);
91
- if (codexBlock) finish(eventRoot, 'deny', codexBlock, null, toolName);
92
- }
93
-
94
- if (isShellTool(toolName) && cmd) {
95
- const destructive =
96
- /\brm\s+-rf\s+\/\b|\bmkfs\b|\bdd\s+if=|:()\s*\{\s*:\|&\s*\}\s*;:/i.test(cmd);
97
- if (destructive) finish(eventRoot, 'deny', 'Blocked destructive shell command', null, toolName);
98
-
99
- const testHint = checkFullTestSuite(cmd, features);
100
- if (testHint) finish(eventRoot, 'allow', null, testHint, toolName);
101
- }
102
-
103
- if (features.grok_postprocessor_light === true && isWriteTool(toolName)) {
104
- try {
105
- runGrokPostprocessorLight(eventRoot, { tool: toolName, paths });
106
- } catch {
107
- /* non-blocking */
108
- }
109
- }
110
-
111
94
  finish(eventRoot, 'allow', null, null, toolName);
112
95
  } catch (err) {
113
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 {
@@ -26,17 +26,89 @@ function resolveHookEvent(event) {
26
26
  if (process.env.GROK_HOOK_EVENT) return process.env.GROK_HOOK_EVENT;
27
27
  const flag = process.argv.find((a) => a.startsWith('--hook-event='));
28
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';
29
32
  if (
30
33
  event.prompt != null ||
31
34
  event.userMessage != null ||
32
35
  event.user_prompt != null ||
33
- event.hook === 'UserPromptSubmit'
36
+ named === 'UserPromptSubmit' ||
37
+ named === 'user_prompt_submit'
34
38
  ) {
35
39
  return 'user_prompt_submit';
36
40
  }
37
41
  return 'session_start';
38
42
  }
39
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
+
40
112
  async function main() {
41
113
  const root = workspaceRoot();
42
114
  let HOOK_EVENT = 'session_start';
@@ -68,19 +140,29 @@ async function main() {
68
140
  const source =
69
141
  HOOK_EVENT === 'user_prompt_submit'
70
142
  ? '0xray/grok-user-prompt-submit'
71
- : '0xray/grok-session-start';
143
+ : HOOK_EVENT === 'pre_compact' || HOOK_EVENT === 'post_compact'
144
+ ? '0xray/grok-compact'
145
+ : '0xray/grok-session-start';
72
146
 
147
+ const intent = extractIntent(event);
148
+ const matchedSignals = await matchStationSignals(eventRoot, intent);
73
149
  const payload = buildSessionBootPayload(eventRoot, source, {
74
150
  hookEvent: HOOK_EVENT,
75
151
  sessionId: event.sessionId || process.env.GROK_SESSION_ID || null,
152
+ ...(intent ? { intent } : {}),
153
+ ...(matchedSignals.length ? { matchedSignals } : {}),
76
154
  });
77
155
 
78
156
  const bootPath = writeSessionBoot(eventRoot, payload) || ensureSessionBoot(eventRoot, source);
157
+ await ingestStationFeedback(eventRoot, sessionId, HOOK_EVENT, matchedSignals);
79
158
 
80
159
  appendHookActivity(eventRoot, 'grok-session-start', 'session-boot-written', 'success', {
81
160
  bootPath,
82
161
  hookEvent: HOOK_EVENT,
83
162
  lead_dev_mode: payload.lead_dev_mode,
163
+ repertoireResume: payload.repertoireResume,
164
+ stationLine: payload.stationLine,
165
+ hotSwap: payload.hotSwap || null,
84
166
  });
85
167
 
86
168
  try {
@@ -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
+ }
@@ -436,6 +436,24 @@ async function handleSessionStart(input, projectRoot, logDir) {
436
436
  /* non-blocking — dist may be absent during dev */
437
437
  }
438
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
+
439
457
  logToActivity(logDir, `session-start: session=${sessionId} source=bridge`);
440
458
  return { ok: true, sessionId, planArchive };
441
459
  }
@@ -862,7 +880,7 @@ async function handleDelegationGate(command, projectRoot, logDir) {
862
880
  await recordHermesSynthesisTurn(projectRoot, sessionId);
863
881
  }
864
882
 
865
- const features = gate.loadDelegationGateFeatures(projectRoot);
883
+ const features = gate.loadDelegationGateFeatures(projectRoot, host);
866
884
  const outcome = gate.evaluatePreToolGate(tool, args, {
867
885
  projectRoot,
868
886
  sessionId,
@@ -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;
@@ -189,7 +189,7 @@ export function runGrokPostprocessorLight(projectRoot, entry = {}) {
189
189
  phase: 'post-process-light',
190
190
  tool: entry.tool ?? 'unknown',
191
191
  paths: entry.paths ?? [],
192
- mode: 'grok-pre-tool-light',
192
+ mode: 'grok-post-tool-light',
193
193
  };
194
194
  writeFileSync(markerPath, `${JSON.stringify(payload, null, 2)}\n`);
195
195
  appendActivity(projectRoot, 'postprocessor-light', 'info', {