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
@@ -1,16 +1,38 @@
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';
8
8
  import { getActivePendingDelegations, satisfyDelegation, } from './pending-delegations.js';
9
9
  export { getActivePendingDelegations } from './pending-delegations.js';
10
- import { allPlanTodos, areSynthesisConsultTodosComplete, getSynthesisConsultTodos, hasValidLeadDevPlanForSpawn, isSynthesisRealignmentPlan, loadPersistedLeadDevPlan, getNextRequiredTodo, validateSpawnMatchesTodo, updatePlanTodoStatus, } from './lead-dev-plan-persistence.js';
10
+ import { allPlanTodos, areSynthesisConsultTodosComplete, findRecentStalePlanArchive, getSynthesisConsultTodos, isLeadDevPlanStale, isSynthesisRealignmentPlan, loadPersistedLeadDevPlan, getNextRequiredTodo, validateSpawnMatchesTodo, updatePlanTodoStatus, } from './lead-dev-plan-persistence.js';
11
11
  import { getSynthesisDueReason, isSynthesisCheckpointDue, recordExecutionSlice, } from './synthesis.js';
12
12
  import { isSynthesisConsultTodoId, tryRecordSynthesisConsultReceipt, } from './synthesis-consult-receipt.js';
13
- export { validateSpawnMatchesTodo, updatePlanTodoStatus, savePersistedLeadDevPlan, } from './lead-dev-plan-persistence.js';
13
+ import { resolveSpawnPlan, hasValidSpawnPlanContext } from './spawn-plan-resolution.js';
14
+ import { isUserAsidesEnabled, isUserAsideTodoId, loadActiveAsidePointer, loadActiveUserAside, } from './user-aside.js';
15
+ import { validateAsideWorktreeCwd, } from './aside-worktree.js';
16
+ import { ceremonyForProfile, resolveSuitProfile, spawnPlanModeForProfile, writeSuitSessionBoot, maybeHeatHostStation, } from './suit-temperament.js';
17
+ export { writeSuitSessionBoot, maybeHeatHostStation };
18
+ export { extractSpawnCwd, validateAsideWorktreeCwd, provisionGitWorktree } from './aside-worktree.js';
19
+ function denyAsideWorktreeCwd(cwdCheck) {
20
+ const base = {
21
+ allow: false,
22
+ reason: cwdCheck.reason ?? 'Aside spawn cwd must match worktree',
23
+ gate: cwdCheck.gate ?? 'aside-worktree-cwd-missing',
24
+ };
25
+ return cwdCheck.hint ? { ...base, hint: cwdCheck.hint } : base;
26
+ }
27
+ function asideWorktreeCwdDenyIfNeeded(activeAside, toolInput, projectRoot) {
28
+ if (!activeAside?.worktree)
29
+ return undefined;
30
+ const cwdCheck = validateAsideWorktreeCwd(activeAside.worktree, toolInput, projectRoot);
31
+ if (!cwdCheck.valid)
32
+ return denyAsideWorktreeCwd(cwdCheck);
33
+ return undefined;
34
+ }
35
+ export { validateSpawnMatchesTodo, updatePlanTodoStatus, savePersistedLeadDevPlan, archiveStaleLeadDevPlan, findRecentStalePlanArchive, } from './lead-dev-plan-persistence.js';
14
36
  export { buildReceiptFromConsultOutput, hasValidSynthesisConsultReceipt, isSynthesisConsultTodoId, loadSynthesisConsultReceipt, parseConsultVerdictFromText, tryRecordSynthesisConsultReceipt, writeSynthesisConsultReceipt, } from './synthesis-consult-receipt.js';
15
37
  export const updatePlanTodoStatusInPlace = updatePlanTodoStatus;
16
38
  const READ_TOOLS = new Set([
@@ -49,21 +71,34 @@ const SYNTHESIS_ALLOWED_CONSULT_TOOLS = new Set([
49
71
  ]);
50
72
  const HERMES_WRITE_TOOLS = new Set(['write_file', 'patch', 'write', 'edit']);
51
73
  const OPENCODE_WRITE_TOOLS = new Set(['write', 'edit', 'multiedit']);
52
- 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
+ });
53
83
  const featuresPath = path.join(projectRoot, '.xray', 'features.json');
54
84
  if (!fs.existsSync(featuresPath)) {
55
- return { lead_dev_mode: true, auto_chain_delegations: true };
85
+ return fallback(resolveSuitProfile(undefined, host));
56
86
  }
57
87
  try {
58
88
  const data = JSON.parse(fs.readFileSync(featuresPath, 'utf8'));
59
89
  const orch = data.multi_agent_orchestration ?? {};
90
+ const profile = resolveSuitProfile(data.suit_temperament, host);
60
91
  return {
61
92
  lead_dev_mode: orch.enabled !== false && orch.lead_dev_mode !== false,
62
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,
63
98
  };
64
99
  }
65
100
  catch {
66
- return { lead_dev_mode: true, auto_chain_delegations: true };
101
+ return fallback(resolveSuitProfile(undefined, host));
67
102
  }
68
103
  }
69
104
  export function normalizeHostToolInput(toolInput) {
@@ -177,29 +212,76 @@ function denyFromPending(primary, pendingCount) {
177
212
  delegationId: primary.id,
178
213
  };
179
214
  }
215
+ function spawnPlanSoftAllow(gate, reason) {
216
+ return { allow: true, reason, gate };
217
+ }
180
218
  /** Spawn plan missing — applies before auto_chain opt-out for subagent tools. */
181
219
  export function evaluateSpawnPlanGate(toolName, toolInput, ctx) {
182
220
  if (!ctx.features.lead_dev_mode || !isSubagentTool(toolName)) {
183
221
  return { allow: true };
184
222
  }
185
- if (!hasValidLeadDevPlanForSpawn(ctx.projectRoot, ctx.sessionId)) {
186
- return {
187
- allow: false,
223
+ const spawnMode = ctx.features.spawn_plan_mode ?? 'deny';
224
+ if (spawnMode === 'off') {
225
+ return { allow: true };
226
+ }
227
+ const activeAside = isUserAsidesEnabled(ctx.projectRoot)
228
+ ? loadActiveUserAside(ctx.projectRoot, ctx.sessionId)
229
+ : null;
230
+ const plan = loadPersistedLeadDevPlan(ctx.projectRoot);
231
+ if (!activeAside && plan && isLeadDevPlanStale(plan, ctx.projectRoot)) {
232
+ const stale = {
233
+ reason: 'Lead-dev plan is stale (unstarted todos exceeded TTL) — ' +
234
+ 're-run xray-orchestrator analyze-complexity to refresh the plan',
235
+ gate: 'spawn-plan-stale',
236
+ hint: { tool: 'analyze-complexity', mcp: 'xray-orchestrator' },
237
+ };
238
+ if (spawnMode === 'warn')
239
+ return spawnPlanSoftAllow(stale.gate, stale.reason);
240
+ return { allow: false, ...stale };
241
+ }
242
+ if (!hasValidSpawnPlanContext(ctx.projectRoot, ctx.sessionId)) {
243
+ if (findRecentStalePlanArchive(ctx.projectRoot)) {
244
+ const archived = {
245
+ reason: 'Lead-dev plan was stale and archived — ' +
246
+ 're-run xray-orchestrator analyze-complexity to refresh the plan',
247
+ gate: 'spawn-plan-stale',
248
+ hint: { tool: 'analyze-complexity', mcp: 'xray-orchestrator' },
249
+ };
250
+ if (spawnMode === 'warn')
251
+ return spawnPlanSoftAllow(archived.gate, archived.reason);
252
+ return { allow: false, ...archived };
253
+ }
254
+ const missing = {
188
255
  reason: 'Codex 59/67: call xray-orchestrator analyze-complexity first — ' +
189
256
  'writes .xray/state/lead-dev-plan.json required before spawn_subagent',
190
257
  gate: 'spawn-plan-missing',
191
258
  };
259
+ if (spawnMode === 'warn')
260
+ return spawnPlanSoftAllow(missing.gate, missing.reason);
261
+ return { allow: false, ...missing };
192
262
  }
193
263
  if (ctx.features.auto_chain_delegations === false) {
264
+ const cwdDeny = asideWorktreeCwdDenyIfNeeded(activeAside, toolInput, ctx.projectRoot);
265
+ if (cwdDeny)
266
+ return cwdDeny;
194
267
  return { allow: true };
195
268
  }
269
+ const normalized = normalizeHostToolInput(toolInput);
270
+ const resolved = isUserAsidesEnabled(ctx.projectRoot)
271
+ ? resolveSpawnPlan(normalized, ctx.projectRoot, ctx.sessionId)
272
+ : { source: 'main', plan: loadPersistedLeadDevPlan(ctx.projectRoot) };
196
273
  const pending = getActivePendingDelegations(ctx.sessionId, ctx.projectRoot);
197
- const plan = loadPersistedLeadDevPlan(ctx.projectRoot);
198
- const expectedTodo = pending[0]?.planTodoId && plan
199
- ? allPlanTodos(plan).find((t) => t.id === pending[0].planTodoId) ?? null
274
+ const expectedTodo = pending[0]?.planTodoId && resolved.plan
275
+ ? allPlanTodos(resolved.plan).find((t) => t.id === pending[0].planTodoId) ?? null
200
276
  : null;
201
- const validation = validateSpawnMatchesTodo(normalizeHostToolInput(toolInput), ctx.projectRoot, expectedTodo);
277
+ const cwdDeny = asideWorktreeCwdDenyIfNeeded(activeAside, toolInput, ctx.projectRoot);
278
+ if (cwdDeny)
279
+ return cwdDeny;
280
+ const validation = validateSpawnMatchesTodo(normalized, ctx.projectRoot, expectedTodo, ctx.sessionId);
202
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
+ }
203
285
  return denyFromSpawnValidation(validation);
204
286
  }
205
287
  return { allow: true };
@@ -213,13 +295,32 @@ export function evaluateSynthesisGate(toolName, toolInput, ctx) {
213
295
  return { allow: true };
214
296
  if (isSynthesisAllowedOrchestratorConsult(toolName, toolInput))
215
297
  return { allow: true };
298
+ // Active user aside: allow aside-track subagent spawns during main synthesis checkpoint.
299
+ if (isUserAsidesEnabled(ctx.projectRoot)) {
300
+ const normalized = normalizeHostToolInput(toolInput);
301
+ const resolved = resolveSpawnPlan(normalized, ctx.projectRoot, ctx.sessionId);
302
+ if (resolved.source === 'aside' &&
303
+ isSubagentTool(toolName) &&
304
+ (normalized.planTodoId
305
+ ? isUserAsideTodoId(normalized.planTodoId)
306
+ : Boolean(resolved.asideId))) {
307
+ const validation = validateSpawnMatchesTodo(normalized, ctx.projectRoot, undefined, ctx.sessionId);
308
+ if (validation.valid) {
309
+ const activeAside = loadActiveUserAside(ctx.projectRoot, ctx.sessionId);
310
+ const cwdDeny = asideWorktreeCwdDenyIfNeeded(activeAside, toolInput, ctx.projectRoot);
311
+ if (cwdDeny)
312
+ return cwdDeny;
313
+ return { allow: true };
314
+ }
315
+ }
316
+ }
216
317
  const plan = loadPersistedLeadDevPlan(ctx.projectRoot);
217
318
  if (plan &&
218
319
  isSynthesisRealignmentPlan(plan) &&
219
320
  !areSynthesisConsultTodosComplete(plan) &&
220
321
  isSubagentTool(toolName)) {
221
322
  const nextTodo = getNextRequiredTodo(plan);
222
- const validation = validateSpawnMatchesTodo(normalizeHostToolInput(toolInput), ctx.projectRoot, nextTodo);
323
+ const validation = validateSpawnMatchesTodo(normalizeHostToolInput(toolInput), ctx.projectRoot, nextTodo, ctx.sessionId);
223
324
  if (validation.valid)
224
325
  return { allow: true };
225
326
  }
@@ -252,6 +353,13 @@ export function evaluatePendingDelegationGate(toolName, toolInput, ctx) {
252
353
  const pending = getActivePendingDelegations(ctx.sessionId, ctx.projectRoot);
253
354
  if (pending.length === 0)
254
355
  return { allow: true };
356
+ // Aside-track work: pending main delegations do not block aside spawns.
357
+ if (isUserAsidesEnabled(ctx.projectRoot) && isSubagentTool(toolName)) {
358
+ const normalized = normalizeHostToolInput(toolInput);
359
+ const resolved = resolveSpawnPlan(normalized, ctx.projectRoot, ctx.sessionId);
360
+ if (resolved.source === 'aside')
361
+ return { allow: true };
362
+ }
255
363
  if (isSubagentTool(toolName))
256
364
  return { allow: true };
257
365
  if (isReadOnlyTool(toolName))
@@ -269,8 +377,110 @@ export function evaluatePendingDelegationGate(toolName, toolInput, ctx) {
269
377
  * Full pre-tool evaluation — synthesis gate first, slice recording, then
270
378
  * pending gate, then spawn todo gate for subagent tools.
271
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
+ }
272
464
  export function evaluatePreToolGate(toolName, toolInput, ctx) {
273
- 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);
274
484
  if (!synthesisBlock.allow)
275
485
  return synthesisBlock;
276
486
  if (!isSynthesisCheckpointDue(ctx.projectRoot, ctx.sessionId)) {
@@ -279,17 +489,22 @@ export function evaluatePreToolGate(toolName, toolInput, ctx) {
279
489
  sessionId: ctx.sessionId,
280
490
  });
281
491
  }
282
- const pendingBlock = evaluatePendingDelegationGate(toolName, toolInput, ctx);
492
+ const pendingBlock = lite
493
+ ? { allow: true }
494
+ : evaluatePendingDelegationGate(toolName, toolInput, ctx);
283
495
  if (!pendingBlock.allow)
284
496
  return pendingBlock;
285
497
  const spawnBlock = evaluateSpawnPlanGate(toolName, toolInput, ctx);
286
498
  if (!spawnBlock.allow)
287
499
  return spawnBlock;
288
- return { allow: true };
500
+ return spawnBlock;
289
501
  }
290
502
  export function evaluatePostToolSpawn(toolName, toolInput, projectRoot, options = {}) {
291
503
  const normalized = normalizeHostToolInput(toolInput);
292
- const spawnCheck = validateSpawnMatchesTodo(normalized, projectRoot);
504
+ const pointer = loadActiveAsidePointer(projectRoot);
505
+ const mainPlan = loadPersistedLeadDevPlan(projectRoot);
506
+ const sessionId = options.sessionId ?? mainPlan?.sessionId ?? pointer?.sessionId ?? null;
507
+ const spawnCheck = validateSpawnMatchesTodo(normalized, projectRoot, undefined, sessionId);
293
508
  const satisfyInput = {
294
509
  toolPrompt: normalized.prompt ?? '',
295
510
  };
@@ -306,7 +521,6 @@ export function evaluatePostToolSpawn(toolName, toolInput, projectRoot, options
306
521
  const expectedTodoId = spawnCheck.expectedTodoId ?? null;
307
522
  if (spawnCheck.valid && expectedTodoId) {
308
523
  const plan = loadPersistedLeadDevPlan(projectRoot);
309
- const sessionId = options.sessionId ?? plan?.sessionId ?? null;
310
524
  const consultTodo = plan
311
525
  ? getSynthesisConsultTodos(plan).find((t) => t.id === expectedTodoId)
312
526
  : undefined;
@@ -317,7 +531,7 @@ export function evaluatePostToolSpawn(toolName, toolInput, projectRoot, options
317
531
  const receipt = tryRecordSynthesisConsultReceipt(expectedTodoId, consultTodo.subagent, sessionId, options.toolOutput, projectRoot);
318
532
  receiptRecorded = receipt != null;
319
533
  }
320
- if (updatePlanTodoStatus(expectedTodoId, 'completed', projectRoot)) {
534
+ if (updatePlanTodoStatus(expectedTodoId, 'completed', projectRoot, sessionId)) {
321
535
  todoCompleted = true;
322
536
  }
323
537
  }
@@ -15,7 +15,31 @@ export interface SpawnTodoValidation {
15
15
  hint?: Record<string, unknown>;
16
16
  expectedTodoId?: string | null;
17
17
  }
18
+ export declare const DEFAULT_PLAN_STALE_MS: number;
19
+ export declare const DEFAULT_PLAN_ARCHIVE_MARKER_MS: number;
18
20
  export declare function leadDevPlanStatePath(projectRoot?: string): string;
21
+ export declare function loadLeadDevPlanStaleMs(projectRoot?: string): number;
22
+ export declare function loadLeadDevPlanArchiveMarkerMs(projectRoot?: string): number;
23
+ /**
24
+ * Mandatory synthesis consults (s.1–s.3) must stay spawnable until complete —
25
+ * never treat an active realignment plan as stale while consult todos remain.
26
+ */
27
+ export declare function isProtectedSynthesisRealignmentPlan(plan: PersistedLeadDevPlan): boolean;
28
+ /**
29
+ * Stale when every outstanding todo is still pending and plan age exceeds TTL.
30
+ * In-progress or completed todos imply active work — plan stays valid.
31
+ */
32
+ export declare function isLeadDevPlanStale(plan: PersistedLeadDevPlan, projectRoot?: string): boolean;
33
+ export declare function archiveStaleLeadDevPlan(projectRoot?: string): {
34
+ archived: boolean;
35
+ archivePath?: string;
36
+ reason?: string;
37
+ };
38
+ /** Recent stale archival — keeps spawn-plan-stale gate after session-start cleanup. */
39
+ export declare function findRecentStalePlanArchive(projectRoot?: string, maxAgeMs?: number): {
40
+ archivePath: string;
41
+ archivedAt: string;
42
+ } | null;
19
43
  export declare function loadPersistedLeadDevPlan(projectRoot?: string): PersistedLeadDevPlan | null;
20
44
  export declare function savePersistedLeadDevPlan(plan: PersistedLeadDevPlan, projectRoot?: string): string;
21
45
  export declare function allPlanTodos(plan: PersistedLeadDevPlan): LeadDevTodo[];
@@ -31,7 +55,7 @@ export declare function hasValidLeadDevPlanForSpawn(projectRoot?: string, _sessi
31
55
  export declare function isSynthesisRealignmentPlan(plan: PersistedLeadDevPlan): boolean;
32
56
  export declare function getSynthesisConsultTodos(plan: PersistedLeadDevPlan): LeadDevTodo[];
33
57
  export declare function areSynthesisConsultTodosComplete(plan: PersistedLeadDevPlan): boolean;
34
- export declare function updatePlanTodoStatus(todoId: string, status: LeadDevTodo['status'], projectRoot?: string): boolean;
58
+ export declare function updatePlanTodoStatus(todoId: string, status: LeadDevTodo['status'], projectRoot?: string, sessionId?: string | null): boolean;
35
59
  export declare function bindPlanToSession(sessionId: string, projectRoot?: string): PersistedLeadDevPlan | null;
36
60
  export interface SpawnToolInput {
37
61
  prompt?: string;
@@ -42,5 +66,5 @@ export interface SpawnToolInput {
42
66
  delegationId?: string;
43
67
  planTodoId?: string;
44
68
  }
45
- export declare function validateSpawnMatchesTodo(toolInput: SpawnToolInput, projectRoot?: string, expectedTodo?: LeadDevTodo | null): SpawnTodoValidation;
46
- export declare function markTodoInProgressOnSpawn(toolInput: SpawnToolInput, projectRoot?: string): string | null;
69
+ export declare function validateSpawnMatchesTodo(toolInput: SpawnToolInput, projectRoot?: string, expectedTodo?: LeadDevTodo | null, sessionId?: string | null): SpawnTodoValidation;
70
+ export declare function markTodoInProgressOnSpawn(toolInput: SpawnToolInput, projectRoot?: string, sessionId?: string | null): string | null;