oh-my-codex 0.18.12 → 0.18.14

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 (317) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +38 -11
  4. package/dist/agents/__tests__/native-config.test.js +25 -0
  5. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  6. package/dist/agents/native-config.d.ts.map +1 -1
  7. package/dist/agents/native-config.js +5 -1
  8. package/dist/agents/native-config.js.map +1 -1
  9. package/dist/autopilot/__tests__/fsm.test.js +7 -0
  10. package/dist/autopilot/__tests__/fsm.test.js.map +1 -1
  11. package/dist/autopilot/__tests__/planner-routing.test.d.ts +2 -0
  12. package/dist/autopilot/__tests__/planner-routing.test.d.ts.map +1 -0
  13. package/dist/autopilot/__tests__/planner-routing.test.js +74 -0
  14. package/dist/autopilot/__tests__/planner-routing.test.js.map +1 -0
  15. package/dist/autopilot/__tests__/ralplan-gate.test.js +936 -0
  16. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  17. package/dist/autopilot/completion-gate.js +1 -1
  18. package/dist/autopilot/completion-gate.js.map +1 -1
  19. package/dist/autopilot/fsm.d.ts +2 -2
  20. package/dist/autopilot/fsm.d.ts.map +1 -1
  21. package/dist/autopilot/fsm.js +3 -0
  22. package/dist/autopilot/fsm.js.map +1 -1
  23. package/dist/autopilot/planner-routing.d.ts +21 -0
  24. package/dist/autopilot/planner-routing.d.ts.map +1 -0
  25. package/dist/autopilot/planner-routing.js +59 -0
  26. package/dist/autopilot/planner-routing.js.map +1 -0
  27. package/dist/autopilot/ralplan-gate.d.ts.map +1 -1
  28. package/dist/autopilot/ralplan-gate.js +62 -18
  29. package/dist/autopilot/ralplan-gate.js.map +1 -1
  30. package/dist/autoresearch/goal.d.ts.map +1 -1
  31. package/dist/autoresearch/goal.js +10 -1
  32. package/dist/autoresearch/goal.js.map +1 -1
  33. package/dist/cli/__tests__/autoresearch-goal.test.js +33 -0
  34. package/dist/cli/__tests__/autoresearch-goal.test.js.map +1 -1
  35. package/dist/cli/__tests__/codex-plugin-layout.test.js +30 -0
  36. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  37. package/dist/cli/__tests__/doctor-artifact-ownership.test.d.ts +2 -0
  38. package/dist/cli/__tests__/doctor-artifact-ownership.test.d.ts.map +1 -0
  39. package/dist/cli/__tests__/doctor-artifact-ownership.test.js +158 -0
  40. package/dist/cli/__tests__/doctor-artifact-ownership.test.js.map +1 -0
  41. package/dist/cli/__tests__/doctor-invalid-config.test.js +35 -0
  42. package/dist/cli/__tests__/doctor-invalid-config.test.js.map +1 -1
  43. package/dist/cli/__tests__/doctor-spark-routing.test.js +13 -0
  44. package/dist/cli/__tests__/doctor-spark-routing.test.js.map +1 -1
  45. package/dist/cli/__tests__/doctor-warning-copy.test.js +1 -0
  46. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  47. package/dist/cli/__tests__/index.test.js +59 -1
  48. package/dist/cli/__tests__/index.test.js.map +1 -1
  49. package/dist/cli/__tests__/nested-help-routing.test.js +4 -0
  50. package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
  51. package/dist/cli/__tests__/package-bin-contract.test.js +7 -1
  52. package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
  53. package/dist/cli/__tests__/performance-goal.test.js +22 -0
  54. package/dist/cli/__tests__/performance-goal.test.js.map +1 -1
  55. package/dist/cli/__tests__/resume.test.js +313 -1
  56. package/dist/cli/__tests__/resume.test.js.map +1 -1
  57. package/dist/cli/__tests__/session-scoped-runtime.test.js +162 -0
  58. package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
  59. package/dist/cli/__tests__/session-search-help.test.js +3 -2
  60. package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
  61. package/dist/cli/__tests__/session-search.test.js +100 -2
  62. package/dist/cli/__tests__/session-search.test.js.map +1 -1
  63. package/dist/cli/__tests__/setup-agents-overwrite.test.js +35 -1
  64. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  65. package/dist/cli/__tests__/setup-install-mode.test.js +39 -5
  66. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  67. package/dist/cli/__tests__/setup-prompts-overwrite.test.js +74 -0
  68. package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +1 -1
  69. package/dist/cli/__tests__/setup-scope.test.js +45 -0
  70. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  71. package/dist/cli/__tests__/team.test.js +17 -3
  72. package/dist/cli/__tests__/team.test.js.map +1 -1
  73. package/dist/cli/__tests__/ultragoal.test.js +37 -0
  74. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  75. package/dist/cli/__tests__/update.test.js +6 -2
  76. package/dist/cli/__tests__/update.test.js.map +1 -1
  77. package/dist/cli/autoresearch-goal.d.ts.map +1 -1
  78. package/dist/cli/autoresearch-goal.js +2 -1
  79. package/dist/cli/autoresearch-goal.js.map +1 -1
  80. package/dist/cli/doctor.d.ts +22 -0
  81. package/dist/cli/doctor.d.ts.map +1 -1
  82. package/dist/cli/doctor.js +272 -5
  83. package/dist/cli/doctor.js.map +1 -1
  84. package/dist/cli/index.d.ts +10 -2
  85. package/dist/cli/index.d.ts.map +1 -1
  86. package/dist/cli/index.js +274 -11
  87. package/dist/cli/index.js.map +1 -1
  88. package/dist/cli/performance-goal.d.ts.map +1 -1
  89. package/dist/cli/performance-goal.js +4 -2
  90. package/dist/cli/performance-goal.js.map +1 -1
  91. package/dist/cli/plugin-marketplace.d.ts +1 -0
  92. package/dist/cli/plugin-marketplace.d.ts.map +1 -1
  93. package/dist/cli/plugin-marketplace.js +67 -5
  94. package/dist/cli/plugin-marketplace.js.map +1 -1
  95. package/dist/cli/project-runtime-codex-homes.d.ts +8 -0
  96. package/dist/cli/project-runtime-codex-homes.d.ts.map +1 -0
  97. package/dist/cli/project-runtime-codex-homes.js +134 -0
  98. package/dist/cli/project-runtime-codex-homes.js.map +1 -0
  99. package/dist/cli/session-search.d.ts.map +1 -1
  100. package/dist/cli/session-search.js +8 -1
  101. package/dist/cli/session-search.js.map +1 -1
  102. package/dist/cli/setup.d.ts +1 -0
  103. package/dist/cli/setup.d.ts.map +1 -1
  104. package/dist/cli/setup.js +183 -10
  105. package/dist/cli/setup.js.map +1 -1
  106. package/dist/cli/ultragoal.d.ts.map +1 -1
  107. package/dist/cli/ultragoal.js +5 -1
  108. package/dist/cli/ultragoal.js.map +1 -1
  109. package/dist/cli/update.d.ts.map +1 -1
  110. package/dist/cli/update.js +5 -0
  111. package/dist/cli/update.js.map +1 -1
  112. package/dist/config/__tests__/codex-hooks.test.js +38 -24
  113. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  114. package/dist/config/__tests__/models.test.js +21 -1
  115. package/dist/config/__tests__/models.test.js.map +1 -1
  116. package/dist/config/codex-hooks.d.ts +6 -0
  117. package/dist/config/codex-hooks.d.ts.map +1 -1
  118. package/dist/config/codex-hooks.js +34 -49
  119. package/dist/config/codex-hooks.js.map +1 -1
  120. package/dist/config/models.d.ts +5 -0
  121. package/dist/config/models.d.ts.map +1 -1
  122. package/dist/config/models.js +23 -0
  123. package/dist/config/models.js.map +1 -1
  124. package/dist/goal-workflows/codex-goal-snapshot.d.ts +2 -0
  125. package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
  126. package/dist/goal-workflows/codex-goal-snapshot.js +10 -0
  127. package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
  128. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +7 -0
  129. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  130. package/dist/hooks/__tests__/keyword-detector.test.js +46 -0
  131. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  132. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +100 -0
  133. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  134. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +75 -0
  135. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  136. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +225 -0
  137. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  138. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +75 -0
  139. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  140. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +200 -0
  141. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  142. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +187 -12
  143. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  144. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +225 -0
  145. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  146. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +0 -0
  147. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
  148. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +75 -0
  149. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  150. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  151. package/dist/hooks/keyword-detector.js +4 -0
  152. package/dist/hooks/keyword-detector.js.map +1 -1
  153. package/dist/hud/__tests__/reconcile.test.js +137 -2
  154. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  155. package/dist/hud/__tests__/state.test.js +107 -0
  156. package/dist/hud/__tests__/state.test.js.map +1 -1
  157. package/dist/hud/__tests__/tmux.test.js +17 -0
  158. package/dist/hud/__tests__/tmux.test.js.map +1 -1
  159. package/dist/hud/reconcile.d.ts.map +1 -1
  160. package/dist/hud/reconcile.js +21 -7
  161. package/dist/hud/reconcile.js.map +1 -1
  162. package/dist/hud/render.d.ts.map +1 -1
  163. package/dist/hud/render.js +9 -0
  164. package/dist/hud/render.js.map +1 -1
  165. package/dist/hud/state.d.ts.map +1 -1
  166. package/dist/hud/state.js +43 -5
  167. package/dist/hud/state.js.map +1 -1
  168. package/dist/hud/types.d.ts +6 -0
  169. package/dist/hud/types.d.ts.map +1 -1
  170. package/dist/hud/types.js.map +1 -1
  171. package/dist/modes/__tests__/base-autopilot-gates.test.js +48 -0
  172. package/dist/modes/__tests__/base-autopilot-gates.test.js.map +1 -1
  173. package/dist/modes/base.d.ts.map +1 -1
  174. package/dist/modes/base.js +1 -0
  175. package/dist/modes/base.js.map +1 -1
  176. package/dist/performance-goal/artifacts.d.ts.map +1 -1
  177. package/dist/performance-goal/artifacts.js +10 -1
  178. package/dist/performance-goal/artifacts.js.map +1 -1
  179. package/dist/pipeline/__tests__/orchestrator.test.js +125 -0
  180. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  181. package/dist/pipeline/__tests__/stages.test.js +109 -0
  182. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  183. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  184. package/dist/pipeline/orchestrator.js +7 -0
  185. package/dist/pipeline/orchestrator.js.map +1 -1
  186. package/dist/ralplan/__tests__/consensus-gate.test.js +552 -1
  187. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  188. package/dist/ralplan/consensus-gate.d.ts +25 -0
  189. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  190. package/dist/ralplan/consensus-gate.js +289 -75
  191. package/dist/ralplan/consensus-gate.js.map +1 -1
  192. package/dist/scripts/__tests__/codex-native-hook.test.js +1149 -47
  193. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  194. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  195. package/dist/scripts/codex-native-hook.js +542 -33
  196. package/dist/scripts/codex-native-hook.js.map +1 -1
  197. package/dist/scripts/codex-native-pre-post.d.ts +1 -0
  198. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  199. package/dist/scripts/codex-native-pre-post.js +130 -0
  200. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  201. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  202. package/dist/scripts/notify-hook/team-tmux-guard.js +87 -8
  203. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  204. package/dist/scripts/notify-hook/tmux-injection.js +1 -1
  205. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  206. package/dist/scripts/run-compiled-ci.d.ts +2 -0
  207. package/dist/scripts/run-compiled-ci.d.ts.map +1 -0
  208. package/dist/scripts/run-compiled-ci.js +77 -0
  209. package/dist/scripts/run-compiled-ci.js.map +1 -0
  210. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
  211. package/dist/scripts/sync-plugin-mirror.js +1 -0
  212. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  213. package/dist/session-history/__tests__/search.test.js +166 -0
  214. package/dist/session-history/__tests__/search.test.js.map +1 -1
  215. package/dist/session-history/search.d.ts +7 -0
  216. package/dist/session-history/search.d.ts.map +1 -1
  217. package/dist/session-history/search.js +99 -25
  218. package/dist/session-history/search.js.map +1 -1
  219. package/dist/sidecar/__tests__/collector.test.js +60 -0
  220. package/dist/sidecar/__tests__/collector.test.js.map +1 -1
  221. package/dist/sidecar/collector.d.ts.map +1 -1
  222. package/dist/sidecar/collector.js +3 -6
  223. package/dist/sidecar/collector.js.map +1 -1
  224. package/dist/state/__tests__/operations.test.js +107 -3
  225. package/dist/state/__tests__/operations.test.js.map +1 -1
  226. package/dist/state/operations.d.ts.map +1 -1
  227. package/dist/state/operations.js +57 -2
  228. package/dist/state/operations.js.map +1 -1
  229. package/dist/team/__tests__/delivery-e2e-smoke.test.js +22 -1
  230. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  231. package/dist/team/__tests__/model-contract.test.js +57 -1
  232. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  233. package/dist/team/__tests__/runtime.test.js +1468 -110
  234. package/dist/team/__tests__/runtime.test.js.map +1 -1
  235. package/dist/team/__tests__/scaling.test.js +63 -0
  236. package/dist/team/__tests__/scaling.test.js.map +1 -1
  237. package/dist/team/__tests__/state.test.js +24 -1
  238. package/dist/team/__tests__/state.test.js.map +1 -1
  239. package/dist/team/__tests__/tmux-session.test.js +512 -0
  240. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  241. package/dist/team/__tests__/worker-bootstrap.test.js +42 -9
  242. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  243. package/dist/team/model-contract.d.ts +16 -0
  244. package/dist/team/model-contract.d.ts.map +1 -1
  245. package/dist/team/model-contract.js +41 -1
  246. package/dist/team/model-contract.js.map +1 -1
  247. package/dist/team/runtime.d.ts.map +1 -1
  248. package/dist/team/runtime.js +116 -30
  249. package/dist/team/runtime.js.map +1 -1
  250. package/dist/team/scaling.d.ts.map +1 -1
  251. package/dist/team/scaling.js +9 -1
  252. package/dist/team/scaling.js.map +1 -1
  253. package/dist/team/state/types.d.ts +2 -0
  254. package/dist/team/state/types.d.ts.map +1 -1
  255. package/dist/team/state/types.js.map +1 -1
  256. package/dist/team/state.d.ts +3 -0
  257. package/dist/team/state.d.ts.map +1 -1
  258. package/dist/team/state.js +20 -0
  259. package/dist/team/state.js.map +1 -1
  260. package/dist/team/tmux-session.d.ts +38 -3
  261. package/dist/team/tmux-session.d.ts.map +1 -1
  262. package/dist/team/tmux-session.js +275 -36
  263. package/dist/team/tmux-session.js.map +1 -1
  264. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  265. package/dist/team/worker-bootstrap.js +26 -1
  266. package/dist/team/worker-bootstrap.js.map +1 -1
  267. package/dist/ultragoal/__tests__/artifacts.test.js +238 -0
  268. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  269. package/dist/ultragoal/__tests__/docs-contract.test.js +3 -0
  270. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  271. package/dist/ultragoal/artifacts.d.ts +15 -0
  272. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  273. package/dist/ultragoal/artifacts.js +167 -4
  274. package/dist/ultragoal/artifacts.js.map +1 -1
  275. package/dist/utils/__tests__/agents-md.test.js +39 -1
  276. package/dist/utils/__tests__/agents-md.test.js.map +1 -1
  277. package/dist/utils/__tests__/agents-model-table.test.js +28 -0
  278. package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
  279. package/dist/utils/agents-md.d.ts +4 -0
  280. package/dist/utils/agents-md.d.ts.map +1 -1
  281. package/dist/utils/agents-md.js +25 -0
  282. package/dist/utils/agents-md.js.map +1 -1
  283. package/dist/utils/agents-model-table.d.ts +7 -3
  284. package/dist/utils/agents-model-table.d.ts.map +1 -1
  285. package/dist/utils/agents-model-table.js +16 -8
  286. package/dist/utils/agents-model-table.js.map +1 -1
  287. package/dist/verification/__tests__/ci-rust-gates.test.js +8 -2
  288. package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
  289. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +71 -3
  290. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
  291. package/package.json +2 -2
  292. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  293. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +59 -8
  294. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +9 -5
  295. package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +3 -0
  296. package/plugins/oh-my-codex/skills/performance-goal/SKILL.md +3 -0
  297. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +1 -1
  298. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +22 -4
  299. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +2 -2
  300. package/plugins/oh-my-codex/skills/ultrawork/references/agent-tiers.md +61 -0
  301. package/skills/autopilot/SKILL.md +9 -5
  302. package/skills/autoresearch-goal/SKILL.md +3 -0
  303. package/skills/ecomode/SKILL.md +1 -1
  304. package/skills/ecomode/references/agent-tiers.md +61 -0
  305. package/skills/performance-goal/SKILL.md +3 -0
  306. package/skills/ralplan/SKILL.md +1 -1
  307. package/skills/ultragoal/SKILL.md +22 -4
  308. package/skills/ultrawork/SKILL.md +2 -2
  309. package/skills/ultrawork/references/agent-tiers.md +61 -0
  310. package/src/scripts/__tests__/codex-native-hook.test.ts +1417 -119
  311. package/src/scripts/codex-native-hook.ts +597 -40
  312. package/src/scripts/codex-native-pre-post.ts +137 -0
  313. package/src/scripts/notify-hook/team-tmux-guard.ts +92 -8
  314. package/src/scripts/notify-hook/tmux-injection.ts +1 -1
  315. package/src/scripts/run-compiled-ci.ts +85 -0
  316. package/src/scripts/sync-plugin-mirror.ts +1 -0
  317. package/templates/AGENTS.md +6 -0
@@ -4,6 +4,28 @@ export declare const RALPLAN_CONSENSUS_BLOCKED_REASONS: {
4
4
  readonly missingSequentialApproval: "missing_sequential_architect_then_critic_approval";
5
5
  };
6
6
  export type RalplanConsensusBlockedReason = typeof RALPLAN_CONSENSUS_BLOCKED_REASONS[keyof typeof RALPLAN_CONSENSUS_BLOCKED_REASONS];
7
+ export interface RalplanNativeReviewDiagnostic {
8
+ role: 'architect' | 'critic';
9
+ session_id: string | null;
10
+ thread_id: string | null;
11
+ tracker_path: string;
12
+ session_found: boolean;
13
+ thread_found: boolean;
14
+ kind: string | null;
15
+ completed: boolean;
16
+ problem: string | null;
17
+ }
18
+ export interface RalplanConsensusGateDiagnostic {
19
+ expected_schema: string[];
20
+ current_session_id: string | null;
21
+ tracker_path: string;
22
+ architect: RalplanNativeReviewDiagnostic;
23
+ critic: RalplanNativeReviewDiagnostic;
24
+ distinct_thread_ids: boolean | null;
25
+ pair_problem: string | null;
26
+ remediation: string[];
27
+ docs: string;
28
+ }
7
29
  export interface RalplanConsensusGateEvidence {
8
30
  complete: boolean;
9
31
  sequence: ['architect-review', 'critic-review'];
@@ -12,6 +34,7 @@ export interface RalplanConsensusGateEvidence {
12
34
  source: string | null;
13
35
  blockedReason: RalplanConsensusBlockedReason | null;
14
36
  blockedDetails?: string[];
37
+ diagnostic?: RalplanConsensusGateDiagnostic;
15
38
  }
16
39
  export interface RalplanNativeSubagentConsensusOptions {
17
40
  requireNativeSubagents?: boolean;
@@ -21,6 +44,7 @@ export interface RalplanNativeSubagentConsensusOptions {
21
44
  export interface RalplanConsensusSource {
22
45
  source: string;
23
46
  value: unknown;
47
+ sessionId?: string;
24
48
  }
25
49
  export declare function buildRalplanConsensusGateFromSources(sources: RalplanConsensusSource[], options?: RalplanNativeSubagentConsensusOptions): RalplanConsensusGateEvidence;
26
50
  export declare function buildRalplanConsensusGateForCwd(cwd: string, options?: {
@@ -34,4 +58,5 @@ export declare function hasDurableRalplanConsensusEvidenceForCwd(cwd: string, op
34
58
  requireNativeSubagents?: boolean;
35
59
  }): boolean;
36
60
  export declare function readLocalRalplanConsensusStateCandidates(cwd: string, sessionId?: string): RalplanConsensusSource[];
61
+ export declare function withParentReturnToRalplanContext(value: unknown, parent: Record<string, unknown>): unknown;
37
62
  //# sourceMappingURL=consensus-gate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"consensus-gate.d.ts","sourceRoot":"","sources":["../../src/ralplan/consensus-gate.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iCAAiC;;;;CAIpC,CAAC;AAEX,MAAM,MAAM,6BAA6B,GACvC,OAAO,iCAAiC,CAAC,MAAM,OAAO,iCAAiC,CAAC,CAAC;AAE3F,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IAChD,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,6BAA6B,GAAG,IAAI,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,qCAAqC;IACpD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,oCAAoC,CAClD,OAAO,EAAE,sBAAsB,EAAE,EACjC,OAAO,GAAE,qCAA0C,GAClD,4BAA4B,CA0E9B;AAED,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1G,4BAA4B,CAY9B;AAED,wBAAgB,wCAAwC,CACtD,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1G,OAAO,CAET;AAED,wBAAgB,wCAAwC,CACtD,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,sBAAsB,EAAE,CAuB1B"}
1
+ {"version":3,"file":"consensus-gate.d.ts","sourceRoot":"","sources":["../../src/ralplan/consensus-gate.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iCAAiC;;;;CAIpC,CAAC;AAEX,MAAM,MAAM,6BAA6B,GACvC,OAAO,iCAAiC,CAAC,MAAM,OAAO,iCAAiC,CAAC,CAAC;AAE3F,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,8BAA8B;IAC7C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,6BAA6B,CAAC;IACzC,MAAM,EAAE,6BAA6B,CAAC;IACtC,mBAAmB,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IAChD,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,6BAA6B,GAAG,IAAI,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,8BAA8B,CAAC;CAC7C;AAED,MAAM,WAAW,qCAAqC;IACpD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAaD,wBAAgB,oCAAoC,CAClD,OAAO,EAAE,sBAAsB,EAAE,EACjC,OAAO,GAAE,qCAA0C,GAClD,4BAA4B,CAqF9B;AAED,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1G,4BAA4B,CAsB9B;AAED,wBAAgB,wCAAwC,CACtD,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1G,OAAO,CAET;AAED,wBAAgB,wCAAwC,CACtD,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,sBAAsB,EAAE,CA0B1B;AAqKD,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAoBzG"}
@@ -9,38 +9,49 @@ export const RALPLAN_CONSENSUS_BLOCKED_REASONS = {
9
9
  };
10
10
  export function buildRalplanConsensusGateFromSources(sources, options = {}) {
11
11
  let nativeBlockedEvidence = null;
12
- let invalidCompleteEvidence = null;
12
+ let firstCompleteEvidence = null;
13
13
  for (const candidate of sources) {
14
- const evidence = extractSequentialConsensusEvidence(candidate.value);
15
- if (evidence) {
14
+ const evidence = resolveConsensusEvidence(candidate.value);
15
+ const candidateOptions = {
16
+ ...options,
17
+ sessionId: options.sessionId ?? candidate.sessionId,
18
+ };
19
+ if (evidence?.kind === 'invalid') {
20
+ if (isConsensusEvidenceNewerThanSelected(evidence, firstCompleteEvidence)) {
21
+ firstCompleteEvidence = { ...evidence, source: candidate.source };
22
+ }
23
+ continue;
24
+ }
25
+ if (evidence?.kind === 'valid') {
16
26
  if (options.requireNativeSubagents
17
- && !hasTrackerBackedNativeRalplanLanes(evidence, options)) {
18
- nativeBlockedEvidence ??= { ...evidence, source: candidate.source };
27
+ && !hasTrackerBackedNativeRalplanLanes(evidence, candidateOptions)) {
28
+ nativeBlockedEvidence ??= { ...evidence, source: candidate.source, options: candidateOptions };
19
29
  continue;
20
30
  }
21
- return {
22
- complete: true,
23
- sequence: ['architect-review', 'critic-review'],
24
- ralplan_architect_review: evidence.ralplan_architect_review,
25
- ralplan_critic_review: evidence.ralplan_critic_review,
26
- source: candidate.source,
27
- blockedReason: null,
28
- };
29
- }
30
- const invalidEvidence = extractInvalidCompleteConsensusEvidence(candidate.value);
31
- if (invalidEvidence) {
32
- invalidCompleteEvidence ??= { ...invalidEvidence, source: candidate.source };
31
+ if (isConsensusEvidenceNewerThanSelected(evidence, firstCompleteEvidence)) {
32
+ firstCompleteEvidence = { ...evidence, source: candidate.source };
33
+ }
33
34
  }
34
35
  }
35
- if (invalidCompleteEvidence) {
36
+ if (firstCompleteEvidence?.kind === 'invalid') {
36
37
  return {
37
38
  complete: false,
38
39
  sequence: ['architect-review', 'critic-review'],
39
- ralplan_architect_review: invalidCompleteEvidence.ralplan_architect_review,
40
- ralplan_critic_review: invalidCompleteEvidence.ralplan_critic_review,
41
- source: invalidCompleteEvidence.source,
40
+ ralplan_architect_review: firstCompleteEvidence.ralplan_architect_review,
41
+ ralplan_critic_review: firstCompleteEvidence.ralplan_critic_review,
42
+ source: firstCompleteEvidence.source,
42
43
  blockedReason: RALPLAN_CONSENSUS_BLOCKED_REASONS.nonApprovingReview,
43
- blockedDetails: invalidCompleteEvidence.blockedDetails,
44
+ blockedDetails: firstCompleteEvidence.blockedDetails,
45
+ };
46
+ }
47
+ if (firstCompleteEvidence?.kind === 'valid') {
48
+ return {
49
+ complete: true,
50
+ sequence: ['architect-review', 'critic-review'],
51
+ ralplan_architect_review: firstCompleteEvidence.ralplan_architect_review,
52
+ ralplan_critic_review: firstCompleteEvidence.ralplan_critic_review,
53
+ source: firstCompleteEvidence.source,
54
+ blockedReason: null,
44
55
  };
45
56
  }
46
57
  if (nativeBlockedEvidence) {
@@ -52,9 +63,11 @@ export function buildRalplanConsensusGateFromSources(sources, options = {}) {
52
63
  source: nativeBlockedEvidence.source,
53
64
  blockedReason: RALPLAN_CONSENSUS_BLOCKED_REASONS.nativeSubagentEvidenceMissing,
54
65
  blockedDetails: [
55
- trackerBackedNativeReviewProblem(nativeBlockedEvidence.ralplan_architect_review, 'architect', options),
56
- trackerBackedNativeReviewProblem(nativeBlockedEvidence.ralplan_critic_review, 'critic', options),
66
+ trackerBackedNativeReviewPairProblem(nativeBlockedEvidence, nativeBlockedEvidence.options),
67
+ trackerBackedNativeReviewProblem(nativeBlockedEvidence.ralplan_architect_review, 'architect', nativeBlockedEvidence.options),
68
+ trackerBackedNativeReviewProblem(nativeBlockedEvidence.ralplan_critic_review, 'critic', nativeBlockedEvidence.options),
57
69
  ].filter((detail) => Boolean(detail)),
70
+ diagnostic: buildTrackerBackedNativeConsensusDiagnostic(nativeBlockedEvidence, nativeBlockedEvidence.options),
58
71
  };
59
72
  }
60
73
  return {
@@ -67,12 +80,22 @@ export function buildRalplanConsensusGateFromSources(sources, options = {}) {
67
80
  };
68
81
  }
69
82
  export function buildRalplanConsensusGateForCwd(cwd, options = {}) {
83
+ const localStateCandidates = readLocalRalplanConsensusStateCandidates(cwd, options.sessionId)
84
+ .map((candidate) => ({
85
+ ...candidate,
86
+ value: options.artifacts
87
+ ? withParentReturnToRalplanContext(candidate.value, options.artifacts)
88
+ : candidate.value,
89
+ }));
70
90
  return buildRalplanConsensusGateFromSources([
71
91
  ...(options.artifacts ? [
72
92
  { source: 'stage-context-artifacts', value: options.artifacts },
73
- { source: 'stage-context-ralplan-artifact', value: options.artifacts.ralplan },
93
+ {
94
+ source: 'stage-context-ralplan-artifact',
95
+ value: withParentReturnToRalplanContext(options.artifacts.ralplan, options.artifacts),
96
+ },
74
97
  ] : []),
75
- ...readLocalRalplanConsensusStateCandidates(cwd, options.sessionId),
98
+ ...localStateCandidates,
76
99
  ], {
77
100
  cwd,
78
101
  sessionId: options.sessionId,
@@ -93,59 +116,74 @@ export function readLocalRalplanConsensusStateCandidates(cwd, sessionId) {
93
116
  ? uniquePaths(sessionIdList.flatMap((id) => [
94
117
  join(scopedStateDir, 'sessions', id),
95
118
  join(localStateDir, 'sessions', id),
96
- ]))
97
- : [localStateDir];
98
- const paths = stateRoots.flatMap((dir) => [
99
- join(dir, 'ralplan-state.json'),
100
- join(dir, 'autopilot-state.json'),
119
+ ])).map((dir) => ({
120
+ dir,
121
+ sessionId: sessionIdFromStateRoot(dir),
122
+ }))
123
+ : [{ dir: localStateDir }];
124
+ const paths = stateRoots.flatMap(({ dir, sessionId }) => [
125
+ { path: join(dir, 'ralplan-state.json'), sessionId },
126
+ { path: join(dir, 'autopilot-state.json'), sessionId },
101
127
  ]);
102
- return paths.flatMap((path) => {
128
+ return paths.flatMap(({ path, sessionId }) => {
103
129
  const state = readJsonState(path);
104
130
  if (!state)
105
131
  return [];
106
- return [{ source: path, value: state }];
132
+ return [{ source: path, value: state, sessionId }];
107
133
  });
108
134
  }
109
- function extractSequentialConsensusEvidence(value) {
135
+ function resolveConsensusEvidence(value) {
110
136
  if (!value || typeof value !== 'object')
111
137
  return null;
112
138
  const record = value;
113
- const gate = record.ralplanConsensusGate ?? record.ralplan_consensus_gate;
114
- if (gate && typeof gate === 'object') {
115
- const gateRecord = gate;
116
- const architectReview = asRecord(gateRecord.ralplan_architect_review ?? gateRecord.architectReview ?? gateRecord.architect_review);
117
- const criticReview = asRecord(gateRecord.ralplan_critic_review ?? gateRecord.criticReview ?? gateRecord.critic_review);
118
- if (gateRecord.complete === true
119
- && hasArchitectThenCriticSequence(gateRecord)
120
- && isApproveReview(architectReview, 'architect')
121
- && isApproveReview(criticReview, 'critic')
122
- && isCriticNotBeforeArchitect(architectReview, criticReview)) {
123
- return { ralplan_architect_review: architectReview, ralplan_critic_review: criticReview };
139
+ const returnToRalplanCycle = isReturnToRalplanCycle(record);
140
+ const advancedReviewCycle = explicitFreshnessReviewCycle(record);
141
+ const staleReturnToRalplanCycle = returnToRalplanCycle && advancedReviewCycle === null;
142
+ const directGate = resolveDirectGate(record);
143
+ let deferredOrderedDirectGate = null;
144
+ if (directGate) {
145
+ if (!returnToRalplanCycle)
146
+ return directGate;
147
+ if (advancedReviewCycle !== null) {
148
+ if (reviewsCarryFreshnessCycle(directGate, advancedReviewCycle))
149
+ return directGate;
150
+ }
151
+ else if (!hasExplicitReturnToRalplanReviewCycle(record) && consensusEvidenceOrder(directGate) !== null) {
152
+ deferredOrderedDirectGate = directGate;
124
153
  }
125
154
  }
126
- const handoffArtifactsAreStale = isReturnToRalplanCycle(record);
155
+ const handoffArtifactsAreStale = staleReturnToRalplanCycle;
127
156
  const topLevelHandoffArtifacts = handoffArtifactsAreStale ? null : asRecord(record.handoff_artifacts);
128
157
  if (topLevelHandoffArtifacts) {
129
- const evidence = extractSequentialConsensusEvidence(topLevelHandoffArtifacts);
158
+ const evidence = resolveConsensusEvidence(withParentReturnToRalplanContext(topLevelHandoffArtifacts, record));
130
159
  if (evidence)
131
160
  return evidence;
132
161
  }
133
162
  const stateRecord = asRecord(record.state);
134
- const stateHandoffArtifacts = handoffArtifactsAreStale || (stateRecord && isReturnToRalplanCycle(stateRecord))
163
+ const stateHasOwnReturnLoopContext = stateRecord !== null && isReturnToRalplanCycle(stateRecord);
164
+ const stateHandoffArtifacts = handoffArtifactsAreStale && !stateHasOwnReturnLoopContext
135
165
  ? null
136
166
  : asRecord(stateRecord?.handoff_artifacts);
137
167
  if (stateHandoffArtifacts) {
138
- const evidence = extractSequentialConsensusEvidence(stateHandoffArtifacts);
168
+ const stateContext = stateHasOwnReturnLoopContext ? stateRecord : record;
169
+ const evidence = resolveConsensusEvidence(withParentReturnToRalplanContext(stateHandoffArtifacts, stateContext));
139
170
  if (evidence)
140
171
  return evidence;
141
172
  }
173
+ if (deferredOrderedDirectGate)
174
+ return deferredOrderedDirectGate;
175
+ if (returnToRalplanCycle && advancedReviewCycle === null)
176
+ return null;
142
177
  const directArchitectReview = asRecord(record.ralplan_architect_review);
143
178
  const directCriticReview = asRecord(record.ralplan_critic_review);
144
179
  if (hasArchitectThenCriticSequence(record)
145
180
  && isApproveReview(directArchitectReview, 'architect')
146
181
  && isApproveReview(directCriticReview, 'critic')
147
- && isCriticNotBeforeArchitect(directArchitectReview, directCriticReview)) {
182
+ && isCriticNotBeforeArchitect(directArchitectReview, directCriticReview)
183
+ && (!returnToRalplanCycle
184
+ || (advancedReviewCycle !== null && reviewPairCarriesFreshnessCycle(directArchitectReview, directCriticReview, advancedReviewCycle)))) {
148
185
  return {
186
+ kind: 'valid',
149
187
  ralplan_architect_review: directArchitectReview,
150
188
  ralplan_critic_review: directCriticReview,
151
189
  };
@@ -157,8 +195,10 @@ function extractSequentialConsensusEvidence(value) {
157
195
  const criticReview = asRecord(latestReviewEntry.ralplan_critic_review ?? latestReviewEntry.critic_review ?? latestReviewEntry.criticReview);
158
196
  if (isApproveReview(architectReview, 'architect')
159
197
  && isApproveReview(criticReview, 'critic')
160
- && isCriticNotBeforeArchitect(architectReview, criticReview)) {
161
- return { ralplan_architect_review: architectReview, ralplan_critic_review: criticReview };
198
+ && isCriticNotBeforeArchitect(architectReview, criticReview)
199
+ && (!returnToRalplanCycle
200
+ || (advancedReviewCycle !== null && reviewPairCarriesFreshnessCycle(architectReview, criticReview, advancedReviewCycle)))) {
201
+ return { kind: 'valid', ralplan_architect_review: architectReview, ralplan_critic_review: criticReview };
162
202
  }
163
203
  }
164
204
  const architectReviews = Array.isArray(record.architectReviews) ? record.architectReviews : [];
@@ -168,31 +208,45 @@ function extractSequentialConsensusEvidence(value) {
168
208
  const criticReview = asRecord(criticReviews.at(-1));
169
209
  if (isApproveReview(architectReview, 'architect')
170
210
  && isApproveReview(criticReview, 'critic')
171
- && isCriticNotBeforeArchitect(architectReview, criticReview)) {
172
- return { ralplan_architect_review: architectReview, ralplan_critic_review: criticReview };
211
+ && isCriticNotBeforeArchitect(architectReview, criticReview)
212
+ && (!returnToRalplanCycle
213
+ || (advancedReviewCycle !== null && reviewPairCarriesFreshnessCycle(architectReview, criticReview, advancedReviewCycle)))) {
214
+ return { kind: 'valid', ralplan_architect_review: architectReview, ralplan_critic_review: criticReview };
173
215
  }
174
216
  }
175
217
  return null;
176
218
  }
177
- function extractInvalidCompleteConsensusEvidence(value) {
178
- if (!value || typeof value !== 'object')
179
- return null;
180
- const record = value;
219
+ function resolveDirectGate(record) {
181
220
  const gate = record.ralplanConsensusGate ?? record.ralplan_consensus_gate;
182
221
  if (gate && typeof gate === 'object') {
183
222
  const gateRecord = gate;
184
223
  const architectReview = asRecord(gateRecord.ralplan_architect_review ?? gateRecord.architectReview ?? gateRecord.architect_review);
185
224
  const criticReview = asRecord(gateRecord.ralplan_critic_review ?? gateRecord.criticReview ?? gateRecord.critic_review);
186
- if (gateRecord.complete === true && hasArchitectThenCriticSequence(gateRecord)) {
225
+ if (gateRecord.complete === true
226
+ && hasArchitectThenCriticSequence(gateRecord)
227
+ && isApproveReview(architectReview, 'architect')
228
+ && isApproveReview(criticReview, 'critic')
229
+ && isCriticNotBeforeArchitect(architectReview, criticReview)) {
230
+ return {
231
+ kind: 'valid',
232
+ ralplan_architect_review: architectReview,
233
+ ralplan_critic_review: criticReview,
234
+ };
235
+ }
236
+ if (gateRecord.complete === true) {
187
237
  const blockedDetails = [
188
238
  ...reviewApprovalProblems(architectReview, 'architect'),
189
239
  ...reviewApprovalProblems(criticReview, 'critic'),
190
240
  ];
241
+ if (!hasArchitectThenCriticSequence(gateRecord)) {
242
+ blockedDetails.push('consensus review sequence is not architect-review then critic-review');
243
+ }
191
244
  if (!isCriticNotBeforeArchitect(architectReview, criticReview)) {
192
245
  blockedDetails.push('critic review is ordered before architect review');
193
246
  }
194
247
  if (blockedDetails.length > 0) {
195
248
  return {
249
+ kind: 'invalid',
196
250
  ralplan_architect_review: architectReview,
197
251
  ralplan_critic_review: criticReview,
198
252
  blockedDetails,
@@ -200,14 +254,93 @@ function extractInvalidCompleteConsensusEvidence(value) {
200
254
  }
201
255
  }
202
256
  }
203
- const stateHandoffArtifacts = asRecord(asRecord(record.state)?.handoff_artifacts);
204
- if (stateHandoffArtifacts) {
205
- const evidence = extractInvalidCompleteConsensusEvidence(stateHandoffArtifacts);
206
- if (evidence)
207
- return evidence;
208
- }
209
257
  return null;
210
258
  }
259
+ export function withParentReturnToRalplanContext(value, parent) {
260
+ const reason = parent.return_to_ralplan_reason ?? parent.returnToRalplanReason;
261
+ if (typeof reason !== 'string' || reason.trim() === '' || !value || typeof value !== 'object' || Array.isArray(value)) {
262
+ return value;
263
+ }
264
+ const record = value;
265
+ const parentReviewCycle = numericValue(parent.return_to_ralplan_parent_review_cycle
266
+ ?? parent.returnToRalplanParentReviewCycle
267
+ ?? parent.review_cycle
268
+ ?? parent.reviewCycle);
269
+ const inheritedReviewCycle = record.review_cycle ?? record.reviewCycle ?? parent.review_cycle ?? parent.reviewCycle;
270
+ return {
271
+ ...record,
272
+ review_cycle: inheritedReviewCycle,
273
+ current_phase: parent.current_phase ?? parent.currentPhase ?? 'ralplan',
274
+ return_to_ralplan_reason: reason,
275
+ return_to_ralplan_parent_review_cycle: parentReviewCycle,
276
+ };
277
+ }
278
+ function explicitFreshnessReviewCycle(record) {
279
+ const parentReviewCycle = numericValue(record.return_to_ralplan_parent_review_cycle ?? record.returnToRalplanParentReviewCycle);
280
+ const candidateReviewCycle = numericValue(record.review_cycle ?? record.reviewCycle);
281
+ return parentReviewCycle !== null
282
+ && candidateReviewCycle !== null
283
+ && candidateReviewCycle > parentReviewCycle
284
+ ? candidateReviewCycle
285
+ : null;
286
+ }
287
+ function reviewsCarryFreshnessCycle(evidence, reviewCycle) {
288
+ return reviewPairCarriesFreshnessCycle(evidence.ralplan_architect_review, evidence.ralplan_critic_review, reviewCycle);
289
+ }
290
+ function isConsensusEvidenceNewerThanSelected(evidence, selected) {
291
+ if (!selected)
292
+ return true;
293
+ const evidenceCycle = consensusEvidenceReviewCycle(evidence);
294
+ const selectedCycle = consensusEvidenceReviewCycle(selected);
295
+ if (evidenceCycle !== null || selectedCycle !== null) {
296
+ if (selectedCycle === null)
297
+ return true;
298
+ if (evidenceCycle === null)
299
+ return false;
300
+ if (evidenceCycle !== selectedCycle)
301
+ return evidenceCycle > selectedCycle;
302
+ }
303
+ const evidenceOrder = consensusEvidenceOrder(evidence);
304
+ const selectedOrder = consensusEvidenceOrder(selected);
305
+ if (evidenceOrder !== null || selectedOrder !== null) {
306
+ if (selectedOrder === null)
307
+ return true;
308
+ if (evidenceOrder === null)
309
+ return false;
310
+ if (evidenceOrder !== selectedOrder)
311
+ return evidenceOrder > selectedOrder;
312
+ }
313
+ return false;
314
+ }
315
+ function consensusEvidenceReviewCycle(evidence) {
316
+ return maxKnownNumber(numericValue(evidence.ralplan_architect_review?.review_cycle ?? evidence.ralplan_architect_review?.reviewCycle), numericValue(evidence.ralplan_critic_review?.review_cycle ?? evidence.ralplan_critic_review?.reviewCycle));
317
+ }
318
+ function consensusEvidenceOrder(evidence) {
319
+ return maxKnownNumber(reviewOrderValue(evidence.ralplan_architect_review ?? {}), reviewOrderValue(evidence.ralplan_critic_review ?? {}));
320
+ }
321
+ function maxKnownNumber(left, right) {
322
+ if (left === null)
323
+ return right;
324
+ if (right === null)
325
+ return left;
326
+ return Math.max(left, right);
327
+ }
328
+ function hasExplicitReturnToRalplanReviewCycle(record) {
329
+ return numericValue(record.review_cycle ?? record.reviewCycle) !== null
330
+ || numericValue(record.return_to_ralplan_parent_review_cycle ?? record.returnToRalplanParentReviewCycle) !== null;
331
+ }
332
+ function reviewPairCarriesFreshnessCycle(architectReview, criticReview, reviewCycle) {
333
+ return reviewCarriesFreshnessCycle(architectReview, reviewCycle)
334
+ && reviewCarriesFreshnessCycle(criticReview, reviewCycle);
335
+ }
336
+ function reviewCarriesFreshnessCycle(review, reviewCycle) {
337
+ const cycle = numericValue(review?.review_cycle ?? review?.reviewCycle);
338
+ return cycle !== null && cycle >= reviewCycle;
339
+ }
340
+ function numericValue(value) {
341
+ const parsed = typeof value === 'number' ? value : typeof value === 'string' ? Number(value) : Number.NaN;
342
+ return Number.isFinite(parsed) ? parsed : null;
343
+ }
211
344
  function asRecord(value) {
212
345
  return value && typeof value === 'object' ? value : null;
213
346
  }
@@ -288,9 +421,7 @@ function reviewOrderValue(review) {
288
421
  return null;
289
422
  }
290
423
  function hasTrackerBackedNativeRalplanLanes(evidence, options) {
291
- const architectThreadId = nativeReviewThreadId(evidence.ralplan_architect_review);
292
- const criticThreadId = nativeReviewThreadId(evidence.ralplan_critic_review);
293
- if (!architectThreadId || !criticThreadId || architectThreadId === criticThreadId)
424
+ if (trackerBackedNativeReviewPairProblem(evidence, options))
294
425
  return false;
295
426
  return isTrackerBackedNativeReview(evidence.ralplan_architect_review, 'architect', options)
296
427
  && isTrackerBackedNativeReview(evidence.ralplan_critic_review, 'critic', options);
@@ -298,9 +429,86 @@ function hasTrackerBackedNativeRalplanLanes(evidence, options) {
298
429
  function nativeReviewThreadId(review) {
299
430
  return typeof review?.thread_id === 'string' ? review.thread_id.trim() : '';
300
431
  }
432
+ function currentTransitionSessionId(evidence, options) {
433
+ const transitionSessionId = typeof options.sessionId === 'string' ? options.sessionId.trim() : '';
434
+ return transitionSessionId
435
+ || nativeReviewSessionId(evidence.ralplan_architect_review)
436
+ || nativeReviewSessionId(evidence.ralplan_critic_review);
437
+ }
438
+ function buildTrackerBackedNativeConsensusDiagnostic(evidence, options) {
439
+ const cwd = typeof options.cwd === 'string' ? options.cwd.trim() : '';
440
+ const trackerPath = cwd ? subagentTrackingPath(cwd) : '.omx/state/subagent-tracking.json';
441
+ const currentSessionId = currentTransitionSessionId(evidence, options);
442
+ const architectThreadId = nativeReviewThreadId(evidence.ralplan_architect_review);
443
+ const criticThreadId = nativeReviewThreadId(evidence.ralplan_critic_review);
444
+ return {
445
+ expected_schema: [
446
+ '.omx/state/subagent-tracking.json contains:',
447
+ 'sessions["<current_session_id>"].threads["<architect_thread_id>"].kind = "subagent"',
448
+ 'sessions["<current_session_id>"].threads["<critic_thread_id>"].kind = "subagent"',
449
+ 'both threads have completed_at',
450
+ 'architect and critic thread IDs are distinct',
451
+ ],
452
+ current_session_id: currentSessionId || null,
453
+ tracker_path: trackerPath,
454
+ architect: buildNativeReviewDiagnostic(evidence.ralplan_architect_review, 'architect', options),
455
+ critic: buildNativeReviewDiagnostic(evidence.ralplan_critic_review, 'critic', options),
456
+ distinct_thread_ids: architectThreadId && criticThreadId ? architectThreadId !== criticThreadId : null,
457
+ pair_problem: trackerBackedNativeReviewPairProblem(evidence, options),
458
+ remediation: [
459
+ 'Re-run native ralplan Architect/Critic reviews.',
460
+ 'Or repair the review artifact so agent_role, provenance_kind, session_id, thread_id, and tracker_path point to completed native subagent threads in the current tracker.',
461
+ ],
462
+ docs: 'docs/contracts/ralplan-consensus-gate.md',
463
+ };
464
+ }
465
+ function buildNativeReviewDiagnostic(review, agentRole, options) {
466
+ const cwd = typeof options.cwd === 'string' ? options.cwd.trim() : '';
467
+ const trackerPath = cwd ? subagentTrackingPath(cwd) : '.omx/state/subagent-tracking.json';
468
+ const problem = trackerBackedNativeReviewProblem(review, agentRole, options);
469
+ const sessionId = review
470
+ ? (typeof options.sessionId === 'string' && options.sessionId.trim()
471
+ ? options.sessionId.trim()
472
+ : nativeReviewSessionId(review))
473
+ : '';
474
+ const threadId = nativeReviewThreadId(review);
475
+ const tracking = cwd && sessionId ? readJsonState(trackerPath) : null;
476
+ const session = asRecord(asRecord(tracking?.sessions)?.[sessionId]);
477
+ const thread = asRecord(asRecord(session?.threads)?.[threadId]);
478
+ const completedAt = typeof thread?.completed_at === 'string' ? thread.completed_at.trim() : '';
479
+ return {
480
+ role: agentRole,
481
+ session_id: sessionId || null,
482
+ thread_id: threadId || null,
483
+ tracker_path: trackerPath,
484
+ session_found: Boolean(session),
485
+ thread_found: Boolean(thread),
486
+ kind: typeof thread?.kind === 'string' ? thread.kind : null,
487
+ completed: Boolean(completedAt),
488
+ problem,
489
+ };
490
+ }
491
+ function trackerBackedNativeReviewPairProblem(evidence, options) {
492
+ const architectThreadId = nativeReviewThreadId(evidence.ralplan_architect_review);
493
+ const criticThreadId = nativeReviewThreadId(evidence.ralplan_critic_review);
494
+ if (architectThreadId && criticThreadId && architectThreadId === criticThreadId) {
495
+ return 'architect and critic reviews must reference distinct native subagent tracker threads';
496
+ }
497
+ const transitionSessionId = typeof options.sessionId === 'string' ? options.sessionId.trim() : '';
498
+ const architectSessionId = transitionSessionId || nativeReviewSessionId(evidence.ralplan_architect_review);
499
+ const criticSessionId = transitionSessionId || nativeReviewSessionId(evidence.ralplan_critic_review);
500
+ if (!architectSessionId || !criticSessionId)
501
+ return null;
502
+ return architectSessionId === criticSessionId
503
+ ? null
504
+ : `architect and critic reviews must resolve to the same native subagent tracker session; architect session_id=${architectSessionId}, critic session_id=${criticSessionId}`;
505
+ }
301
506
  function isTrackerBackedNativeReview(review, agentRole, options) {
302
507
  return trackerBackedNativeReviewProblem(review, agentRole, options) === null;
303
508
  }
509
+ function nativeReviewSessionId(review) {
510
+ return typeof review?.session_id === 'string' ? review.session_id.trim() : '';
511
+ }
304
512
  function trackerBackedNativeReviewProblem(review, agentRole, options) {
305
513
  const issues = [];
306
514
  if (!review)
@@ -316,18 +524,15 @@ function trackerBackedNativeReviewProblem(review, agentRole, options) {
316
524
  : '';
317
525
  const reviewSessionId = typeof review.session_id === 'string' ? review.session_id.trim() : '';
318
526
  const threadId = typeof review.thread_id === 'string' ? review.thread_id.trim() : '';
319
- const artifactPath = typeof review.artifact_path === 'string' ? review.artifact_path.trim() : '';
320
527
  const trackerPath = typeof review.tracker_path === 'string' ? review.tracker_path.trim() : '';
321
528
  if (!sessionId)
322
529
  issues.push(`${agentRole} review cannot resolve session_id`);
323
- if (!reviewSessionId || reviewSessionId !== sessionId)
324
- issues.push(`${agentRole} review session_id=${reviewSessionId || 'missing'} does not match ${sessionId || 'missing'}`);
530
+ if (reviewSessionId && reviewSessionId !== sessionId)
531
+ issues.push(`${agentRole} review session_id=${reviewSessionId} does not match ${sessionId || 'missing'}`);
325
532
  if (!threadId)
326
533
  issues.push(`${agentRole} review missing thread_id`);
327
- if (!artifactPath)
328
- issues.push(`${agentRole} review missing artifact_path`);
329
- if (!trackerPath || !trackerPath.endsWith('subagent-tracking.json'))
330
- issues.push(`${agentRole} review missing subagent-tracking.json tracker_path`);
534
+ if (trackerPath && !trackerPath.endsWith('subagent-tracking.json'))
535
+ issues.push(`${agentRole} review tracker_path=${trackerPath} is not subagent-tracking.json`);
331
536
  const cwd = typeof options.cwd === 'string' ? options.cwd.trim() : '';
332
537
  if (!cwd)
333
538
  issues.push(`${agentRole} review cannot resolve cwd for tracker lookup`);
@@ -348,6 +553,9 @@ function trackerBackedNativeReviewProblem(review, agentRole, options) {
348
553
  return `${agentRole} tracker thread ${threadId} is the session leader`;
349
554
  if (thread.kind !== 'subagent')
350
555
  return `${agentRole} tracker thread ${threadId} has kind=${String(thread.kind || 'missing')}`;
556
+ const completedAt = typeof thread.completed_at === 'string' ? thread.completed_at.trim() : '';
557
+ if (!completedAt)
558
+ return `${agentRole} tracker thread ${threadId} is not completed`;
351
559
  return null;
352
560
  }
353
561
  function currentSessionNativeLeaderThreadId(cwd) {
@@ -399,6 +607,12 @@ function readLocalCurrentSessionIds(cwd) {
399
607
  function localBaseStateDir(cwd) {
400
608
  return join(resolveWorkingDirectoryForState(cwd), '.omx', 'state');
401
609
  }
610
+ function sessionIdFromStateRoot(path) {
611
+ const normalized = path.replace(/\\/g, '/');
612
+ const match = /\/sessions\/([^/]+)$/.exec(normalized);
613
+ const sessionId = match?.[1];
614
+ return sessionId && validateLocalSessionId(sessionId).length > 0 ? sessionId : undefined;
615
+ }
402
616
  function uniquePaths(paths) {
403
617
  return [...new Set(paths)];
404
618
  }