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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "3.5.4",
3
+ "version": "4.0.0",
4
4
  "description": "Multi-agent orchestration and Codex governance for OpenCode, Hermes, Grok Build, and OpenClaw",
5
5
  "readme": "README.md",
6
6
  "license": "MIT",
@@ -64,7 +64,7 @@
64
64
  "version:bump": "node scripts/node/version-manager.mjs",
65
65
  "version": "node scripts/node/version-manager.mjs",
66
66
  "prebuild": "rm -rf dist tsconfig.tsbuildinfo tsconfig.*.tsbuildinfo",
67
- "build": "tsc && mkdir -p dist/public dist/scripts && cp -r public/* dist/public/ && cp scripts/hooks/pre-command dist/scripts/ && cp scripts/hooks/pre-command.mjs dist/scripts/ && cp README.md AGENTS.md SKILLS.md CHANGELOG.md LICENSE .gitignore.default dist/ && find src -name '*.mjs' ! -path '*/__tests__/*' | while read f; do tgt=\"dist/${f#src/}\"; mkdir -p \"$(dirname $tgt)\"; cp \"$f\" \"$tgt\"; done && for dir in skills integrations mcps; do find src/$dir -type f ! -name '*.ts' ! -path '*/.pytest_cache/*' | while read f; do tgt=\"dist/${f#src/}\"; mkdir -p \"$(dirname $tgt)\"; cp \"$f\" \"$tgt\"; done; done && mkdir -p dist/plugin && (find dist/plugin -name '*codex-injection*.js' -exec cp {} dist/plugin/xray-codex-injection.js \\; 2>/dev/null || true) && cp -r src/opencode/ .opencode/ && mkdir -p .xray && for f in codex.json features.json features.schema.json config.json; do cp xray/$f .xray/$f 2>/dev/null || true; done",
67
+ "build": "tsc && chmod +x dist/cli/index.js && mkdir -p dist/public dist/scripts && cp -r public/* dist/public/ && cp scripts/hooks/pre-command dist/scripts/ && cp scripts/hooks/pre-command.mjs dist/scripts/ && cp README.md AGENTS.md SKILLS.md CHANGELOG.md LICENSE .gitignore.default dist/ && find src -name '*.mjs' ! -path '*/__tests__/*' | while read f; do tgt=\"dist/${f#src/}\"; mkdir -p \"$(dirname $tgt)\"; cp \"$f\" \"$tgt\"; done && for dir in skills integrations mcps; do find src/$dir -type f ! -name '*.ts' ! -path '*/.pytest_cache/*' | while read f; do tgt=\"dist/${f#src/}\"; mkdir -p \"$(dirname $tgt)\"; cp \"$f\" \"$tgt\"; done; done && mkdir -p dist/plugin && (find dist/plugin -name '*codex-injection*.js' -exec cp {} dist/plugin/xray-codex-injection.js \\; 2>/dev/null || true) && cp -r src/opencode/ .opencode/ && mkdir -p .opencode/skills && cp -R src/skills/. .opencode/skills/ && mkdir -p .xray && for f in codex.json features.json features.schema.json config.json; do cp xray/$f .xray/$f 2>/dev/null || true; done",
68
68
  "build:all": "npm run build",
69
69
  "ci-install": "npm ci",
70
70
  "clean": "rm -rf dist tsconfig.tsbuildinfo tsconfig.*.tsbuildinfo",
@@ -129,11 +129,19 @@
129
129
  "verify:orchestrator-behavior": "npm run build && node scripts/mjs/verify-orchestrator-behavior.mjs",
130
130
  "verify:grok-delegation-gate": "npm run build && node scripts/mjs/verify-grok-delegation-gate.mjs && node scripts/mjs/verify-grok-synthesis-gate.mjs",
131
131
  "verify:grok-synthesis-gate": "npm run build && node scripts/mjs/verify-grok-synthesis-gate.mjs",
132
- "verify:hermes-delegation-gate": "npm run build && node scripts/mjs/verify-hermes-delegation-gate.mjs",
132
+ "verify:hermes-delegation-gate": "npm run build && node scripts/mjs/verify-hermes-delegation-gate.mjs && node scripts/mjs/verify-hermes-session-start.mjs",
133
133
  "verify:delegation-gate": "npm run build && node scripts/mjs/verify-delegation-gate-core.mjs --host=grok && node scripts/mjs/verify-delegation-gate-core.mjs --host=hermes && node scripts/mjs/verify-delegation-gate-core.mjs --host=opencode && node scripts/mjs/verify-grok-delegation-gate.mjs && node scripts/mjs/verify-grok-synthesis-gate.mjs && node scripts/mjs/verify-hermes-delegation-gate.mjs",
134
- "verify:synthesis": "npm run build && node scripts/mjs/verify-synthesis-core.mjs && node scripts/mjs/verify-synthesis-gate-core.mjs && node scripts/mjs/verify-synthesis-outcome-core.mjs && node scripts/mjs/verify-synthesis-p2-core.mjs && node scripts/mjs/verify-synthesis-e2e-core.mjs",
134
+ "verify:synthesis": "npm run build && node scripts/mjs/verify-synthesis-core.mjs && node scripts/mjs/verify-synthesis-gate-core.mjs && node scripts/mjs/verify-synthesis-outcome-core.mjs && node scripts/mjs/verify-synthesis-p2-core.mjs && node scripts/mjs/verify-synthesis-e2e-core.mjs && node scripts/mjs/verify-confer-core.mjs",
135
+ "verify:confer": "npm run build && node scripts/mjs/verify-confer-core.mjs",
136
+ "verify:user-aside": "npm run build && node scripts/mjs/verify-user-aside-core.mjs",
137
+ "verify:pipeline-facets": "npm run build && node scripts/mjs/verify-pipeline-facets.mjs",
135
138
  "verify:find-project-root": "node scripts/mjs/verify-find-project-root-core.mjs",
136
- "verify:consumer-gitignore": "node scripts/mjs/verify-consumer-gitignore-core.mjs"
139
+ "verify:consumer-gitignore": "node scripts/mjs/verify-consumer-gitignore-core.mjs",
140
+ "verify:pre-commit-diff": "node scripts/mjs/verify-pre-commit-diff-core.mjs",
141
+ "verify:pre-push-diff": "node scripts/mjs/verify-pre-push-diff-core.mjs",
142
+ "verify:temperament-live": "node scripts/mjs/verify-temperament-live.mjs",
143
+ "verify:four-floor-compact": "node scripts/mjs/verify-four-floor-compact.mjs",
144
+ "verify:four-floor-compact:live": "XRAY_LIVE_SUCCESSOR=1 node scripts/mjs/verify-four-floor-compact.mjs"
137
145
  },
138
146
  "files": [
139
147
  "dist/",
@@ -149,6 +157,14 @@
149
157
  "scripts/mjs/verify-grok-delegation-gate.mjs",
150
158
  "scripts/mjs/verify-grok-synthesis-gate.mjs",
151
159
  "scripts/mjs/verify-hermes-delegation-gate.mjs",
160
+ "scripts/mjs/verify-hermes-session-start.mjs",
161
+ "scripts/mjs/verify-pre-push-diff-core.mjs",
162
+ "scripts/mjs/verify-confer-core.mjs",
163
+ "scripts/mjs/verify-user-aside-core.mjs",
164
+ "scripts/mjs/verify-pipeline-facets.mjs",
165
+ "scripts/mjs/verify-temperament-live.mjs",
166
+ "scripts/mjs/verify-four-floor-compact.mjs",
167
+ "scripts/mjs/run-repertoire-mcp.mjs",
152
168
  "scripts/mjs/verify-delegation-gate-core.mjs",
153
169
  "scripts/mjs/delegation-gate-fixture.mjs",
154
170
  "src/opencode/",
@@ -158,6 +174,7 @@
158
174
  "src/opencode/openclaw/",
159
175
  "src/opencode/workflows/",
160
176
  "src/integrations/grok/plugin/0xray/",
177
+ "src/integrations/openclaw/plugin/",
161
178
  "src/skills/",
162
179
  "src/mcps/",
163
180
  ".plugin/",
@@ -185,9 +202,11 @@
185
202
  ".xray/features.schema.json",
186
203
  ".xray/config.json",
187
204
  ".gitignore.default",
188
- "LICENSE"
205
+ "LICENSE",
206
+ "vendor/@0xray/repertoire/"
189
207
  ],
190
208
  "dependencies": {
209
+ "@0xray/repertoire": "file:./vendor/@0xray/repertoire",
191
210
  "@modelcontextprotocol/sdk": "^1.0.4",
192
211
  "commander": "^11.1.0",
193
212
  "express": "^5.2.1",
@@ -30,19 +30,34 @@ if (!fs.existsSync(gitHooksDir)) {
30
30
  }
31
31
 
32
32
  const isConsumer = packageRoot.includes("node_modules");
33
+
34
+ function firstExistingRelative(root, rels) {
35
+ return rels.find((rel) => fs.existsSync(path.join(root, rel))) || rels[0];
36
+ }
37
+
33
38
  const runHookRelativePath = isConsumer
34
- ? "node_modules/0xray/scripts/hooks/run-hook.js"
39
+ ? firstExistingRelative(targetDir, [
40
+ "node_modules/0xray/scripts/hooks/run-hook.js",
41
+ "node_modules/0xray/dist/scripts/hooks/run-hook.js",
42
+ ])
35
43
  : "scripts/hooks/run-hook.js";
36
44
  const loadReflectionRelativePath = isConsumer
37
- ? "node_modules/0xray/scripts/node/load-reflection-config.mjs"
45
+ ? firstExistingRelative(targetDir, [
46
+ "node_modules/0xray/scripts/node/load-reflection-config.mjs",
47
+ "node_modules/0xray/dist/scripts/node/load-reflection-config.mjs",
48
+ ])
38
49
  : "scripts/node/load-reflection-config.mjs";
39
50
  const autoReflectionRelativePath = isConsumer
40
- ? "node_modules/0xray/scripts/node/auto-reflection-generator.mjs"
51
+ ? firstExistingRelative(targetDir, [
52
+ "node_modules/0xray/scripts/node/auto-reflection-generator.mjs",
53
+ "node_modules/0xray/dist/scripts/node/auto-reflection-generator.mjs",
54
+ ])
41
55
  : "scripts/node/auto-reflection-generator.mjs";
42
56
 
43
57
  function hookRunnerExists(projectRoot) {
44
58
  return (
45
59
  fs.existsSync(path.join(projectRoot, "node_modules/0xray/scripts/hooks/run-hook.js")) ||
60
+ fs.existsSync(path.join(projectRoot, "node_modules/0xray/dist/scripts/hooks/run-hook.js")) ||
46
61
  fs.existsSync(path.join(projectRoot, "scripts/hooks/run-hook.js"))
47
62
  );
48
63
  }
@@ -108,9 +123,9 @@ BRANCH=$(git rev-parse --abbrev-ref HEAD)
108
123
  ) &
109
124
 
110
125
  MODE="minimal"
111
- COMMIT_THRESHOLD=25
126
+ COMMIT_THRESHOLD=50
112
127
  DAYS_THRESHOLD=14
113
- AUTO_GENERATE=true
128
+ AUTO_GENERATE=false
114
129
  PROMPT_USER=true
115
130
 
116
131
  if command -v node >/dev/null 2>&1; then
@@ -119,7 +134,7 @@ if command -v node >/dev/null 2>&1; then
119
134
  export PROJECT_ROOT="$PROJECT_ROOT"
120
135
  REFLECTION_JSON=$(node "$LOAD_SCRIPT" --json 2>/dev/null || echo '{}')
121
136
  MODE=$(node -e 'const c=JSON.parse(process.argv[1]);process.stdout.write(String(c.mode||"minimal"))' "$REFLECTION_JSON")
122
- COMMIT_THRESHOLD=$(node -e 'const c=JSON.parse(process.argv[1]);process.stdout.write(String(c.commitThreshold??25))' "$REFLECTION_JSON")
137
+ COMMIT_THRESHOLD=$(node -e 'const c=JSON.parse(process.argv[1]);process.stdout.write(String(c.commitThreshold??50))' "$REFLECTION_JSON")
123
138
  DAYS_THRESHOLD=$(node -e 'const c=JSON.parse(process.argv[1]);process.stdout.write(String(c.daysThreshold??14))' "$REFLECTION_JSON")
124
139
  AUTO_GENERATE=$(node -e 'const c=JSON.parse(process.argv[1]);process.stdout.write(c.autoGenerate===false?"false":"true")' "$REFLECTION_JSON")
125
140
  PROMPT_USER=$(node -e 'const c=JSON.parse(process.argv[1]);process.stdout.write(c.promptUser===false?"false":"true")' "$REFLECTION_JSON")
@@ -20,8 +20,9 @@
20
20
  */
21
21
 
22
22
  import { existsSync, readFileSync, writeFileSync, mkdirSync, appendFileSync } from "fs";
23
- import { join, dirname } from "path";
23
+ import { join, dirname, resolve } from "path";
24
24
  import { execSync, exec, execFileSync } from "child_process";
25
+ import { fileURLToPath, pathToFileURL } from "url";
25
26
 
26
27
  // ── Parse arguments ──────────────────────────────────────────
27
28
 
@@ -203,82 +204,152 @@ function runTypeScriptCheck(files) {
203
204
  }
204
205
  }
205
206
 
206
- // ── Codex validation ─────────────────────────────────────────
207
+ // ── Codex validation (diff-hunk scoped) ──────────────────────
208
+
209
+ /** Parse + lines from a unified diff (staged or commit-range). */
210
+ export function parseAddedLinesFromDiff(diff) {
211
+ const addedLines = [];
212
+ for (const line of diff.split("\n")) {
213
+ if (
214
+ line.startsWith("+++") ||
215
+ line.startsWith("---") ||
216
+ line.startsWith("@@") ||
217
+ line.startsWith("diff ") ||
218
+ line.startsWith("index ")
219
+ ) {
220
+ continue;
221
+ }
222
+ if (line.startsWith("+")) {
223
+ addedLines.push(line.slice(1));
224
+ }
225
+ }
226
+ return addedLines;
227
+ }
207
228
 
208
- async function runCodexValidation(files) {
209
- /**
210
- * Run lightweight codex validation on files.
211
- * Uses dynamic import of framework modules when available.
212
- */
213
- log("Running Codex validation...");
229
+ /**
230
+ * Collect added lines per file from git diff.
231
+ * scope `staged` → --cached (pre-commit); scope `range` → COMMIT_RANGE (pre-push).
232
+ */
233
+ export function getAddedLinesByFile(
234
+ files,
235
+ { scope = "staged", range = null, root = projectRoot } = {},
236
+ ) {
237
+ const addedByFile = new Map();
238
+
239
+ for (const file of files) {
240
+ if (!/\.(ts|tsx|js|jsx|mjs)$/.test(file)) continue;
241
+ try {
242
+ const gitArgs =
243
+ scope === "range" && range
244
+ ? ["diff", range, "-U0", "--", file]
245
+ : ["diff", "--cached", "-U0", "--", file];
246
+ const diff = execFileSync("git", gitArgs, {
247
+ cwd: root,
248
+ encoding: "utf-8",
249
+ stdio: ["pipe", "pipe", "pipe"],
250
+ });
251
+ const addedLines = parseAddedLinesFromDiff(diff);
252
+ if (addedLines.length > 0) {
253
+ addedByFile.set(file, addedLines);
254
+ }
255
+ } catch {
256
+ // Deletions-only or unreadable diff — skip codex for this file
257
+ }
258
+ }
214
259
 
215
- const tsFiles = files.filter((f) => /\.(ts|tsx)$/.test(f));
216
- const jsFiles = files.filter((f) => /\.(js|jsx|mjs)$/.test(f));
260
+ return addedByFile;
261
+ }
217
262
 
218
- if (tsFiles.length === 0 && jsFiles.length === 0) {
219
- return { passed: true, warnings: [], errors: [] };
220
- }
263
+ /** Pre-commit: staged diff hunks only. */
264
+ export function getStagedAddedLinesByFile(files, root = projectRoot) {
265
+ return getAddedLinesByFile(files, { scope: "staged", root });
266
+ }
267
+
268
+ /** Pre-push: added lines in commit range (e.g. remote..local). */
269
+ export function getRangeAddedLinesByFile(files, range, root = projectRoot) {
270
+ return getAddedLinesByFile(files, { scope: "range", range, root });
271
+ }
221
272
 
222
- // Quick static checks without framework dependency
273
+ export function scanAddedLinesForCodex(file, addedLines) {
223
274
  const errors = [];
224
275
  const warnings = [];
276
+ const content = addedLines.join("\n");
277
+ const lines = addedLines;
225
278
 
226
- for (const file of [...tsFiles, ...jsFiles]) {
227
- const filePath = join(projectRoot, file);
228
- if (!existsSync(filePath)) continue;
279
+ const consoleLogLines = lines.reduce((acc, line, i) => {
280
+ if (/\bconsole\.(log|warn|error)\b/.test(line) && !line.includes("NOSONAR")) {
281
+ acc.push(i + 1);
282
+ }
283
+ return acc;
284
+ }, []);
285
+ if (consoleLogLines.length > 0) {
286
+ errors.push(
287
+ `${file}: console.log/warn/error in staged diff at hunk line(s) ${consoleLogLines.slice(0, 3).join(", ")}`,
288
+ );
289
+ }
229
290
 
230
- try {
231
- const content = readFileSync(filePath, "utf-8");
232
- const lines = content.split("\n");
291
+ const todoLines = lines.reduce((acc, line, i) => {
292
+ if (/\/\/\s*(TODO|FIXME|HACK|XXX)\b/i.test(line)) {
293
+ acc.push(i + 1);
294
+ }
295
+ return acc;
296
+ }, []);
297
+ if (todoLines.length > 0) {
298
+ warnings.push(`${file}: ${todoLines.length} TODO/FIXME in staged diff`);
299
+ }
233
300
 
234
- // Check for console.log (codex violation)
235
- const consoleLogLines = lines.reduce((acc, line, i) => {
236
- if (/\bconsole\.(log|warn|error)\b/.test(line) && !line.includes("NOSONAR")) {
237
- acc.push(i + 1);
238
- }
239
- return acc;
240
- }, []);
241
- if (consoleLogLines.length > 0) {
242
- errors.push(`${file}: console.log/warn/error found at lines ${consoleLogLines.slice(0, 3).join(", ")}`);
243
- }
301
+ const tsIgnoreLines = lines.reduce((acc, line, i) => {
302
+ if (/@ts-ignore|@ts-nocheck|@ts-expect-error/.test(line)) {
303
+ acc.push(i + 1);
304
+ }
305
+ return acc;
306
+ }, []);
307
+ if (tsIgnoreLines.length > 0) {
308
+ warnings.push(`${file}: ${tsIgnoreLines.length} @ts-ignore/@ts-nocheck in staged diff`);
309
+ }
244
310
 
245
- // Check for TODO/FIXME
246
- const todoLines = lines.reduce((acc, line, i) => {
247
- if (/\/\/\s*(TODO|FIXME|HACK|XXX)\b/i.test(line)) {
248
- acc.push(i + 1);
249
- }
250
- return acc;
251
- }, []);
252
- if (todoLines.length > 0) {
253
- warnings.push(`${file}: ${todoLines.length} TODO/FIXME comment(s) found`);
311
+ if (/\bany\b/.test(content)) {
312
+ const anyLines = lines.reduce((acc, line, i) => {
313
+ if (/\bany\b/.test(line) && !line.includes("//") && !line.includes("*")) {
314
+ acc.push(i + 1);
254
315
  }
316
+ return acc;
317
+ }, []);
318
+ if (anyLines.length > 0) {
319
+ warnings.push(`${file}: ${anyLines.length} use(s) of 'any' in staged diff`);
320
+ }
321
+ }
255
322
 
256
- // Check for @ts-ignore
257
- const tsIgnoreLines = lines.reduce((acc, line, i) => {
258
- if (/@ts-ignore|@ts-nocheck|@ts-expect-error/.test(line)) {
259
- acc.push(i + 1);
260
- }
261
- return acc;
262
- }, []);
263
- if (tsIgnoreLines.length > 0) {
264
- warnings.push(`${file}: ${tsIgnoreLines.length} @ts-ignore/@ts-nocheck found`);
265
- }
323
+ return { errors, warnings };
324
+ }
266
325
 
267
- // Check for any type
268
- if (/\bany\b/.test(content)) {
269
- const anyLines = lines.reduce((acc, line, i) => {
270
- if (/\bany\b/.test(line) && !line.includes("//") && !line.includes("*")) {
271
- acc.push(i + 1);
272
- }
273
- return acc;
274
- }, []);
275
- if (anyLines.length > 3) {
276
- warnings.push(`${file}: ${anyLines.length} uses of 'any' type`);
277
- }
278
- }
279
- } catch {
280
- // Skip unreadable files
281
- }
326
+ async function runCodexValidation(files, options = {}) {
327
+ /**
328
+ * Run lightweight codex validation on diff hunks only (staged or commit range).
329
+ */
330
+ const scope = options.scope || "staged";
331
+ const range = options.range || null;
332
+ const scopeLabel = scope === "range" && range ? `range ${range}` : "staged";
333
+ log(`Running Codex validation (diff-hunk scope: ${scopeLabel})...`);
334
+
335
+ const codexFiles = files.filter((f) => /\.(ts|tsx|js|jsx|mjs)$/.test(f));
336
+ if (codexFiles.length === 0) {
337
+ return { passed: true, warnings: [], errors: [] };
338
+ }
339
+
340
+ const addedByFile =
341
+ scope === "range" && range
342
+ ? getRangeAddedLinesByFile(codexFiles, range)
343
+ : getStagedAddedLinesByFile(codexFiles);
344
+ const errors = [];
345
+ const warnings = [];
346
+
347
+ for (const file of codexFiles) {
348
+ const addedLines = addedByFile.get(file);
349
+ if (!addedLines || addedLines.length === 0) continue;
350
+ const scan = scanAddedLinesForCodex(file, addedLines);
351
+ errors.push(...scan.errors);
352
+ warnings.push(...scan.warnings);
282
353
  }
283
354
 
284
355
  const passed = errors.length === 0;
@@ -301,8 +372,9 @@ async function runLogMaintenance() {
301
372
 
302
373
  try {
303
374
  const distDirs = [
304
- join(projectRoot, "dist"),
375
+ join(projectRoot, "node_modules", "0xray", "dist"),
305
376
  join(projectRoot, "node_modules", "xray", "dist"),
377
+ join(projectRoot, "dist"),
306
378
  ];
307
379
 
308
380
  for (const distDir of distDirs) {
@@ -310,7 +382,9 @@ async function runLogMaintenance() {
310
382
  if (!existsSync(triggerPath)) continue;
311
383
 
312
384
  try {
313
- const { archiveLogFiles, cleanupLogFiles } = await import(triggerPath);
385
+ const { archiveLogFiles, cleanupLogFiles } = await import(
386
+ pathToFileURL(triggerPath).href
387
+ );
314
388
 
315
389
  // Archive logs
316
390
  try {
@@ -375,7 +449,7 @@ async function runLogMaintenance() {
375
449
 
376
450
  // ── Comprehensive validation (pre-push) ──────────────────────
377
451
 
378
- async function runFullValidation(files) {
452
+ async function runFullValidation(files, commitRange = null) {
379
453
  /**
380
454
  * Full validation suite for pre-push.
381
455
  * Includes TypeScript check, codex validation, and test hints.
@@ -385,8 +459,11 @@ async function runFullValidation(files) {
385
459
  // TypeScript check
386
460
  const tsResult = runTypeScriptCheck(files);
387
461
 
388
- // Codex validation
389
- const codexResult = await runCodexValidation(files);
462
+ // Codex validation — commit range diff (not --cached)
463
+ const codexResult = await runCodexValidation(files, {
464
+ scope: commitRange ? "range" : "staged",
465
+ range: commitRange,
466
+ });
390
467
 
391
468
  // Check for test files
392
469
  const sourceFiles = files.filter((f) =>
@@ -466,6 +543,67 @@ async function handlePreCommit() {
466
543
  process.exit(0);
467
544
  }
468
545
 
546
+ function loadFeaturesJson() {
547
+ const featuresPath = join(projectRoot, ".xray", "features.json");
548
+ if (!existsSync(featuresPath)) return {};
549
+ try {
550
+ return JSON.parse(readFileSync(featuresPath, "utf-8"));
551
+ } catch {
552
+ return {};
553
+ }
554
+ }
555
+
556
+ function resolveXrayDistModule(relPath) {
557
+ const candidates = [
558
+ join(projectRoot, "node_modules", "0xray", "dist", relPath),
559
+ join(projectRoot, "node_modules", "xray", "dist", relPath),
560
+ join(projectRoot, "dist", relPath),
561
+ ];
562
+ return candidates.find((p) => existsSync(p)) || null;
563
+ }
564
+
565
+ async function runSessionInferenceCapture() {
566
+ const features = loadFeaturesJson();
567
+ const cfg = features.inference_session_capture ?? {};
568
+ if (cfg.enabled !== true) {
569
+ log("Session inference capture disabled");
570
+ return;
571
+ }
572
+
573
+ const modulePath = resolveXrayDistModule("inference/session-capture.js");
574
+ if (!modulePath) {
575
+ log("Session capture module missing (node_modules/0xray/dist or dist)");
576
+ return;
577
+ }
578
+
579
+ const minCommits = typeof cfg.min_commits === "number" && cfg.min_commits > 0
580
+ ? cfg.min_commits
581
+ : 3;
582
+ const lookback = typeof cfg.lookback_commits === "number" && cfg.lookback_commits > 0
583
+ ? cfg.lookback_commits
584
+ : 20;
585
+
586
+ try {
587
+ const mod = await import(pathToFileURL(modulePath).href);
588
+ const inference = mod.captureSessionInference(`HEAD~${lookback}`, "HEAD");
589
+ if (!inference) {
590
+ log("Session capture: no commits in span");
591
+ return;
592
+ }
593
+ if ((inference.metrics?.commits ?? 0) < minCommits) {
594
+ log(
595
+ `Session capture: ${inference.metrics?.commits ?? 0} commits < min ${minCommits}`,
596
+ );
597
+ return;
598
+ }
599
+ const outDir = join(projectRoot, "docs", "inference");
600
+ const saved = mod.saveSessionInference(inference, outDir);
601
+ log(`Session capture saved ${saved}`);
602
+ } catch (err) {
603
+ logError(`Session capture failed: ${err.message}`);
604
+ }
605
+ }
606
+
469
607
  async function handlePostCommit() {
470
608
  const commitSha = process.env.COMMIT_SHA || "unknown";
471
609
  const branch = process.env.BRANCH || "unknown";
@@ -474,6 +612,7 @@ async function handlePostCommit() {
474
612
 
475
613
  // Run log maintenance
476
614
  await runLogMaintenance();
615
+ await runSessionInferenceCapture();
477
616
 
478
617
  // Record metrics
479
618
  recordMetrics(0, 0);
@@ -487,15 +626,20 @@ async function handlePrePush() {
487
626
  .split("\n")
488
627
  .map((f) => f.trim())
489
628
  .filter(Boolean);
629
+ const commitRange = (process.env.COMMIT_RANGE || "").trim() || null;
490
630
 
491
631
  if (changedFiles.length === 0) {
492
632
  log("No changed files to validate");
493
633
  process.exit(0);
494
634
  }
495
635
 
496
- log(`Validating ${changedFiles.length} changed file(s) for push...`);
636
+ log(
637
+ `Validating ${changedFiles.length} changed file(s) for push` +
638
+ (commitRange ? ` (range ${commitRange})` : "") +
639
+ "...",
640
+ );
497
641
 
498
- const result = await runFullValidation(changedFiles);
642
+ const result = await runFullValidation(changedFiles, commitRange);
499
643
 
500
644
  if (!result.passed) {
501
645
  console.error("\n❌ Pre-push validation failed:\n");
@@ -586,22 +730,27 @@ const handlers = {
586
730
  "pre-command": handlePreCommand,
587
731
  };
588
732
 
589
- const handler = handlers[hookType];
590
- if (!handler) {
591
- console.error(`Unknown hook type: ${hookType}`);
592
- console.error(`Valid types: ${Object.keys(handlers).join(", ")}`);
593
- process.exit(1);
594
- }
733
+ const isDirectRun =
734
+ process.argv[1] &&
735
+ resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url));
595
736
 
596
- // Run with timing
597
- const startTime = Date.now();
598
- handler()
599
- .then(() => {
600
- const duration = Date.now() - startTime;
601
- log(`Hook completed in ${duration}ms`);
602
- })
603
- .catch((err) => {
604
- logError(`Hook crashed: ${err.message}`);
605
- console.error(`0xRay hook error: ${err.message}`);
737
+ if (isDirectRun) {
738
+ const handler = handlers[hookType];
739
+ if (!handler) {
740
+ console.error(`Unknown hook type: ${hookType}`);
741
+ console.error(`Valid types: ${Object.keys(handlers).join(", ")}`);
606
742
  process.exit(1);
607
- });
743
+ }
744
+
745
+ const startTime = Date.now();
746
+ handler()
747
+ .then(() => {
748
+ const duration = Date.now() - startTime;
749
+ log(`Hook completed in ${duration}ms`);
750
+ })
751
+ .catch((err) => {
752
+ logError(`Hook crashed: ${err.message}`);
753
+ console.error(`0xRay hook error: ${err.message}`);
754
+ process.exit(1);
755
+ });
756
+ }
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CWD-proof Repertoire MCP launcher for the 0xray framework checkout.
4
+ * Grok/OpenCode spawn this in-repo path so they never have to resolve `../repertoire`.
5
+ */
6
+ import { spawn } from 'node:child_process';
7
+ import { existsSync } from 'node:fs';
8
+ import { dirname, join } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+
11
+ const xrayRoot = join(dirname(fileURLToPath(import.meta.url)), '../..');
12
+ const candidates = [
13
+ join(xrayRoot, 'node_modules', '@0xray', 'repertoire', 'dist', 'mcp', 'server.js'),
14
+ join(xrayRoot, 'vendor', '@0xray', 'repertoire', 'dist', 'mcp', 'server.js'),
15
+ join(xrayRoot, '..', 'repertoire', 'dist', 'mcp', 'server.js'),
16
+ ];
17
+ const server = candidates.find((p) => existsSync(p));
18
+ if (!server) {
19
+ process.stderr.write(
20
+ 'repertoire MCP missing — build ../repertoire or install @0xray/repertoire\n',
21
+ );
22
+ process.exit(1);
23
+ }
24
+
25
+ const child = spawn(process.execPath, [server], {
26
+ stdio: 'inherit',
27
+ env: process.env,
28
+ });
29
+ child.on('error', (err) => {
30
+ process.stderr.write(`repertoire MCP spawn failed: ${err.message}\n`);
31
+ process.exit(1);
32
+ });
33
+ child.on('exit', (code, signal) => {
34
+ if (signal) {
35
+ process.kill(process.pid, signal);
36
+ return;
37
+ }
38
+ process.exit(code ?? 1);
39
+ });