specrails-desktop 2.55.0 → 2.55.1

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 (360) hide show
  1. package/cli/dist/args.js +80 -0
  2. package/cli/dist/desktop-client.js +125 -0
  3. package/cli/dist/desktop-control.js +339 -0
  4. package/cli/dist/format.js +45 -0
  5. package/cli/dist/help.js +68 -0
  6. package/cli/dist/output.js +47 -0
  7. package/cli/dist/run-command.js +340 -0
  8. package/cli/dist/specrails-desktop.js +41 -1107
  9. package/cli/dist/status.js +111 -0
  10. package/client/dist/assets/{ActivityFeedPage-ILXMZXcb.js → ActivityFeedPage-DmJcQpNe.js} +1 -1
  11. package/client/dist/assets/{AgentBrowserCapture-UcsupCy7.js → AgentBrowserCapture-NxBHrU-V.js} +1 -1
  12. package/client/dist/assets/{AgentModeAnalyticsPane-CQuxYh8B.js → AgentModeAnalyticsPane-CGAKTJfU.js} +2 -2
  13. package/client/dist/assets/{AgentModeCodePane-zPWbW7ei.js → AgentModeCodePane-DNSs5_oe.js} +2 -2
  14. package/client/dist/assets/{AgentModeJobsPane-CInByIdl.js → AgentModeJobsPane-DLoVYDnG.js} +1 -1
  15. package/client/dist/assets/{AgentsPage-BWvgxaBv.js → AgentsPage-CAzMn9Gg.js} +1 -1
  16. package/client/dist/assets/{AnalyticsPage-DP3jakv-.js → AnalyticsPage-C06KT4Y0.js} +1 -1
  17. package/client/dist/assets/{CodePage-BKXiwE5a.js → CodePage-aX1mxGyT.js} +1 -1
  18. package/client/dist/assets/{DesktopAnalyticsPage-DryJOaMz.js → DesktopAnalyticsPage-BtscfiQD.js} +1 -1
  19. package/client/dist/assets/{DocsDialog-BsCG9ksG.js → DocsDialog-CNOcXhp-.js} +1 -1
  20. package/client/dist/assets/{DocsPage-Cc-GeKYl.js → DocsPage-C2BugxaI.js} +1 -1
  21. package/client/dist/assets/{ExportDropdown-ClahJdDn.js → ExportDropdown-BVGKEgkd.js} +1 -1
  22. package/client/dist/assets/{InteractiveJobComposer-DfLF6N0f.js → InteractiveJobComposer-CCncBqNu.js} +1 -1
  23. package/client/dist/assets/{JobDetailModal-DHeur9YK.js → JobDetailModal-Cn_k3-RM.js} +1 -1
  24. package/client/dist/assets/{JobDetailPage-CraDKzeG.js → JobDetailPage-BogJFBsk.js} +1 -1
  25. package/client/dist/assets/{JobsPage-CcbuSwj7.js → JobsPage-DL4E8ZyU.js} +1 -1
  26. package/client/dist/assets/{LoopBuilderPage-BKtNp494.js → LoopBuilderPage-9L6URQLY.js} +1 -1
  27. package/client/dist/assets/{LoopPreviewModal-DbZd9isy.js → LoopPreviewModal-CAPqTIgL.js} +1 -1
  28. package/client/dist/assets/{LoopsPage-DEg6sIkG.js → LoopsPage-aU8dYw7L.js} +1 -1
  29. package/client/dist/assets/{MinimizedChatsContext-BGtEjWsc.js → MinimizedChatsContext-D3QzgV0B.js} +1 -1
  30. package/client/dist/assets/{PluginsPage-BVqSsPzL.js → PluginsPage-D_tsW9B5.js} +1 -1
  31. package/client/dist/assets/{ProjectSettingsDialog-CAjLgJAZ.js → ProjectSettingsDialog-_ZbNuspP.js} +1 -1
  32. package/client/dist/assets/{RepositoryDeliveries-DrcrxLe0.js → RepositoryDeliveries-Du2UCf1a.js} +1 -1
  33. package/client/dist/assets/{RepositoryScopeSelector-CAGY3xW6.js → RepositoryScopeSelector-hPGZNRBm.js} +1 -1
  34. package/client/dist/assets/ReviewPacketPage-CG-Dv0El.js +4 -0
  35. package/client/dist/assets/{TemplatePreviewModal-Bqs-9fhn.js → TemplatePreviewModal-C19H2b2o.js} +1 -1
  36. package/client/dist/assets/{TicketDetailModalContext-C0jQ5yOk.js → TicketDetailModalContext-DAK-NoK6.js} +1 -1
  37. package/client/dist/assets/{Trans-DtWlCJN9.js → Trans-DEbgkuAY.js} +1 -1
  38. package/client/dist/assets/{dashboard-CTfEtkqX.js → dashboard-B9uWNGO2.js} +1 -1
  39. package/client/dist/assets/{dashboard-DMklepmz.js → dashboard-BIwmO9wc.js} +1 -1
  40. package/client/dist/assets/{dashboard-DBAP2_SQ.js → dashboard-BV4vOZkR.js} +1 -1
  41. package/client/dist/assets/{dashboard-D40HP2ks.js → dashboard-Bf6MPVsM.js} +1 -1
  42. package/client/dist/assets/{dashboard-Csf1yGSN.js → dashboard-C8klWVvZ.js} +1 -1
  43. package/client/dist/assets/{dashboard-C29Qwa-L.js → dashboard-D1ORhPF0.js} +1 -1
  44. package/client/dist/assets/{dashboard-Cr4D8oMn.js → dashboard-DSubvs9x.js} +1 -1
  45. package/client/dist/assets/{dashboard-CSJzf5OT.js → dashboard-px_vlRx_.js} +1 -1
  46. package/client/dist/assets/{formatDistanceToNow-DYmvOA3R.js → formatDistanceToNow-Cc2u5FwQ.js} +1 -1
  47. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-BAhW5E6V.js → getTimezoneOffsetInMilliseconds-BHm2U-w1.js} +1 -1
  48. package/client/dist/assets/{index-BfAZg5DG.js → index-BcligJ3-.js} +29 -29
  49. package/client/dist/assets/index-C51x61Bz.css +2 -0
  50. package/client/dist/assets/{jira-api-B27Za5FP.js → jira-api-DrGxiD9p.js} +1 -1
  51. package/client/dist/assets/packet-8nn9RsU7.js +1 -0
  52. package/client/dist/assets/packet-B0H15elv.js +1 -0
  53. package/client/dist/assets/packet-BQvBgrwh.js +1 -0
  54. package/client/dist/assets/packet-BR7mO0-a.js +1 -0
  55. package/client/dist/assets/packet-BgcQ6q_K.js +1 -0
  56. package/client/dist/assets/packet-D2s92Jnn.js +1 -0
  57. package/client/dist/assets/packet-YbtcD1HS.js +1 -0
  58. package/client/dist/assets/packet-c0Qj_9eX.js +1 -0
  59. package/client/dist/assets/{project-repositories-DixIZHTA.js → project-repositories-9Wzs0coQ.js} +1 -1
  60. package/client/dist/assets/{spending-BGmZBX5B.js → spending-T5GM7wpn.js} +1 -1
  61. package/client/dist/assets/{useDesktop-CPB4cnwI.js → useDesktop-QogiN0zR.js} +1 -1
  62. package/client/dist/assets/{useRuntimeRuns-DEQ9HdAM.js → useRuntimeRuns-Dqmz9fS9.js} +1 -1
  63. package/client/dist/assets/{useSharedWebSocket-DcPRKR8R.js → useSharedWebSocket-Dz-HI6De.js} +2 -2
  64. package/client/dist/index.html +17 -17
  65. package/docs/codex.md +5 -5
  66. package/docs/customizing.md +1 -1
  67. package/docs/gemini-cli-provider-study.md +14 -14
  68. package/docs/gemini-core-support-evaluation.md +1 -1
  69. package/docs/gemini.md +5 -5
  70. package/docs/internals/README.md +6 -2
  71. package/docs/internals/adding-a-provider.md +15 -15
  72. package/docs/internals/agent-runtime-framework-evaluation.md +8 -8
  73. package/docs/internals/api-reference.md +2 -2
  74. package/docs/internals/architecture.md +9 -9
  75. package/docs/internals/browser-capture-performance.md +3 -3
  76. package/docs/internals/code-explorer-story.md +2 -2
  77. package/docs/internals/companion-rails-as-loops-contract.md +2 -2
  78. package/docs/internals/embedded-browser-native-webview-evaluation.md +5 -5
  79. package/docs/internals/gemini-mcp-registration.md +2 -2
  80. package/docs/internals/global-artifacts-alignment-contract.md +1 -1
  81. package/docs/internals/global-artifacts-relocation-evaluation.md +1 -1
  82. package/docs/internals/interactive-jobs.md +8 -8
  83. package/docs/internals/legacy-implementation-notes.md +722 -0
  84. package/docs/internals/loop-step-log-explorer.md +8 -8
  85. package/docs/internals/mission-rail-cards.md +14 -14
  86. package/docs/internals/modular-architecture.md +107 -0
  87. package/docs/internals/profiles.md +1 -1
  88. package/docs/internals/project-builder.md +18 -18
  89. package/docs/internals/review-packet.md +8 -8
  90. package/docs/internals/safe-pr-review-flow.md +11 -11
  91. package/docs/internals/source-architecture.md +131 -0
  92. package/docs/internals/source-map.md +1354 -0
  93. package/docs/internals/spec-addenda.md +65 -9
  94. package/docs/internals/switch-to-agent-mode-design.md +11 -11
  95. package/docs/tracking-cost.md +1 -1
  96. package/package.json +5 -2
  97. package/server/dist/agent-mcp-config.js +1 -1
  98. package/server/dist/attachment-manager.js +1 -1
  99. package/server/dist/build-dirs.js +2 -2
  100. package/server/dist/config.js +0 -3
  101. package/server/dist/core-completion.js +1 -1
  102. package/server/dist/core-execution.js +1 -1
  103. package/server/dist/db/activity.js +39 -0
  104. package/server/dist/db/connection.js +41 -0
  105. package/server/dist/db/conversations.js +48 -0
  106. package/server/dist/db/jobs.js +251 -0
  107. package/server/dist/db/migrations.js +1521 -0
  108. package/server/dist/db/proposals.js +50 -0
  109. package/server/dist/db/settings.js +15 -0
  110. package/server/dist/db/stats.js +61 -0
  111. package/server/dist/db/telemetry.js +56 -0
  112. package/server/dist/db/templates.js +37 -0
  113. package/server/dist/db/types.js +2 -0
  114. package/server/dist/db.js +66 -2224
  115. package/server/dist/desktop-db.js +3 -3
  116. package/server/dist/desktop-router.js +8 -8
  117. package/server/dist/git-diagnostics.js +1 -1
  118. package/server/dist/index.js +11 -11
  119. package/server/dist/integration-branch.js +3 -14
  120. package/server/dist/jira/jira-issue-fields.js +0 -1
  121. package/server/dist/jira/jira-materializer.js +1 -1
  122. package/server/dist/jira/jira-sync-manager.js +1 -1
  123. package/server/dist/mcp/mcp-admin-router.js +1 -1
  124. package/server/dist/mcp/mcp-server.js +1 -1
  125. package/server/dist/mcp/tools/jobs.js +1 -1
  126. package/server/dist/mcp/tools/rails.js +2 -2
  127. package/server/dist/mcp/tools/specs.js +2 -2
  128. package/server/dist/mcp/tools/types.js +3 -3
  129. package/server/dist/mobile/mobile-gateway.js +1 -1
  130. package/server/dist/mobile/mobile-missions.js +1 -1
  131. package/server/dist/{desktop-analytics.js → modules/accounting/runtime/desktop-analytics.js} +2 -2
  132. package/server/dist/{pricing.js → modules/accounting/runtime/pricing.js} +1 -1
  133. package/server/dist/{result-event.js → modules/accounting/runtime/result-event.js} +3 -3
  134. package/server/dist/{spending.js → modules/accounting/runtime/spending.js} +0 -3
  135. package/server/dist/{telemetry-compactor.js → modules/accounting/runtime/telemetry-compactor.js} +1 -1
  136. package/server/dist/{telemetry-receiver.js → modules/accounting/runtime/telemetry-receiver.js} +2 -2
  137. package/server/dist/{agent-runtime-bridge.js → modules/agent-runtime/runtime/agent-runtime-bridge.js} +2 -2
  138. package/server/dist/{agent-runtime-controls.js → modules/agent-runtime/runtime/agent-runtime-controls.js} +7 -7
  139. package/server/dist/{agent-runtime-effective-config.js → modules/agent-runtime/runtime/agent-runtime-effective-config.js} +1 -1
  140. package/server/dist/{agent-runtime-loader.js → modules/agent-runtime/runtime/agent-runtime-loader.js} +3 -3
  141. package/server/dist/{agent-runtime-paths.js → modules/agent-runtime/runtime/agent-runtime-paths.js} +1 -1
  142. package/server/dist/{agent-runtime-settings-router.js → modules/agent-runtime/runtime/agent-runtime-settings-router.js} +2 -2
  143. package/server/dist/{agent-runtime-settings.js → modules/agent-runtime/runtime/agent-runtime-settings.js} +3 -3
  144. package/server/dist/{agent-runtime-settlement.js → modules/agent-runtime/runtime/agent-runtime-settlement.js} +6 -6
  145. package/server/dist/{agent-defaults.js → modules/agents/runtime/agent-defaults.js} +3 -3
  146. package/server/dist/{agent-generator.js → modules/agents/runtime/agent-generator.js} +7 -7
  147. package/server/dist/{agent-refine-manager.js → modules/agents/runtime/agent-refine-manager.js} +5 -5
  148. package/server/dist/{agent-store.js → modules/agents/runtime/agent-store.js} +1 -1
  149. package/server/dist/{profile-manager.js → modules/agents/runtime/profile-manager.js} +2 -2
  150. package/server/dist/{profiles-router.js → modules/agents/runtime/profiles-router.js} +5 -5
  151. package/server/dist/{browser-capture-manager.js → modules/browser/runtime/browser-capture-manager.js} +2 -4
  152. package/server/dist/{browser-playwright.js → modules/browser/runtime/browser-playwright.js} +1 -1
  153. package/server/dist/{blueprint-chat-manager.js → modules/builder/runtime/blueprint-chat-manager.js} +7 -7
  154. package/server/dist/{blueprint-commit.js → modules/builder/runtime/blueprint-commit.js} +8 -8
  155. package/server/dist/{blueprint-draft-parser.js → modules/builder/runtime/blueprint-draft-parser.js} +1 -1
  156. package/server/dist/{blueprint-generation.js → modules/builder/runtime/blueprint-generation.js} +1 -1
  157. package/server/dist/{blueprint-operator-prompt.js → modules/builder/runtime/blueprint-operator-prompt.js} +1 -1
  158. package/server/dist/{blueprint-router.js → modules/builder/runtime/blueprint-router.js} +3 -3
  159. package/server/dist/{blueprint-spec-quality.js → modules/builder/runtime/blueprint-spec-quality.js} +1 -1
  160. package/server/dist/{milestone-chain.js → modules/builder/runtime/milestone-chain.js} +1 -1
  161. package/server/dist/{milestone-progress.js → modules/builder/runtime/milestone-progress.js} +6 -6
  162. package/server/dist/{code-activity.js → modules/code/runtime/code-activity.js} +1 -1
  163. package/server/dist/{code-explorer-router.js → modules/code/runtime/code-explorer-router.js} +5 -5
  164. package/server/dist/{file-provenance.js → modules/code/runtime/file-provenance.js} +1 -1
  165. package/server/dist/{file-story-manager.js → modules/code/runtime/file-story-manager.js} +2 -2
  166. package/server/dist/{file-story.js → modules/code/runtime/file-story.js} +2 -2
  167. package/server/dist/{file-summary-generator.js → modules/code/runtime/file-summary-generator.js} +3 -3
  168. package/server/dist/{file-summary-manager.js → modules/code/runtime/file-summary-manager.js} +3 -3
  169. package/server/dist/{project-code-discovery.js → modules/code/runtime/project-code-discovery.js} +2 -2
  170. package/server/dist/modules/conversations/domain/draft-stream.js +91 -0
  171. package/server/dist/modules/conversations/domain/recovery-context.js +101 -0
  172. package/server/dist/modules/conversations/index.js +10 -0
  173. package/server/dist/{chat-manager.js → modules/conversations/runtime/chat-manager.js} +32 -216
  174. package/server/dist/{context-budget.js → modules/conversations/runtime/context-budget.js} +1 -1
  175. package/server/dist/{explore-cwd-manager.js → modules/conversations/runtime/explore-cwd-manager.js} +1 -1
  176. package/server/dist/{explore-smash.js → modules/conversations/runtime/explore-smash.js} +1 -1
  177. package/server/dist/{explore-stdin-session.js → modules/conversations/runtime/explore-stdin-session.js} +1 -1
  178. package/server/dist/modules/delivery/adapters/decisions/chains.js +138 -0
  179. package/server/dist/modules/delivery/adapters/decisions/contracts.js +2 -0
  180. package/server/dist/modules/delivery/adapters/decisions/create.js +234 -0
  181. package/server/dist/modules/delivery/adapters/decisions/discard.js +251 -0
  182. package/server/dist/modules/delivery/adapters/decisions/dispatch.js +107 -0
  183. package/server/dist/modules/delivery/adapters/decisions/evidence.js +205 -0
  184. package/server/dist/modules/delivery/adapters/decisions/merge-local.js +338 -0
  185. package/server/dist/modules/delivery/adapters/decisions/metadata.js +109 -0
  186. package/server/dist/modules/delivery/adapters/decisions/observations.js +260 -0
  187. package/server/dist/modules/delivery/adapters/decisions/ownership.js +83 -0
  188. package/server/dist/modules/delivery/adapters/decisions/publish.js +242 -0
  189. package/server/dist/modules/delivery/adapters/decisions/recovery.js +425 -0
  190. package/server/dist/modules/delivery/adapters/decisions/retry.js +112 -0
  191. package/server/dist/modules/delivery/adapters/decisions/transitions.js +94 -0
  192. package/server/dist/modules/delivery/domain/decision-policy.js +50 -0
  193. package/server/dist/modules/delivery/domain/state.js +2 -0
  194. package/server/dist/modules/delivery/index.js +7 -0
  195. package/server/dist/{active-pr-continuation.js → modules/delivery/runtime/active-pr-continuation.js} +2 -2
  196. package/server/dist/{delivery-evidence.js → modules/delivery/runtime/delivery-evidence.js} +3 -3
  197. package/server/dist/{multi-repo-bases.js → modules/delivery/runtime/multi-repo-bases.js} +1 -1
  198. package/server/dist/{multi-repo-checkout.js → modules/delivery/runtime/multi-repo-checkout.js} +4 -4
  199. package/server/dist/{multi-repo-delivery.js → modules/delivery/runtime/multi-repo-delivery.js} +4 -4
  200. package/server/dist/{multi-repo-execution.js → modules/delivery/runtime/multi-repo-execution.js} +8 -8
  201. package/server/dist/{pr-body.js → modules/delivery/runtime/pr-body.js} +1 -1
  202. package/server/dist/{pr-follow-up-scope.js → modules/delivery/runtime/pr-follow-up-scope.js} +2 -2
  203. package/server/dist/{pr-follow-up.js → modules/delivery/runtime/pr-follow-up.js} +1 -1
  204. package/server/dist/{pr-naming.js → modules/delivery/runtime/pr-naming.js} +1 -1
  205. package/server/dist/{pr-publisher.js → modules/delivery/runtime/pr-publisher.js} +2 -2
  206. package/server/dist/{rail-isolated-launch.js → modules/delivery/runtime/rail-isolated-launch.js} +29 -27
  207. package/server/dist/{rail-launch-parser.js → modules/delivery/runtime/rail-launch-parser.js} +2 -2
  208. package/server/dist/{rail-merge-orchestrator.js → modules/delivery/runtime/rail-merge-orchestrator.js} +5 -5
  209. package/server/dist/modules/delivery/runtime/rail-pr-decision.js +12 -0
  210. package/server/dist/{rail-pr-delivery.js → modules/delivery/runtime/rail-pr-delivery.js} +1 -1
  211. package/server/dist/{rail-pr-store.js → modules/delivery/runtime/rail-pr-store.js} +2 -2
  212. package/server/dist/{rail-pr-ticket-effects.js → modules/delivery/runtime/rail-pr-ticket-effects.js} +3 -3
  213. package/server/dist/{rail-worktree-release.js → modules/delivery/runtime/rail-worktree-release.js} +4 -4
  214. package/server/dist/{rails-router.js → modules/delivery/runtime/rails-router.js} +66 -67
  215. package/server/dist/{review-packet.js → modules/delivery/runtime/review-packet.js} +3 -3
  216. package/server/dist/modules/execution/adapters/budget-storage.js +21 -0
  217. package/server/dist/modules/execution/adapters/usage-reader.js +38 -0
  218. package/server/dist/modules/execution/application/enforce-budget.js +14 -0
  219. package/server/dist/modules/execution/application/record-job-invocations.js +64 -0
  220. package/server/dist/modules/execution/application/recover-job-usage.js +200 -0
  221. package/server/dist/modules/execution/domain/job-accounting.js +2 -0
  222. package/server/dist/modules/execution/domain/scheduling.js +24 -0
  223. package/server/dist/modules/execution/domain/usage.js +21 -0
  224. package/server/dist/modules/execution/index.js +14 -0
  225. package/server/dist/modules/execution/ports.js +2 -0
  226. package/server/dist/{accept-ladder.js → modules/execution/runtime/accept-ladder.js} +1 -1
  227. package/server/dist/{interactive-job-session.js → modules/execution/runtime/interactive-job-session.js} +11 -11
  228. package/server/dist/{job-phase-breakdown.js → modules/execution/runtime/job-phase-breakdown.js} +1 -1
  229. package/server/dist/{queue-manager.js → modules/execution/runtime/queue-manager.js} +74 -491
  230. package/server/dist/{revision-seed.js → modules/execution/runtime/revision-seed.js} +1 -1
  231. package/server/dist/{spawn-lifecycle.js → modules/execution/runtime/spawn-lifecycle.js} +3 -3
  232. package/server/dist/{stuck-run-detector.js → modules/execution/runtime/stuck-run-detector.js} +1 -1
  233. package/server/dist/{loop-command-catalog.js → modules/loops/runtime/loop-command-catalog.js} +1 -1
  234. package/server/dist/{loop-executors.js → modules/loops/runtime/loop-executors.js} +17 -17
  235. package/server/dist/{loop-factory.js → modules/loops/runtime/loop-factory.js} +2 -21
  236. package/server/dist/{loop-graph.js → modules/loops/runtime/loop-graph.js} +25 -0
  237. package/server/dist/{loop-role-engines.js → modules/loops/runtime/loop-role-engines.js} +4 -4
  238. package/server/dist/{loop-run-manager.js → modules/loops/runtime/loop-run-manager.js} +101 -26
  239. package/server/dist/{loop-runs-store.js → modules/loops/runtime/loop-runs-store.js} +1 -1
  240. package/server/dist/{loop-shell-invocation.js → modules/loops/runtime/loop-shell-invocation.js} +2 -2
  241. package/server/dist/{loop-step-idle.js → modules/loops/runtime/loop-step-idle.js} +1 -1
  242. package/server/dist/{loop-templates.js → modules/loops/runtime/loop-templates.js} +24 -29
  243. package/server/dist/{loops-router.js → modules/loops/runtime/loops-router.js} +2 -2
  244. package/server/dist/{agent-chat-manager.js → modules/missions/runtime/agent-chat-manager.js} +19 -19
  245. package/server/dist/{agent-chat-router.js → modules/missions/runtime/agent-chat-router.js} +6 -6
  246. package/server/dist/{agent-context-resolver.js → modules/missions/runtime/agent-context-resolver.js} +8 -8
  247. package/server/dist/{agent-fence-promotion.js → modules/missions/runtime/agent-fence-promotion.js} +1 -1
  248. package/server/dist/{agent-input-store.js → modules/missions/runtime/agent-input-store.js} +1 -1
  249. package/server/dist/{agent-operator-prompt.js → modules/missions/runtime/agent-operator-prompt.js} +17 -7
  250. package/server/dist/{agent-spec-framing.js → modules/missions/runtime/agent-spec-framing.js} +4 -4
  251. package/server/dist/{agent-steering.js → modules/missions/runtime/agent-steering.js} +1 -1
  252. package/server/dist/{mission-run-notify.js → modules/missions/runtime/mission-run-notify.js} +1 -1
  253. package/server/dist/modules/project-settings/adapters/http.js +24 -0
  254. package/server/dist/modules/project-settings/adapters/sqlite.js +120 -0
  255. package/server/dist/modules/project-settings/application.js +11 -0
  256. package/server/dist/modules/project-settings/domain.js +95 -0
  257. package/server/dist/modules/project-settings/index.js +11 -0
  258. package/server/dist/modules/project-settings/ports.js +2 -0
  259. package/server/dist/{contract-refine-runner.js → modules/specs/runtime/contract-refine-runner.js} +12 -12
  260. package/server/dist/{proposal-manager.js → modules/specs/runtime/proposal-manager.js} +8 -8
  261. package/server/dist/{smash-runner.js → modules/specs/runtime/smash-runner.js} +26 -58
  262. package/server/dist/{spec-addenda-core.js → modules/specs/runtime/spec-addenda-core.js} +2 -2
  263. package/server/dist/{spec-addenda.js → modules/specs/runtime/spec-addenda.js} +3 -3
  264. package/server/dist/{spec-launcher-manager.js → modules/specs/runtime/spec-launcher-manager.js} +8 -8
  265. package/server/dist/{spec-models.js → modules/specs/runtime/spec-models.js} +1 -1
  266. package/server/dist/{ticket-watcher.js → modules/specs/runtime/ticket-watcher.js} +1 -1
  267. package/server/dist/{background-process-control.js → modules/terminals/runtime/background-process-control.js} +1 -1
  268. package/server/dist/{background-process-service.js → modules/terminals/runtime/background-process-service.js} +3 -3
  269. package/server/dist/{background-process-store.js → modules/terminals/runtime/background-process-store.js} +1 -1
  270. package/server/dist/{background-windows-bootstrap.js → modules/terminals/runtime/background-windows-bootstrap.js} +3 -3
  271. package/server/dist/{terminal-manager.js → modules/terminals/runtime/terminal-manager.js} +3 -3
  272. package/server/dist/project-git.js +1 -1
  273. package/server/dist/project-profile-support.js +32 -0
  274. package/server/dist/project-registry.js +34 -40
  275. package/server/dist/project-router-background-processes.js +1 -1
  276. package/server/dist/project-router-chat.js +6 -6
  277. package/server/dist/project-router-git.js +1 -1
  278. package/server/dist/project-router-helpers.js +2 -2
  279. package/server/dist/project-router-jobs.js +14 -12
  280. package/server/dist/project-router-loop-runs.js +12 -12
  281. package/server/dist/project-router-settings.js +15 -75
  282. package/server/dist/project-router-setup.js +2 -2
  283. package/server/dist/project-router-spending.js +4 -4
  284. package/server/dist/project-router-terminals.js +4 -4
  285. package/server/dist/project-router-tickets.js +14 -14
  286. package/server/dist/project-router.js +13 -13
  287. package/server/dist/providers/codex-adapter.js +3 -3
  288. package/server/dist/providers/gemini-adapter.js +1 -1
  289. package/server/dist/providers/telemetry-env.js +55 -0
  290. package/server/dist/runtime-role-prompts-router.js +2 -2
  291. package/server/dist/setup-manager.js +2 -48
  292. package/server/dist/shared/git-branch-name.js +16 -0
  293. package/server/dist/transient-children.js +3 -3
  294. package/server/dist/util/distribute-int.js +33 -0
  295. package/client/dist/assets/ReviewPacketPage-D-UjTef3.js +0 -4
  296. package/client/dist/assets/index-BAtqmAZR.css +0 -2
  297. package/client/dist/assets/packet-CjS_478C.js +0 -1
  298. package/client/dist/assets/packet-D69dKsHN.js +0 -1
  299. package/client/dist/assets/packet-D9rU6Oxo.js +0 -1
  300. package/client/dist/assets/packet-DMDFoamg.js +0 -1
  301. package/client/dist/assets/packet-Dd2RMs1h.js +0 -1
  302. package/client/dist/assets/packet-DjC9OibC.js +0 -1
  303. package/client/dist/assets/packet-DwPtJoDz.js +0 -1
  304. package/client/dist/assets/packet-ceahDg8_.js +0 -1
  305. package/server/dist/rail-pr-decision.js +0 -2377
  306. package/server/dist/ticket-broadcast.js +0 -47
  307. /package/server/dist/{ai-invocations.js → modules/accounting/runtime/ai-invocations.js} +0 -0
  308. /package/server/dist/{codex-otel-bridge.js → modules/accounting/runtime/codex-otel-bridge.js} +0 -0
  309. /package/server/dist/{metrics.js → modules/accounting/runtime/metrics.js} +0 -0
  310. /package/server/dist/{telemetry-export.js → modules/accounting/runtime/telemetry-export.js} +0 -0
  311. /package/server/dist/{agent-runtime-accounting.js → modules/agent-runtime/runtime/agent-runtime-accounting.js} +0 -0
  312. /package/server/dist/{agent-runtime-controls-router.js → modules/agent-runtime/runtime/agent-runtime-controls-router.js} +0 -0
  313. /package/server/dist/{agent-runtime-events.js → modules/agent-runtime/runtime/agent-runtime-events.js} +0 -0
  314. /package/server/dist/{agent-runtime-history.js → modules/agent-runtime/runtime/agent-runtime-history.js} +0 -0
  315. /package/server/dist/{agent-runtime-metrics.js → modules/agent-runtime/runtime/agent-runtime-metrics.js} +0 -0
  316. /package/server/dist/{agent-runtime-package.js → modules/agent-runtime/runtime/agent-runtime-package.js} +0 -0
  317. /package/server/dist/{agent-runtime-repositories.js → modules/agent-runtime/runtime/agent-runtime-repositories.js} +0 -0
  318. /package/server/dist/{agent-runtime-verification-suggestions.js → modules/agent-runtime/runtime/agent-runtime-verification-suggestions.js} +0 -0
  319. /package/server/dist/{agent-refine-db.js → modules/agents/runtime/agent-refine-db.js} +0 -0
  320. /package/server/dist/{browser-capture-types.js → modules/browser/runtime/browser-capture-types.js} +0 -0
  321. /package/server/dist/{browser-context-pool.js → modules/browser/runtime/browser-context-pool.js} +0 -0
  322. /package/server/dist/{browser-network.js → modules/browser/runtime/browser-network.js} +0 -0
  323. /package/server/dist/{browser-viewport.js → modules/browser/runtime/browser-viewport.js} +0 -0
  324. /package/server/dist/{blueprint-render.js → modules/builder/runtime/blueprint-render.js} +0 -0
  325. /package/server/dist/{blueprint-spec-fixtures.js → modules/builder/runtime/blueprint-spec-fixtures.js} +0 -0
  326. /package/server/dist/{blueprint-store.js → modules/builder/runtime/blueprint-store.js} +0 -0
  327. /package/server/dist/{blueprint-types.js → modules/builder/runtime/blueprint-types.js} +0 -0
  328. /package/server/dist/{builder-cwd-manager.js → modules/builder/runtime/builder-cwd-manager.js} +0 -0
  329. /package/server/dist/{milestone-chain-store.js → modules/builder/runtime/milestone-chain-store.js} +0 -0
  330. /package/server/dist/{changes-reader.js → modules/code/runtime/changes-reader.js} +0 -0
  331. /package/server/dist/{context-scope.js → modules/conversations/runtime/context-scope.js} +0 -0
  332. /package/server/dist/{explore-contract-refine.js → modules/conversations/runtime/explore-contract-refine.js} +0 -0
  333. /package/server/dist/{explore-draft-title.js → modules/conversations/runtime/explore-draft-title.js} +0 -0
  334. /package/server/dist/{merge-manager.js → modules/delivery/runtime/merge-manager.js} +0 -0
  335. /package/server/dist/{multi-repo-execution-store.js → modules/delivery/runtime/multi-repo-execution-store.js} +0 -0
  336. /package/server/dist/{pr-lifecycle.js → modules/delivery/runtime/pr-lifecycle.js} +0 -0
  337. /package/server/dist/{rail-isolation.js → modules/delivery/runtime/rail-isolation.js} +0 -0
  338. /package/server/dist/{rail-pr-recovery-git.js → modules/delivery/runtime/rail-pr-recovery-git.js} +0 -0
  339. /package/server/dist/{rail-worktrees-store.js → modules/delivery/runtime/rail-worktrees-store.js} +0 -0
  340. /package/server/dist/{rails-store.js → modules/delivery/runtime/rails-store.js} +0 -0
  341. /package/server/dist/{job-listing.js → modules/execution/runtime/job-listing.js} +0 -0
  342. /package/server/dist/{job-spawn-idempotency.js → modules/execution/runtime/job-spawn-idempotency.js} +0 -0
  343. /package/server/dist/{run-duration-stats.js → modules/execution/runtime/run-duration-stats.js} +0 -0
  344. /package/server/dist/{verification-sentinel.js → modules/execution/runtime/verification-sentinel.js} +0 -0
  345. /package/server/dist/{loop-constants.js → modules/loops/runtime/loop-constants.js} +0 -0
  346. /package/server/dist/{loop-decider.js → modules/loops/runtime/loop-decider.js} +0 -0
  347. /package/server/dist/{loop-effect.js → modules/loops/runtime/loop-effect.js} +0 -0
  348. /package/server/dist/{loop-preview.js → modules/loops/runtime/loop-preview.js} +0 -0
  349. /package/server/dist/{loop-templates-ported.js → modules/loops/runtime/loop-templates-ported.js} +0 -0
  350. /package/server/dist/{loops-store.js → modules/loops/runtime/loops-store.js} +0 -0
  351. /package/server/dist/{agent-chat-registry.js → modules/missions/runtime/agent-chat-registry.js} +0 -0
  352. /package/server/dist/{agent-cwd-manager.js → modules/missions/runtime/agent-cwd-manager.js} +0 -0
  353. /package/server/dist/{agent-failure-briefing.js → modules/missions/runtime/agent-failure-briefing.js} +0 -0
  354. /package/server/dist/{agent-tier.js → modules/missions/runtime/agent-tier.js} +0 -0
  355. /package/server/dist/{spec-contract-prompt.js → modules/specs/runtime/spec-contract-prompt.js} +0 -0
  356. /package/server/dist/{spec-draft-parser.js → modules/specs/runtime/spec-draft-parser.js} +0 -0
  357. /package/server/dist/{ticket-store.js → modules/specs/runtime/ticket-store.js} +0 -0
  358. /package/server/dist/{terminal-marks-store.js → modules/terminals/runtime/terminal-marks-store.js} +0 -0
  359. /package/server/dist/{terminal-osc-parser.js → modules/terminals/runtime/terminal-osc-parser.js} +0 -0
  360. /package/server/dist/{terminal-settings.js → modules/terminals/runtime/terminal-settings.js} +0 -0
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergedEvidenceDetail = mergedEvidenceDetail;
4
+ exports.rerouteFromStalePr = rerouteFromStalePr;
5
+ exports.settleObservedExistingPr = settleObservedExistingPr;
6
+ exports.settleObservedClosedPr = settleObservedClosedPr;
7
+ exports.persistRetryablePrObservationFailure = persistRetryablePrObservationFailure;
8
+ exports.persistMovedPrHead = persistMovedPrHead;
9
+ exports.persistRecoveryBlocked = persistRecoveryBlocked;
10
+ exports.persistProtectedRecoveryRetry = persistProtectedRecoveryRetry;
11
+ exports.settleMergedPr = settleMergedPr;
12
+ const rail_worktree_release_1 = require("../../runtime/rail-worktree-release");
13
+ const rail_pr_store_1 = require("../../runtime/rail-pr-store");
14
+ const ownership_1 = require("./ownership");
15
+ const transitions_1 = require("./transitions");
16
+ const evidence_1 = require("./evidence");
17
+ const chains_1 = require("./chains");
18
+ function mergedEvidenceDetail(observation) {
19
+ return observation.includesExpectedSha === null
20
+ ? 'GitHub did not return enough commit evidence to prove the previous PR included the verified implementation commit'
21
+ : 'the previous PR merged without the verified implementation commit';
22
+ }
23
+ async function rerouteFromStalePr(deps, row, detail, exactWasPushed) {
24
+ const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
25
+ const cleanupWarnings = await (0, rail_worktree_release_1.releaseRailWorktrees)({
26
+ db: deps.db, git: deps.git, repoDir: deps.project.path,
27
+ worktreeIds: (0, ownership_1.releasableWorktreeIds)(deps, snap),
28
+ expectedHeadByBranch: (0, rail_worktree_release_1.durableBranchHeads)(snap.branches),
29
+ overlayEvidenceByBranch: (0, rail_worktree_release_1.durableOverlayCleanupEvidence)(snap.branches),
30
+ settlementIgnoredByBranch: (0, rail_worktree_release_1.durableSettlementIgnoredPaths)(snap.branches),
31
+ onSafetyArchive: (0, transitions_1.safetyArchiveRecorder)(deps, row),
32
+ });
33
+ const partial = row.implementation_outcome === 'partially_succeeded';
34
+ const preserved = row.delivery_sha ? 'the preserved exact commit' : 'the preserved recorded branch';
35
+ const conflict = (0, transitions_1.casTransition)(deps, row, 'on_review', {
36
+ prUrl: null,
37
+ prNumber: null,
38
+ prState: exactWasPushed ? 'pushed' : 'local-only',
39
+ deliveryOutcome: partial ? 'partial' : 'ready',
40
+ statusCode: cleanupWarnings.length > 0 ? 'cleanup_incomplete' : partial ? 'partial_success' : 'ready_for_review',
41
+ statusDetail: `${detail}; create a new draft PR from ${preserved}`,
42
+ cleanupWarnings,
43
+ // The replacement PR belongs to this generation. Per-unit branch ownership
44
+ // remains unchanged so a borrowed/pre-existing ref is still never deleted.
45
+ isContinuation: false,
46
+ });
47
+ if (conflict)
48
+ return conflict;
49
+ const after = (0, transitions_1.finalizeTransition)(deps, row.id);
50
+ return {
51
+ status: 200,
52
+ body: {
53
+ ok: true,
54
+ decision: 'on_review',
55
+ prUrl: null,
56
+ prState: after?.prState ?? (exactWasPushed ? 'pushed' : 'local-only'),
57
+ rerouted: true,
58
+ detail,
59
+ },
60
+ };
61
+ }
62
+ async function settleObservedExistingPr(deps, row, observation, pushed) {
63
+ const next = observation.state === 'MERGED' || observation.isDraft === false ? 'pr_ready' : 'pr_draft';
64
+ const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
65
+ const cleanupWarnings = await (0, rail_worktree_release_1.releaseRailWorktrees)({
66
+ db: deps.db, git: deps.git, repoDir: deps.project.path,
67
+ worktreeIds: (0, ownership_1.releasableWorktreeIds)(deps, snap),
68
+ expectedHeadByBranch: (0, rail_worktree_release_1.durableBranchHeads)(snap.branches),
69
+ overlayEvidenceByBranch: (0, rail_worktree_release_1.durableOverlayCleanupEvidence)(snap.branches),
70
+ settlementIgnoredByBranch: (0, rail_worktree_release_1.durableSettlementIgnoredPaths)(snap.branches),
71
+ onSafetyArchive: (0, transitions_1.safetyArchiveRecorder)(deps, row),
72
+ });
73
+ const conflict = (0, transitions_1.casTransition)(deps, row, next, {
74
+ prState: 'pr-created',
75
+ deliveryOutcome: 'delivered',
76
+ statusCode: cleanupWarnings.length > 0 ? 'cleanup_incomplete' : next === 'pr_ready' ? 'pr_ready' : 'existing_pr_updated',
77
+ statusDetail: null,
78
+ cleanupWarnings,
79
+ });
80
+ if (conflict)
81
+ return conflict;
82
+ await (0, evidence_1.releaseDeliveredRecoveryLineage)(deps, row, row.delivery_sha);
83
+ const after = (0, transitions_1.finalizeTransition)(deps, row.id);
84
+ return {
85
+ status: 200,
86
+ body: {
87
+ ok: true,
88
+ decision: next,
89
+ prUrl: after?.prUrl ?? row.pr_url,
90
+ prState: 'pr-created',
91
+ deliveryVerified: true,
92
+ verifiedSha: row.delivery_sha,
93
+ remoteHeadSha: observation.headRefOid,
94
+ pushed,
95
+ },
96
+ };
97
+ }
98
+ async function settleObservedClosedPr(deps, row, observation) {
99
+ const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
100
+ const cleanupWarnings = await (0, rail_worktree_release_1.releaseRailWorktrees)({
101
+ db: deps.db, git: deps.git, repoDir: deps.project.path,
102
+ worktreeIds: (0, ownership_1.releasableWorktreeIds)(deps, snap),
103
+ expectedHeadByBranch: (0, rail_worktree_release_1.durableBranchHeads)(snap.branches),
104
+ overlayEvidenceByBranch: (0, rail_worktree_release_1.durableOverlayCleanupEvidence)(snap.branches),
105
+ settlementIgnoredByBranch: (0, rail_worktree_release_1.durableSettlementIgnoredPaths)(snap.branches),
106
+ onSafetyArchive: (0, transitions_1.safetyArchiveRecorder)(deps, row),
107
+ });
108
+ const conflict = (0, transitions_1.casTransition)(deps, row, 'pr_closed', {
109
+ prState: 'pr-created',
110
+ deliveryOutcome: 'delivered',
111
+ statusCode: cleanupWarnings.length > 0 ? 'cleanup_incomplete' : 'pr_closed',
112
+ statusDetail: null,
113
+ cleanupWarnings,
114
+ });
115
+ if (conflict)
116
+ return conflict;
117
+ await (0, evidence_1.releaseDeliveredRecoveryLineage)(deps, row, row.delivery_sha);
118
+ const after = (0, transitions_1.finalizeTransition)(deps, row.id);
119
+ return {
120
+ status: 200,
121
+ body: {
122
+ ok: true,
123
+ decision: 'pr_closed',
124
+ closed: true,
125
+ merged: false,
126
+ prUrl: after?.prUrl ?? row.pr_url,
127
+ prState: 'pr-created',
128
+ deliveryVerified: true,
129
+ verifiedSha: row.delivery_sha,
130
+ remoteHeadSha: observation.headRefOid,
131
+ pushed: false,
132
+ },
133
+ };
134
+ }
135
+ function persistRetryablePrObservationFailure(deps, row, detail) {
136
+ const conflict = (0, transitions_1.casTransition)(deps, row, 'pr_failed', {
137
+ deliveryOutcome: 'retryable_failure',
138
+ statusCode: 'push_failed',
139
+ statusDetail: detail,
140
+ });
141
+ if (conflict)
142
+ return conflict;
143
+ (0, transitions_1.finalizeTransition)(deps, row.id);
144
+ return { status: 200, body: { ok: true, decision: 'pr_failed', prUrl: row.pr_url, detail } };
145
+ }
146
+ function persistMovedPrHead(deps, row, detail) {
147
+ const conflict = (0, transitions_1.casTransition)(deps, row, 'pr_failed', {
148
+ deliveryOutcome: 'blocked',
149
+ statusCode: 'branch_verification_failed',
150
+ statusDetail: detail,
151
+ });
152
+ if (conflict)
153
+ return conflict;
154
+ (0, transitions_1.finalizeTransition)(deps, row.id);
155
+ return { status: 200, body: { ok: true, decision: 'pr_failed', prUrl: row.pr_url, detail } };
156
+ }
157
+ function persistRecoveryBlocked(deps, row, detail, deliverySha) {
158
+ const conflict = (0, transitions_1.casTransition)(deps, row, 'pr_failed', {
159
+ deliveryOutcome: 'blocked',
160
+ statusCode: 'recovery_unavailable',
161
+ statusDetail: detail,
162
+ ...(deliverySha !== undefined ? { deliverySha } : {}),
163
+ isContinuation: true,
164
+ });
165
+ if (conflict)
166
+ return conflict;
167
+ (0, transitions_1.finalizeTransition)(deps, row.id);
168
+ return {
169
+ status: 200,
170
+ body: {
171
+ ok: true,
172
+ decision: 'pr_failed',
173
+ prUrl: row.pr_url,
174
+ recoveryUnavailable: true,
175
+ detail,
176
+ },
177
+ };
178
+ }
179
+ function persistProtectedRecoveryRetry(deps, row, snap, matchingUnitIndexes, runId, candidateSha, detail) {
180
+ const recoveredIndexes = new Set(matchingUnitIndexes);
181
+ const recoveredBranches = snap.branches.map((unit, index) => recoveredIndexes.has(index)
182
+ ? {
183
+ ...unit,
184
+ runId,
185
+ branch: row.branch,
186
+ succeeded: true,
187
+ implementationOutcome: 'succeeded',
188
+ deliveryOutcome: 'ready',
189
+ finalSha: candidateSha,
190
+ changed: unit.changed ?? (unit.initialSha ? unit.initialSha.toLowerCase() !== candidateSha.toLowerCase() : true),
191
+ failureCode: null,
192
+ branchOwnership: 'borrowed-pr',
193
+ }
194
+ : unit);
195
+ const conflict = (0, transitions_1.casTransition)(deps, row, 'pr_failed', {
196
+ branches: recoveredBranches,
197
+ deliverySha: candidateSha,
198
+ deliveryOutcome: 'retryable_failure',
199
+ statusCode: 'settlement_interrupted',
200
+ statusDetail: detail,
201
+ isContinuation: true,
202
+ });
203
+ if (conflict)
204
+ return conflict;
205
+ (0, transitions_1.finalizeTransition)(deps, row.id);
206
+ return {
207
+ status: 200,
208
+ body: {
209
+ ok: true,
210
+ decision: 'pr_failed',
211
+ prUrl: row.pr_url,
212
+ recovered: true,
213
+ detail,
214
+ },
215
+ };
216
+ }
217
+ async function settleMergedPr(deps, row) {
218
+ const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
219
+ const cleanupWarnings = await (0, rail_worktree_release_1.releaseRailWorktrees)({
220
+ db: deps.db, git: deps.git, repoDir: deps.project.path,
221
+ worktreeIds: (0, ownership_1.releasableWorktreeIds)(deps, snap), state: 'merged',
222
+ expectedHeadByBranch: (0, rail_worktree_release_1.durableBranchHeads)(snap.branches),
223
+ overlayEvidenceByBranch: (0, rail_worktree_release_1.durableOverlayCleanupEvidence)(snap.branches),
224
+ settlementIgnoredByBranch: (0, rail_worktree_release_1.durableSettlementIgnoredPaths)(snap.branches),
225
+ onSafetyArchive: (0, transitions_1.safetyArchiveRecorder)(deps, row),
226
+ });
227
+ await (0, ownership_1.deleteOwnedBranchesIfUnchanged)(deps, row, snap, cleanupWarnings);
228
+ const conflict = (0, transitions_1.casTransitionWithTicketEffect)(deps, row, 'merged', {
229
+ deliveryOutcome: 'delivered',
230
+ statusCode: cleanupWarnings.length > 0 ? 'cleanup_incomplete' : 'merged',
231
+ statusDetail: null,
232
+ cleanupWarnings,
233
+ }, {
234
+ deliveryId: row.id,
235
+ ticketIds: snap.ticketIds,
236
+ targetStatus: 'done',
237
+ jiraAction: 'merged',
238
+ prUrl: row.pr_url,
239
+ });
240
+ if (conflict)
241
+ return conflict;
242
+ await (0, evidence_1.releaseDeliveredRecoveryLineage)(deps, row, row.delivery_sha);
243
+ (0, transitions_1.applyTerminalTicketEffect)(deps, row, 'merged', cleanupWarnings);
244
+ (0, transitions_1.finalizeTransition)(deps, row.id);
245
+ await (0, chains_1.sweepMergedChainAncestors)(deps, row);
246
+ return {
247
+ status: 200,
248
+ body: {
249
+ ok: true,
250
+ decision: 'merged',
251
+ merged: true,
252
+ prUrl: row.pr_url,
253
+ ...(row.delivery_sha ? {
254
+ deliveryVerified: true,
255
+ verifiedSha: row.delivery_sha,
256
+ pushed: false,
257
+ } : {}),
258
+ },
259
+ };
260
+ }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unitWasDelivered = unitWasDelivered;
4
+ exports.ownedDeliveryBranches = ownedDeliveryBranches;
5
+ exports.immutableHeadForOwnedBranch = immutableHeadForOwnedBranch;
6
+ exports.deleteOwnedBranchesIfUnchanged = deleteOwnedBranchesIfUnchanged;
7
+ exports.releasableWorktreeIds = releasableWorktreeIds;
8
+ const rail_worktrees_store_1 = require("../../runtime/rail-worktrees-store");
9
+ const evidence_1 = require("./evidence");
10
+ /** A legacy record's `succeeded` bit meant delivery eligibility. New records
11
+ * state that eligibility directly; blocked/no-change units are never swept as
12
+ * a side effect of delivering another unit in the same batch. */
13
+ function unitWasDelivered(unit) {
14
+ return unit.deliveryOutcome === undefined ? unit.succeeded : unit.deliveryOutcome === 'ready';
15
+ }
16
+ /** Branch deletion is ownership-based, never name-derived. Legacy rows without
17
+ * ownership evidence degrade to preservation. A multi-unit assembled head is
18
+ * owned when it is distinct from every recorded unit branch. */
19
+ function ownedDeliveryBranches(row, snap, cleanupWarnings) {
20
+ const unknownOwnership = row.is_continuation !== 1
21
+ ? snap.branches.filter((unit) => unitWasDelivered(unit) && unit.branchOwnership === undefined)
22
+ : [];
23
+ if (cleanupWarnings && unknownOwnership.length > 0) {
24
+ cleanupWarnings.push(`branch cleanup preserved ${unknownOwnership.length} legacy ${unknownOwnership.length === 1 ? 'branch' : 'branches'} because ownership was not recorded`);
25
+ }
26
+ const owned = new Set(snap.branches
27
+ .filter((unit) => unit.branchOwnership === 'created' && unitWasDelivered(unit))
28
+ .map((unit) => unit.branch));
29
+ if (row.is_continuation !== 1 && snap.branches.length > 1 && row.branch &&
30
+ !snap.branches.some((unit) => unit.branch === row.branch))
31
+ owned.add(row.branch);
32
+ return owned;
33
+ }
34
+ function immutableHeadForOwnedBranch(row, snap, branch) {
35
+ if (branch === row.branch && row.delivery_sha && evidence_1.COMMIT_SHA_RE.test(row.delivery_sha)) {
36
+ return row.delivery_sha.toLowerCase();
37
+ }
38
+ const unitHeads = new Set(snap.branches
39
+ .filter((unit) => unitWasDelivered(unit) && unit.branch === branch && unit.finalSha && evidence_1.COMMIT_SHA_RE.test(unit.finalSha))
40
+ .map((unit) => unit.finalSha.toLowerCase()));
41
+ return unitHeads.size === 1 ? [...unitHeads][0] : null;
42
+ }
43
+ async function deleteOwnedBranchesIfUnchanged(deps, row, snap, cleanupWarnings, protectedBranches = new Set()) {
44
+ for (const branch of ownedDeliveryBranches(row, snap, cleanupWarnings)) {
45
+ if (!branch || branch === row.base_branch)
46
+ continue;
47
+ // A failed release leaves the linked worktree mounted for inspection. Do
48
+ // not even attempt to delete its checked-out branch: preserving the files
49
+ // while erasing their durable ref would make the recovery story depend on
50
+ // Git's incidental checked-out-branch rejection.
51
+ if (protectedBranches.has(branch)) {
52
+ cleanupWarnings.push(`branch ${branch}: retained with its worktree for inspection`);
53
+ continue;
54
+ }
55
+ try {
56
+ const expectedHead = immutableHeadForOwnedBranch(row, snap, branch);
57
+ if (!expectedHead) {
58
+ cleanupWarnings.push(`branch ${branch}: retained because no unambiguous immutable delivered HEAD was recorded`);
59
+ continue;
60
+ }
61
+ const observed = await deps.git.run(['rev-parse', '--verify', `refs/heads/${branch}`], deps.project.path);
62
+ const observedHead = observed.code === 0 ? observed.stdout.trim().toLowerCase() : '';
63
+ if (!evidence_1.COMMIT_SHA_RE.test(observedHead) || observedHead !== expectedHead) {
64
+ cleanupWarnings.push(`branch ${branch}: retained because its current tip no longer matches delivered HEAD ${expectedHead.slice(0, 12)}`);
65
+ continue;
66
+ }
67
+ const deleted = await deps.git.run(['branch', '-D', branch], deps.project.path);
68
+ if (deleted.code !== 0) {
69
+ cleanupWarnings.push(`branch ${branch}: ${(deleted.stderr.trim() || deleted.stdout.trim()).split('\n')[0] || `exit ${deleted.code}`}`);
70
+ }
71
+ }
72
+ catch (err) {
73
+ cleanupWarnings.push(`branch ${branch}: ${err instanceof Error ? err.message : String(err)}`);
74
+ }
75
+ }
76
+ }
77
+ function releasableWorktreeIds(deps, snap) {
78
+ const preservedBranches = new Set(snap.branches.filter((unit) => !unitWasDelivered(unit)).map((unit) => unit.branch));
79
+ return snap.worktreeIds.filter((id) => {
80
+ const wt = (0, rail_worktrees_store_1.getRailWorktree)(deps.db, id);
81
+ return !wt || !preservedBranches.has(wt.branch);
82
+ });
83
+ }
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runPublish = runPublish;
4
+ exports.runPollMerge = runPollMerge;
5
+ exports.runReopen = runReopen;
6
+ const pr_lifecycle_1 = require("../../runtime/pr-lifecycle");
7
+ const observations_1 = require("./observations");
8
+ const transitions_1 = require("./transitions");
9
+ async function runPublish(deps, row) {
10
+ if (!row.delivery_sha || !row.branch) {
11
+ return (0, observations_1.persistMovedPrHead)(deps, row, 'the draft PR has no immutable delivery SHA/head identity; refusing to mutate unverifiable review state');
12
+ }
13
+ const beforePublish = await (0, pr_lifecycle_1.observePrLifecycle)(deps.exec, deps.project.path, row.pr_url, row.delivery_sha);
14
+ if (!beforePublish.ok) {
15
+ return { status: 502, body: { error: 'gh_failed', detail: beforePublish.detail } };
16
+ }
17
+ if (!(0, pr_lifecycle_1.matchesRecordedPrIdentity)(beforePublish, row.branch, row.base_branch)) {
18
+ return (0, observations_1.rerouteFromStalePr)(deps, row, `the recorded PR is ${beforePublish.state.toLowerCase()} but no longer matches its original head/base identity`, beforePublish.includesExpectedSha === true);
19
+ }
20
+ if (beforePublish.state === 'MERGED') {
21
+ return beforePublish.includesExpectedSha === true
22
+ ? (0, observations_1.settleMergedPr)(deps, row)
23
+ : (0, observations_1.rerouteFromStalePr)(deps, row, (0, observations_1.mergedEvidenceDetail)(beforePublish), false);
24
+ }
25
+ if (beforePublish.state === 'CLOSED') {
26
+ return beforePublish.includesExpectedSha === true
27
+ ? (0, observations_1.settleObservedClosedPr)(deps, row, beforePublish)
28
+ : (0, observations_1.rerouteFromStalePr)(deps, row, 'the draft PR closed without the verified implementation commit', false);
29
+ }
30
+ if (beforePublish.includesExpectedSha !== true) {
31
+ return (0, observations_1.persistRetryablePrObservationFailure)(deps, row, 'the draft PR no longer exposes the verified implementation commit; Retry push is available and will use the preserved exact SHA');
32
+ }
33
+ if (beforePublish.isDraft === false) {
34
+ return (0, observations_1.settleObservedExistingPr)(deps, row, beforePublish, false);
35
+ }
36
+ let r;
37
+ try {
38
+ r = await deps.exec.run('gh', ['pr', 'ready', row.pr_url], deps.project.path);
39
+ }
40
+ catch (err) {
41
+ r = { code: 1, stdout: '', stderr: err instanceof Error ? err.message : String(err) };
42
+ }
43
+ // `gh pr ready` is externally mutating and may return an ambiguous error.
44
+ // Re-observe exact remote truth in every case before changing the ledger.
45
+ const afterPublish = await (0, pr_lifecycle_1.observePrLifecycle)(deps.exec, deps.project.path, row.pr_url, row.delivery_sha);
46
+ if (!afterPublish.ok) {
47
+ if (r.code !== 0)
48
+ return (0, transitions_1.ghFailed)(r);
49
+ return { status: 502, body: { error: 'gh_failed', detail: `PR readiness could not be verified: ${afterPublish.detail}` } };
50
+ }
51
+ if (!(0, pr_lifecycle_1.matchesRecordedPrIdentity)(afterPublish, row.branch, row.base_branch)) {
52
+ return (0, observations_1.rerouteFromStalePr)(deps, row, `the PR identity changed while publishing it for review (${afterPublish.state.toLowerCase()})`, afterPublish.includesExpectedSha === true);
53
+ }
54
+ if (afterPublish.state === 'MERGED') {
55
+ return afterPublish.includesExpectedSha === true
56
+ ? (0, observations_1.settleMergedPr)(deps, row)
57
+ : (0, observations_1.rerouteFromStalePr)(deps, row, (0, observations_1.mergedEvidenceDetail)(afterPublish), false);
58
+ }
59
+ if (afterPublish.state === 'CLOSED') {
60
+ return afterPublish.includesExpectedSha === true
61
+ ? (0, observations_1.settleObservedClosedPr)(deps, row, afterPublish)
62
+ : (0, observations_1.rerouteFromStalePr)(deps, row, 'the PR closed without the verified implementation commit while being published', false);
63
+ }
64
+ if (afterPublish.includesExpectedSha !== true) {
65
+ return (0, observations_1.persistRetryablePrObservationFailure)(deps, row, 'the PR no longer exposes the verified implementation commit after publishing; Retry push is available');
66
+ }
67
+ if (afterPublish.isDraft) {
68
+ if (r.code !== 0)
69
+ return (0, transitions_1.ghFailed)(r);
70
+ return { status: 502, body: { error: 'gh_failed', detail: 'PR remained a draft after publishing' } };
71
+ }
72
+ return (0, observations_1.settleObservedExistingPr)(deps, row, afterPublish, false);
73
+ }
74
+ async function runPollMerge(deps, row) {
75
+ const observed = await (0, pr_lifecycle_1.observePrLifecycle)(deps.exec, deps.project.path, row.pr_url, row.delivery_sha);
76
+ if (!observed.ok)
77
+ return { status: 502, body: { error: 'gh_failed', detail: observed.detail } };
78
+ const { state, isDraft } = observed;
79
+ if (!row.branch) {
80
+ return (0, observations_1.persistMovedPrHead)(deps, row, `the ${state.toLowerCase()} PR has no recorded delivery branch; refusing to infer recoverable work`);
81
+ }
82
+ if (!row.delivery_sha) {
83
+ // A legacy OPEN row cannot be retried without an immutable object. Once the
84
+ // attached PR is terminal, however, keeping that stale URL would strand the
85
+ // only recorded branch behind Discard. Detach it so Create PR can perform
86
+ // the existing one-time legacy ref capture, without claiming any delivery.
87
+ if (state === 'CLOSED' || state === 'MERGED') {
88
+ return (0, observations_1.rerouteFromStalePr)(deps, row, `the previous PR is ${state.toLowerCase()} and this legacy delivery has no persisted verified SHA`, false);
89
+ }
90
+ return (0, observations_1.persistMovedPrHead)(deps, row, 'the open PR has no persisted verified delivery SHA; refusing to infer delivery from a mutable branch');
91
+ }
92
+ if (!(0, pr_lifecycle_1.matchesRecordedPrIdentity)(observed, row.branch, row.base_branch)) {
93
+ return (0, observations_1.rerouteFromStalePr)(deps, row, `the recorded PR is ${state.toLowerCase()} but no longer matches its original head/base identity`, observed.includesExpectedSha === true);
94
+ }
95
+ if (state === 'CLOSED') {
96
+ if (observed.includesExpectedSha !== true) {
97
+ return (0, observations_1.rerouteFromStalePr)(deps, row, 'the previous PR closed without the verified implementation commit', false);
98
+ }
99
+ return (0, observations_1.settleObservedClosedPr)(deps, row, observed);
100
+ }
101
+ if (state === 'OPEN') {
102
+ if (observed.includesExpectedSha !== true) {
103
+ const detail = 'the open PR no longer exposes the verified implementation commit; Retry push is available and will use the preserved exact SHA';
104
+ const result = (0, observations_1.persistRetryablePrObservationFailure)(deps, row, detail);
105
+ return {
106
+ ...result,
107
+ body: {
108
+ ...result.body,
109
+ deliveryVerified: false,
110
+ verifiedSha: row.delivery_sha,
111
+ remoteHeadSha: observed.headRefOid,
112
+ },
113
+ };
114
+ }
115
+ // A successful reopen can be observed even if the explicit action lost its
116
+ // follow-up `gh view` response. Polling heals pr_closed from remote truth.
117
+ if (row.decision === 'pr_closed') {
118
+ const next = isDraft ? 'pr_draft' : 'pr_ready';
119
+ const conflict = (0, transitions_1.casTransition)(deps, row, next, {
120
+ deliveryOutcome: 'delivered', statusCode: isDraft ? 'pr_draft_ready' : 'pr_ready',
121
+ });
122
+ if (conflict)
123
+ return conflict;
124
+ (0, transitions_1.finalizeTransition)(deps, row.id);
125
+ return {
126
+ status: 200,
127
+ body: {
128
+ ok: true,
129
+ decision: next,
130
+ merged: false,
131
+ reopened: true,
132
+ prUrl: row.pr_url,
133
+ deliveryVerified: true,
134
+ verifiedSha: row.delivery_sha,
135
+ remoteHeadSha: observed.headRefOid,
136
+ pushed: false,
137
+ },
138
+ };
139
+ }
140
+ return {
141
+ status: 200,
142
+ body: {
143
+ ok: true,
144
+ decision: row.decision,
145
+ merged: false,
146
+ deliveryVerified: true,
147
+ verifiedSha: row.delivery_sha,
148
+ remoteHeadSha: observed.headRefOid,
149
+ pushed: false,
150
+ },
151
+ };
152
+ }
153
+ if (state !== 'MERGED') {
154
+ return { status: 502, body: { error: 'gh_failed', detail: `unexpected PR state: ${state}` } };
155
+ }
156
+ // A PR can merge just before a continuation push; GitHub may then accept a
157
+ // later update to the head branch even though that object was never part of
158
+ // the merge. Never move tickets to Done from state=MERGED alone.
159
+ if (observed.includesExpectedSha !== true) {
160
+ return (0, observations_1.rerouteFromStalePr)(deps, row, (0, observations_1.mergedEvidenceDetail)(observed), false);
161
+ }
162
+ return (0, observations_1.settleMergedPr)(deps, row);
163
+ }
164
+ async function runReopen(deps, row) {
165
+ if (!row.delivery_sha || !row.branch) {
166
+ return (0, observations_1.rerouteFromStalePr)(deps, row, 'the closed PR cannot be reopened safely because its immutable delivery SHA/head identity is unavailable', false);
167
+ }
168
+ const beforeReopen = await (0, pr_lifecycle_1.observePrLifecycle)(deps.exec, deps.project.path, row.pr_url, row.delivery_sha);
169
+ if (!beforeReopen.ok) {
170
+ return { status: 502, body: { error: 'gh_failed', detail: beforeReopen.detail } };
171
+ }
172
+ if (!(0, pr_lifecycle_1.matchesRecordedPrIdentity)(beforeReopen, row.branch, row.base_branch) ||
173
+ beforeReopen.includesExpectedSha !== true) {
174
+ return (0, observations_1.rerouteFromStalePr)(deps, row, 'the closed PR no longer proves the recorded head/base and verified implementation commit', false);
175
+ }
176
+ if (beforeReopen.state === 'MERGED')
177
+ return (0, observations_1.settleMergedPr)(deps, row);
178
+ if (beforeReopen.state === 'OPEN') {
179
+ const next = beforeReopen.isDraft ? 'pr_draft' : 'pr_ready';
180
+ const conflict = (0, transitions_1.casTransition)(deps, row, next, {
181
+ deliveryOutcome: 'delivered', statusCode: beforeReopen.isDraft ? 'pr_draft_ready' : 'pr_ready',
182
+ statusDetail: null,
183
+ });
184
+ if (conflict)
185
+ return conflict;
186
+ (0, transitions_1.finalizeTransition)(deps, row.id);
187
+ return {
188
+ status: 200,
189
+ body: {
190
+ ok: true, decision: next, reopened: true, prUrl: row.pr_url,
191
+ deliveryVerified: true, verifiedSha: row.delivery_sha,
192
+ remoteHeadSha: beforeReopen.headRefOid, pushed: false,
193
+ },
194
+ };
195
+ }
196
+ let reopened;
197
+ try {
198
+ reopened = await deps.exec.run('gh', ['pr', 'reopen', row.pr_url], deps.project.path);
199
+ }
200
+ catch (err) {
201
+ reopened = { code: 1, stdout: '', stderr: err instanceof Error ? err.message : String(err) };
202
+ }
203
+ const observed = await (0, pr_lifecycle_1.observePrLifecycle)(deps.exec, deps.project.path, row.pr_url, row.delivery_sha);
204
+ if (!observed.ok) {
205
+ if (reopened.code !== 0)
206
+ return (0, transitions_1.ghFailed)(reopened);
207
+ return { status: 502, body: { error: 'gh_failed', detail: observed.detail } };
208
+ }
209
+ const identityMatches = (0, pr_lifecycle_1.matchesRecordedPrIdentity)(observed, row.branch, row.base_branch);
210
+ if (observed.state === 'MERGED') {
211
+ if (identityMatches && observed.includesExpectedSha === true)
212
+ return (0, observations_1.settleMergedPr)(deps, row);
213
+ return (0, observations_1.rerouteFromStalePr)(deps, row, identityMatches ? (0, observations_1.mergedEvidenceDetail)(observed) : 'the PR identity changed while it was being reopened', false);
214
+ }
215
+ if (observed.state === 'CLOSED') {
216
+ if (!identityMatches || observed.includesExpectedSha !== true) {
217
+ return (0, observations_1.rerouteFromStalePr)(deps, row, 'the PR remained closed without proving the recorded head/base and verified implementation commit', false);
218
+ }
219
+ if (reopened.code !== 0)
220
+ return (0, transitions_1.ghFailed)(reopened);
221
+ return { status: 502, body: { error: 'gh_failed', detail: 'PR remained closed after reopen' } };
222
+ }
223
+ if (!identityMatches || observed.includesExpectedSha !== true) {
224
+ return (0, observations_1.rerouteFromStalePr)(deps, row, 'the reopened PR no longer proves the recorded head/base and verified implementation commit', true);
225
+ }
226
+ const next = observed.isDraft ? 'pr_draft' : 'pr_ready';
227
+ const conflict = (0, transitions_1.casTransition)(deps, row, next, {
228
+ deliveryOutcome: 'delivered', statusCode: observed.isDraft ? 'pr_draft_ready' : 'pr_ready',
229
+ statusDetail: null,
230
+ });
231
+ if (conflict)
232
+ return conflict;
233
+ (0, transitions_1.finalizeTransition)(deps, row.id);
234
+ return {
235
+ status: 200,
236
+ body: {
237
+ ok: true, decision: next, reopened: true, prUrl: row.pr_url,
238
+ deliveryVerified: true, verifiedSha: row.delivery_sha,
239
+ remoteHeadSha: observed.headRefOid, pushed: false,
240
+ },
241
+ };
242
+ }