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
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Multi-host delegation gate SSOT — pending-delegations + spawn todo enforcement.
3
3
  * Grok / Hermes / OpenCode adapters call evaluatePreToolGate via delegation-gate-runtime.
4
- * Grok-only codex/surface checks remain in pre-tool-use.js after the SSOT gate.
4
+ * Constitution (11/29/69 + destructive shell) lives here. Grok may still extra-block Codex 2/7.
5
5
  */
6
6
  import * as fs from 'fs';
7
7
  import * as path from 'path';
@@ -13,6 +13,8 @@ import { isSynthesisConsultTodoId, tryRecordSynthesisConsultReceipt, } from './s
13
13
  import { resolveSpawnPlan, hasValidSpawnPlanContext } from './spawn-plan-resolution.js';
14
14
  import { isUserAsidesEnabled, isUserAsideTodoId, loadActiveAsidePointer, loadActiveUserAside, } from './user-aside.js';
15
15
  import { validateAsideWorktreeCwd, } from './aside-worktree.js';
16
+ import { ceremonyForProfile, resolveSuitProfile, spawnPlanModeForProfile, writeSuitSessionBoot, maybeHeatHostStation, } from './suit-temperament.js';
17
+ export { writeSuitSessionBoot, maybeHeatHostStation };
16
18
  export { extractSpawnCwd, validateAsideWorktreeCwd, provisionGitWorktree } from './aside-worktree.js';
17
19
  function denyAsideWorktreeCwd(cwdCheck) {
18
20
  const base = {
@@ -30,7 +32,7 @@ function asideWorktreeCwdDenyIfNeeded(activeAside, toolInput, projectRoot) {
30
32
  return denyAsideWorktreeCwd(cwdCheck);
31
33
  return undefined;
32
34
  }
33
- export { validateSpawnMatchesTodo, updatePlanTodoStatus, savePersistedLeadDevPlan, } from './lead-dev-plan-persistence.js';
35
+ export { validateSpawnMatchesTodo, updatePlanTodoStatus, savePersistedLeadDevPlan, archiveStaleLeadDevPlan, findRecentStalePlanArchive, } from './lead-dev-plan-persistence.js';
34
36
  export { buildReceiptFromConsultOutput, hasValidSynthesisConsultReceipt, isSynthesisConsultTodoId, loadSynthesisConsultReceipt, parseConsultVerdictFromText, tryRecordSynthesisConsultReceipt, writeSynthesisConsultReceipt, } from './synthesis-consult-receipt.js';
35
37
  export const updatePlanTodoStatusInPlace = updatePlanTodoStatus;
36
38
  const READ_TOOLS = new Set([
@@ -69,21 +71,34 @@ const SYNTHESIS_ALLOWED_CONSULT_TOOLS = new Set([
69
71
  ]);
70
72
  const HERMES_WRITE_TOOLS = new Set(['write_file', 'patch', 'write', 'edit']);
71
73
  const OPENCODE_WRITE_TOOLS = new Set(['write', 'edit', 'multiedit']);
72
- export function loadDelegationGateFeatures(projectRoot = process.cwd()) {
74
+ export function loadDelegationGateFeatures(projectRoot = process.cwd(), host = 'generic') {
75
+ const fallback = (profile) => ({
76
+ lead_dev_mode: true,
77
+ auto_chain_delegations: true,
78
+ spawn_plan_mode: spawnPlanModeForProfile(profile),
79
+ ceremony: ceremonyForProfile(profile),
80
+ suit_profile: profile,
81
+ no_new_surface: true,
82
+ });
73
83
  const featuresPath = path.join(projectRoot, '.xray', 'features.json');
74
84
  if (!fs.existsSync(featuresPath)) {
75
- return { lead_dev_mode: true, auto_chain_delegations: true };
85
+ return fallback(resolveSuitProfile(undefined, host));
76
86
  }
77
87
  try {
78
88
  const data = JSON.parse(fs.readFileSync(featuresPath, 'utf8'));
79
89
  const orch = data.multi_agent_orchestration ?? {};
90
+ const profile = resolveSuitProfile(data.suit_temperament, host);
80
91
  return {
81
92
  lead_dev_mode: orch.enabled !== false && orch.lead_dev_mode !== false,
82
93
  auto_chain_delegations: orch.auto_chain_delegations !== false,
94
+ spawn_plan_mode: spawnPlanModeForProfile(profile),
95
+ ceremony: ceremonyForProfile(profile),
96
+ suit_profile: profile,
97
+ no_new_surface: profile === 'strict' ? true : orch.no_new_surface !== false,
83
98
  };
84
99
  }
85
100
  catch {
86
- return { lead_dev_mode: true, auto_chain_delegations: true };
101
+ return fallback(resolveSuitProfile(undefined, host));
87
102
  }
88
103
  }
89
104
  export function normalizeHostToolInput(toolInput) {
@@ -197,40 +212,53 @@ function denyFromPending(primary, pendingCount) {
197
212
  delegationId: primary.id,
198
213
  };
199
214
  }
215
+ function spawnPlanSoftAllow(gate, reason) {
216
+ return { allow: true, reason, gate };
217
+ }
200
218
  /** Spawn plan missing — applies before auto_chain opt-out for subagent tools. */
201
219
  export function evaluateSpawnPlanGate(toolName, toolInput, ctx) {
202
220
  if (!ctx.features.lead_dev_mode || !isSubagentTool(toolName)) {
203
221
  return { allow: true };
204
222
  }
223
+ const spawnMode = ctx.features.spawn_plan_mode ?? 'deny';
224
+ if (spawnMode === 'off') {
225
+ return { allow: true };
226
+ }
205
227
  const activeAside = isUserAsidesEnabled(ctx.projectRoot)
206
228
  ? loadActiveUserAside(ctx.projectRoot, ctx.sessionId)
207
229
  : null;
208
230
  const plan = loadPersistedLeadDevPlan(ctx.projectRoot);
209
231
  if (!activeAside && plan && isLeadDevPlanStale(plan, ctx.projectRoot)) {
210
- return {
211
- allow: false,
232
+ const stale = {
212
233
  reason: 'Lead-dev plan is stale (unstarted todos exceeded TTL) — ' +
213
234
  're-run xray-orchestrator analyze-complexity to refresh the plan',
214
235
  gate: 'spawn-plan-stale',
215
236
  hint: { tool: 'analyze-complexity', mcp: 'xray-orchestrator' },
216
237
  };
238
+ if (spawnMode === 'warn')
239
+ return spawnPlanSoftAllow(stale.gate, stale.reason);
240
+ return { allow: false, ...stale };
217
241
  }
218
242
  if (!hasValidSpawnPlanContext(ctx.projectRoot, ctx.sessionId)) {
219
243
  if (findRecentStalePlanArchive(ctx.projectRoot)) {
220
- return {
221
- allow: false,
244
+ const archived = {
222
245
  reason: 'Lead-dev plan was stale and archived — ' +
223
246
  're-run xray-orchestrator analyze-complexity to refresh the plan',
224
247
  gate: 'spawn-plan-stale',
225
248
  hint: { tool: 'analyze-complexity', mcp: 'xray-orchestrator' },
226
249
  };
250
+ if (spawnMode === 'warn')
251
+ return spawnPlanSoftAllow(archived.gate, archived.reason);
252
+ return { allow: false, ...archived };
227
253
  }
228
- return {
229
- allow: false,
254
+ const missing = {
230
255
  reason: 'Codex 59/67: call xray-orchestrator analyze-complexity first — ' +
231
256
  'writes .xray/state/lead-dev-plan.json required before spawn_subagent',
232
257
  gate: 'spawn-plan-missing',
233
258
  };
259
+ if (spawnMode === 'warn')
260
+ return spawnPlanSoftAllow(missing.gate, missing.reason);
261
+ return { allow: false, ...missing };
234
262
  }
235
263
  if (ctx.features.auto_chain_delegations === false) {
236
264
  const cwdDeny = asideWorktreeCwdDenyIfNeeded(activeAside, toolInput, ctx.projectRoot);
@@ -246,13 +274,16 @@ export function evaluateSpawnPlanGate(toolName, toolInput, ctx) {
246
274
  const expectedTodo = pending[0]?.planTodoId && resolved.plan
247
275
  ? allPlanTodos(resolved.plan).find((t) => t.id === pending[0].planTodoId) ?? null
248
276
  : null;
277
+ const cwdDeny = asideWorktreeCwdDenyIfNeeded(activeAside, toolInput, ctx.projectRoot);
278
+ if (cwdDeny)
279
+ return cwdDeny;
249
280
  const validation = validateSpawnMatchesTodo(normalized, ctx.projectRoot, expectedTodo, ctx.sessionId);
250
281
  if (!validation.valid) {
282
+ if (spawnMode === 'warn') {
283
+ return spawnPlanSoftAllow(validation.gate ?? 'spawn-todo-persistence', validation.reason ?? 'Spawn did not match lead-dev plan todo (frontier: warn, not deny)');
284
+ }
251
285
  return denyFromSpawnValidation(validation);
252
286
  }
253
- const cwdDeny = asideWorktreeCwdDenyIfNeeded(activeAside, toolInput, ctx.projectRoot);
254
- if (cwdDeny)
255
- return cwdDeny;
256
287
  return { allow: true };
257
288
  }
258
289
  /** Block writes / spawns / shell while synthesis checkpoint is due. */
@@ -346,8 +377,110 @@ export function evaluatePendingDelegationGate(toolName, toolInput, ctx) {
346
377
  * Full pre-tool evaluation — synthesis gate first, slice recording, then
347
378
  * pending gate, then spawn todo gate for subagent tools.
348
379
  */
380
+ const CONSTITUTION_ANY = /:\s*any\b|as\s+any\b/;
381
+ const CONSTITUTION_TS_IGNORE = /@ts-ignore|@ts-expect-error/;
382
+ const CONSTITUTION_EVAL = /\beval\s*\(/;
383
+ const CONSTITUTION_DESTRUCTIVE = /\brm\s+-rf\s+\/(?:\s|$)|\bmkfs\b|\bdd\s+if=|:()\s*\{\s*:\|&\s*\}\s*;:/i;
384
+ const SURFACE_DENY = [
385
+ /(?:^|\/)src\/mcps\/[^/]+\.server\.(ts|js)$/i,
386
+ /(?:^|\/)src\/skills\/[^/]+\/SKILL\.md$/i,
387
+ /(?:^|\/)src\/mcps\/orchestrator\/handlers\/[^/]+-handler\.(ts|js)$/i,
388
+ /(?:^|\/)src\/nucleus\/autonomy-kernel\.(ts|js)$/i,
389
+ /(?:^|\/)src\/mcps\/[^/]+\/handlers\/autonomy-handler\.(ts|js)$/i,
390
+ ];
391
+ function collectWriteContent(toolInput) {
392
+ return [
393
+ toolInput.new_string,
394
+ toolInput.contents,
395
+ toolInput.content,
396
+ toolInput.command,
397
+ toolInput.prompt,
398
+ ]
399
+ .filter((v) => v != null)
400
+ .map(String)
401
+ .join('\n');
402
+ }
403
+ function collectWritePaths(toolInput) {
404
+ const paths = [];
405
+ for (const key of ['path', 'file_path', 'filePath', 'target_notebook']) {
406
+ const v = toolInput[key];
407
+ if (typeof v === 'string' && v)
408
+ paths.push(v);
409
+ }
410
+ const extra = toolInput.paths;
411
+ if (Array.isArray(extra)) {
412
+ for (const p of extra) {
413
+ if (typeof p === 'string' && p)
414
+ paths.push(p);
415
+ }
416
+ }
417
+ return paths;
418
+ }
419
+ /** Codex 11 / 29 / 69 + destructive shell — always on, all hosts that call this SSOT. */
420
+ export function evaluateConstitutionGate(toolName, toolInput, ctx) {
421
+ const content = collectWriteContent(toolInput);
422
+ const paths = collectWritePaths(toolInput);
423
+ const writing = isWriteTool(toolName, ctx.host ?? 'generic');
424
+ if (writing && ctx.features.no_new_surface !== false) {
425
+ for (const p of paths) {
426
+ const normalized = p.replace(/\\/g, '/');
427
+ const abs = path.isAbsolute(p) ? p : path.join(ctx.projectRoot, p);
428
+ if (fs.existsSync(abs))
429
+ continue;
430
+ if (SURFACE_DENY.some((re) => re.test(normalized))) {
431
+ return {
432
+ allow: false,
433
+ reason: 'Codex 69: new MCP/skill/handler surface — rewire existing',
434
+ gate: 'no-new-surface',
435
+ };
436
+ }
437
+ }
438
+ }
439
+ if (writing && content) {
440
+ if (CONSTITUTION_ANY.test(content) || CONSTITUTION_TS_IGNORE.test(content)) {
441
+ return {
442
+ allow: false,
443
+ reason: 'Codex 11 Type Safety: no `any` / @ts-ignore / @ts-expect-error',
444
+ gate: 'codex-11',
445
+ };
446
+ }
447
+ if (CONSTITUTION_EVAL.test(content)) {
448
+ return {
449
+ allow: false,
450
+ reason: 'Codex 29 Security: eval() prohibited',
451
+ gate: 'codex-29',
452
+ };
453
+ }
454
+ }
455
+ if (isShellTool(toolName) && CONSTITUTION_DESTRUCTIVE.test(String(toolInput.command ?? ''))) {
456
+ return {
457
+ allow: false,
458
+ reason: 'Blocked destructive shell command',
459
+ gate: 'destructive-shell',
460
+ };
461
+ }
462
+ return { allow: true };
463
+ }
349
464
  export function evaluatePreToolGate(toolName, toolInput, ctx) {
350
- const synthesisBlock = evaluateSynthesisGate(toolName, toolInput, ctx);
465
+ if (ctx.host === 'openclaw') {
466
+ try {
467
+ maybeHeatHostStation(ctx.projectRoot, 'openclaw', {
468
+ source: '0xray/openclaw-pre-tool',
469
+ sessionId: ctx.sessionId || 'openclaw',
470
+ hookEvent: ctx.hookEvent || 'session_start',
471
+ });
472
+ }
473
+ catch {
474
+ /* station heat is best-effort — constitution still runs */
475
+ }
476
+ }
477
+ const constitution = evaluateConstitutionGate(toolName, toolInput, ctx);
478
+ if (!constitution.allow)
479
+ return constitution;
480
+ const lite = ctx.features.ceremony === 'lite';
481
+ const synthesisBlock = lite
482
+ ? { allow: true }
483
+ : evaluateSynthesisGate(toolName, toolInput, ctx);
351
484
  if (!synthesisBlock.allow)
352
485
  return synthesisBlock;
353
486
  if (!isSynthesisCheckpointDue(ctx.projectRoot, ctx.sessionId)) {
@@ -356,7 +489,9 @@ export function evaluatePreToolGate(toolName, toolInput, ctx) {
356
489
  sessionId: ctx.sessionId,
357
490
  });
358
491
  }
359
- const pendingBlock = evaluatePendingDelegationGate(toolName, toolInput, ctx);
492
+ const pendingBlock = lite
493
+ ? { allow: true }
494
+ : evaluatePendingDelegationGate(toolName, toolInput, ctx);
360
495
  if (!pendingBlock.allow)
361
496
  return pendingBlock;
362
497
  const spawnBlock = evaluateSpawnPlanGate(toolName, toolInput, ctx);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * 0xRay 4.0 suit temperament — how loudly the Autonomous Engine insists.
3
+ *
4
+ * v2 three-subsystem OS stays: Inference · External Governance · Autonomous Engine.
5
+ * This module does not replace thinDispatch or Codex. It only scales *ceremony*
6
+ * (spawn-plan deny, synthesis, confer) by host strength.
7
+ *
8
+ * Frontier (Grok 4.6 / Grok Build): engine available, spawn warns if no plan.
9
+ * Guided (OpenCode / Hermes / OpenClaw, including free models): full v2 ceremony.
10
+ * Missing config → guided (existing consumers unchanged).
11
+ */
12
+ export type SuitHost = 'grok' | 'hermes' | 'opencode' | 'openclaw' | 'generic';
13
+ export type SuitProfile = 'frontier' | 'guided' | 'strict';
14
+ export type SuitProfileOrAuto = 'auto' | SuitProfile;
15
+ export type CeremonyLevel = 'full' | 'lite';
16
+ export type SpawnPlanMode = 'deny' | 'warn' | 'off';
17
+ export interface SuitTemperamentConfig {
18
+ /** auto = pick from host_defaults */
19
+ profile?: SuitProfileOrAuto;
20
+ host_defaults?: Partial<Record<SuitHost, SuitProfile>>;
21
+ }
22
+ export declare const DEFAULT_HOST_PROFILES: Record<SuitHost, SuitProfile>;
23
+ export declare function loadSuitTemperamentRaw(projectRoot: string): SuitTemperamentConfig | undefined;
24
+ export declare function resolveSuitProfile(raw: SuitTemperamentConfig | undefined, host: SuitHost): SuitProfile;
25
+ /**
26
+ * Host-aware when known. Kernel/MCP (`generic`) uses last session-boot profile.
27
+ * A Hermes/OpenCode host ignores a leftover Grok boot (and vice versa).
28
+ */
29
+ export declare function resolveRuntimeSuitProfile(projectRoot: string, host?: SuitHost): SuitProfile;
30
+ /**
31
+ * Write station heat when this host/session has no live card yet.
32
+ * OpenClaw has no SessionStart — PreToolUse is the session boundary.
33
+ * Install/init cards without a session id are not a live session.
34
+ */
35
+ export declare function maybeHeatHostStation(projectRoot: string, host: SuitHost, extra?: Record<string, unknown>): string | null;
36
+ /** Merge temperament fields into session-boot.json for the host that just started. */
37
+ export declare function writeSuitSessionBoot(projectRoot: string, host: SuitHost, extra?: Record<string, unknown>): string;
38
+ export declare function ceremonyForProfile(profile: SuitProfile): CeremonyLevel;
39
+ export declare function spawnPlanModeForProfile(profile: SuitProfile): SpawnPlanMode;
40
+ export declare function conferDefaultForProfile(profile: SuitProfile): boolean;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * 0xRay 4.0 suit temperament — how loudly the Autonomous Engine insists.
3
+ *
4
+ * v2 three-subsystem OS stays: Inference · External Governance · Autonomous Engine.
5
+ * This module does not replace thinDispatch or Codex. It only scales *ceremony*
6
+ * (spawn-plan deny, synthesis, confer) by host strength.
7
+ *
8
+ * Frontier (Grok 4.6 / Grok Build): engine available, spawn warns if no plan.
9
+ * Guided (OpenCode / Hermes / OpenClaw, including free models): full v2 ceremony.
10
+ * Missing config → guided (existing consumers unchanged).
11
+ */
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+ import { createRequire } from 'node:module';
15
+ const requireCjs = createRequire(import.meta.url);
16
+ const stationHeat = requireCjs('../integrations/hooks/station-hook-runtime.cjs');
17
+ export const DEFAULT_HOST_PROFILES = {
18
+ grok: 'frontier',
19
+ hermes: 'guided',
20
+ opencode: 'guided',
21
+ openclaw: 'guided',
22
+ generic: 'guided',
23
+ };
24
+ function isSuitProfile(value) {
25
+ return value === 'frontier' || value === 'guided' || value === 'strict';
26
+ }
27
+ export function loadSuitTemperamentRaw(projectRoot) {
28
+ const featuresPath = path.join(projectRoot, '.xray', 'features.json');
29
+ if (!fs.existsSync(featuresPath))
30
+ return undefined;
31
+ try {
32
+ const data = JSON.parse(fs.readFileSync(featuresPath, 'utf8'));
33
+ return data.suit_temperament;
34
+ }
35
+ catch {
36
+ return undefined;
37
+ }
38
+ }
39
+ function isSuitHost(value) {
40
+ return (value === 'grok' ||
41
+ value === 'hermes' ||
42
+ value === 'opencode' ||
43
+ value === 'openclaw' ||
44
+ value === 'generic');
45
+ }
46
+ function readSessionBoot(projectRoot) {
47
+ try {
48
+ const bootPath = path.join(projectRoot, '.xray', 'state', 'session-boot.json');
49
+ if (!fs.existsSync(bootPath))
50
+ return null;
51
+ const boot = JSON.parse(fs.readFileSync(bootPath, 'utf8'));
52
+ return {
53
+ host: isSuitHost(boot.host) ? boot.host : null,
54
+ suit_profile: isSuitProfile(boot.suit_profile) ? boot.suit_profile : null,
55
+ };
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ export function resolveSuitProfile(raw, host) {
62
+ // No key / empty object without profile → guided (existing consumers).
63
+ if (!raw || !raw.profile)
64
+ return 'guided';
65
+ if (raw.profile !== 'auto') {
66
+ return raw.profile;
67
+ }
68
+ const defaults = {
69
+ ...DEFAULT_HOST_PROFILES,
70
+ ...(raw.host_defaults ?? {}),
71
+ };
72
+ return defaults[host] ?? 'guided';
73
+ }
74
+ /**
75
+ * Host-aware when known. Kernel/MCP (`generic`) uses last session-boot profile.
76
+ * A Hermes/OpenCode host ignores a leftover Grok boot (and vice versa).
77
+ */
78
+ export function resolveRuntimeSuitProfile(projectRoot, host = 'generic') {
79
+ const raw = loadSuitTemperamentRaw(projectRoot);
80
+ const boot = readSessionBoot(projectRoot);
81
+ if (raw?.profile === 'auto' && boot?.suit_profile) {
82
+ if (host === 'generic' || boot.host == null || boot.host === host) {
83
+ return boot.suit_profile;
84
+ }
85
+ }
86
+ return resolveSuitProfile(raw, host);
87
+ }
88
+ function concreteSessionId(value) {
89
+ return typeof value === 'string' && value.length > 0 ? value : null;
90
+ }
91
+ /**
92
+ * Write station heat when this host/session has no live card yet.
93
+ * OpenClaw has no SessionStart — PreToolUse is the session boundary.
94
+ * Install/init cards without a session id are not a live session.
95
+ */
96
+ export function maybeHeatHostStation(projectRoot, host, extra = {}) {
97
+ const bootPath = path.join(projectRoot, '.xray', 'state', 'session-boot.json');
98
+ const cardPath = path.join(projectRoot, '.xray', 'state', 'STATION.md');
99
+ let existing = {};
100
+ if (fs.existsSync(bootPath)) {
101
+ try {
102
+ existing = JSON.parse(fs.readFileSync(bootPath, 'utf8'));
103
+ }
104
+ catch {
105
+ existing = {};
106
+ }
107
+ }
108
+ const sessionId = concreteSessionId(extra.sessionId);
109
+ const existingSessionId = concreteSessionId(existing.sessionId);
110
+ const sameHost = existing.host === host;
111
+ const sameSession = existingSessionId !== null && sessionId !== null && existingSessionId === sessionId;
112
+ if (sameHost && sameSession && fs.existsSync(cardPath)) {
113
+ return bootPath;
114
+ }
115
+ return writeSuitSessionBoot(projectRoot, host, extra);
116
+ }
117
+ /** Merge temperament fields into session-boot.json for the host that just started. */
118
+ export function writeSuitSessionBoot(projectRoot, host, extra = {}) {
119
+ const profile = resolveSuitProfile(loadSuitTemperamentRaw(projectRoot), host);
120
+ const stateDir = path.join(projectRoot, '.xray', 'state');
121
+ fs.mkdirSync(stateDir, { recursive: true });
122
+ const bootPath = path.join(stateDir, 'session-boot.json');
123
+ let existing = {};
124
+ if (fs.existsSync(bootPath)) {
125
+ try {
126
+ existing = JSON.parse(fs.readFileSync(bootPath, 'utf8'));
127
+ }
128
+ catch {
129
+ existing = {};
130
+ }
131
+ }
132
+ const heat = stationHeat.applyStationHeat(projectRoot, host, extra, existing);
133
+ const payload = {
134
+ ...existing,
135
+ ...extra,
136
+ ...heat,
137
+ host,
138
+ suit_profile: profile,
139
+ ceremony: ceremonyForProfile(profile),
140
+ spawn_plan_mode: spawnPlanModeForProfile(profile),
141
+ timestamp: new Date().toISOString(),
142
+ };
143
+ fs.writeFileSync(bootPath, JSON.stringify(payload, null, 2));
144
+ stationHeat.writeStationMarkdown(projectRoot, payload);
145
+ return bootPath;
146
+ }
147
+ export function ceremonyForProfile(profile) {
148
+ return profile === 'frontier' ? 'lite' : 'full';
149
+ }
150
+ export function spawnPlanModeForProfile(profile) {
151
+ if (profile === 'frontier')
152
+ return 'warn';
153
+ return 'deny';
154
+ }
155
+ export function conferDefaultForProfile(profile) {
156
+ return profile !== 'frontier';
157
+ }
@@ -119,7 +119,7 @@ export function buildUserAsidePlan(asideId, title, description, taskInputs = [],
119
119
  return null;
120
120
  const safeId = assertSafeAsideId(asideId);
121
121
  const taskTypes = taskInputs.map((t) => t.type ?? 'implement');
122
- const basePlan = buildLeadDevPlan(description, taskTypes, taskInputs, mcpOverallComplexity);
122
+ const basePlan = buildLeadDevPlan(description, taskTypes, taskInputs, mcpOverallComplexity, projectRoot);
123
123
  if (!basePlan)
124
124
  return null;
125
125
  return {
@@ -7,7 +7,7 @@ import { getOrCreateLogger } from "./plugin-logger.js";
7
7
  import { resolveStateDir, importSystemPromptGenerator, loadXrayComponents, getProcessorManager, getXrayStateManager, getFeaturesConfigLoader, getDetectTaskType, getSystemPromptGenerator, } from "./plugin-modules.js";
8
8
  import { getFrameworkIdentity, classifyTaskType, isWriteEditOperation, isPublishOperation, resolveAgentName, registerAllProcessors, registerAfterPostProcessors, logPreProcessorResults, logPostProcessorResults, logTestAutoCreationResult, spawnPromise, } from "./plugin-helpers.js";
9
9
  import { runEnforcerQualityGate } from "./plugin-quality-gate.js";
10
- import { evaluatePostToolSpawn, evaluatePreToolGate, isSubagentTool, loadDelegationGateFeatures, } from "../nucleus/delegation-gate.js";
10
+ import { evaluatePostToolSpawn, evaluatePreToolGate, isSubagentTool, loadDelegationGateFeatures, writeSuitSessionBoot, } from "../nucleus/delegation-gate.js";
11
11
  import { readFileSync } from "fs";
12
12
  import { join } from "path";
13
13
  // Re-export all public API for test compatibility
@@ -23,6 +23,15 @@ let _lastTuneToolCallCount = 0;
23
23
  export default async function xrayCodexPlugin(input) {
24
24
  const { directory: inputDirectory } = input;
25
25
  const directory = inputDirectory || process.cwd();
26
+ try {
27
+ writeSuitSessionBoot(directory, "opencode", {
28
+ source: "0xray/opencode-plugin",
29
+ hookEvent: process.env.XRAY_HOOK_EVENT || "session_start",
30
+ });
31
+ }
32
+ catch {
33
+ /* session-boot is best-effort */
34
+ }
26
35
  return {
27
36
  "experimental.chat.system.transform": async (_input, output) => {
28
37
  try {
@@ -40,7 +49,9 @@ export default async function xrayCodexPlugin(input) {
40
49
  });
41
50
  }
42
51
  if (output.system && Array.isArray(output.system)) {
43
- output.system = [leanPrompt];
52
+ const cardPath = path.join(directory, ".xray", "state", "STATION.md");
53
+ const card = fs.existsSync(cardPath) ? fs.readFileSync(cardPath, "utf8").trim() : "";
54
+ output.system = card ? [leanPrompt, card] : [leanPrompt];
44
55
  }
45
56
  }
46
57
  catch (error) {
@@ -84,7 +95,7 @@ export default async function xrayCodexPlugin(input) {
84
95
  throw new Error(`ENFORCER BLOCKED: ${qualityGateResult.violations.join("; ")}`);
85
96
  }
86
97
  logger.log(`✅ Quality gate passed for ${tool}`);
87
- const features = loadDelegationGateFeatures(directory);
98
+ const features = loadDelegationGateFeatures(directory, "opencode");
88
99
  let sessionId = process.env.GROK_SESSION_ID ?? null;
89
100
  try {
90
101
  const boot = JSON.parse(readFileSync(join(directory, ".xray", "state", "session-boot.json"), "utf8"));
@@ -397,10 +397,16 @@ fi
397
397
  (async () => {
398
398
  try {
399
399
  // Use dynamic import that works in both dev and consumer
400
- const basePath = process.env.XRAY_BASE_PATH || '.';
401
- const distPath = process.env.XRAY_DIST_PATH || 'dist';
402
- // First archive logs (compress and rotate) before cleanup
403
- const { archiveLogFiles } = await import(basePath + '/' + distPath + '/postprocessor/triggers/GitHookTrigger.js');
400
+ const { pathToFileURL } = await import('url');
401
+ const { existsSync } = await import('fs');
402
+ const { join } = await import('path');
403
+ const candidates = [
404
+ join(process.cwd(), 'node_modules/0xray/dist/postprocessor/triggers/GitHookTrigger.js'),
405
+ join(process.cwd(), 'dist/postprocessor/triggers/GitHookTrigger.js'),
406
+ ];
407
+ const triggerPath = candidates.find((p) => existsSync(p));
408
+ if (!triggerPath) return;
409
+ const { archiveLogFiles } = await import(pathToFileURL(triggerPath).href);
404
410
  const archiveResult = await archiveLogFiles({
405
411
  archiveDirectory: 'logs/framework',
406
412
  maxFileSizeMB: 10, // Archive if > 10MB
@@ -415,7 +421,7 @@ fi
415
421
  }
416
422
 
417
423
  // Then cleanup old files
418
- const { cleanupLogFiles } = await import(basePath + '/' + distPath + '/postprocessor/triggers/GitHookTrigger.js');
424
+ const { cleanupLogFiles } = await import(pathToFileURL(triggerPath).href);
419
425
  const result = await cleanupLogFiles({
420
426
  maxAgeHours: 24,
421
427
  excludePatterns: [
package/opencode.json CHANGED
@@ -16,6 +16,94 @@
16
16
  },
17
17
  "global-git": {
18
18
  "enabled": false
19
+ },
20
+ "xray-governance": {
21
+ "type": "local",
22
+ "command": [
23
+ "npx",
24
+ "-y",
25
+ "0xray",
26
+ "mcp",
27
+ "governance"
28
+ ],
29
+ "enabled": true,
30
+ "environment": {
31
+ "XRAY_FORCE_MCP_GOVERNANCE": "true"
32
+ }
33
+ },
34
+ "xray-skills": {
35
+ "type": "local",
36
+ "command": [
37
+ "npx",
38
+ "-y",
39
+ "0xray",
40
+ "mcp",
41
+ "skills"
42
+ ],
43
+ "enabled": true
44
+ },
45
+ "xray-orchestrator": {
46
+ "type": "local",
47
+ "command": [
48
+ "npx",
49
+ "-y",
50
+ "0xray",
51
+ "mcp",
52
+ "orchestrator"
53
+ ],
54
+ "enabled": true
55
+ },
56
+ "xray-enforcer": {
57
+ "type": "local",
58
+ "command": [
59
+ "npx",
60
+ "-y",
61
+ "0xray",
62
+ "mcp",
63
+ "enforcer"
64
+ ],
65
+ "enabled": true
66
+ },
67
+ "xray-researcher": {
68
+ "type": "local",
69
+ "command": [
70
+ "npx",
71
+ "-y",
72
+ "0xray",
73
+ "mcp",
74
+ "researcher"
75
+ ],
76
+ "enabled": true
77
+ },
78
+ "xray-code-review": {
79
+ "type": "local",
80
+ "command": [
81
+ "npx",
82
+ "-y",
83
+ "0xray",
84
+ "mcp",
85
+ "code-review"
86
+ ],
87
+ "enabled": true
88
+ },
89
+ "xray-architect-tools": {
90
+ "type": "local",
91
+ "command": [
92
+ "npx",
93
+ "-y",
94
+ "0xray",
95
+ "mcp",
96
+ "architect-tools"
97
+ ],
98
+ "enabled": true
99
+ },
100
+ "repertoire": {
101
+ "type": "local",
102
+ "command": [
103
+ "node",
104
+ "/tmp/xray-v4-validate/node_modules/@0xray/repertoire/dist/mcp/server.js"
105
+ ],
106
+ "enabled": true
19
107
  }
20
108
  },
21
109
  "agent": {