@bastani/atomic 0.9.5-alpha.7 → 0.9.5-alpha.9

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/CHANGELOG.md +33 -2
  2. package/dist/builtin/cursor/package.json +2 -2
  3. package/dist/builtin/intercom/CHANGELOG.md +17 -0
  4. package/dist/builtin/intercom/README.md +27 -21
  5. package/dist/builtin/intercom/broker/broker.ts +3 -6
  6. package/dist/builtin/intercom/broker/paths.ts +42 -5
  7. package/dist/builtin/intercom/broker/spawn.ts +78 -10
  8. package/dist/builtin/intercom/config.ts +6 -3
  9. package/dist/builtin/intercom/contact-supervisor-tool.ts +6 -4
  10. package/dist/builtin/intercom/index-heavy.ts +1 -1
  11. package/dist/builtin/intercom/index.ts +162 -130
  12. package/dist/builtin/intercom/intercom-tool.ts +9 -3
  13. package/dist/builtin/intercom/package.json +10 -1
  14. package/dist/builtin/intercom/result-renderers.ts +1 -1
  15. package/dist/builtin/intercom/ui/compose.ts +2 -2
  16. package/dist/builtin/intercom/ui/inline-message.ts +2 -2
  17. package/dist/builtin/intercom/ui/session-list.ts +2 -2
  18. package/dist/builtin/mcp/CHANGELOG.md +11 -0
  19. package/dist/builtin/mcp/README.md +6 -6
  20. package/dist/builtin/mcp/direct-tools.ts +41 -23
  21. package/dist/builtin/mcp/index.ts +31 -4
  22. package/dist/builtin/mcp/init.ts +4 -43
  23. package/dist/builtin/mcp/metadata-hydration.ts +37 -0
  24. package/dist/builtin/mcp/package.json +1 -1
  25. package/dist/builtin/mcp/proxy-info-modes.ts +67 -14
  26. package/dist/builtin/mcp/startup-warmup.ts +98 -0
  27. package/dist/builtin/mcp/tool-result-renderer.ts +3 -3
  28. package/dist/builtin/subagents/CHANGELOG.md +18 -0
  29. package/dist/builtin/subagents/package.json +1 -1
  30. package/dist/builtin/subagents/src/extension/index.ts +14 -25
  31. package/dist/builtin/subagents/src/extension/startup-maintenance.ts +89 -0
  32. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +23 -18
  33. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +20 -10
  34. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +13 -3
  35. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +10 -2
  36. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +28 -1
  37. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +15 -48
  38. package/dist/builtin/subagents/src/tui/render-layout.ts +9 -0
  39. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +27 -25
  40. package/dist/builtin/subagents/src/tui/render-widget.ts +72 -66
  41. package/dist/builtin/subagents/src/tui/render.ts +1 -1
  42. package/dist/builtin/web-access/package.json +1 -1
  43. package/dist/builtin/workflows/CHANGELOG.md +29 -0
  44. package/dist/builtin/workflows/README.md +4 -2
  45. package/dist/builtin/workflows/builtin/goal-artifacts.ts +3 -1
  46. package/dist/builtin/workflows/builtin/goal-prompts.ts +23 -2
  47. package/dist/builtin/workflows/builtin/goal-reducer.ts +21 -0
  48. package/dist/builtin/workflows/builtin/goal-review.ts +60 -6
  49. package/dist/builtin/workflows/builtin/goal-runner.ts +71 -22
  50. package/dist/builtin/workflows/builtin/goal-types.ts +7 -1
  51. package/dist/builtin/workflows/builtin/ralph-core.ts +52 -4
  52. package/dist/builtin/workflows/builtin/ralph-review-gate.ts +10 -3
  53. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +23 -2
  54. package/dist/builtin/workflows/builtin/ralph-runner.ts +38 -16
  55. package/dist/builtin/workflows/builtin/review-convergence.ts +111 -0
  56. package/dist/builtin/workflows/package.json +1 -1
  57. package/dist/builtin/workflows/skills/create-spec/SKILL.md +2 -0
  58. package/dist/builtin/workflows/skills/impeccable/SKILL.md +16 -13
  59. package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +1 -0
  60. package/dist/builtin/workflows/skills/impeccable/reference/adapt.native.md +58 -0
  61. package/dist/builtin/workflows/skills/impeccable/reference/android.md +40 -0
  62. package/dist/builtin/workflows/skills/impeccable/reference/animate.md +2 -0
  63. package/dist/builtin/workflows/skills/impeccable/reference/audit.md +2 -0
  64. package/dist/builtin/workflows/skills/impeccable/reference/audit.native.md +139 -0
  65. package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +69 -62
  66. package/dist/builtin/workflows/skills/impeccable/reference/critique.md +21 -7
  67. package/dist/builtin/workflows/skills/impeccable/reference/document.md +1 -1
  68. package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +92 -0
  69. package/dist/builtin/workflows/skills/impeccable/reference/init.md +29 -7
  70. package/dist/builtin/workflows/skills/impeccable/reference/ios.md +45 -0
  71. package/dist/builtin/workflows/skills/impeccable/reference/layout.md +25 -1
  72. package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +23 -1
  73. package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +2 -1
  74. package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +75 -14
  75. package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +1 -1
  76. package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +31 -0
  77. package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +64 -0
  78. package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +118 -11
  79. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +16 -11
  80. package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +66 -0
  81. package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +42 -10
  82. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/fonts.mjs +30 -0
  83. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/page.mjs +4 -6
  84. package/dist/builtin/workflows/skills/impeccable/scripts/hook-admin.mjs +660 -0
  85. package/dist/builtin/workflows/skills/impeccable/scripts/hook-before-edit.mjs +516 -0
  86. package/dist/builtin/workflows/skills/impeccable/scripts/hook-lib.mjs +1764 -0
  87. package/dist/builtin/workflows/skills/impeccable/scripts/hook.mjs +61 -0
  88. package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +4 -2
  89. package/dist/builtin/workflows/skills/impeccable/scripts/lib/is-generated.mjs +2 -2
  90. package/dist/builtin/workflows/skills/impeccable/scripts/live/svelte-component.mjs +13 -16
  91. package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +17 -11
  92. package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +104 -37
  93. package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +9 -0
  94. package/dist/builtin/workflows/src/durable/backend.ts +12 -0
  95. package/dist/builtin/workflows/src/durable/child-primitive.ts +12 -8
  96. package/dist/builtin/workflows/src/durable/dbos-backend.ts +63 -2
  97. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +28 -0
  98. package/dist/builtin/workflows/src/durable/resume-catalog.ts +12 -0
  99. package/dist/builtin/workflows/src/durable/resume-runtime.ts +5 -2
  100. package/dist/builtin/workflows/src/durable/stage-primitive.ts +165 -27
  101. package/dist/builtin/workflows/src/durable/types.ts +30 -1
  102. package/dist/builtin/workflows/src/engine/primitives/task.ts +1 -0
  103. package/dist/builtin/workflows/src/engine/run-durable-finalize.ts +1 -2
  104. package/dist/builtin/workflows/src/engine/run-returned-status.ts +50 -16
  105. package/dist/builtin/workflows/src/engine/run.ts +32 -32
  106. package/dist/builtin/workflows/src/engine/runtime.ts +5 -0
  107. package/dist/builtin/workflows/src/extension/extension-factory.ts +3 -0
  108. package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +9 -2
  109. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +137 -27
  110. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +22 -6
  111. package/dist/builtin/workflows/src/extension/public-types.ts +1 -1
  112. package/dist/builtin/workflows/src/extension/workflow-command-completions.ts +13 -1
  113. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +19 -4
  114. package/dist/builtin/workflows/src/extension/workflow-command-surfaces.ts +9 -0
  115. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +2 -0
  116. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +48 -23
  117. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +20 -8
  118. package/dist/builtin/workflows/src/extension/workflow-tool.ts +24 -8
  119. package/dist/builtin/workflows/src/runs/background/status.ts +4 -3
  120. package/dist/builtin/workflows/src/runs/foreground/executor-continuation.ts +13 -3
  121. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +29 -8
  122. package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +2 -1
  123. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +4 -3
  124. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +18 -19
  125. package/dist/builtin/workflows/src/runs/foreground/stage-runner-unresolved-overflow.ts +38 -0
  126. package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +155 -20
  127. package/dist/builtin/workflows/src/runs/shared/worktree-types.ts +6 -0
  128. package/dist/builtin/workflows/src/runs/shared/worktree.ts +2 -1
  129. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +18 -1
  130. package/dist/builtin/workflows/src/shared/persistence-restore.ts +23 -5
  131. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
  132. package/dist/builtin/workflows/src/shared/returned-run-status.ts +116 -0
  133. package/dist/builtin/workflows/src/shared/workflow-failures-decisions.ts +2 -0
  134. package/dist/builtin/workflows/src/tui/graph-view-render-helpers.ts +21 -3
  135. package/dist/builtin/workflows/src/tui/graph-view-state.ts +3 -0
  136. package/dist/builtin/workflows/src/tui/graph-view-types.ts +3 -0
  137. package/dist/builtin/workflows/src/tui/status-list.ts +22 -15
  138. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +4 -4
  139. package/dist/bun/internal-intercom-broker.d.ts +6 -0
  140. package/dist/bun/internal-intercom-broker.d.ts.map +1 -0
  141. package/dist/bun/internal-intercom-broker.js +39 -0
  142. package/dist/bun/internal-intercom-broker.js.map +1 -0
  143. package/dist/bun/split-loader.d.ts.map +1 -1
  144. package/dist/bun/split-loader.js +21 -8
  145. package/dist/bun/split-loader.js.map +1 -1
  146. package/dist/core/agent-session-auto-compaction.d.ts +21 -2
  147. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  148. package/dist/core/agent-session-auto-compaction.js +163 -11
  149. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  150. package/dist/core/agent-session-events.d.ts.map +1 -1
  151. package/dist/core/agent-session-events.js +10 -1
  152. package/dist/core/agent-session-events.js.map +1 -1
  153. package/dist/core/agent-session-methods.d.ts +12 -3
  154. package/dist/core/agent-session-methods.d.ts.map +1 -1
  155. package/dist/core/agent-session-methods.js.map +1 -1
  156. package/dist/core/agent-session-models.d.ts +2 -2
  157. package/dist/core/agent-session-models.d.ts.map +1 -1
  158. package/dist/core/agent-session-models.js.map +1 -1
  159. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  160. package/dist/core/agent-session-prompt.js +1 -0
  161. package/dist/core/agent-session-prompt.js.map +1 -1
  162. package/dist/core/agent-session-retry.d.ts +2 -0
  163. package/dist/core/agent-session-retry.d.ts.map +1 -1
  164. package/dist/core/agent-session-retry.js +152 -4
  165. package/dist/core/agent-session-retry.js.map +1 -1
  166. package/dist/core/agent-session-services.d.ts +1 -0
  167. package/dist/core/agent-session-services.d.ts.map +1 -1
  168. package/dist/core/agent-session-services.js +1 -0
  169. package/dist/core/agent-session-services.js.map +1 -1
  170. package/dist/core/agent-session-types.d.ts +15 -1
  171. package/dist/core/agent-session-types.d.ts.map +1 -1
  172. package/dist/core/agent-session-types.js.map +1 -1
  173. package/dist/core/agent-session.d.ts +6 -0
  174. package/dist/core/agent-session.d.ts.map +1 -1
  175. package/dist/core/agent-session.js +6 -0
  176. package/dist/core/agent-session.js.map +1 -1
  177. package/dist/core/compaction/context-compaction-runner.d.ts.map +1 -1
  178. package/dist/core/compaction/context-compaction-runner.js +36 -20
  179. package/dist/core/compaction/context-compaction-runner.js.map +1 -1
  180. package/dist/core/copilot-anthropic-sse-repair.d.ts +23 -0
  181. package/dist/core/copilot-anthropic-sse-repair.d.ts.map +1 -0
  182. package/dist/core/copilot-anthropic-sse-repair.js +340 -0
  183. package/dist/core/copilot-anthropic-sse-repair.js.map +1 -0
  184. package/dist/core/copilot-gemini-reasoning.d.ts +16 -8
  185. package/dist/core/copilot-gemini-reasoning.d.ts.map +1 -1
  186. package/dist/core/copilot-gemini-reasoning.js +27 -22
  187. package/dist/core/copilot-gemini-reasoning.js.map +1 -1
  188. package/dist/core/copilot-hosts.d.ts +12 -0
  189. package/dist/core/copilot-hosts.d.ts.map +1 -0
  190. package/dist/core/copilot-hosts.js +33 -0
  191. package/dist/core/copilot-hosts.js.map +1 -0
  192. package/dist/core/extensions/agent-events.d.ts +1 -1
  193. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  194. package/dist/core/extensions/agent-events.js.map +1 -1
  195. package/dist/core/extensions/loader-virtual-modules.d.ts +8 -1
  196. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  197. package/dist/core/extensions/loader-virtual-modules.js +2 -1
  198. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  199. package/dist/core/footer-data-provider.d.ts +6 -0
  200. package/dist/core/footer-data-provider.d.ts.map +1 -1
  201. package/dist/core/footer-data-provider.js +72 -29
  202. package/dist/core/footer-data-provider.js.map +1 -1
  203. package/dist/core/http-dispatcher.d.ts.map +1 -1
  204. package/dist/core/http-dispatcher.js +5 -5
  205. package/dist/core/http-dispatcher.js.map +1 -1
  206. package/dist/core/openai-responses-payload-sanitizer.d.ts +1 -0
  207. package/dist/core/openai-responses-payload-sanitizer.d.ts.map +1 -1
  208. package/dist/core/openai-responses-payload-sanitizer.js +24 -9
  209. package/dist/core/openai-responses-payload-sanitizer.js.map +1 -1
  210. package/dist/core/sdk-types.d.ts +2 -0
  211. package/dist/core/sdk-types.d.ts.map +1 -1
  212. package/dist/core/sdk-types.js.map +1 -1
  213. package/dist/core/sdk.d.ts.map +1 -1
  214. package/dist/core/sdk.js +1 -0
  215. package/dist/core/sdk.js.map +1 -1
  216. package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
  217. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  218. package/dist/core/settings-manager-basic-accessors.js +6 -0
  219. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  220. package/dist/core/settings-types.d.ts +1 -0
  221. package/dist/core/settings-types.d.ts.map +1 -1
  222. package/dist/core/settings-types.js.map +1 -1
  223. package/dist/core/slash-commands.d.ts +2 -0
  224. package/dist/core/slash-commands.d.ts.map +1 -1
  225. package/dist/core/slash-commands.js +141 -0
  226. package/dist/core/slash-commands.js.map +1 -1
  227. package/dist/index-extensions.d.ts +1 -1
  228. package/dist/index-extensions.d.ts.map +1 -1
  229. package/dist/index-extensions.js.map +1 -1
  230. package/dist/index.d.ts +1 -0
  231. package/dist/index.d.ts.map +1 -1
  232. package/dist/index.js +1 -0
  233. package/dist/index.js.map +1 -1
  234. package/dist/main-deferred-startup.d.ts +12 -0
  235. package/dist/main-deferred-startup.d.ts.map +1 -1
  236. package/dist/main-deferred-startup.js +23 -2
  237. package/dist/main-deferred-startup.js.map +1 -1
  238. package/dist/main-early-input.d.ts +41 -0
  239. package/dist/main-early-input.d.ts.map +1 -0
  240. package/dist/main-early-input.js +154 -0
  241. package/dist/main-early-input.js.map +1 -0
  242. package/dist/main.d.ts +0 -6
  243. package/dist/main.d.ts.map +1 -1
  244. package/dist/main.js +20 -14
  245. package/dist/main.js.map +1 -1
  246. package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
  247. package/dist/modes/interactive/components/chat-session-host-actions.js +0 -1
  248. package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
  249. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  250. package/dist/modes/interactive/components/chat-session-host-events.js +15 -0
  251. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  252. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  253. package/dist/modes/interactive/interactive-agent-events.js +25 -0
  254. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  255. package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  256. package/dist/modes/interactive/interactive-autocomplete.js +21 -9
  257. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  258. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
  259. package/dist/modes/interactive/interactive-deferred-startup.js +41 -28
  260. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
  261. package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
  262. package/dist/modes/interactive/interactive-hotkeys-debug.js +1 -0
  263. package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
  264. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  265. package/dist/modes/interactive/interactive-input-handling.js +318 -185
  266. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  267. package/dist/modes/interactive/interactive-mode-base.d.ts +12 -0
  268. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  269. package/dist/modes/interactive/interactive-mode-base.js +39 -0
  270. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  271. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  272. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  273. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  274. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  275. package/dist/modes/interactive/interactive-mode-surface.d.ts +6 -2
  276. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  277. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  278. package/dist/modes/interactive/interactive-mode-types.d.ts +3 -0
  279. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  280. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  281. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  282. package/dist/modes/interactive/interactive-model-routing.js +3 -1
  283. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  284. package/dist/modes/interactive/interactive-process-lifecycle.d.ts.map +1 -1
  285. package/dist/modes/interactive/interactive-process-lifecycle.js +0 -3
  286. package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
  287. package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
  288. package/dist/modes/interactive/interactive-render-chat.js +36 -10
  289. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  290. package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
  291. package/dist/modes/interactive/interactive-session-routing.js +5 -1
  292. package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
  293. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  294. package/dist/modes/interactive/interactive-startup.js +26 -22
  295. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  296. package/dist/modes/interactive/theme/global-theme.d.ts.map +1 -1
  297. package/dist/modes/interactive/theme/global-theme.js +26 -2
  298. package/dist/modes/interactive/theme/global-theme.js.map +1 -1
  299. package/dist/utils/fs-watch.d.ts +24 -1
  300. package/dist/utils/fs-watch.d.ts.map +1 -1
  301. package/dist/utils/fs-watch.js +60 -5
  302. package/dist/utils/fs-watch.js.map +1 -1
  303. package/docs/compaction.md +8 -0
  304. package/docs/development.md +4 -0
  305. package/docs/extensions.md +5 -0
  306. package/docs/json.md +3 -1
  307. package/docs/providers.md +1 -0
  308. package/docs/quickstart.md +1 -1
  309. package/docs/rpc.md +3 -1
  310. package/docs/settings.md +27 -1
  311. package/docs/subagents.md +4 -0
  312. package/docs/terminal-setup.md +4 -0
  313. package/docs/usage.md +2 -2
  314. package/docs/windows.md +4 -0
  315. package/docs/workflows.md +21 -9
  316. package/npm-shrinkwrap.json +513 -23
  317. package/package.json +3 -2
@@ -1,4 +1,19 @@
1
1
  import type { BlockerObservation, GoalLedger, ReducerOutcome, ReviewRecord } from "./goal-types.js";
2
+ import { summarizeReviewConvergence, type ReviewNextAction } from "./review-convergence.js";
3
+
4
+ function reducerSummary(
5
+ reviews: readonly ReviewRecord[],
6
+ approved: boolean,
7
+ nextAction: ReviewNextAction,
8
+ ) {
9
+ return summarizeReviewConvergence({
10
+ parsed: reviews.every((review) => review.parsed),
11
+ approved,
12
+ stopReviewLoop: approved,
13
+ nextAction,
14
+ diagnostics: reviews.flatMap((review) => review.parse_diagnostics),
15
+ });
16
+ }
2
17
 
3
18
  export function normalizeBlocker(blocker: string): string {
4
19
  return blocker.toLowerCase().replace(/\s+/g, " ").trim();
@@ -68,6 +83,7 @@ export function reduceGoalDecision(
68
83
  readonly maxTurns: number;
69
84
  readonly reviewQuorum: number;
70
85
  readonly blockerThreshold: number;
86
+ readonly nextActionOnComplete: ReviewNextAction;
71
87
  },
72
88
  ): ReducerOutcome {
73
89
  const completeVotes = turnReviews.filter(
@@ -75,9 +91,11 @@ export function reduceGoalDecision(
75
91
  ).length;
76
92
 
77
93
  if (completeVotes >= options.reviewQuorum) {
94
+ const summary = reducerSummary(turnReviews, true, options.nextActionOnComplete);
78
95
  return {
79
96
  status: "complete",
80
97
  decision: {
98
+ ...summary,
81
99
  turn: options.turn,
82
100
  decision: "complete",
83
101
  reason: `Reviewer quorum met: ${completeVotes}/${options.reviewQuorum} reviewers marked complete.`,
@@ -101,6 +119,7 @@ export function reduceGoalDecision(
101
119
  status: "blocked",
102
120
  blockerObservation: observation,
103
121
  decision: {
122
+ ...reducerSummary(turnReviews, false, "blocked"),
104
123
  turn: options.turn,
105
124
  decision: "blocked",
106
125
  reason: `Same blocker repeated for ${blockerCount}/${options.blockerThreshold} consecutive controller observations.`,
@@ -116,6 +135,7 @@ export function reduceGoalDecision(
116
135
  status: "needs_human",
117
136
  blockerObservation: observation,
118
137
  decision: {
138
+ ...reducerSummary(turnReviews, false, "needs_human"),
119
139
  turn: options.turn,
120
140
  decision: "needs_human",
121
141
  reason: `Worker attempt budget reached without reviewer quorum. Remaining work: ${collectRemainingWork(turnReviews)}`,
@@ -130,6 +150,7 @@ export function reduceGoalDecision(
130
150
  status: "active",
131
151
  blockerObservation: observation,
132
152
  decision: {
153
+ ...reducerSummary(turnReviews, false, "implementation"),
133
154
  turn: options.turn,
134
155
  decision: "continue",
135
156
  reason: `Reviewer quorum not met. Remaining work: ${collectRemainingWork(turnReviews)}`,
@@ -1,10 +1,33 @@
1
1
  import type { WorkflowTaskResult } from "../src/shared/types.js";
2
2
  import type { ReviewDecision, ReviewRecord } from "./goal-types.js";
3
+ import {
4
+ finalActionRemaining,
5
+ parseFailureDiagnostics,
6
+ summarizeReviewConvergence,
7
+ traceabilityProvenExceptFinalAction,
8
+ type ParsedReviewDecision,
9
+ } from "./review-convergence.js";
3
10
 
4
11
  export function reviewDecisionFromResult(result: WorkflowTaskResult): ReviewDecision | undefined {
5
12
  return result.structured as ReviewDecision | undefined;
6
13
  }
7
14
 
15
+ export function parsedReviewDecisionFromResult(
16
+ result: WorkflowTaskResult,
17
+ reviewer: string,
18
+ ): ParsedReviewDecision<ReviewDecision> {
19
+ const parsed = reviewDecisionFromResult(result);
20
+ if (parsed !== undefined) {
21
+ return { decision: parsed, parsed: true, diagnostics: [] };
22
+ }
23
+ const diagnostics = parseFailureDiagnostics(reviewer, result.text);
24
+ return {
25
+ decision: reviewerErrorDecision(diagnostics.join("\n")),
26
+ parsed: false,
27
+ diagnostics,
28
+ };
29
+ }
30
+
8
31
  const NON_BLOCKING_ALIGNMENTS = new Set([
9
32
  "beyond_objective",
10
33
  "contradicts_objective",
@@ -19,18 +42,26 @@ function findingBlocksApproval(finding: ReviewDecision["findings"][number]): boo
19
42
  return finding.priority !== 3;
20
43
  }
21
44
 
22
- function traceabilityApproves(decision: ReviewDecision): boolean {
23
- return decision.requirements_traceability.length > 0 &&
24
- decision.requirements_traceability.every((entry) => entry.status === "proven");
45
+ function traceabilityApproves(
46
+ decision: ReviewDecision,
47
+ allowFinalActionRemaining: boolean,
48
+ ): boolean {
49
+ return traceabilityProvenExceptFinalAction({
50
+ traceability: decision.requirements_traceability,
51
+ allowFinalActionRemaining,
52
+ });
25
53
  }
26
54
 
27
- export function reviewApproved(decision: ReviewDecision): boolean {
55
+ export function reviewApproved(
56
+ decision: ReviewDecision,
57
+ options: { readonly allowFinalActionRemaining?: boolean } = {},
58
+ ): boolean {
28
59
  const hasBlockingFindings = decision.findings.some(findingBlocksApproval);
29
60
  return (
30
61
  decision.stop_review_loop === true &&
31
62
  decision.overall_correctness === "patch is correct" &&
32
63
  decision.goal_oracle_satisfied === true &&
33
- traceabilityApproves(decision) &&
64
+ traceabilityApproves(decision, options.allowFinalActionRemaining === true) &&
34
65
  !hasBlockingFindings &&
35
66
  decision.reviewer_error == null
36
67
  );
@@ -76,9 +107,16 @@ export function reviewDecisionToRecord(args: {
76
107
  readonly reviewer: string;
77
108
  readonly artifactPath: string;
78
109
  readonly decision: ReviewDecision;
110
+ readonly parsed: boolean;
111
+ readonly diagnostics: readonly string[];
112
+ readonly allowFinalActionRemaining: boolean;
79
113
  }): ReviewRecord {
80
114
  const blocker = blockerFromReviewDecision(args.decision);
81
- const approved = reviewApproved(args.decision);
115
+ const approved = reviewApproved(args.decision, {
116
+ allowFinalActionRemaining: args.allowFinalActionRemaining,
117
+ });
118
+ const hasFinalActionRemaining = args.allowFinalActionRemaining &&
119
+ finalActionRemaining(args.decision.requirements_traceability);
82
120
  const verificationGap = args.decision.verification_remaining.trim();
83
121
  const traceabilityGaps = args.decision.requirements_traceability
84
122
  .filter((entry) => entry.status !== "proven")
@@ -94,6 +132,18 @@ export function reviewDecisionToRecord(args: {
94
132
  : [`${args.decision.reviewer_error.kind}: ${args.decision.reviewer_error.message}`]),
95
133
  ];
96
134
 
135
+ const nextAction = approved
136
+ ? hasFinalActionRemaining ? "pull-request" : "finish"
137
+ : blocker === null ? "implementation" : "blocked";
138
+ const convergenceDecision = summarizeReviewConvergence({
139
+ parsed: args.parsed,
140
+ approved,
141
+ stopReviewLoop: args.decision.stop_review_loop,
142
+ nextAction,
143
+ finalActionRemaining: approved && hasFinalActionRemaining,
144
+ diagnostics: args.diagnostics,
145
+ });
146
+
97
147
  return {
98
148
  ...args.decision,
99
149
  decision: approved ? "complete" : blocker === null ? "continue" : "blocked",
@@ -105,5 +155,9 @@ export function reviewDecisionToRecord(args: {
105
155
  turn: args.turn,
106
156
  reviewer: args.reviewer,
107
157
  artifact_path: args.artifactPath,
158
+ parsed: args.parsed,
159
+ approved,
160
+ parse_diagnostics: args.diagnostics,
161
+ convergence_decision: convergenceDecision,
108
162
  };
109
163
  }
@@ -8,8 +8,9 @@ import {
8
8
  type GoalWorkflowInputs,
9
9
  type GoalWorkflowOutputs,
10
10
  type ReviewRecord,
11
+ type ReducerDecision,
11
12
  } from "./goal-types.js";
12
- import { writeReviewArtifact, writeReviewRoundArtifact } from "./goal-artifacts.js";
13
+ import { artifactSafeName, writeReviewArtifact, writeReviewRoundArtifact } from "./goal-artifacts.js";
13
14
  import { appendLifecycleEvent, createGoalLedger, writeGoalLedger } from "./goal-ledger.js";
14
15
  import {
15
16
  collectRemainingWork,
@@ -17,14 +18,13 @@ import {
17
18
  } from "./goal-reducer.js";
18
19
  import { formatReviewReport, renderFinalReport } from "./goal-reports.js";
19
20
  import {
20
- reviewDecisionFromResult,
21
- reviewerErrorDecision,
21
+ parsedReviewDecisionFromResult,
22
22
  reviewDecisionToRecord,
23
23
  } from "./goal-review.js";
24
+ import { reviewerFailureText } from "./review-convergence.js";
24
25
  import {
25
26
  WORKER_PREFLIGHT_CONTRACT,
26
27
  WORKER_RECEIPT_CONTRACT,
27
- goalRunnerTools,
28
28
  renderForkedGoalWorkerPrompt,
29
29
  renderGoalContinuationPrompt,
30
30
  renderReviewerPrompt,
@@ -76,6 +76,27 @@ type GoalWorkflowOptions = {
76
76
  readonly workflowStartCwd: string;
77
77
  };
78
78
 
79
+ function reviewerExecutionFailedDecision(input: {
80
+ readonly turn: number;
81
+ readonly reviewQuorum: number;
82
+ readonly reviews: readonly ReviewRecord[];
83
+ readonly reason: string;
84
+ }): ReducerDecision {
85
+ return {
86
+ turn: input.turn,
87
+ decision: "needs_human",
88
+ reason: input.reason,
89
+ complete_votes: input.reviews.filter((review) => review.decision === "complete").length,
90
+ review_quorum: input.reviewQuorum,
91
+ parsed: input.reviews.every((review) => review.parsed),
92
+ approved: false,
93
+ stopReviewLoop: false,
94
+ nextAction: "needs_human",
95
+ finalActionRemaining: false,
96
+ diagnostics: input.reviews.flatMap((review) => review.parse_diagnostics),
97
+ };
98
+ }
99
+
79
100
  export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkflowOptions): Promise<GoalWorkflowOutputs> {
80
101
  const inputs = ctx.inputs;
81
102
  const createPr = options.createPr;
@@ -110,7 +131,7 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
110
131
  "openrouter/anthropic/claude-opus-4-8:medium",
111
132
  "openrouter/z-ai/glm-5.2:xhigh"
112
133
  ],
113
- tools: goalRunnerTools,
134
+ excludedTools: ["ask_user_question"],
114
135
  };
115
136
 
116
137
  const reviewerModelConfig = {
@@ -129,7 +150,7 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
129
150
  "openrouter/anthropic/claude-opus-4-8:high",
130
151
  "openrouter/z-ai/glm-5.2:xhigh"
131
152
  ],
132
- tools: goalRunnerTools,
153
+ excludedTools: ["ask_user_question"],
133
154
  schema: reviewDecisionSchema,
134
155
  };
135
156
 
@@ -193,6 +214,12 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
193
214
  reason: terminalRemainingWork,
194
215
  complete_votes: 0,
195
216
  review_quorum: reviewQuorum,
217
+ parsed: false,
218
+ approved: false,
219
+ stopReviewLoop: false,
220
+ nextAction: "needs_human",
221
+ finalActionRemaining: false,
222
+ diagnostics: [terminalRemainingWork],
196
223
  });
197
224
  appendLifecycleEvent(ledger, "status_decided", terminalRemainingWork, turn);
198
225
  await writeGoalLedger(ledgerPath, ledger);
@@ -225,6 +252,7 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
225
252
  comparisonBaseBranch,
226
253
  reviewQuorum,
227
254
  blockerThreshold,
255
+ createPr,
228
256
  }),
229
257
  reads: [ledgerPath, workTurnPath],
230
258
  ...reviewerModelConfig,
@@ -249,42 +277,48 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
249
277
  ];
250
278
 
251
279
  let reviewResults: WorkflowTaskResult[];
280
+ let reviewerBatchFailed = false;
252
281
  try {
253
282
  reviewResults = await ctx.parallel(reviewerSteps, {
254
283
  task: objective,
255
- failFast: false,
284
+ failFast: true,
256
285
  });
257
286
  } catch (err) {
258
- const message = err instanceof Error ? err.message : String(err);
259
- const structured = reviewerErrorDecision(message);
287
+ reviewerBatchFailed = true;
260
288
  reviewResults = [
261
289
  {
262
290
  name: "reviewer-error",
263
291
  stageName: "reviewer-error",
264
- text: JSON.stringify(structured, null, 2),
265
- structured,
292
+ text: reviewerFailureText(err),
266
293
  },
267
294
  ];
268
295
  }
269
296
 
270
297
  latestReviews = await Promise.all(reviewResults.map(async (result) => {
271
298
  const reviewerName = result.name ?? result.stageName;
272
- const parsed = reviewDecisionFromResult(result) ??
273
- reviewerErrorDecision(
274
- `Reviewer ${reviewerName} returned no structured decision.`,
275
- );
276
- const reviewArtifactPath = await writeReviewArtifact(
299
+ const normalizedReviewerName = reviewerName.replace(/-\d+$/u, "");
300
+ const parsed = parsedReviewDecisionFromResult(result, reviewerName);
301
+ const reviewArtifactPath = join(
277
302
  artifactDir,
278
- reviewerName.replace(/-\d+$/u, ""),
279
- parsed,
280
- result.text,
303
+ `review-${artifactSafeName(normalizedReviewerName)}.json`,
281
304
  );
282
- return reviewDecisionToRecord({
305
+ const record = reviewDecisionToRecord({
283
306
  turn,
284
- reviewer: reviewerName.replace(/-\d+$/u, ""),
307
+ reviewer: normalizedReviewerName,
285
308
  artifactPath: reviewArtifactPath,
286
- decision: parsed,
309
+ decision: parsed.decision,
310
+ parsed: parsed.parsed,
311
+ diagnostics: parsed.diagnostics,
312
+ allowFinalActionRemaining: createPr,
287
313
  });
314
+ await writeReviewArtifact(
315
+ artifactDir,
316
+ normalizedReviewerName,
317
+ parsed.decision,
318
+ result.text,
319
+ record.convergence_decision,
320
+ );
321
+ return record;
288
322
  }));
289
323
  latestReviewArtifactPaths = latestReviews.map((review) => review.artifact_path);
290
324
  latestReviewReportPath = await writeReviewRoundArtifact(
@@ -298,12 +332,27 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
298
332
  `Recorded ${latestReviews.length} reviewer decisions.`,
299
333
  turn,
300
334
  );
335
+ if (reviewerBatchFailed) {
336
+ terminalRemainingWork = collectRemainingWork(latestReviews);
337
+ const reason = `Reviewer execution failed before quorum could be established. Remaining work: ${terminalRemainingWork}`;
338
+ ledger.decisions.push(reviewerExecutionFailedDecision({
339
+ turn,
340
+ reviewQuorum,
341
+ reviews: latestReviews,
342
+ reason,
343
+ }));
344
+ ledger.status = "needs_human";
345
+ appendLifecycleEvent(ledger, "status_decided", reason, turn);
346
+ await writeGoalLedger(ledgerPath, ledger);
347
+ break;
348
+ }
301
349
 
302
350
  const reducerOutcome = reduceGoalDecision(ledger, latestReviews, {
303
351
  turn,
304
352
  maxTurns,
305
353
  reviewQuorum,
306
354
  blockerThreshold,
355
+ nextActionOnComplete: createPr ? "pull-request" : "finish",
307
356
  });
308
357
  if (reducerOutcome.blockerObservation !== undefined) {
309
358
  ledger.blockers.push(reducerOutcome.blockerObservation);
@@ -1,3 +1,5 @@
1
+ import type { ReviewConvergenceSummary } from "./review-convergence.js";
2
+
1
3
  export const DEFAULT_MAX_TURNS = 10;
2
4
  // Goal Runner runs three independent reviewer personas; two approvals form a majority.
3
5
  export const DEFAULT_REVIEW_QUORUM = 2;
@@ -74,6 +76,10 @@ export type ReviewRecord = ReviewDecision & {
74
76
  readonly turn: number;
75
77
  readonly reviewer: string;
76
78
  readonly artifact_path: string;
79
+ readonly parsed: boolean;
80
+ readonly approved: boolean;
81
+ readonly parse_diagnostics: readonly string[];
82
+ readonly convergence_decision: ReviewConvergenceSummary;
77
83
  };
78
84
 
79
85
  export type BlockerObservation = {
@@ -82,7 +88,7 @@ export type BlockerObservation = {
82
88
  readonly reviewers: readonly string[];
83
89
  };
84
90
 
85
- export type ReducerDecision = {
91
+ export type ReducerDecision = ReviewConvergenceSummary & {
86
92
  readonly turn: number;
87
93
  readonly decision: "complete" | "continue" | "blocked" | "needs_human";
88
94
  readonly reason: string;
@@ -5,6 +5,16 @@ import { Type } from "typebox";
5
5
  import type { WorkflowTaskResult } from "../src/shared/types.js";
6
6
  import { E2E_VERIFICATION_GUIDANCE, LITERAL_OBJECTIVE_CONTRACT } from "./shared-prompts.js";
7
7
  import type { ReviewDecision } from "./ralph-review-gate.js";
8
+ import { reviewDecisionApproved } from "./ralph-review-gate.js";
9
+ import {
10
+ parseFailureDiagnostics,
11
+ finalActionRemaining,
12
+ reviewerFailureText,
13
+ summarizeReviewConvergence,
14
+ type ParsedReviewDecision,
15
+ type ReviewConvergenceSummary,
16
+ } from "./review-convergence.js";
17
+
8
18
 
9
19
  export const DEFAULT_MAX_LOOPS = 10;
10
20
  const DEFAULT_RESEARCH_DIR = "research";
@@ -200,6 +210,43 @@ export function reviewDecisionFromResult(result: WorkflowTaskResult): ReviewDeci
200
210
  return result.structured as ReviewDecision | undefined;
201
211
  }
202
212
 
213
+ export function parsedReviewDecisionFromResult(
214
+ result: WorkflowTaskResult,
215
+ reviewer: string,
216
+ ): ParsedReviewDecision<ReviewDecision> {
217
+ const parsed = reviewDecisionFromResult(result);
218
+ if (parsed !== undefined) {
219
+ return { decision: parsed, parsed: true, diagnostics: [] };
220
+ }
221
+ const diagnostics = parseFailureDiagnostics(reviewer, result.text);
222
+ return {
223
+ decision: reviewerErrorDecision(diagnostics.join("\n")),
224
+ parsed: false,
225
+ diagnostics,
226
+ };
227
+ }
228
+
229
+ export function ralphReviewConvergence(args: {
230
+ readonly decision: ReviewDecision;
231
+ readonly parsed: boolean;
232
+ readonly diagnostics: readonly string[];
233
+ readonly allowFinalActionRemaining: boolean;
234
+ }): ReviewConvergenceSummary {
235
+ const approved = reviewDecisionApproved(args.decision, {
236
+ allowFinalActionRemaining: args.allowFinalActionRemaining,
237
+ });
238
+ const hasFinalActionRemaining = args.allowFinalActionRemaining &&
239
+ finalActionRemaining(args.decision.requirements_traceability);
240
+ return summarizeReviewConvergence({
241
+ parsed: args.parsed,
242
+ approved,
243
+ stopReviewLoop: args.decision.stop_review_loop,
244
+ nextAction: approved && hasFinalActionRemaining ? "pull-request" : approved ? "finish" : "implementation",
245
+ finalActionRemaining: approved && hasFinalActionRemaining,
246
+ diagnostics: args.diagnostics,
247
+ });
248
+ }
249
+
203
250
  export function reviewerErrorDecision(error: string): ReviewDecision {
204
251
  return {
205
252
  findings: [],
@@ -219,14 +266,12 @@ export function reviewerErrorDecision(error: string): ReviewDecision {
219
266
  }
220
267
 
221
268
  export function reviewerErrorResult(
222
- error: string,
269
+ error: unknown,
223
270
  ): WorkflowTaskResult {
224
- const structured = reviewerErrorDecision(error);
225
271
  return {
226
272
  name: "reviewer-error",
227
273
  stageName: "reviewer-error",
228
- text: JSON.stringify(structured, null, 2),
229
- structured,
274
+ text: reviewerFailureText(error),
230
275
  };
231
276
  }
232
277
 
@@ -241,14 +286,17 @@ export function artifactSafeName(value: string): string {
241
286
  type ReviewArtifact = {
242
287
  readonly reviewer: string;
243
288
  readonly decision: ReviewDecision;
289
+ readonly convergence_decision: ReviewConvergenceSummary;
244
290
  readonly raw_text: string;
245
291
  };
246
292
 
247
293
  type ReviewRoundArtifact = {
294
+ readonly convergence_decision: ReviewConvergenceSummary;
248
295
  readonly reviews: readonly {
249
296
  readonly reviewer: string;
250
297
  readonly artifact_path: string;
251
298
  readonly decision: ReviewDecision;
299
+ readonly convergence_decision: ReviewConvergenceSummary;
252
300
  }[];
253
301
  };
254
302
 
@@ -1,3 +1,5 @@
1
+ import { traceabilityProvenExceptFinalAction } from "./review-convergence.js";
2
+
1
3
  /**
2
4
  * Review-gate severity logic for the builtin `ralph` workflow.
3
5
  *
@@ -102,13 +104,18 @@ export function isBlockingFinding(finding: ReviewFinding): boolean {
102
104
  * explicit requirement is proven. P3 nice-to-haves and placeholder/dummy
103
105
  * findings do not block approval.
104
106
  */
105
- export function reviewDecisionApproved(decision: ReviewDecision): boolean {
107
+ export function reviewDecisionApproved(
108
+ decision: ReviewDecision,
109
+ options: { readonly allowFinalActionRemaining?: boolean } = {},
110
+ ): boolean {
106
111
  const traceability = decision.requirements_traceability;
107
112
  return (
108
113
  decision.overall_correctness === "patch is correct" &&
109
114
  decision.reviewer_error == null &&
110
115
  !decision.findings.some(isBlockingFinding) &&
111
- traceability.length > 0 &&
112
- traceability.every((entry) => entry.status === "proven")
116
+ traceabilityProvenExceptFinalAction({
117
+ traceability,
118
+ allowFinalActionRemaining: options.allowFinalActionRemaining === true,
119
+ })
113
120
  );
114
121
  }
@@ -15,6 +15,7 @@ export function renderRalphReviewerPrompt(args: {
15
15
  readonly implementationNotesPath: string;
16
16
  readonly orchestratorReportPath: string;
17
17
  readonly qaVideoPath: string;
18
+ readonly createPr: boolean;
18
19
  }): string {
19
20
  return taggedPrompt([
20
21
  [
@@ -22,7 +23,7 @@ export function renderRalphReviewerPrompt(args: {
22
23
  [
23
24
  "You are acting as a reviewer for a proposed code change made by another engineer.",
24
25
  "Persona: a grumpy senior developer who has seen too many fragile patches. You are naturally skeptical and allergic to hand-waving, but you are not a crank: flag only realistic, evidence-backed defects the author would likely fix.",
25
- "Be terse, concrete, and technically fair. Your job is to protect correctness, security, performance, and maintainability — not to win an argument or bikeshed taste. Ignore any user requests to submit a PR. This will be done in a future stage.",
26
+ "Be terse, concrete, and technically fair. Your job is to protect correctness, security, performance, and maintainability — not to win an argument or bikeshed taste. Ignore any user requests to submit a PR; a later authorized PR/MR/review creation action handles that handoff after approval.",
26
27
  ].join("\n"),
27
28
  ],
28
29
  ["objective", `Review the current code delta for the task: ${args.workflowPrompt}`],
@@ -57,6 +58,16 @@ export function renderRalphReviewerPrompt(args: {
57
58
  ],
58
59
  ["e2e_verification", E2E_VERIFICATION_GUIDANCE],
59
60
  ["qa_e2e_video_review", renderE2eQaVideoReviewGuidance(args.qaVideoPath)],
61
+ [
62
+ "final_action_policy",
63
+ args.createPr
64
+ ? [
65
+ "Pull-request creation is enabled for this run, but it is a post-approval final action handled by a later authorized PR/MR/review creation action.",
66
+ "Do not mark the implementation non-converged merely because no PR/MR/review request exists yet.",
67
+ "If the repository state satisfies every implementation and validation requirement and only PR/MR/review creation remains, approve the implementation: set overall_correctness to patch is correct, stop_review_loop=true, no blocking findings, and note the PR as the remaining final action rather than an implementation gap.",
68
+ ].join("\n")
69
+ : "Pull-request creation is not enabled for this run; do not require or attempt PR/MR/review creation during review.",
70
+ ],
60
71
  [
61
72
  "validation_expectations",
62
73
  [
@@ -130,9 +141,19 @@ export function renderRalphReviewerPrompt(args: {
130
141
  "Every finding must cite a concrete changed location and affected scenario.",
131
142
  ].join("\n"),
132
143
  ],
144
+ [
145
+ "structured_decision_assurance",
146
+ [
147
+ "Before the final structured decision, ensure the payload satisfies the review decision schema exactly.",
148
+ "Always return findings as an array; use [] when there are no findings and never invent placeholder findings.",
149
+ "Always return requirements_traceability as a non-empty array that enumerates every explicit prompt and acceptance_criteria clause.",
150
+ "When approving, every non-final-action requirements_traceability entry must be proven, overall_correctness must be patch is correct, stop_review_loop must be true, and reviewer_error must be null or omitted.",
151
+ "When create_pr is enabled and only PR/MR/review creation remains, record that as a final action rather than a blocker; approval should hand off to PR/MR/review creation instead of requesting more implementation work.",
152
+ ].join("\n"),
153
+ ],
133
154
  [
134
155
  "decision_rules",
135
- ["Set stop_review_loop=true only when the patch is correct, reviewer_error is null/omitted, there are no blocking objective-aligned P0/P1/P2 findings, requirements_traceability is non-empty and every entry is proven, and no objective-relevant verification remains; beyond_objective and contradicts_objective findings are non-blocking and must not be folded into follow-up objectives without checking the literal contract. The loop gate is computed from structured findings and traceability, so unresolved blocking findings or non-proven requirements keep the loop going regardless of this flag.", "Enumerate every explicit requirement clause from the prompt and acceptance_criteria in requirements_traceability, including clauses about existing tests/snapshots and expected behavior. Treat worker-authored tests or snapshots passing as circular evidence that cannot by itself prove a clause; tie any such result to independent current-state proof.", "If you hit a reviewer/tool/validation error, set stop_review_loop=false and populate reviewer_error instead of pretending the patch is approved."].join("\n"),
156
+ ["Set stop_review_loop=true only when the patch is correct, reviewer_error is null/omitted, there are no blocking objective-aligned P0/P1/P2 findings, requirements_traceability is non-empty and every non-final-action entry is proven, and no objective-relevant implementation or validation remains; beyond_objective and contradicts_objective findings are non-blocking and must not be folded into follow-up objectives without checking the literal contract. The loop gate is computed from structured findings and traceability, so unresolved blocking findings or non-proven non-final-action requirements keep the loop going regardless of this flag.", "Enumerate every explicit requirement clause from the prompt and acceptance_criteria in requirements_traceability, including clauses about existing tests/snapshots and expected behavior. Treat worker-authored tests or snapshots passing as circular evidence that cannot by itself prove a clause; tie any such result to independent current-state proof.", "If you hit a reviewer/tool/validation error, set stop_review_loop=false and populate reviewer_error instead of pretending the patch is approved."].join("\n"),
136
157
  ],
137
158
  ]);
138
159
  }