@overdeck/desktop 0.45.24 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/drizzle/overdeck/0000_overdeck_init.sql +36 -1
  2. package/package.json +1 -1
  3. package/server/{acceptance-criteria-DDCnXF58.js → acceptance-criteria-10Ur5Dne.js} +2 -2
  4. package/server/activity-logger-CMthG6Vd.js +3 -0
  5. package/server/{activity-logger-DDlOIAML.js → activity-logger-CyteR4JO.js} +24 -13
  6. package/server/{advancing-selfheal-BVwW4qRn.js → advancing-selfheal-BNwqxseD.js} +6 -6
  7. package/server/{agent-gc-CHcnvonI.js → agent-gc-C3h9Or3a.js} +5 -5
  8. package/server/agent-state-CYXJVG72.js +3 -0
  9. package/server/agent-state-service-C63p_ftq.js +2 -0
  10. package/server/{agent-state-service-BsgWxZuB.js → agent-state-service-Ds6OeFvo.js} +15 -9
  11. package/server/{agents-EbI0zCJl.js → agents-J5mEnekq.js} +23 -16
  12. package/server/agents-ePFVoZbu.js +3 -0
  13. package/server/archive-planning-B2XplFzT.js +2 -0
  14. package/server/{archive-planning-Du25Jtst.js → archive-planning-BwhxeP7C.js} +22 -26
  15. package/server/{artifact-index-jobs-CbEDfCDu.js → artifact-index-jobs-D1q_vR3V.js} +2 -2
  16. package/server/{assemble-J2ZZ2C15.js → assemble-Bgwqv-Ro.js} +2 -2
  17. package/server/auto-spawn-consent-CQ9Bi9q6.js +1141 -0
  18. package/server/{backlog-auto-trigger-2R2jog7n.js → backlog-auto-trigger-n1lzPgN4.js} +3 -3
  19. package/server/{behavior-B3exJ42O.js → behavior-td6-xhQk.js} +2 -2
  20. package/server/boot-reconciled-stop-events-C7gGe3oB.js +44 -0
  21. package/server/bridge-pool-patrol-CYH2OLb5.js +136 -0
  22. package/server/{briefing-freshness-D1wzUIWv.js → briefing-freshness-DRqZ8lAz.js} +2 -2
  23. package/server/{build-info-Ie_D0_BT.js → build-info-7yiEpl6u.js} +5 -3
  24. package/server/{build-info-CZk_TITh.js → build-info-CpG__c63.js} +1 -1
  25. package/server/{checkpoint-manager-DwbQoqrC.js → checkpoint-manager-CkKmB0wZ.js} +1 -1
  26. package/server/{checkpoint-manager-BI1Wxoku.js → checkpoint-manager-DBcyNR8w.js} +2 -2
  27. package/server/checkpoint-worker.js +1 -1
  28. package/server/{checkpoints-CQB1h765.js → checkpoints-D95apurL.js} +2 -2
  29. package/server/{checkpoints-BJIs5QIA.js → checkpoints-Wm963lm8.js} +1 -1
  30. package/server/{claude-hooks-provision-8Ngo8TpT.js → claude-hooks-provision-4RPxNkE8.js} +1 -1
  31. package/server/{claude-hooks-provision-D8GXF3_s.js → claude-hooks-provision-Bjitl9aI.js} +13 -2
  32. package/server/{claude-permissions-DNWEVV6z.js → claude-permissions-CpbpvUQ2.js} +2 -2
  33. package/server/{claude-settings-overlay-DWy-Bb4Y.js → claude-settings-overlay-BzkHYDwR.js} +1 -1
  34. package/server/{claude-settings-overlay-CEdaqpWI.js → claude-settings-overlay-_H9Yrzab.js} +2 -2
  35. package/server/cli-CjOCSnfj.js +3 -0
  36. package/server/{cli-RoOx5DUf.js → cli-Cte9ZFGn.js} +9 -9
  37. package/server/{cliproxy-C8a1vtTU.js → cliproxy-C5fMJ7rY.js} +2 -2
  38. package/server/{cliproxy-fHfIeiGd.js → cliproxy-DaAbWMjC.js} +1 -1
  39. package/server/{close-issue-DoOifFIK.js → close-issue-BPh1ARCF.js} +5 -5
  40. package/server/{closed-issue-reaper-CktPXo8m.js → closed-issue-reaper-DHRfRMrp.js} +1 -1
  41. package/server/{closed-issue-reaper-Bk3SU4RC.js → closed-issue-reaper-DoOZqGFK.js} +88 -17
  42. package/server/{codex-BZXGhUVB.js → codex-BzGDW_d3.js} +36 -7
  43. package/server/{codex-GcHuUF-k.js → codex-o8FJwzmy.js} +1 -1
  44. package/server/{codex-parser-CFZ1_1Jl.js → codex-parser-Dt-ycU8L.js} +2 -2
  45. package/server/compaction-continuation-CvXpbZ4w.js +200 -0
  46. package/server/{config-CKxYiCmX.js → config-Bi3u1VK7.js} +4 -3
  47. package/server/{config-BZ0sHTju.js → config-BvLe652W.js} +2 -2
  48. package/server/{config-DzV30TOm.js → config-CL3Gyvja.js} +1 -1
  49. package/server/{config-yaml-DySPNmKN.js → config-yaml-CxdwhAIA.js} +276 -14
  50. package/server/conflict-gate-CX80JYYS.js +3 -0
  51. package/server/{conflict-gate-BaCVrH-N.js → conflict-gate-E4nt7ZeS.js} +60 -14
  52. package/server/{context-layers-igZ4FI4_.js → context-layers-C_IIysnm.js} +3 -3
  53. package/server/{context-layers-BrPmE__h.js → context-layers-DAG83UZt.js} +2 -2
  54. package/server/{control-settings-BQp7_4uD.js → control-settings-CiqGxXnc.js} +56 -19
  55. package/server/{conversation-compaction-eQB5CkOe.js → conversation-compaction-BE3CNtHF.js} +1 -1
  56. package/server/{conversation-compaction-CgrR8YYp.js → conversation-compaction-D6-yLtqt.js} +8 -8
  57. package/server/{conversation-service-DPJ71F33.js → conversation-service-DBxoYMDl.js} +10 -8
  58. package/server/conversation-service-D_TS2b1r.js +3 -0
  59. package/server/{conversations-CAsJF9kh.js → conversations-BKDVpB-3.js} +1 -1
  60. package/server/{conversations-6AfUfbwc.js → conversations-D0UEdLtk.js} +4 -4
  61. package/server/{cost-R-m6Yi-W.js → cost-DS1s0DbG.js} +3 -3
  62. package/server/{cost-B2ddP6wq.js → cost-DpgYmYqR.js} +12 -2
  63. package/server/{cost-sync-BsN6ER0n.js → cost-sync-tOCCGnEt.js} +3 -3
  64. package/server/{dag-B1ucnjDU.js → dag-BtkgLeqY.js} +2 -2
  65. package/server/{dangerous-git-ops-BXqeWVSf.js → dangerous-git-ops-CFLykHWt.js} +1 -1
  66. package/server/dashboard-db-worker.js +7 -7
  67. package/server/deacon-BIblC-WX.js +4 -0
  68. package/server/{deacon-nudge-log-6wVqAaqz.js → deacon-nudge-log-B08gF0mh.js} +3 -3
  69. package/server/{deacon-CU_cAYSR.js → deacon-pLRLbPvR.js} +3308 -2707
  70. package/server/deacon-pending-lifecycle-B-Io84AP.js +33 -0
  71. package/server/deacon-swarm-B1XkIvfr.js +2 -0
  72. package/server/{deacon-swarm-BXZZ1Z2-.js → deacon-swarm-v5PMun-m.js} +15 -14
  73. package/server/deacon.js +14 -19
  74. package/server/dead-end-trip-D8A3msX9.js +13 -0
  75. package/server/delivery-BX9HR4wQ.js +3 -0
  76. package/server/{deploy-patrol-AiFoP8dw.js → deploy-patrol-sYgOxLeb.js} +69 -18
  77. package/server/deploy-queue-VfohaPN_.js +169 -0
  78. package/server/deploy-queue-gHJBycaF.js +3 -0
  79. package/server/deploy-window-CFRZ0-kt.js +3 -0
  80. package/server/{deploy-window-C3F-tihF.js → deploy-window-D4DQb8VP.js} +40 -16
  81. package/server/{dev-supervisor-bcOWqdQE.js → dev-supervisor-DiOBDM1c.js} +2 -2
  82. package/server/{devcontainer-renderer-_d6XhyND.js → devcontainer-renderer-BUOIlfgD.js} +3 -3
  83. package/server/dist-B3YPQa5A.js +3 -0
  84. package/server/{dist-Cb_0uvpS.js → dist-C3A8B8wM.js} +1 -1
  85. package/server/{dist-src-BSoS7mkd.js → dist-src-C0adpegX.js} +1 -1
  86. package/server/{docker-DcMTFTUC.js → docker-BJzlkqYB.js} +2 -2
  87. package/server/docker-Y3PElJb0.js +3 -0
  88. package/server/dod-DlNtcH6n.js +91 -0
  89. package/server/durable-review-pipeline-Cibps-Rg.js +20 -0
  90. package/server/durable-review-pipeline-DP6bIcOY.js +3 -0
  91. package/server/{ensure-devcontainer-DNi-ono3.js → ensure-devcontainer-BAofzBPv.js} +4 -4
  92. package/server/{ensure-devcontainer-BZgOhRo7.js → ensure-devcontainer-DMAbWqtQ.js} +1 -1
  93. package/server/{esm-shims-OSHAYaS1.js → esm-shims-BeObUkaw.js} +1 -1
  94. package/server/{event-store-EV2cMiXj.js → event-store-5UKzh9Jf.js} +1 -1
  95. package/server/{event-store-CQL6NeqB.js → event-store-CrHcVC5_.js} +23 -4
  96. package/server/{events-DTfAe4My.js → events-BNrvchBg.js} +3 -3
  97. package/server/{events-BTdrdEq8.js → events-CF8QDbuV.js} +1 -1
  98. package/server/{factory-CFibJuaw.js → factory-Cmm9Hsho.js} +5 -5
  99. package/server/{feature-registry-population-DKZFMbFt.js → feature-registry-population-B6HpNWRy.js} +4 -4
  100. package/server/{feature-registry-storage-BdPuLcBX.js → feature-registry-storage-DJEFx1Pf.js} +2 -2
  101. package/server/{features-ez2271oH.js → features-D5km80UI.js} +2 -2
  102. package/server/{feedback-target-CoFDHiM8.js → feedback-target-BJ5ZADsu.js} +1 -1
  103. package/server/{feedback-target-7mqqwrX6.js → feedback-target-DSxEL6lP.js} +8 -8
  104. package/server/{feedback-writer-CY5L1lB7.js → feedback-writer-C27Hak8a.js} +5 -5
  105. package/server/{feedback-writer-D3a22RCd.js → feedback-writer-CoB9Z6aU.js} +1 -1
  106. package/server/{flywheel-DHrgCphM.js → flywheel-BHx8XuMr.js} +47 -20
  107. package/server/{flywheel-SVF02Jpq.js → flywheel-DZZdtiOL.js} +1 -1
  108. package/server/{flywheel-DzGtWnJ1.js → flywheel-f662Q-y2.js} +16 -15
  109. package/server/flywheel-merge-order-D_xLMbJU.js +462 -0
  110. package/server/flywheel-merge-order-Dil0LmdN.js +2 -0
  111. package/server/forge-B5o319qI.js +3 -0
  112. package/server/forge-BaKGCya6.js +383 -0
  113. package/server/{from-kNxT0bZC.js → from-B3tZbB55.js} +1 -1
  114. package/server/fs-lock-Bre3sGoz.js +130 -0
  115. package/server/{fts-db-CE46vDkZ.js → fts-db-IVc4_M3f.js} +2 -2
  116. package/server/{fts-operations-CqY6zl-i.js → fts-operations-B9jG8wa3.js} +2 -2
  117. package/server/{git-utils-CRw2zLPC.js → git-utils-CsvYfJU3.js} +30 -5
  118. package/server/git-utils-Xg4PFN45.js +3 -0
  119. package/server/{github-app-ClZ2lk8D.js → github-app-Bmg4R9mv.js} +1 -1
  120. package/server/{github-app-C3QrAUd0.js → github-app-CmNk0zLU.js} +3 -3
  121. package/server/{github-client-DfQYVUaw.js → github-client-B6KM9_wA.js} +1 -1
  122. package/server/{github-client-BnIsSrEN.js → github-client-qazkPrg0.js} +3 -3
  123. package/server/github-pr-lookup-DAcVeRLK.js +58 -0
  124. package/server/{harness-binary-DPUi-Pv8.js → harness-binary-BSpiXaLw.js} +2 -2
  125. package/server/{harness-resolve-3lNZkyT4.js → harness-resolve-BAJu5MX8.js} +4 -4
  126. package/server/{health-events-BDOHby5Q.js → health-events-2Z6Wa9SM.js} +1 -1
  127. package/server/{health-events-BBcTYQKU.js → health-events-BwX32k8d.js} +2 -2
  128. package/server/{hooks-DPVX1rwQ.js → hooks-D1g1jKLI.js} +1 -1
  129. package/server/{hooks-CKZgXlJb.js → hooks-DbtbimEf.js} +2 -2
  130. package/server/{hume-Cz8igP9E.js → hume-DXNiu6nQ.js} +2 -2
  131. package/server/hume-VUCNbTgn.js +3 -0
  132. package/server/{idle-stack-reaper-CuLF0j2H.js → idle-stack-reaper-CRA1e0jr.js} +1 -1
  133. package/server/{idle-stack-reaper-DDIRwxUY.js → idle-stack-reaper-Cy-dQzW4.js} +99 -6
  134. package/server/in-flight-guard-D-sSkADM.js +45 -0
  135. package/server/{infra-BEqFxlJc.js → infra-BDQDRopn.js} +81 -5
  136. package/server/{injection-C8aiVJrF.js → injection-6AGnXxlj.js} +7 -7
  137. package/server/{injection-CPUIqNhI.js → injection-Bl8d_jHZ.js} +1 -1
  138. package/server/inspect-agent-CUwVmr2h.js +2 -0
  139. package/server/{inspect-agent-BLuJ1AkT.js → inspect-agent-nXdIptyh.js} +26 -25
  140. package/server/{internal-token-s0-oKybJ.js → internal-token-DzK385vD.js} +2 -2
  141. package/server/{internal-token-BrcU6qfe.js → internal-token-Ias7N8Kg.js} +1 -1
  142. package/server/{io-C9kF1wtJ.js → io-B00PBNku.js} +44 -27
  143. package/server/{issue-closed-CDJk4pIp.js → issue-closed-BehTG1be.js} +8 -8
  144. package/server/{issue-lifecycle-ojZAzDBP.js → issue-lifecycle-Birk-ifu.js} +42 -30
  145. package/server/{issue-lifecycle-B8sZHVHh.js → issue-lifecycle-BqSuQvbn.js} +1 -1
  146. package/server/{issue-service-singleton-BvJ09SaR.js → issue-service-singleton-B2wXiIlw.js} +1 -1
  147. package/server/{issue-service-singleton-Yx5DdmVJ.js → issue-service-singleton-C6ZduvuY.js} +10 -10
  148. package/server/{issues-BMmP_77e.js → issues-DQ5-LatB.js} +2 -2
  149. package/server/{jsonl-parser-BXSlHwEh.js → jsonl-parser-BDpnGFCl.js} +5 -4
  150. package/server/{label-cleanup-B0UJwnv5.js → label-cleanup-Dwnky8FG.js} +3 -3
  151. package/server/{lifecycle-xmBfK2GJ.js → lifecycle-B3s4sM1G.js} +6 -7
  152. package/server/{lifecycle-yPd___5E.js → lifecycle-B4Xdb4cY.js} +2 -2
  153. package/server/{lifecycle-io-DPo7x11I.js → lifecycle-io-CzTHEooc.js} +1 -1
  154. package/server/{lifecycle-io-BREGpnLk.js → lifecycle-io-DCo6s6ks.js} +5 -5
  155. package/server/{linear-client-BsuUvkdA.js → linear-client-9uq7fhiV.js} +3 -3
  156. package/server/{linear-client-CTskEeT_.js → linear-client-CnbtHiic.js} +1 -1
  157. package/server/linear-mcp-auth-BxUOzswy.js +280 -0
  158. package/server/linear-mcp-auth-D46fBCLf.js +2 -0
  159. package/server/memory-fts-worker.js +1 -1
  160. package/server/{merge-CefQNAnq.js → merge-DiW9RdSB.js} +13 -11
  161. package/server/{merge-agent-4WOWlSYA.js → merge-agent-BLUgRsz3.js} +234 -84
  162. package/server/{merge-agent-CKkgIBPB.js → merge-agent-DQTXZk8z.js} +1 -1
  163. package/server/{merge-batch-ClFn2T-y.js → merge-batch-Cp_j9BGk.js} +1 -1
  164. package/server/merge-completeness-B46KqhtY.js +277 -0
  165. package/server/merge-completeness-BLbB5-6n.js +3 -0
  166. package/server/merge-ops-1abz6O_P.js +2 -0
  167. package/server/merge-rebase-CJJVAJuz.js +2 -0
  168. package/server/{merge-rebase-BfaTyXsw.js → merge-rebase-DIkBjgwq.js} +3 -3
  169. package/server/{merge-set-DJ8-UErs.js → merge-set-CBgHfwM0.js} +11 -5
  170. package/server/merge-set-DeUxFsC3.js +3 -0
  171. package/server/{merge-B1DiziGU.js → merge-sr8Nrnmi.js} +1 -1
  172. package/server/merge-sync-CpGmk6Ch.js +3 -0
  173. package/server/{merge-sync-VPV28g0g.js → merge-sync-kr4vqyjM.js} +409 -153
  174. package/server/{merge-train-CHopycP0.js → merge-train-Dmrcus12.js} +18 -8
  175. package/server/{merge-train-deps-D1cOZzy2.js → merge-train-deps-D_uGX91G.js} +21 -15
  176. package/server/merge-verification-NvaAd8CZ.js +220 -0
  177. package/server/merged-docker-cleanup-worker-DH_hrGPI.js +3 -0
  178. package/server/merged-docker-cleanup-worker-Y1R06TEl.js +107 -0
  179. package/server/{multipart-parser-duPAfSBw.js → multipart-parser-R-oC8dQg.js} +2 -2
  180. package/server/{no-resume-mode-Nw29vaFb.js → no-resume-mode-BgD0JUmM.js} +1 -1
  181. package/server/node_modules/.package-lock.json +30 -30
  182. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/package.json +3 -3
  183. package/server/node_modules/@google-cloud/common/package.json +2 -2
  184. package/server/node_modules/@types/node/README.md +1 -1
  185. package/server/node_modules/@types/node/crypto.d.ts +1 -1
  186. package/server/node_modules/@types/node/package.json +2 -2
  187. package/server/node_modules/gaxios/build/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  188. package/server/node_modules/gaxios/build/esm/tsconfig.tsbuildinfo +1 -1
  189. package/server/node_modules/gaxios/package.json +1 -1
  190. package/server/node_modules/google-auth-library/build/src/auth/googleauth.js +24 -19
  191. package/server/node_modules/google-auth-library/package.json +1 -1
  192. package/server/node_modules/google-gax/build/protos/google/api/auth.proto +2 -1
  193. package/server/node_modules/google-gax/build/protos/google/api/backend.proto +12 -1
  194. package/server/node_modules/google-gax/build/protos/google/api/billing.proto +1 -1
  195. package/server/node_modules/google-gax/build/protos/google/api/client.proto +165 -53
  196. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1/resources.proto +1 -1
  197. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1beta/quota_adjuster_settings.proto +7 -3
  198. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1beta/resources.proto +1 -1
  199. package/server/node_modules/google-gax/build/protos/google/api/config_change.proto +1 -1
  200. package/server/node_modules/google-gax/build/protos/google/api/context.proto +1 -1
  201. package/server/node_modules/google-gax/build/protos/google/api/control.proto +3 -3
  202. package/server/node_modules/google-gax/build/protos/google/api/distribution.proto +1 -1
  203. package/server/node_modules/google-gax/build/protos/google/api/documentation.proto +1 -1
  204. package/server/node_modules/google-gax/build/protos/google/api/endpoint.proto +1 -1
  205. package/server/node_modules/google-gax/build/protos/google/api/error_reason.proto +186 -1
  206. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/checked.proto +31 -3
  207. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/eval.proto +8 -9
  208. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/explain.proto +1 -2
  209. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/syntax.proto +20 -22
  210. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/value.proto +2 -3
  211. package/server/node_modules/google-gax/build/protos/google/api/field_behavior.proto +1 -1
  212. package/server/node_modules/google-gax/build/protos/google/api/field_info.proto +1 -1
  213. package/server/node_modules/google-gax/build/protos/google/api/http.proto +1 -1
  214. package/server/node_modules/google-gax/build/protos/google/api/httpbody.proto +1 -1
  215. package/server/node_modules/google-gax/build/protos/google/api/label.proto +1 -1
  216. package/server/node_modules/google-gax/build/protos/google/api/launch_stage.proto +1 -1
  217. package/server/node_modules/google-gax/build/protos/google/api/log.proto +1 -1
  218. package/server/node_modules/google-gax/build/protos/google/api/logging.proto +1 -1
  219. package/server/node_modules/google-gax/build/protos/google/api/metric.proto +1 -1
  220. package/server/node_modules/google-gax/build/protos/google/api/monitored_resource.proto +1 -1
  221. package/server/node_modules/google-gax/build/protos/google/api/monitoring.proto +1 -1
  222. package/server/node_modules/google-gax/build/protos/google/api/policy.proto +1 -1
  223. package/server/node_modules/google-gax/build/protos/google/api/quota.proto +1 -1
  224. package/server/node_modules/google-gax/build/protos/google/api/resource.proto +1 -1
  225. package/server/node_modules/google-gax/build/protos/google/api/routing.proto +8 -4
  226. package/server/node_modules/google-gax/build/protos/google/api/service.proto +2 -3
  227. package/server/node_modules/google-gax/build/protos/google/api/source_info.proto +1 -1
  228. package/server/node_modules/google-gax/build/protos/google/api/system_parameter.proto +1 -1
  229. package/server/node_modules/google-gax/build/protos/google/api/usage.proto +7 -27
  230. package/server/node_modules/google-gax/build/protos/google/api/visibility.proto +1 -1
  231. package/server/node_modules/google-gax/build/protos/google/longrunning/operations.proto +20 -1
  232. package/server/node_modules/google-gax/build/protos/google/protobuf/any.proto +52 -108
  233. package/server/node_modules/google-gax/build/protos/google/protobuf/compiler/ruby/ruby_generated_code.proto +2 -0
  234. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_features.proto +21 -1
  235. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_file_options.proto +24 -0
  236. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_options.proto +15 -0
  237. package/server/node_modules/google-gax/build/protos/google/protobuf/descriptor.proto +118 -30
  238. package/server/node_modules/google-gax/build/protos/google/protobuf/field_mask.proto +16 -18
  239. package/server/node_modules/google-gax/build/protos/google/protobuf/internal_options.proto +8 -1
  240. package/server/node_modules/google-gax/build/protos/google/protobuf/json/json_enumval_custom_string.proto +26 -0
  241. package/server/node_modules/google-gax/build/protos/google/protobuf/json_enumvalue_options.proto +29 -0
  242. package/server/node_modules/google-gax/build/protos/google/protobuf/json_options.proto +14 -0
  243. package/server/node_modules/google-gax/build/protos/google/protobuf/struct.proto +38 -22
  244. package/server/node_modules/google-gax/build/protos/google/protobuf/test_protos/forced_micro_string.proto +3 -0
  245. package/server/node_modules/google-gax/build/protos/google/protobuf/test_protos/repeated_field_proxy_import_message.proto +14 -0
  246. package/server/node_modules/google-gax/build/protos/google/protobuf/timestamp.proto +9 -8
  247. package/server/node_modules/google-gax/build/protos/google/protobuf/util/json_format_proto3.proto +18 -0
  248. package/server/node_modules/google-gax/build/protos/google/rpc/code.proto +1 -1
  249. package/server/node_modules/google-gax/build/protos/google/rpc/context/attribute_context.proto +7 -2
  250. package/server/node_modules/google-gax/build/protos/google/rpc/context/audit_context.proto +1 -1
  251. package/server/node_modules/google-gax/build/protos/google/rpc/error_details.proto +5 -5
  252. package/server/node_modules/google-gax/build/protos/google/rpc/http.proto +1 -1
  253. package/server/node_modules/google-gax/build/protos/google/rpc/status.proto +1 -2
  254. package/server/node_modules/google-gax/build/protos/google/type/calendar_period.proto +1 -1
  255. package/server/node_modules/google-gax/build/protos/google/type/color.proto +9 -10
  256. package/server/node_modules/google-gax/build/protos/google/type/date.proto +11 -9
  257. package/server/node_modules/google-gax/build/protos/google/type/datetime.proto +17 -17
  258. package/server/node_modules/google-gax/build/protos/google/type/dayofweek.proto +1 -1
  259. package/server/node_modules/google-gax/build/protos/google/type/decimal.proto +11 -13
  260. package/server/node_modules/google-gax/build/protos/google/type/expr.proto +1 -1
  261. package/server/node_modules/google-gax/build/protos/google/type/fraction.proto +1 -1
  262. package/server/node_modules/google-gax/build/protos/google/type/interval.proto +1 -2
  263. package/server/node_modules/google-gax/build/protos/google/type/latlng.proto +4 -5
  264. package/server/node_modules/google-gax/build/protos/google/type/localized_text.proto +3 -3
  265. package/server/node_modules/google-gax/build/protos/google/type/money.proto +1 -2
  266. package/server/node_modules/google-gax/build/protos/google/type/month.proto +1 -1
  267. package/server/node_modules/google-gax/build/protos/google/type/phone_number.proto +20 -15
  268. package/server/node_modules/google-gax/build/protos/google/type/postal_address.proto +39 -39
  269. package/server/node_modules/google-gax/build/protos/google/type/quaternion.proto +4 -4
  270. package/server/node_modules/google-gax/build/protos/google/type/timeofday.proto +11 -8
  271. package/server/node_modules/google-gax/package.json +5 -5
  272. package/server/node_modules/retry-request/package.json +4 -4
  273. package/server/node_modules/teeny-request/package.json +5 -5
  274. package/server/node_modules/undici/lib/cache/memory-cache-store.js +54 -9
  275. package/server/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
  276. package/server/node_modules/undici/lib/core/request.js +12 -1
  277. package/server/node_modules/undici/lib/dispatcher/client-h1.js +11 -2
  278. package/server/node_modules/undici/lib/global.js +36 -16
  279. package/server/node_modules/undici/lib/handler/cache-handler.js +236 -116
  280. package/server/node_modules/undici/lib/handler/cache-revalidation-handler.js +3 -3
  281. package/server/node_modules/undici/lib/handler/retry-handler.js +24 -0
  282. package/server/node_modules/undici/lib/interceptor/cache.js +152 -62
  283. package/server/node_modules/undici/lib/interceptor/decompress.js +5 -2
  284. package/server/node_modules/undici/lib/util/cache.js +328 -66
  285. package/server/node_modules/undici/lib/util/date.js +23 -6
  286. package/server/node_modules/undici/lib/web/cookies/util.js +78 -8
  287. package/server/node_modules/undici/package.json +1 -1
  288. package/server/{orphan-proposed-reconciler-BvKkWMJQ.js → orphan-proposed-reconciler-B6vJHxtX.js} +242 -34
  289. package/server/{orphan-proposed-reconciler-CTSGcK8p.js → orphan-proposed-reconciler-DcgTPPFY.js} +1 -1
  290. package/server/package-lock.json +31 -31
  291. package/server/package.json +1 -1
  292. package/server/{pan-dir-B0c3w0Ya.js → pan-dir-DMzF5wne.js} +25 -11
  293. package/server/{paths-D-xWGHdh.js → paths-sJBSb7Ul.js} +2 -2
  294. package/server/pending-lifecycle-claim-DilzGfgk.js +110 -0
  295. package/server/persistent-logger-H_VjuOu7.js +57 -0
  296. package/server/{pickup-DUCLWrJY.js → pickup-DWhqzliO.js} +4 -3
  297. package/server/pipeline-membership-C88VBnhJ.js +3 -0
  298. package/server/pipeline-membership-D9SBvItj.js +57 -0
  299. package/server/pipeline-membership-gather-4eR-7Tqy.js +3 -0
  300. package/server/pipeline-membership-gather-CeVGnNJ2.js +593 -0
  301. package/server/{pipeline-notifier-BXkJzDC4.js → pipeline-notifier-D0ALV6Nw.js} +2 -2
  302. package/server/{pipeline-notifier-BJr8gQX6.js → pipeline-notifier-DT6xLFao.js} +1 -1
  303. package/server/post-merge-lifecycle-worker-8HIeS_J6.js +50 -0
  304. package/server/{project-pipelines-C0MWUeCU.js → project-pipelines-9SKt2bEc.js} +2 -2
  305. package/server/{project-repos-B6GycDh9.js → project-repos-B5pIphKg.js} +7 -3
  306. package/server/project-repos-DPjOdfPa.js +3 -0
  307. package/server/projects-_n3Zui6K.js +3 -0
  308. package/server/{prompts-DxzFXuLl.js → prompts-CgzMBvQF.js} +2 -2
  309. package/server/{providers-u4Ga0jOr.js → providers-BI1mOBQ4.js} +1 -1
  310. package/server/{providers-qQAwGQDW.js → providers-BJQSnAAp.js} +7 -7
  311. package/server/public/assets/{chunk-BO2N2NFS-BamJdinX.js → chunk-BO2N2NFS-D_pGACYN.js} +4 -4
  312. package/server/public/assets/{diagram-OG6HWLK6-DfOB8-w4.js → diagram-OG6HWLK6-BO6fe3hH.js} +1 -1
  313. package/server/public/assets/{dist-ByIuzMQW.js → dist-5zingMiA.js} +3 -3
  314. package/server/public/assets/{dist-D7zYSEA6.js → dist-CVxhbI2E.js} +1 -1
  315. package/server/public/assets/{ganttDiagram-6RSMTGT7-EdmRyXL3.js → ganttDiagram-6RSMTGT7-Bgj4A7kp.js} +1 -1
  316. package/server/public/assets/{highlighted-body-OFNGDK62-MerOfTX8.js → highlighted-body-OFNGDK62-DNPK7_cm.js} +1 -1
  317. package/server/public/assets/index-DEpY-D1O.js +807 -0
  318. package/server/public/assets/index-Ddkcz3WT.css +1 -0
  319. package/server/public/assets/{linear-BBbArIcK.js → linear-BB0jQT16.js} +1 -1
  320. package/server/public/assets/mermaid-GHXKKRXX-BzPfaQJ1.js +1 -0
  321. package/server/public/assets/{pieDiagram-4H26LBE5-BKIddiJN.js → pieDiagram-4H26LBE5-DeGIzzpZ.js} +1 -1
  322. package/server/public/assets/{prod-B8vYiu52.js → prod-XBLvikex.js} +4 -4
  323. package/server/public/assets/{quadrantDiagram-W4KKPZXB-D6RtoULk.js → quadrantDiagram-W4KKPZXB-BV9SLeWz.js} +1 -1
  324. package/server/public/assets/{sankeyDiagram-5OEKKPKP-CLrCedZX.js → sankeyDiagram-5OEKKPKP-Dwja0gj8.js} +1 -1
  325. package/server/public/assets/{xychartDiagram-2RQKCTM6-hznR8DYl.js → xychartDiagram-2RQKCTM6-DCB4qvfw.js} +1 -1
  326. package/server/public/index.html +2 -2
  327. package/server/{pull-requests-_lHueOHW.js → pull-requests-7BgLDsIo.js} +19 -10
  328. package/server/{pull-requests-7N8WKseP.js → pull-requests-Dq0y6IxE.js} +1 -1
  329. package/server/{queries-CjNIf-Ub.js → queries-C-MUZaIy.js} +824 -192
  330. package/server/{rally-CyWT_lNO.js → rally-CPysR4T_.js} +3 -3
  331. package/server/rally-D_VW4bJv.js +3 -0
  332. package/server/{rally-api-C8e_1JRi.js → rally-api-8Ptlp2os.js} +2 -2
  333. package/server/{rally-api-ClOSd-Tt.js → rally-api-CgosKdKL.js} +1 -1
  334. package/server/{rally-client-sgtVqzNU.js → rally-client-CCX0hADj.js} +1 -1
  335. package/server/{rally-client-lc-nokqr.js → rally-client-iYMHWQD7.js} +5 -5
  336. package/server/{reap-terminal-sessions-7KeHv1R1.js → reap-terminal-sessions-4Xg9NGA8.js} +2 -2
  337. package/server/{reap-terminal-sessions-BtHPo6Xc.js → reap-terminal-sessions-Qf-9LVQc.js} +2 -2
  338. package/server/{rebuild-stack-lwtsW0GO.js → rebuild-stack-CMdgaylx.js} +16 -7
  339. package/server/{rebuild-stack-CFvcBHsS.js → rebuild-stack-DqcOVmJO.js} +2 -2
  340. package/server/{reconstruct-cache-C3Ui7ojV.js → reconstruct-cache-CMZJ_Vjq.js} +9 -7
  341. package/server/record-BTwWhtBb.js +3 -0
  342. package/server/{record-update-dE1Aw83j.js → record-update-DaOKS7Wb.js} +124 -157
  343. package/server/record-update-DhI7eySG.js +3 -0
  344. package/server/{recovery-trip-BvRWfUXM.js → recovery-trip-DDH-02ng.js} +2 -2
  345. package/server/{release-engine-Cx48W7z8.js → release-engine-B2X9AfFC.js} +5 -5
  346. package/server/{release-set-CQfuN9-v.js → release-set-G4XKyQ8K.js} +3 -3
  347. package/server/{remote-C_2hasl7.js → remote-BXarMvqf.js} +3 -3
  348. package/server/{remote-ChgimyYa.js → remote-CUhyqjXk.js} +3 -3
  349. package/server/{remote-agents-By1ige5O.js → remote-agents-Bba-MgSA.js} +311 -48
  350. package/server/{remote-agents-CA3Ihlxj.js → remote-agents-CLZB3Coc.js} +2 -2
  351. package/server/{remote-completion-fVe9e_3u.js → remote-completion-CwAp79EC.js} +13 -13
  352. package/server/resume-mOREjlYu.js +3 -0
  353. package/server/{review-agent-CIGOQYBD.js → review-agent--pOptAEV.js} +65 -50
  354. package/server/{review-agent-DNboMyW4.js → review-agent-BTCNkq2h.js} +1 -1
  355. package/server/{review-artifacts-nRDPuMxd.js → review-artifacts-BNmw8dWE.js} +7 -6
  356. package/server/{review-context-2uj-YQ8J.js → review-context-DFxYOOJW.js} +9 -9
  357. package/server/{in-flight-guard-CAAkqPLu.js → review-convoy-liveness-BgU_1jJf.js} +3 -44
  358. package/server/review-status-CGvlA4o_.js +7737 -0
  359. package/server/review-status-Dma9SFaN.js +3 -0
  360. package/server/review-status-emit-DURrmGYX.js +50 -0
  361. package/server/{review-status-enrichment-Dci-ZwEt.js → review-status-enrichment-8NiNXi5W.js} +4 -4
  362. package/server/review-status-source-BLx_1siH.js +3 -0
  363. package/server/{review-status-source-CxuEjLGg.js → review-status-source-DIk1JSow.js} +24 -3
  364. package/server/{review-status-sync-BTOpxtTC.js → review-status-sync-0GxOqeqF.js} +11 -6
  365. package/server/{review-status-sync-DSDK3OMy.js → review-status-sync-muT-EBp2.js} +1 -1
  366. package/server/{review-verdict-feedback-CTd4QMBu.js → review-verdict-feedback-HwF6ODFy.js} +1 -1
  367. package/server/{review-verdict-feedback-CCjVA7Uk.js → review-verdict-feedback-xJNdqBnX.js} +65 -11
  368. package/server/{rollup-FGsKki9R.js → rollup-BQaol5TX.js} +8 -8
  369. package/server/{rollup-BKQC7jp4.js → rollup-BR4t_wck.js} +1 -1
  370. package/server/{scanner-CnqEZeDy.js → scanner-C-D2cFdX.js} +8 -7
  371. package/server/{sequence-io-D909zgeH.js → sequence-io-Bmf1EZM5.js} +4 -4
  372. package/server/{sequencer-agent-CzkcK6P5.js → sequencer-agent-CigMyKh2.js} +7 -6
  373. package/server/server.js +2005 -614
  374. package/server/{service-CLeAoU6G.js → service-CD0DvFvD.js} +114 -68
  375. package/server/{session-fork-CHI1XvL9.js → session-fork-B6cQ5eya.js} +2 -2
  376. package/server/{session-history-BT3IvqhC.js → session-history-3ON_IJjm.js} +7 -55
  377. package/server/settings-CVmWiJ-r.js +2 -0
  378. package/server/{settings-C0zgxOGf.js → settings-PilbFZAM.js} +3 -2
  379. package/server/{settings-BTMvpNFU.js → settings-VN0qOh4U.js} +3 -3
  380. package/server/{shadow-engineering-BJfgm-hX.js → shadow-engineering-DXvx77oE.js} +3 -3
  381. package/server/{shadow-state-7a-524T8.js → shadow-state-BBk_zacw.js} +2 -2
  382. package/server/{shadow-state-DnDyjujH.js → shadow-state-CZBp7pwq.js} +1 -1
  383. package/server/{shadow-utils-Db3oroFG.js → shadow-utils-DdZ05AJS.js} +2 -2
  384. package/server/{ship-log-D9MlVzYU.js → ship-log-7kJfjUX2.js} +1 -1
  385. package/server/{smart-compaction-CV2ukKND.js → smart-compaction-8fA5k5XN.js} +1 -1
  386. package/server/{smart-compaction-KCYScAU1.js → smart-compaction-ByhL9cRS.js} +8 -7
  387. package/server/{spawn-planning-session-DKpdFyOC.js → spawn-planning-session-pcF-YeFE.js} +38 -50
  388. package/server/spawn-planning-session-vLUJoFjy.js +3 -0
  389. package/server/{specialist-completion-Ky9wCDpb.js → specialist-completion-B07XjWD2.js} +1 -1
  390. package/server/{specialist-context-Bn3dCGS2.js → specialist-context-DJ-zFyL3.js} +5 -5
  391. package/server/{specialist-handoff-logger-CMEwYxa2.js → specialist-handoff-logger-aKSxbIgD.js} +2 -2
  392. package/server/{specialist-logs-C5p8G7tx.js → specialist-logs-Dae-n52_.js} +3 -3
  393. package/server/{specialists-CC4r-c2s.js → specialists-6PWdtWcg.js} +1177 -311
  394. package/server/{specialists-DM6bWjsi.js → specialists-Bz-wFT7R.js} +1 -1
  395. package/server/{specialists-jiuuyVkp.js → specialists-DUiExaxb.js} +18 -18
  396. package/server/{specialists-CShuVGWT.js → specialists-KR3pKulN.js} +1 -1
  397. package/server/specs--enInima.js +3 -0
  398. package/server/src-B948bGVR.js +11452 -0
  399. package/server/{src-CXmtj0im.js → src-rac0Mepv.js} +6 -6
  400. package/server/{src-CdmnTM2m.js → src-vHy2-oCv.js} +3 -3
  401. package/server/{stack-health-Bn3o8FBX.js → stack-health-BikqHSjn.js} +1 -1
  402. package/server/{stack-health-DxSdG9cW.js → stack-health-DqLTiEu4.js} +7 -5
  403. package/server/{stale-task-claims-KJKxxiiQ.js → stale-task-claims-Cab_Fo_Z.js} +5 -4
  404. package/server/{staleness-DPm7ClwA.js → staleness-C-a5rBxF.js} +1 -1
  405. package/server/{staleness-CT34nwr9.js → staleness-CGTZyp6V.js} +1 -1
  406. package/server/{state-home-Cn_Qu8IX.js → state-home-722Dkx92.js} +2 -2
  407. package/server/{state-mapping-BL_-3Yt8.js → state-mapping-CybR81Uf.js} +1 -1
  408. package/server/{state-migrate-BGg2ZaOt.js → state-migrate-2u8wIpoL.js} +4 -4
  409. package/server/{stuck-remediation-DYuPRYYw.js → stuck-remediation-CC6q3eqQ.js} +84 -26
  410. package/server/{stuck-remediation-s9_2qfi6.js → stuck-remediation-r1TJu68G.js} +1 -1
  411. package/server/{substrate-bug-weights-service-B-FwCs5V.js → substrate-bug-weights-service-CzIyyWFT.js} +3 -3
  412. package/server/{summary-fork-DpcxN9tf.js → summary-fork-BqgmgPDt.js} +2 -2
  413. package/server/{summary-fork-D1RAk9rJ.js → summary-fork-Df2WFijM.js} +8 -8
  414. package/server/supervisor/{injection-budget-Csw5tqfJ.js → injection-budget-Cg_KIb3o.js} +1 -1
  415. package/server/supervisor/{paths-DehGY2Fj.js → paths-BBOnCYlO.js} +10 -2
  416. package/server/supervisor/pty-supervisor.js +50 -4
  417. package/server/supervisor/{pty-token-x-ea28Us.js → pty-token-BbjwEUUM.js} +3 -3
  418. package/server/supervisor-B4anCCSm.js +2 -0
  419. package/server/{supervisor-wM4ooB5O.js → supervisor-BxqSpjcN.js} +3 -3
  420. package/server/{swarm-readiness-DlP_UjHq.js → swarm-readiness-DfFxa9-n.js} +3 -3
  421. package/server/{system-prerequisites-DUDj1YHf.js → system-prerequisites-ICLSkhhZ.js} +2 -2
  422. package/server/{teardown-workspace-DeTTImn-.js → teardown-workspace-DRdi_CPa.js} +15 -16
  423. package/server/{test-agent-queue-MbxX5vqq.js → test-agent-queue-A_-p-i0I.js} +8 -7
  424. package/server/{test-verdict-gscuksPv.js → test-verdict-BHgTAwIG.js} +1 -1
  425. package/server/{test-verdict-bWYBtqBg.js → test-verdict-C4i9aqEP.js} +1 -1
  426. package/server/{tldr-daemon-BYFkts95.js → tldr-daemon-CvWXBhX1.js} +1 -1
  427. package/server/{tldr-daemon-C-69c3OI.js → tldr-daemon-wvsU6bKv.js} +2 -2
  428. package/server/{tmux-R7N7y-Mh.js → tmux-CfDHob9M.js} +174 -4
  429. package/server/{tmux-B6z7h_vZ.js → tmux-Ctk6RV5l.js} +1 -1
  430. package/server/{token-BK6t8BIT.js → token-DrxwytsZ.js} +2 -2
  431. package/server/{token-util-DxXu-vd1.js → token-util-B48BlCba.js} +1 -1
  432. package/server/token-util-D411CAq9.js +3 -0
  433. package/server/{tracker-config-G6latr8C.js → tracker-config-BcPMElRB.js} +2 -2
  434. package/server/{tracker-utils-DHv5pSDT.js → tracker-utils-CJ6BHjcD.js} +3 -3
  435. package/server/{traefik-connect-Df2uXPsQ.js → traefik-connect-DZ6nMYMj.js} +1 -1
  436. package/server/{tunnel-DGdUkGoZ.js → tunnel-Bp-dRHZz.js} +1 -1
  437. package/server/{tunnel-CDVKJpRv.js → tunnel-DUbUPElU.js} +3 -3
  438. package/server/{typed-errors-BHhE85Ul.js → typed-errors-CKeoDdU3.js} +1 -1
  439. package/server/{typed-errors-2BTMxkZq.js → typed-errors-DyjseiB6.js} +1 -1
  440. package/server/{types-hraoaQIp.js → types-Cm5ASJbq.js} +1 -1
  441. package/server/{types-5M0lupud.js → types-Di8wdakq.js} +1 -1
  442. package/server/uat-promote-verification-CoJuh7XO.js +92 -0
  443. package/server/uat-train-4Q0k06CQ.js +0 -0
  444. package/server/uat-train-Dewoatps.js +2 -0
  445. package/server/{validate-IfDGkaVR.js → validate-B0C8p66t.js} +8 -6
  446. package/server/{validation-Dw1pzDzr.js → validation-B_kIRfNe.js} +4 -4
  447. package/server/{validation-CC9OPqJZ.js → validation-hVOwQk8T.js} +1 -1
  448. package/server/{verification-artifact-B3itKTxu.js → verification-artifact-BxlxTiYK.js} +1 -1
  449. package/server/{verification-artifact-TVFSz_q1.js → verification-artifact-D70AtckY.js} +1 -1
  450. package/server/{verification-runner-BW4HOKAz.js → verification-runner-Bc3cJvpC.js} +1 -1
  451. package/server/{verification-runner-CkgX6EtI.js → verification-runner-KZTz6u72.js} +40 -18
  452. package/server/{vtt-parser-DYPbKcIJ.js → vtt-parser-CE_i3Bcw.js} +1 -1
  453. package/server/{work-agent-prompt-Du8Vh2aJ.js → work-agent-prompt-ByrPAzOy.js} +20 -9
  454. package/server/{workflows-mbQzh6mQ.js → workflows-D0vP1WrK.js} +252 -99
  455. package/server/workflows-DtDX08ed.js +2 -0
  456. package/server/{workspace--8tnhDI0.js → workspace-COWvdibH.js} +1 -1
  457. package/server/{workspace-BPUws1-_.js → workspace-DQkRPLlQ.js} +3 -3
  458. package/server/workspace-anchor-drift-DXYIAHzr.js +224 -0
  459. package/server/workspace-anchor-drift-pwz23TI1.js +3 -0
  460. package/server/{workspace-config-CIVWZOQr.js → workspace-config-BdZM4PvZ.js} +1 -1
  461. package/server/{workspace-manager-CBhNdzE4.js → workspace-manager-BPgTrG66.js} +157 -118
  462. package/server/workspace-manager-C1F3XsnS.js +3 -0
  463. package/server/{workspace-metadata-BzHnwwX4.js → workspace-metadata-CdjzAP8x.js} +1 -1
  464. package/server/{workspace-metadata-_WygnyoX.js → workspace-metadata-DkO_iTLo.js} +2 -2
  465. package/server/{workspaces-Do_9J0LQ.js → workspaces-CRBJikLp.js} +749 -299
  466. package/sync-sources/dev-skills/pan-dashboard-restart/SKILL.md +34 -10
  467. package/sync-sources/hooks/linear-mcp-auth-hook +97 -0
  468. package/sync-sources/rules/ask-user-question-self-contained.md +9 -0
  469. package/sync-sources/skills/pan-close/SKILL.md +5 -3
  470. package/sync-sources/skills/pan-merge/SKILL.md +7 -5
  471. package/sync-sources/skills/pan-peer-review/SKILL.md +195 -0
  472. package/sync-sources/skills/pan-release/SKILL.md +57 -0
  473. package/sync-sources/skills/pan-reload/SKILL.md +3 -3
  474. package/sync-sources/skills/pan-restart/SKILL.md +5 -4
  475. package/sync-sources/skills/pan-review/SKILL.md +7 -1
  476. package/sync-sources/skills/pan-sync-main/SKILL.md +9 -8
  477. package/sync-sources/skills/pipeline-status/SKILL.md +10 -1
  478. package/sync-sources/skills/workspace-add-repo/SKILL.md +16 -1
  479. package/server/activity-logger-OEUBdfZ8.js +0 -3
  480. package/server/agent-state-Bc3tzUC8.js +0 -3
  481. package/server/agent-state-service-D5UGKIJL.js +0 -2
  482. package/server/agents-wi9NWzs2.js +0 -3
  483. package/server/archive-planning-BZDgzoEj.js +0 -3
  484. package/server/cli-B86rejVV.js +0 -3
  485. package/server/conflict-gate-BhAY7TUd.js +0 -3
  486. package/server/conversation-service-BLd3MYsG.js +0 -3
  487. package/server/deacon-kiQrb4ZT.js +0 -4
  488. package/server/deacon-swarm-C-GwfjJy.js +0 -2
  489. package/server/deploy-window-DkZraDyj.js +0 -3
  490. package/server/dist-Bzy0y69j.js +0 -3
  491. package/server/dod-C6n9RV3G.js +0 -66
  492. package/server/flywheel-merge-order-UU0tiUld.js +0 -245
  493. package/server/flywheel-merge-order-UUcsCDb6.js +0 -2
  494. package/server/forge-CNFnyqps.js +0 -270
  495. package/server/forge-DXnS_YFH.js +0 -2
  496. package/server/git-utils-D0_yhCgF.js +0 -3
  497. package/server/github-pr-lookup-D16NGsSO.js +0 -44
  498. package/server/hume-ccTf4wTX.js +0 -3
  499. package/server/inspect-agent-Brtz0URj.js +0 -2
  500. package/server/label-reconciler-B4iOAjlC.js +0 -113
  501. package/server/launcher-generator-BBWG_SiS.js +0 -473
  502. package/server/merge-ops-CR44oU9-.js +0 -2
  503. package/server/merge-set-bUqbm3yc.js +0 -3
  504. package/server/merge-sync-BJYeOODr.js +0 -3
  505. package/server/merge-verification-BkaOqPsw.js +0 -124
  506. package/server/pipeline-membership-mY3GprlK.js +0 -420
  507. package/server/project-repos-DXKQsc_m.js +0 -3
  508. package/server/projects-vjjcmiN8.js +0 -3
  509. package/server/public/assets/index-CWeMerGO.js +0 -804
  510. package/server/public/assets/index-CenuJ3Cw.css +0 -1
  511. package/server/public/assets/mermaid-GHXKKRXX-CpPWAFwE.js +0 -1
  512. package/server/rally-zhhtXuDP.js +0 -3
  513. package/server/record-CN0pj4_5.js +0 -3
  514. package/server/record-update-bLJxAXH4.js +0 -3
  515. package/server/resume-BFv1PGpA.js +0 -3
  516. package/server/review-status-btEYlaxA.js +0 -3
  517. package/server/review-status-kZj_KyCk.js +0 -1470
  518. package/server/settings-66A6uvIA.js +0 -2
  519. package/server/spawn-planning-session-qUC2VWu3.js +0 -2
  520. package/server/specs-C8Wsn2XO.js +0 -3
  521. package/server/src-DtcUOZCq.js +0 -4826
  522. package/server/supervisor-FTJAIsAK.js +0 -2
  523. package/server/token-util-DuPuNriz.js +0 -3
  524. package/server/tracker-utils-B4ylXZQK.js +0 -3
  525. package/server/uat-train-B05BWkp-.js +0 -2
  526. package/server/uat-train-DDSrSoV1.js +0 -2152
  527. package/server/workflows-BQu4RFQ-.js +0 -2
  528. package/server/workspace-manager-CWT55qeI.js +0 -3
@@ -1,44 +1,49 @@
1
- import { $n as resolveIssueIdSync, Br as getOverdeckHome, Jn as extractPrefixSync, Nr as encodeClaudeProjectDir, Tn as init_projects, Vr as init_paths, Xt as isStatePlaneOnlyStatus, Yn as init_issue_id, Yt as init_state_plane, Zn as parseIssueIdSync, ar as GitError, ir as FsError, kn as listProjectsSync, mn as findProjectByTeamSync, mr as init_errors, qn as extractNumberSync, t as init_config_yaml, tt as resolveModel, un as extractTeamPrefix, yn as getProjectSync, zn as resolveProjectFromIssueSync } from "./config-yaml-DySPNmKN.js";
2
- import { Q as getWorkAgentLifecycleStateSync, St as jsonResponse, bt as httpHandler, dt as rejectUnauthorizedDashboardRequest, et as spawnPanCli, gt as getHeaderFromMap, n as _serverManagedMerges, pt as rejectUnsafeDashboardMutationRequest } from "./specialists-CC4r-c2s.js";
3
- import { a as init_activity_logger, n as emitActivityEntrySync } from "./activity-logger-DDlOIAML.js";
4
- import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-BEqFxlJc.js";
5
- import { $ as init_child_env, H as sessionExists, M as listSessionNames, Q as buildChildEnvWithoutTmuxSync, i as capturePane, w as init_tmux } from "./tmux-R7N7y-Mh.js";
6
- import { a as init_event_store, n as getEventStore } from "./event-store-CQL6NeqB.js";
7
- import { _ as setAutoMerge, b as setReviewStatusSync, c as getReviewStatusSync, d as loadReviewStatuses, l as init_review_status, p as markWorkspaceStuck, v as setDeaconIgnored } from "./review-status-kZj_KyCk.js";
8
- import { _ as init_queue_position, a as EventStoreService, g as findPositionInQueueSync, h as computeQueuePositionFromStatusSync, s as init_domain_services } from "./issue-lifecycle-ojZAzDBP.js";
9
- import { o as getPricingSync, s as init_cost, t as calculateCostSync } from "./cost-B2ddP6wq.js";
10
- import { Ar as saveAgentRuntimeState, Kt as transitionIssueToInReview, Or as getAgentRuntimeStateSync, X as messageAgent, b as init_agents, i as listRunningAgents, lt as spawnAgent, qn as getAgentState } from "./queries-CjNIf-Ub.js";
11
- import { f as CostWriter, l as CostDoorLive } from "./service-CLeAoU6G.js";
12
- import { a as init_tracker_config, t as getGitHubConfig } from "./tracker-config-G6latr8C.js";
13
- import { i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils-DHv5pSDT.js";
14
- import { o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-s0-oKybJ.js";
15
- import { a as PAN_DIRNAME, i as PAN_CONTINUE_FILENAME, p as init_types } from "./types-hraoaQIp.js";
16
- import { o as init_merge_sync, r as getAllActiveQueues } from "./merge-sync-VPV28g0g.js";
17
- import { A as init_xbrief_index, M as readXBriefDocument, _ as XBRIEF_INSPECTION_POLICIES, c as mergeRecordStatusOverrides, g as serializeXBriefDocument, k as findXBriefByIssue, o as init_io, r as findPlan, s as isPlanningComplete, u as readPlan, v as init_types$1 } from "./io-C9kF1wtJ.js";
18
- import { it as findConversationForCostSessionSync, k as init_conversations } from "./conversations-6AfUfbwc.js";
19
- import { a as normalizeModelOverrideSync, i as init_model_validation } from "./launcher-generator-BBWG_SiS.js";
20
- import { f as init_config, m as loadConfigSync$1 } from "./config-BZ0sHTju.js";
21
- import { a as getWorkspaceStackHealth, n as collectDockerContainerLifecycleSnapshot, r as composeProjectNameForWorkspace, s as init_stack_health } from "./stack-health-DxSdG9cW.js";
22
- import { a as criticalPath, l as init_dag, t as actionableDoc } from "./dag-B1ucnjDU.js";
23
- import { E as verifyAppCanMerge, M as withConcurrencyLimit, f as init_github_app, j as init_concurrency, m as isIntegrationPermissionError } from "./github-app-C3QrAUd0.js";
24
- import { a as readEventsFromLineSync, i as init_events, l as init_wal, o as readEventsSync, r as getLastEventMetadataSync, t as appendCostEventSync } from "./events-DTfAe4My.js";
25
- import { n as getContainersReferencingWorkspacePath, r as init_workspace_manager } from "./workspace-manager-CBhNdzE4.js";
26
- import { r as init_devcontainer_renderer, t as DEVCONTAINER_DIRNAME } from "./devcontainer-renderer-_d6XhyND.js";
27
- import { a as init_jsonl_parser, t as getActiveSessionModelSync } from "./jsonl-parser-BXSlHwEh.js";
28
- import { r as init_in_flight_guard, t as createInFlightGuard } from "./in-flight-guard-CAAkqPLu.js";
29
- import { i as findWorkspacePath, o as init_archive_planning } from "./archive-planning-Du25Jtst.js";
30
- import { a as loadWorkspaceMetadataSync, i as listWorkspaceMetadataSync } from "./workspace-metadata-_WygnyoX.js";
31
- import { n as enrichReviewStatusFromSessions } from "./review-status-enrichment-Dci-ZwEt.js";
32
- import { n as generateDailySummary, r as init_cli } from "./cli-RoOx5DUf.js";
33
- import { a as getDiffStat, i as getDiffBase, o as init_review_context, r as getChangedFiles } from "./review-context-2uj-YQ8J.js";
34
- import { n as getTldrDaemonServiceSync, r as init_tldr_daemon } from "./tldr-daemon-C-69c3OI.js";
35
- import { C as init_operations, S as gitPush, T as listGitOperationsSync, a as init_merge_agent, w as init_git_activity, x as MainDivergedError, y as syncMainIntoWorkspace } from "./merge-agent-4WOWlSYA.js";
36
- import { F as enqueueMerge, I as getAllActiveQueues$1, L as getCurrentMerge, P as dequeueMerge, z as markMergeProcessing } from "./merge-CefQNAnq.js";
37
- import { n as init_release_set, t as getReleaseSetSync } from "./release-set-CQfuN9-v.js";
38
- import { i as init_conflict_gate, r as getCachedConflictGateMergeability } from "./conflict-gate-BaCVrH-N.js";
39
- import { r as runVerificationForIssue } from "./verification-runner-CkgX6EtI.js";
40
- import { t as teardownWorkspace } from "./teardown-workspace-DeTTImn-.js";
41
- import { t as init_rebuild_stack } from "./rebuild-stack-lwtsW0GO.js";
1
+ import { An as extractTeamPrefix, Er as GitError, Fr as init_errors, Gn as init_projects, Pn as findProjectByTeamSync, Tr as FsError, Yn as listProjectsSync, ar as resolveProjectFromIssueSync, br as resolveIssueIdSync, ci as getOverdeckHome, gn as isStatePlaneOnlyStatus, gr as init_issue_id, hn as init_state_plane, hr as extractPrefixSync, li as init_paths, mr as extractNumberSync, t as init_config_yaml, ti as encodeClaudeProjectDir, tt as resolveModel, vr as parseIssueIdSync, zn as getProjectSync } from "./config-yaml-CxdwhAIA.js";
2
+ import { At as jsonResponse, Ot as httpHandler, ct as spawnPanCli, n as _serverManagedMerges, nt as isInternalAgentRequest, ot as getWorkAgentLifecycleStateSync, rt as resolveRequestedStartedBy, wt as getHeaderFromMap, xt as rejectUnsafeDashboardMutationRequest, yt as rejectUnauthorizedDashboardRequest } from "./specialists-6PWdtWcg.js";
3
+ import { o as init_activity_logger, r as emitActivityEntrySync } from "./activity-logger-CyteR4JO.js";
4
+ import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-BDQDRopn.js";
5
+ import { H as sessionExists, M as listSessionNames, at as buildChildEnvWithoutTmuxSync, i as capturePane, ot as init_child_env, w as init_tmux } from "./tmux-CfDHob9M.js";
6
+ import { a as init_event_store, n as getEventStore } from "./event-store-CrHcVC5_.js";
7
+ import { C as setReviewStatusSync, _ as markWorkspaceStuck, b as setAutoMerge, d as getReviewStatusSync, h as loadReviewStatuses, p as init_review_status, r as clearFeedbackDeliveryStuck, x as setDeaconIgnored } from "./review-status-CGvlA4o_.js";
8
+ import { _ as findPositionInQueueSync, a as EventStoreService, g as computeQueuePositionFromStatusSync, s as init_domain_services, v as init_queue_position } from "./issue-lifecycle-Birk-ifu.js";
9
+ import { o as getPricingSync, s as init_cost, t as calculateCostSync } from "./cost-DpgYmYqR.js";
10
+ import { Br as saveAgentRuntimeState, Qn as decideResumeGate, Rr as getAgentRuntimeStateSync, X as messageAgent, Zn as clearYieldForResumeSync, Zt as transitionIssueToInReview, _r as saveAgentStateSync, b as init_agents, er as getAgentResumeGateBlockReason, i as listRunningAgents, ir as init_agent_state, rr as getAgentStateSync, tr as getAgentState, ut as spawnAgent } from "./queries-C-MUZaIy.js";
11
+ import { f as CostWriter, l as CostDoorLive } from "./service-CD0DvFvD.js";
12
+ import { a as init_tracker_config, t as getGitHubConfig } from "./tracker-config-BcPMElRB.js";
13
+ import { n as resolveGitHubIssueSync, t as init_tracker_utils } from "./tracker-utils-CJ6BHjcD.js";
14
+ import { o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-DzK385vD.js";
15
+ import { r as notifyPipelineSync, t as init_pipeline_notifier } from "./pipeline-notifier-D0ALV6Nw.js";
16
+ import { a as PAN_DIRNAME, i as PAN_CONTINUE_FILENAME, p as init_types } from "./types-Cm5ASJbq.js";
17
+ import { a as getAllActiveQueues, c as init_merge_sync } from "./merge-sync-kr4vqyjM.js";
18
+ import { l as resolveWorkspaceRepoRootsSync, r as init_project_repos } from "./project-repos-B5pIphKg.js";
19
+ import { O as findXBriefByIssue, _ as XBRIEF_INSPECTION_POLICIES, c as mergeRecordStatusOverrides, g as serializeXBriefDocument, j as readXBriefDocument, k as init_xbrief_index, o as init_io, r as findPlan, s as isPlanningComplete, u as readPlan, v as init_types$1 } from "./io-B00PBNku.js";
20
+ import { it as findConversationForCostSessionSync, k as init_conversations } from "./conversations-D0UEdLtk.js";
21
+ import { E as normalizeModelOverrideSync, T as init_model_validation } from "./auto-spawn-consent-CQ9Bi9q6.js";
22
+ import { f as init_config, m as loadConfigSync$1 } from "./config-BvLe652W.js";
23
+ import { a as getWorkspaceStackHealth, n as collectDockerContainerLifecycleSnapshot, r as composeProjectNameForWorkspace, s as init_stack_health } from "./stack-health-DqLTiEu4.js";
24
+ import { a as criticalPath, l as init_dag, t as actionableDoc } from "./dag-BtkgLeqY.js";
25
+ import { E as verifyAppCanMerge, M as withConcurrencyLimit, f as init_github_app, j as init_concurrency, m as isIntegrationPermissionError } from "./github-app-CmNk0zLU.js";
26
+ import { a as readEventsFromLineSync, i as init_events, l as init_wal, o as readEventsSync, r as getLastEventMetadataSync, t as appendCostEventSync } from "./events-BNrvchBg.js";
27
+ import { n as getContainersReferencingWorkspacePath, r as init_workspace_manager } from "./workspace-manager-BPgTrG66.js";
28
+ import { r as init_devcontainer_renderer, t as DEVCONTAINER_DIRNAME } from "./devcontainer-renderer-BUOIlfgD.js";
29
+ import { a as init_jsonl_parser, t as getActiveSessionModelSync } from "./jsonl-parser-BDpnGFCl.js";
30
+ import { i as findWorkspacePath } from "./archive-planning-BwhxeP7C.js";
31
+ import { n as init_merge_verification, t as handlePostRebaseVerificationDeferral } from "./merge-verification-NvaAd8CZ.js";
32
+ import { i as init_conflict_gate, r as getCachedConflictGateMergeability } from "./conflict-gate-E4nt7ZeS.js";
33
+ import { r as init_in_flight_guard, t as createInFlightGuard } from "./in-flight-guard-D-sSkADM.js";
34
+ import { a as loadWorkspaceMetadataSync, i as listWorkspaceMetadataSync } from "./workspace-metadata-DkO_iTLo.js";
35
+ import { n as enrichReviewStatusFromSessions } from "./review-status-enrichment-8NiNXi5W.js";
36
+ import { n as generateDailySummary, r as init_cli } from "./cli-Cte9ZFGn.js";
37
+ import { a as getDiffStat, i as getDiffBase, o as init_review_context, r as getChangedFiles } from "./review-context-DFxYOOJW.js";
38
+ import { n as getTldrDaemonServiceSync, r as init_tldr_daemon } from "./tldr-daemon-wvsU6bKv.js";
39
+ import { C as init_operations, S as gitPush, T as listGitOperationsSync, a as init_merge_agent, w as init_git_activity, x as MainDivergedError, y as syncMainIntoWorkspace } from "./merge-agent-BLUgRsz3.js";
40
+ import { F as enqueueMerge, I as getAllActiveQueues$1, L as getCurrentMerge, P as dequeueMerge, z as markMergeProcessing } from "./merge-DiW9RdSB.js";
41
+ import { t as rebaseFeatureBranch } from "./merge-rebase-DIkBjgwq.js";
42
+ import { n as init_release_set, t as getReleaseSetSync } from "./release-set-G4XKyQ8K.js";
43
+ import { r as runVerificationForIssue } from "./verification-runner-KZTz6u72.js";
44
+ import { n as init_durable_review_pipeline, r as registerDurableReviewPipelineHandler } from "./durable-review-pipeline-Cibps-Rg.js";
45
+ import { t as teardownWorkspace } from "./teardown-workspace-DRdi_CPa.js";
46
+ import { t as init_rebuild_stack } from "./rebuild-stack-CMdgaylx.js";
42
47
  import { basename, dirname, join, resolve, sep } from "node:path";
43
48
  import { Effect, Layer, Option, Stream } from "effect";
44
49
  import { closeSync, existsSync, fstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, renameSync, writeFileSync } from "fs";
@@ -97,7 +102,7 @@ async function captureInterestedAgent(state, agentId) {
97
102
  try {
98
103
  const remoteState = await readFile(join(homedir$1(), ".overdeck", "agents", agentId, "remote-state.json"), "utf-8").then((text) => JSON.parse(text)).catch(() => null);
99
104
  if (remoteState?.location === "remote" && remoteState?.vmName) {
100
- const { getRemoteAgentOutput } = await import("./remote-agents-CA3Ihlxj.js");
105
+ const { getRemoteAgentOutput } = await import("./remote-agents-CLZB3Coc.js");
101
106
  stdout = await getRemoteAgentOutput(agentId, remoteState.vmName, 50);
102
107
  } else stdout = await Effect.runPromise(capturePane(agentId, 50));
103
108
  } catch {
@@ -340,7 +345,7 @@ async function processPendingFeedbackDeliveries(options) {
340
345
  const staleThresholdMs = options?.staleThresholdMs ?? STALE_THRESHOLD_MS;
341
346
  const now = options?.now ?? Date.now();
342
347
  const deliver = options?._deliver ?? messageAgent;
343
- const getAgentState = options?._getAgentState ?? ((agentId) => Effect.runPromise(getAgentState(agentId)));
348
+ const getAgentState$1 = options?._getAgentState ?? ((agentId) => Effect.runPromise(getAgentState(agentId)));
344
349
  const loadStatuses = options?._loadStatuses ?? loadReviewStatuses;
345
350
  const getStatus = options?._getStatus ?? getReviewStatusSync;
346
351
  if (!existsSync$1(filePath)) return;
@@ -355,7 +360,7 @@ async function processPendingFeedbackDeliveries(options) {
355
360
  const createdAt = Date.parse(delivery.createdAt);
356
361
  if (Number.isFinite(createdAt) && now - createdAt > staleThresholdMs) continue;
357
362
  if (!isDeliveryStillRelevant(delivery, statuses[delivery.issueId] ?? getStatus(delivery.issueId))) continue;
358
- if (!await getAgentState(delivery.agentId)) {
363
+ if (!await getAgentState$1(delivery.agentId)) {
359
364
  remaining.push(delivery);
360
365
  continue;
361
366
  }
@@ -390,7 +395,7 @@ var DatabaseProvisionerError = class extends Error {
390
395
  };
391
396
  //#endregion
392
397
  //#region ../../lib/db-provisioners/flyway-postgres.ts
393
- const execAsync$8 = promisify(exec);
398
+ const execAsync$9 = promisify(exec);
394
399
  function shellQuote(value) {
395
400
  return `'${value.replace(/'/g, `'\\''`)}'`;
396
401
  }
@@ -463,7 +468,7 @@ async function cleanFile(filePath) {
463
468
  async function repairFlywayIfNeeded$1(issueId, pgContainer, dbName, projectConfig, workspacePath, log) {
464
469
  const emit = log || ((msg) => console.log(`[flyway-repair] ${msg}`));
465
470
  try {
466
- await execAsync$8(`docker exec "${pgContainer}" pg_isready -U postgres`, {
471
+ await execAsync$9(`docker exec "${pgContainer}" pg_isready -U postgres`, {
467
472
  encoding: "utf-8",
468
473
  timeout: 5e3
469
474
  });
@@ -475,7 +480,7 @@ async function repairFlywayIfNeeded$1(issueId, pgContainer, dbName, projectConfi
475
480
  }
476
481
  let rowCount = 0;
477
482
  try {
478
- const { stdout } = await execAsync$8(`docker exec "${pgContainer}" psql -U postgres -d ${dbName} -t -A -c "SELECT count(*) FROM flyway_schema_history;"`, {
483
+ const { stdout } = await execAsync$9(`docker exec "${pgContainer}" psql -U postgres -d ${dbName} -t -A -c "SELECT count(*) FROM flyway_schema_history;"`, {
479
484
  encoding: "utf-8",
480
485
  timeout: 1e4
481
486
  });
@@ -499,7 +504,7 @@ async function repairFlywayIfNeeded$1(issueId, pgContainer, dbName, projectConfi
499
504
  message: `Flyway baseline not found: ${flywayFile}`
500
505
  };
501
506
  emit(`Loading Flyway baseline from ${flywayFile}`);
502
- await execAsync$8(`docker exec -i "${pgContainer}" psql -U postgres -d ${dbName} < "${flywayFile}"`, {
507
+ await execAsync$9(`docker exec -i "${pgContainer}" psql -U postgres -d ${dbName} < "${flywayFile}"`, {
503
508
  encoding: "utf-8",
504
509
  timeout: 6e4
505
510
  });
@@ -523,7 +528,7 @@ async function repairFlywayIfNeeded$1(issueId, pgContainer, dbName, projectConfi
523
528
  const tmpSql = `/tmp/flyway-checksum-sync-${Date.now()}.sql`;
524
529
  await writeFile(tmpSql, updates.join("\n"));
525
530
  try {
526
- const { stdout } = await execAsync$8(`docker exec -i "${pgContainer}" psql -U postgres -d ${dbName} < "${tmpSql}"`, {
531
+ const { stdout } = await execAsync$9(`docker exec -i "${pgContainer}" psql -U postgres -d ${dbName} < "${tmpSql}"`, {
527
532
  encoding: "utf-8",
528
533
  timeout: 3e4
529
534
  });
@@ -538,7 +543,7 @@ async function repairFlywayIfNeeded$1(issueId, pgContainer, dbName, projectConfi
538
543
  }
539
544
  }
540
545
  try {
541
- const { stdout } = await execAsync$8(`docker exec "${pgContainer}" psql -U postgres -d ${dbName} -t -A -c "SELECT count(*) FROM flyway_schema_history;"`, {
546
+ const { stdout } = await execAsync$9(`docker exec "${pgContainer}" psql -U postgres -d ${dbName} -t -A -c "SELECT count(*) FROM flyway_schema_history;"`, {
542
547
  encoding: "utf-8",
543
548
  timeout: 1e4
544
549
  });
@@ -565,34 +570,34 @@ const flywayPostgresProvisioner = {
565
570
  const logger = requireLogger(ctx.logger, "[refresh-db]");
566
571
  logger.log(`Starting DB refresh for ${ctx.issueId}`);
567
572
  try {
568
- await execAsync$8(`docker stop "${ctx.apiContainer}"`, {
573
+ await execAsync$9(`docker stop "${ctx.apiContainer}"`, {
569
574
  encoding: "utf-8",
570
575
  timeout: 3e4
571
576
  });
572
577
  } catch {
573
578
  logger.log("API container not running or already stopped");
574
579
  }
575
- await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '${sqlString(ctx.databaseName)}' AND pid <> pg_backend_pid();"`, {
580
+ await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '${sqlString(ctx.databaseName)}' AND pid <> pg_backend_pid();"`, {
576
581
  encoding: "utf-8",
577
582
  timeout: 1e4
578
583
  });
579
- await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d postgres -c "DROP DATABASE IF EXISTS ${sqlIdentifier(ctx.databaseName)};"`, {
584
+ await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d postgres -c "DROP DATABASE IF EXISTS ${sqlIdentifier(ctx.databaseName)};"`, {
580
585
  encoding: "utf-8",
581
586
  timeout: 1e4
582
587
  });
583
- await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d postgres -c "CREATE DATABASE ${sqlIdentifier(ctx.databaseName)} OWNER postgres;"`, {
588
+ await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d postgres -c "CREATE DATABASE ${sqlIdentifier(ctx.databaseName)} OWNER postgres;"`, {
584
589
  encoding: "utf-8",
585
590
  timeout: 1e4
586
591
  });
587
592
  logger.log(`Loading seed file: ${ctx.seedFile}`);
588
- await execAsync$8(`docker exec -i ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} < ${shellQuote(ctx.seedFile)}`, {
593
+ await execAsync$9(`docker exec -i ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} < ${shellQuote(ctx.seedFile)}`, {
589
594
  encoding: "utf-8",
590
595
  timeout: 6e5
591
596
  });
592
597
  const repairResult = await repairFlywayIfNeeded$1(ctx.issueId, ctx.pgContainer, ctx.databaseName, ctx.projectConfig, ctx.workspacePath, (msg) => logger.log(msg));
593
598
  logger.log(`Flyway setup: ${repairResult.message}`);
594
599
  try {
595
- await execAsync$8(`docker start "${ctx.apiContainer}"`, {
600
+ await execAsync$9(`docker start "${ctx.apiContainer}"`, {
596
601
  encoding: "utf-8",
597
602
  timeout: 3e4
598
603
  });
@@ -601,7 +606,7 @@ const flywayPostgresProvisioner = {
601
606
  }
602
607
  let seedVerifyResult;
603
608
  if (ctx.seedVerifyQuery) try {
604
- const { stdout } = await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -t -A -c ${shellQuote(ctx.seedVerifyQuery)}`, {
609
+ const { stdout } = await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -t -A -c ${shellQuote(ctx.seedVerifyQuery)}`, {
605
610
  encoding: "utf-8",
606
611
  timeout: 1e4
607
612
  });
@@ -614,7 +619,7 @@ const flywayPostgresProvisioner = {
614
619
  const logger = requireLogger(ctx.logger, "[db-seed]");
615
620
  logger.setText(`Finding database container ${ctx.pgContainer}...`);
616
621
  try {
617
- const { stdout } = await execAsync$8(`docker ps --filter "name=${ctx.pgContainer}" --format "{{.Names}}"`);
622
+ const { stdout } = await execAsync$9(`docker ps --filter "name=${ctx.pgContainer}" --format "{{.Names}}"`);
618
623
  if (!stdout.trim()) {
619
624
  logger.fail(`Database container not running: ${ctx.pgContainer}`);
620
625
  logger.log("\nStart the workspace containers first:");
@@ -626,7 +631,7 @@ const flywayPostgresProvisioner = {
626
631
  return;
627
632
  }
628
633
  if (!ctx.force) try {
629
- const { stdout } = await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT count(*) FROM flyway_schema_history" -t 2>/dev/null`);
634
+ const { stdout } = await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT count(*) FROM flyway_schema_history" -t 2>/dev/null`);
630
635
  const count = parseInt(stdout.trim(), 10);
631
636
  if (count > 0) {
632
637
  logger.info(`Database already seeded (${count} migrations). Use --force to reseed.`);
@@ -636,16 +641,16 @@ const flywayPostgresProvisioner = {
636
641
  if (ctx.force) {
637
642
  logger.setText("Dropping existing database...");
638
643
  try {
639
- await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -c "DROP DATABASE IF EXISTS ${sqlIdentifier(ctx.databaseName)}; CREATE DATABASE ${sqlIdentifier(ctx.databaseName)};"`);
644
+ await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -c "DROP DATABASE IF EXISTS ${sqlIdentifier(ctx.databaseName)}; CREATE DATABASE ${sqlIdentifier(ctx.databaseName)};"`);
640
645
  } catch (error) {
641
646
  logger.warn(`Could not drop database: ${error instanceof Error ? error.message : String(error)}`);
642
647
  }
643
648
  }
644
649
  logger.setText("Copying seed file to container...");
645
- await execAsync$8(`docker cp ${shellQuote(ctx.seedFile)} ${shellQuote(`${ctx.pgContainer}:/tmp/seed.sql`)}`);
650
+ await execAsync$9(`docker cp ${shellQuote(ctx.seedFile)} ${shellQuote(`${ctx.pgContainer}:/tmp/seed.sql`)}`);
646
651
  logger.setText("Executing seed...");
647
652
  try {
648
- await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -f /tmp/seed.sql`, { timeout: 6e5 });
653
+ await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -f /tmp/seed.sql`, { timeout: 6e5 });
649
654
  } catch (error) {
650
655
  const message = error instanceof Error ? error.message : String(error);
651
656
  if (message.includes("ERROR")) {
@@ -653,10 +658,10 @@ const flywayPostgresProvisioner = {
653
658
  return;
654
659
  }
655
660
  }
656
- await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} rm /tmp/seed.sql`);
661
+ await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} rm /tmp/seed.sql`);
657
662
  logger.succeed("Database seeded successfully");
658
663
  try {
659
- const { stdout } = await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT version, description FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 3" -t`);
664
+ const { stdout } = await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT version, description FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 3" -t`);
660
665
  logger.log("\nRecent migrations:");
661
666
  stdout.trim().split("\n").forEach((line) => logger.log(` ${line.trim()}`));
662
667
  } catch {}
@@ -675,7 +680,7 @@ const flywayPostgresProvisioner = {
675
680
  if (!snapshotCmd) throw new DatabaseProvisionerError("No snapshot configuration found");
676
681
  const fullCmd = `${snapshotCmd} > "${outputPath}" 2>&1`;
677
682
  try {
678
- await execAsync$8(fullCmd, { timeout: 3e5 });
683
+ await execAsync$9(fullCmd, { timeout: 3e5 });
679
684
  } catch (error) {
680
685
  const message = error instanceof Error ? error.message : String(error);
681
686
  if (existsSync$1(outputPath)) if (readFileSync$1(outputPath, "utf-8").includes("PostgreSQL database dump")) {
@@ -692,7 +697,7 @@ const flywayPostgresProvisioner = {
692
697
  if (ctx.sanitize && ctx.dbConfig.seed_command) {
693
698
  logger.setText("Running sanitization...");
694
699
  try {
695
- await execAsync$8(ctx.dbConfig.seed_command, { cwd: ctx.projectConfig.path });
700
+ await execAsync$9(ctx.dbConfig.seed_command, { cwd: ctx.projectConfig.path });
696
701
  } catch (error) {
697
702
  logger.warn(`Sanitization warning: ${error instanceof Error ? error.message : String(error)}`);
698
703
  }
@@ -747,7 +752,7 @@ const flywayPostgresProvisioner = {
747
752
  async status(ctx) {
748
753
  const logger = requireLogger(ctx.logger, "[db-status]");
749
754
  logger.setText(`Checking container ${ctx.pgContainer}...`);
750
- const { stdout: containerStatus } = await execAsync$8(`docker ps --filter "name=${ctx.pgContainer}" --format "{{.Status}}"`);
755
+ const { stdout: containerStatus } = await execAsync$9(`docker ps --filter "name=${ctx.pgContainer}" --format "{{.Status}}"`);
751
756
  if (!containerStatus.trim()) {
752
757
  logger.fail(`Container not running: ${ctx.pgContainer}`);
753
758
  return;
@@ -755,18 +760,18 @@ const flywayPostgresProvisioner = {
755
760
  logger.succeed(`Container: ${ctx.pgContainer}`);
756
761
  logger.log(` Status: ${containerStatus.trim()}`);
757
762
  try {
758
- const { stdout: version } = await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT version, description FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 1" -t`);
763
+ const { stdout: version } = await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT version, description FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 1" -t`);
759
764
  const [ver, desc] = version.trim().split("|").map((s) => s.trim());
760
765
  logger.log(` Flyway: V${ver} - ${desc}`);
761
766
  } catch {
762
767
  logger.warn(" Flyway: Not initialized");
763
768
  }
764
769
  try {
765
- const { stdout: tableCount } = await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public'" -t`);
770
+ const { stdout: tableCount } = await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public'" -t`);
766
771
  logger.log(` Tables: ${tableCount.trim()}`);
767
772
  } catch {}
768
773
  try {
769
- const { stdout: dbSize } = await execAsync$8(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT pg_size_pretty(pg_database_size('${sqlString(ctx.databaseName)}'))" -t`);
774
+ const { stdout: dbSize } = await execAsync$9(`docker exec ${shellQuote(ctx.pgContainer)} psql -U postgres -d ${shellQuote(ctx.databaseName)} -c "SELECT pg_size_pretty(pg_database_size('${sqlString(ctx.databaseName)}'))" -t`);
770
775
  logger.log(` Size: ${dbSize.trim()}`);
771
776
  } catch {}
772
777
  }
@@ -798,7 +803,7 @@ init_issue_id();
798
803
  init_cli();
799
804
  init_projects();
800
805
  init_devcontainer_renderer();
801
- const execAsync$7 = promisify(exec);
806
+ const execAsync$8 = promisify(exec);
802
807
  function requireDatabaseName(dbConfig) {
803
808
  if (!dbConfig) throw new Error("No database configuration found in projects.yaml");
804
809
  const name = dbConfig.name?.trim();
@@ -814,7 +819,7 @@ const postWorkspaceContainerizeRoute = HttpRouter.add("POST", "/api/workspaces/:
814
819
  const workspacePath = join(projectPath, "workspaces", `feature-${issueLower}`);
815
820
  if (existsSync$1(join(workspacePath, ".devcontainer"))) return jsonResponse({ error: "Workspace is already containerized" }, { status: 400 });
816
821
  try {
817
- yield* Effect.promise(() => execAsync$7("docker info >/dev/null 2>&1", { encoding: "utf-8" }));
822
+ yield* Effect.promise(() => execAsync$8("docker info >/dev/null 2>&1", { encoding: "utf-8" }));
818
823
  } catch {
819
824
  return jsonResponse({ error: "Docker is not running. Start Docker Desktop first." }, { status: 400 });
820
825
  }
@@ -931,7 +936,7 @@ const postWorkspaceContainerActionRoute = HttpRouter.add("POST", "/api/workspace
931
936
  }
932
937
  if (!workspacePath) return jsonResponse({ error: `Workspace not found for ${issueId}` }, { status: 404 });
933
938
  if (!composeFile && ["start", "restart"].includes(action)) {
934
- const { ensureDevcontainerSync } = yield* Effect.promise(() => import("./ensure-devcontainer-BZgOhRo7.js"));
939
+ const { ensureDevcontainerSync } = yield* Effect.promise(() => import("./ensure-devcontainer-DMAbWqtQ.js"));
935
940
  if (ensureDevcontainerSync({
936
941
  workspacePath,
937
942
  issueId
@@ -948,7 +953,7 @@ const postWorkspaceContainerActionRoute = HttpRouter.add("POST", "/api/workspace
948
953
  }
949
954
  if (!composeFile) return jsonResponse({ error: `No docker-compose file found in workspace` }, { status: 404 });
950
955
  try {
951
- yield* Effect.promise(() => execAsync$7("docker info >/dev/null 2>&1", { encoding: "utf-8" }));
956
+ yield* Effect.promise(() => execAsync$8("docker info >/dev/null 2>&1", { encoding: "utf-8" }));
952
957
  } catch {
953
958
  return jsonResponse({ error: "Docker is not running. Start Docker Desktop first." }, { status: 400 });
954
959
  }
@@ -962,7 +967,7 @@ const postWorkspaceContainerActionRoute = HttpRouter.add("POST", "/api/workspace
962
967
  };
963
968
  const serviceNames = serviceMap[containerName.toLowerCase()];
964
969
  if (!serviceNames) return jsonResponse({ error: `Unknown container: ${containerName}. Valid: ${Object.keys(serviceMap).join(", ")}` }, { status: 400 });
965
- const { stdout: projectNameOut } = yield* Effect.promise(() => execAsync$7(`docker compose -f "${composeFile}" config --format json 2>/dev/null | jq -r '.name // empty'`, { encoding: "utf-8" }));
970
+ const { stdout: projectNameOut } = yield* Effect.promise(() => execAsync$8(`docker compose -f "${composeFile}" config --format json 2>/dev/null | jq -r '.name // empty'`, { encoding: "utf-8" }));
966
971
  const projectName = projectNameOut.trim();
967
972
  if (containerName.toLowerCase() === "api" && ["start", "restart"].includes(action)) {
968
973
  const tPrefix = extractTeamPrefix(issueId);
@@ -991,7 +996,7 @@ const postWorkspaceContainerActionRoute = HttpRouter.add("POST", "/api/workspace
991
996
  for (const serviceName of serviceNames) try {
992
997
  const cmd = `docker compose -f "${composeFile}" ${projectName ? `--project-name "${projectName}"` : ""} ${action} ${serviceName}`;
993
998
  console.log(`[container-control] Running: ${cmd}`);
994
- yield* Effect.promise(() => execAsync$7(cmd, {
999
+ yield* Effect.promise(() => execAsync$8(cmd, {
995
1000
  encoding: "utf-8",
996
1001
  timeout: 3e4
997
1002
  }));
@@ -1052,7 +1057,7 @@ const postWorkspaceRefreshDbRoute = HttpRouter.add("POST", "/api/workspaces/:iss
1052
1057
  break;
1053
1058
  }
1054
1059
  if (!composeFile) return jsonResponse({ error: "No docker-compose file found in workspace" }, { status: 404 });
1055
- const { stdout: projectNameOut } = yield* Effect.promise(() => execAsync$7(`docker compose -f "${composeFile}" config --format json 2>/dev/null | jq -r '.name // empty'`, { encoding: "utf-8" }));
1060
+ const { stdout: projectNameOut } = yield* Effect.promise(() => execAsync$8(`docker compose -f "${composeFile}" config --format json 2>/dev/null | jq -r '.name // empty'`, { encoding: "utf-8" }));
1056
1061
  const projectName = projectNameOut.trim();
1057
1062
  if (!projectName) return jsonResponse({ error: "Could not determine docker compose project name" }, { status: 500 });
1058
1063
  const pgContainer = `${projectName}-postgres-1`;
@@ -1086,7 +1091,7 @@ const containerOpsRouteLayer = Layer.mergeAll(postWorkspaceContainerizeRoute, po
1086
1091
  //#endregion
1087
1092
  //#region ../../lib/stashes.ts
1088
1093
  init_errors();
1089
- const execAsync$6 = promisify(exec);
1094
+ const execAsync$7 = promisify(exec);
1090
1095
  const ISO_STASH_TIMESTAMP_PATTERN = "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2}))";
1091
1096
  const ISSUE_ID_PATTERN = "([A-Z]+(?:-[A-Z]+)*-\\d+)";
1092
1097
  const ISSUE_ID_REGEX = new RegExp(`^${ISSUE_ID_PATTERN}$`);
@@ -1162,16 +1167,22 @@ function parseStashListLine(line) {
1162
1167
  };
1163
1168
  }
1164
1169
  async function listStashesPromise(repoPath) {
1165
- const { stdout } = await execAsync$6("git stash list --format=\"%gd%x09%H%x09%cI%x09%gs\"", {
1166
- cwd: repoPath,
1167
- encoding: "utf-8"
1168
- });
1170
+ let stdout;
1171
+ try {
1172
+ ({stdout} = await execAsync$7("git stash list --format=\"%gd%x09%H%x09%cI%x09%gs\"", {
1173
+ cwd: repoPath,
1174
+ encoding: "utf-8"
1175
+ }));
1176
+ } catch (error) {
1177
+ if ((error instanceof Error ? error.message : String(error)).includes("not a git repository")) return [];
1178
+ throw error;
1179
+ }
1169
1180
  return stdout.split("\n").map((line) => parseStashListLine(line)).filter((entry) => entry !== null);
1170
1181
  }
1171
1182
  async function resolveStashOperationRef(repoPath, ref, stackRef) {
1172
1183
  const candidateRef = /^stash@\{\d+\}$/.test(ref) ? ref : stackRef;
1173
1184
  if (candidateRef) {
1174
- const { stdout: resolvedSha } = await execAsync$6(`git rev-parse --verify ${JSON.stringify(candidateRef)}`, {
1185
+ const { stdout: resolvedSha } = await execAsync$7(`git rev-parse --verify ${JSON.stringify(candidateRef)}`, {
1175
1186
  cwd: repoPath,
1176
1187
  encoding: "utf-8"
1177
1188
  });
@@ -1180,7 +1191,7 @@ async function resolveStashOperationRef(repoPath, ref, stackRef) {
1180
1191
  }
1181
1192
  const matchingEntry = (await Effect.runPromise(listStashes(repoPath))).find((entry) => entry.ref === ref);
1182
1193
  if (!matchingEntry?.stackRef) throw new Error(`Stash ${ref} not found`);
1183
- const { stdout: resolvedSha } = await execAsync$6(`git rev-parse --verify ${JSON.stringify(matchingEntry.stackRef)}`, {
1194
+ const { stdout: resolvedSha } = await execAsync$7(`git rev-parse --verify ${JSON.stringify(matchingEntry.stackRef)}`, {
1184
1195
  cwd: repoPath,
1185
1196
  encoding: "utf-8"
1186
1197
  });
@@ -1189,7 +1200,7 @@ async function resolveStashOperationRef(repoPath, ref, stackRef) {
1189
1200
  }
1190
1201
  async function dropStashPromise(repoPath, ref, stackRef) {
1191
1202
  const operationRef = await resolveStashOperationRef(repoPath, ref, stackRef);
1192
- await execAsync$6(`git stash drop ${JSON.stringify(operationRef)}`, {
1203
+ await execAsync$7(`git stash drop ${JSON.stringify(operationRef)}`, {
1193
1204
  cwd: repoPath,
1194
1205
  encoding: "utf-8"
1195
1206
  });
@@ -1197,7 +1208,7 @@ async function dropStashPromise(repoPath, ref, stackRef) {
1197
1208
  async function createRecoveryBranchFromStashPromise(repoPath, stashRef, issueId, shortDescription, stackRef) {
1198
1209
  const operationRef = await resolveStashOperationRef(repoPath, stashRef, stackRef);
1199
1210
  const branchName = `recovery/${validateIssueId(issueId)}-${sanitizeShortDescription(shortDescription)}`;
1200
- await execAsync$6(`git branch ${JSON.stringify(branchName)} ${JSON.stringify(operationRef)}`, {
1211
+ await execAsync$7(`git branch ${JSON.stringify(branchName)} ${JSON.stringify(operationRef)}`, {
1201
1212
  cwd: repoPath,
1202
1213
  encoding: "utf-8"
1203
1214
  });
@@ -2762,12 +2773,80 @@ const internalEventsRouteLayer = Layer.mergeAll(internalEventsRoute, internalEve
2762
2773
  //#endregion
2763
2774
  //#region routes/workspaces/merge-strike.ts
2764
2775
  init_agents();
2776
+ init_agent_state();
2777
+ init_tmux();
2778
+ const execAsync$6 = promisify(exec);
2765
2779
  function mergeVerificationOptions(request) {
2766
2780
  return {
2767
2781
  syncTargetBranch: false,
2768
2782
  ...request.kind === "strike" ? { skipPlanChecklist: true } : {}
2769
2783
  };
2770
2784
  }
2785
+ /**
2786
+ * PAN-3067: the PAN-2487 CI-green skip bypasses the verification runner — which
2787
+ * is what records verificationStatus on local runs — and that skip is the exact
2788
+ * path every strike merge takes (its CI is already green). Record the verdict
2789
+ * here so DoD row 3 has evidence and close-out can proceed.
2790
+ */
2791
+ async function recordCiGreenVerificationVerdict(issueId, workspacePath) {
2792
+ try {
2793
+ const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-Xg4PFN45.js");
2794
+ const verifiedAnchor = await snapshotWorkspaceHeadsPromise(issueId, workspacePath).catch(() => void 0);
2795
+ const { setReviewStatusSync } = await import("./review-status-Dma9SFaN.js");
2796
+ setReviewStatusSync(issueId, {
2797
+ verificationStatus: "passed",
2798
+ verificationNotes: "merge-verify: CI green on the merged tip (PAN-2487 local-gate skip)",
2799
+ ...verifiedAnchor ? { lastVerifiedCommit: verifiedAnchor } : {}
2800
+ });
2801
+ } catch (recordErr) {
2802
+ const message = recordErr instanceof Error ? recordErr.message : String(recordErr);
2803
+ console.warn(`[merge] Could not record CI-green verification verdict for ${issueId}: ${message}`);
2804
+ }
2805
+ }
2806
+ /**
2807
+ * PAN-3120: resume the work agent for a merge-requested rebase and narrate it to
2808
+ * the operator (Awaiting Merge tracker + ship log), so a scheduler-yielded agent
2809
+ * shows as "Preparing work agent" rather than a silent step or a dead end.
2810
+ * Status writes go through the caller's `setStatus` to keep this module free of
2811
+ * the workspaces-route import cycle.
2812
+ */
2813
+ async function prepareWorkAgentForRebase(opts) {
2814
+ const { appendShipLog } = await import("./ship-log-7kJfjUX2.js");
2815
+ opts.setStatus({
2816
+ mergeStep: "preparing-work-agent",
2817
+ mergeNotes: `Preparing work agent ${opts.agentId} to rebase ${opts.scopeNote}…`
2818
+ });
2819
+ appendShipLog(opts.issueId, `Preparing work agent ${opts.agentId} for rebase…`, "rebasing");
2820
+ try {
2821
+ const recovery = await ensureAgentReadyForMerge(opts.issueId, opts.workspacePath, opts.rebaseMsg, {
2822
+ agentId: opts.agentId,
2823
+ ...opts.allowFreshStart === void 0 ? {} : { allowFreshStart: opts.allowFreshStart }
2824
+ });
2825
+ opts.setStatus({
2826
+ mergeStep: "rebasing",
2827
+ mergeNotes: `${recovery.detail} Waiting for ${opts.scopeNote} to be rebased and pushed.`
2828
+ });
2829
+ appendShipLog(opts.issueId, `✓ ${recovery.detail}`, "rebasing");
2830
+ console.log(`[merge] ${recovery.detail}`);
2831
+ return {
2832
+ ok: true,
2833
+ detail: recovery.detail
2834
+ };
2835
+ } catch (prepError) {
2836
+ const message = prepError instanceof Error ? prepError.message : String(prepError);
2837
+ const error = `Work agent ${opts.agentId} could not be prepared for the rebase: ${message}`;
2838
+ opts.setStatus(opts.deferFailureStatus ? { mergeNotes: error } : {
2839
+ mergeStatus: "failed",
2840
+ readyForMerge: false,
2841
+ mergeNotes: error
2842
+ });
2843
+ appendShipLog(opts.issueId, `✗ ${error}`, "rebasing");
2844
+ return {
2845
+ ok: false,
2846
+ error
2847
+ };
2848
+ }
2849
+ }
2771
2850
  function parseStrikeMergeRequest(raw) {
2772
2851
  if (!raw || typeof raw !== "object") return null;
2773
2852
  const request = raw;
@@ -2830,23 +2909,55 @@ async function validateStrikeMergeRequest(issueId, request, status, deps) {
2830
2909
  }
2831
2910
  return null;
2832
2911
  }
2912
+ /**
2913
+ * PAN-3120: clear whatever gate would stop THIS merge from reaching the work
2914
+ * agent. The preemptive scheduler yields idle work agents to free slots, so the
2915
+ * agent a merge needs is routinely paused by the system itself — and a paused
2916
+ * agent silently diverts `messageAgent` into a mail queue nothing drains, which
2917
+ * the merge then waits 30 minutes on. Returns a human-readable note when a gate
2918
+ * was cleared so the operator sees why the agent came back.
2919
+ */
2920
+ async function clearMergePreparationGate(agentId) {
2921
+ const state = getAgentStateSync(agentId);
2922
+ if (!state) return null;
2923
+ const decision = decideResumeGate(getAgentResumeGateBlockReason(state), "merge-preparation");
2924
+ if (decision.decision === "block") throw new Error(decision.reason);
2925
+ if (decision.decision !== "proceed") return null;
2926
+ if (decision.clearYield) {
2927
+ clearYieldForResumeSync(agentId);
2928
+ return `cleared scheduler yield (${state.pausedReason ?? "yielded"})`;
2929
+ }
2930
+ if (decision.clearStoppedByUser) {
2931
+ delete state.stoppedByUser;
2932
+ saveAgentStateSync(state);
2933
+ return "cleared operator-stop gate for the requested merge";
2934
+ }
2935
+ return null;
2936
+ }
2937
+ /** A message diverted to the mail queue never reaches the agent — treat it as a failure, not a resume. */
2938
+ function assertDelivered(agentId, outcome) {
2939
+ if (outcome.delivered) return;
2940
+ throw new Error(`Merge preparation request for ${agentId} was not delivered${outcome.reason ? ` (${outcome.reason})` : ""}${outcome.queuedToMail ? " — it went to the mail queue, so no rebase would ever happen" : ""}.`);
2941
+ }
2833
2942
  async function ensureAgentReadyForMerge(issueId, workspacePath, rebaseMsg, options) {
2834
2943
  const agentId = options?.agentId ?? `agent-${issueId.toLowerCase()}`;
2944
+ const gateNote = await clearMergePreparationGate(agentId);
2945
+ const gateSuffix = gateNote ? ` (${gateNote})` : "";
2835
2946
  const lifecycle = getWorkAgentLifecycleStateSync(agentId);
2836
2947
  if (lifecycle.hasLiveTmuxSession) {
2837
- await messageAgent(agentId, rebaseMsg);
2948
+ assertDelivered(agentId, await messageAgent(agentId, rebaseMsg));
2838
2949
  return {
2839
2950
  recovered: true,
2840
2951
  agentId,
2841
- detail: "Work agent already running; sent merge preparation request."
2952
+ detail: `Work agent already running; sent merge preparation request${gateSuffix}.`
2842
2953
  };
2843
2954
  }
2844
2955
  if (await Effect.runPromise(getAgentState(agentId))) try {
2845
- await messageAgent(agentId, rebaseMsg);
2956
+ assertDelivered(agentId, await messageAgent(agentId, rebaseMsg));
2846
2957
  return {
2847
2958
  recovered: true,
2848
2959
  agentId,
2849
- detail: getWorkAgentLifecycleStateSync(agentId).canResumeSession ? "Resumed work agent and sent merge preparation request." : "Restarted work agent and sent merge preparation request."
2960
+ detail: `${getWorkAgentLifecycleStateSync(agentId).canResumeSession ? "Resumed" : "Restarted"} work agent and sent merge preparation request${gateSuffix}.`
2850
2961
  };
2851
2962
  } catch (error) {
2852
2963
  if (!lifecycle.canStartFresh) throw error;
@@ -2859,10 +2970,102 @@ async function ensureAgentReadyForMerge(issueId, workspacePath, rebaseMsg, optio
2859
2970
  issueId,
2860
2971
  workspace: workspacePath,
2861
2972
  role: "work",
2862
- prompt: rebaseMsg
2973
+ prompt: rebaseMsg,
2974
+ startedBy: "merge-strike"
2863
2975
  })).id} and sent merge preparation request.`
2864
2976
  };
2865
2977
  }
2978
+ async function rebaseWithAgentFallback(options) {
2979
+ const { issueId, workspacePath, branchName, targetBranch, agentId, rebaseMsg, allowFreshStart, setStatus } = options;
2980
+ let serverRebaseReason;
2981
+ let conflictFiles = [];
2982
+ if (existsSync$1(workspacePath)) try {
2983
+ const result = await Effect.runPromise(rebaseFeatureBranch(workspacePath, branchName, targetBranch, issueId));
2984
+ console.log(`[merge] Server-side rebase completed for ${issueId}`);
2985
+ return {
2986
+ success: true,
2987
+ newHead: result.newHead
2988
+ };
2989
+ } catch (error) {
2990
+ const detail = error;
2991
+ conflictFiles = Array.isArray(detail.conflictedFiles) ? detail.conflictedFiles.filter((file) => typeof file === "string") : [];
2992
+ const message = error instanceof Error ? error.message : typeof detail.message === "string" ? detail.message : void 0;
2993
+ serverRebaseReason = conflictFiles.length > 0 ? `Rebase conflicts in: ${conflictFiles.join(", ")}` : message || "Server-side rebase failed";
2994
+ console.warn(`[merge] ${serverRebaseReason} — escalating to the work agent for ${issueId}`);
2995
+ }
2996
+ try {
2997
+ const preparation = await prepareWorkAgentForRebase({
2998
+ issueId,
2999
+ workspacePath,
3000
+ agentId,
3001
+ rebaseMsg,
3002
+ allowFreshStart,
3003
+ scopeNote: branchName,
3004
+ setStatus,
3005
+ deferFailureStatus: true
3006
+ });
3007
+ if (!preparation.ok) throw new Error(preparation.error);
3008
+ const { stdout: headBefore } = await execAsync$6(`git rev-parse origin/${branchName} 2>/dev/null || echo NONE`, {
3009
+ cwd: workspacePath,
3010
+ encoding: "utf-8",
3011
+ timeout: 1e4
3012
+ });
3013
+ const timeoutMs = 1800 * 1e3;
3014
+ const startTime = Date.now();
3015
+ let newHead = null;
3016
+ while (Date.now() - startTime < timeoutMs) {
3017
+ await new Promise((resolve) => setTimeout(resolve, 5e3));
3018
+ try {
3019
+ await execAsync$6("git fetch origin", {
3020
+ cwd: workspacePath,
3021
+ encoding: "utf-8",
3022
+ timeout: 15e3
3023
+ });
3024
+ const { stdout: headNow } = await execAsync$6(`git rev-parse origin/${branchName}`, {
3025
+ cwd: workspacePath,
3026
+ encoding: "utf-8",
3027
+ timeout: 5e3
3028
+ });
3029
+ if (headNow.trim() !== headBefore.trim()) {
3030
+ newHead = headNow.trim();
3031
+ console.log(`[merge] Work agent pushed rebased branch for ${issueId} (new HEAD: ${newHead.slice(0, 8)})`);
3032
+ break;
3033
+ }
3034
+ } catch {}
3035
+ if (!await Effect.runPromise(sessionExists(agentId))) {
3036
+ console.log(`[merge] Work agent ${agentId} stopped during rebase`);
3037
+ break;
3038
+ }
3039
+ }
3040
+ if (newHead) return {
3041
+ success: true,
3042
+ newHead
3043
+ };
3044
+ if (!await Effect.runPromise(sessionExists(agentId))) {
3045
+ const agentReason = `Work agent ${agentId} stopped before completing the rebase onto ${targetBranch}`;
3046
+ return {
3047
+ success: false,
3048
+ reason: serverRebaseReason ? `${serverRebaseReason}; ${agentReason}` : agentReason,
3049
+ conflictFiles,
3050
+ retryable: conflictFiles.length === 0
3051
+ };
3052
+ }
3053
+ return {
3054
+ success: false,
3055
+ reason: `Work agent did not push the rebased branch within ${timeoutMs / 6e4} minutes`,
3056
+ conflictFiles,
3057
+ retryable: conflictFiles.length === 0
3058
+ };
3059
+ } catch (error) {
3060
+ const agentReason = error instanceof Error ? error.message : `Work agent ${agentId} could not be prepared for merge`;
3061
+ return {
3062
+ success: false,
3063
+ reason: serverRebaseReason ? `${serverRebaseReason}; ${agentReason}` : agentReason,
3064
+ conflictFiles,
3065
+ retryable: conflictFiles.length === 0
3066
+ };
3067
+ }
3068
+ }
2866
3069
  //#endregion
2867
3070
  //#region routes/workspaces/internal-strike-merge.ts
2868
3071
  init_issue_id();
@@ -2916,6 +3119,7 @@ function internalStrikeMergeRoute(triggerMerge) {
2916
3119
  * stay owned by ../workspaces.js and are imported here.
2917
3120
  */
2918
3121
  init_merge_agent();
3122
+ init_merge_verification();
2919
3123
  init_operations();
2920
3124
  init_git_activity();
2921
3125
  init_issue_id();
@@ -2928,7 +3132,7 @@ init_tracker_utils();
2928
3132
  init_tmux();
2929
3133
  init_domain_services();
2930
3134
  const execAsync$5 = promisify(exec);
2931
- const execFileAsync$3 = promisify(execFile);
3135
+ const execFileAsync$4 = promisify(execFile);
2932
3136
  const shouldBlockApproveForDirtyStatus = (status) => status.trim() !== "" && !isStatePlaneOnlyStatus(status);
2933
3137
  /**
2934
3138
  * Check whether origin/branchName already contains origin/targetBranch.
@@ -2936,7 +3140,7 @@ const shouldBlockApproveForDirtyStatus = (status) => status.trim() !== "" && !is
2936
3140
  */
2937
3141
  async function isBranchAlreadyRebased(workspacePath, branchName, targetBranch) {
2938
3142
  try {
2939
- await Promise.all([execFileAsync$3("git", [
3143
+ await Promise.all([execFileAsync$4("git", [
2940
3144
  "fetch",
2941
3145
  "origin",
2942
3146
  targetBranch
@@ -2944,7 +3148,7 @@ async function isBranchAlreadyRebased(workspacePath, branchName, targetBranch) {
2944
3148
  cwd: workspacePath,
2945
3149
  encoding: "utf-8",
2946
3150
  timeout: 15e3
2947
- }), execFileAsync$3("git", [
3151
+ }), execFileAsync$4("git", [
2948
3152
  "fetch",
2949
3153
  "origin",
2950
3154
  branchName
@@ -2953,7 +3157,7 @@ async function isBranchAlreadyRebased(workspacePath, branchName, targetBranch) {
2953
3157
  encoding: "utf-8",
2954
3158
  timeout: 15e3
2955
3159
  })]);
2956
- await execFileAsync$3("git", [
3160
+ await execFileAsync$4("git", [
2957
3161
  "merge-base",
2958
3162
  "--is-ancestor",
2959
3163
  `origin/${targetBranch}`,
@@ -2963,7 +3167,7 @@ async function isBranchAlreadyRebased(workspacePath, branchName, targetBranch) {
2963
3167
  encoding: "utf-8",
2964
3168
  timeout: 5e3
2965
3169
  });
2966
- const { stdout: currentHead } = await execFileAsync$3("git", ["rev-parse", `origin/${branchName}`], {
3170
+ const { stdout: currentHead } = await execFileAsync$4("git", ["rev-parse", `origin/${branchName}`], {
2967
3171
  cwd: workspacePath,
2968
3172
  encoding: "utf-8",
2969
3173
  timeout: 5e3
@@ -2972,7 +3176,8 @@ async function isBranchAlreadyRebased(workspacePath, branchName, targetBranch) {
2972
3176
  alreadyRebased: true,
2973
3177
  currentHead: currentHead.trim()
2974
3178
  };
2975
- } catch {
3179
+ } catch (error) {
3180
+ console.warn(`[merge] Could not determine whether ${branchName} contains origin/${targetBranch}: ${error instanceof Error ? error.message : String(error)}`);
2976
3181
  return { alreadyRebased: false };
2977
3182
  }
2978
3183
  }
@@ -2991,7 +3196,7 @@ async function reconcileGitHubMergeStatus(issueId, status) {
2991
3196
  const prRef = parseGitHubPullRequestUrl(status.prUrl);
2992
3197
  if (!prRef) return false;
2993
3198
  try {
2994
- const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-ClZ2lk8D.js");
3199
+ const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-Bmg4R9mv.js");
2995
3200
  if (!isGitHubAppConfigured()) return false;
2996
3201
  const prState = await Effect.runPromise(getPullRequestState(prRef.owner, prRef.repo, prRef.number));
2997
3202
  console.log(`[merge] reconcileGitHubMergeStatus: ${issueId} PR #${prRef.number} merged=${prState.merged} state=${prState.state}`);
@@ -3043,7 +3248,7 @@ async function ensurePRExists(issueId, options) {
3043
3248
  if (options?.cwd) execOptions.cwd = options.cwd;
3044
3249
  let existingOut = "";
3045
3250
  try {
3046
- const { stdout } = await execFileAsync$3("gh", [
3251
+ const { stdout } = await execFileAsync$4("gh", [
3047
3252
  "pr",
3048
3253
  "view",
3049
3254
  branchName,
@@ -3066,7 +3271,7 @@ async function ensurePRExists(issueId, options) {
3066
3271
  const bodyFile = pathJoin(tmpdir(), `pan-pr-body-${issueId}-${Date.now()}.md`);
3067
3272
  await writeFileAsync(bodyFile, prBody, "utf-8");
3068
3273
  try {
3069
- const { stdout: rawOut } = await execFileAsync$3("gh", [
3274
+ const { stdout: rawOut } = await execFileAsync$4("gh", [
3070
3275
  "pr",
3071
3276
  "create",
3072
3277
  "--head",
@@ -3137,20 +3342,23 @@ const postWorkspaceSyncMainRoute = HttpRouter.add("POST", "/api/issues/:issueId/
3137
3342
  if (result.alreadyUpToDate) return jsonResponse({
3138
3343
  success: true,
3139
3344
  alreadyUpToDate: true,
3140
- message: "Already up to date with main"
3345
+ message: "Already up to date with main",
3346
+ repos: result.repos
3141
3347
  });
3142
3348
  return jsonResponse({
3143
3349
  success: true,
3144
3350
  commitCount: result.commitCount || 0,
3145
3351
  changedFiles: result.changedFiles || [],
3146
- message: `Synced ${result.commitCount || 0} commit(s) from main`
3352
+ message: `Synced ${result.commitCount || 0} commit(s) from main`,
3353
+ repos: result.repos
3147
3354
  });
3148
3355
  } else {
3149
3356
  const status = result.reason?.includes("uncommitted") ? 400 : 500;
3150
3357
  return jsonResponse({
3151
3358
  success: false,
3152
3359
  error: result.reason || "Sync failed",
3153
- conflictFiles: result.conflictFiles
3360
+ conflictFiles: result.conflictFiles,
3361
+ repos: result.repos
3154
3362
  }, { status });
3155
3363
  }
3156
3364
  })));
@@ -3180,7 +3388,7 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3180
3388
  };
3181
3389
  const strikeError = await validateStrikeMergeRequest(issueId, request, reviewStatus, {
3182
3390
  projectPath: getProjectPath(void 0, extractPrefixSync(issueId) ?? issueId.split("-")[0]),
3183
- git: async (args, cwd) => (await execFileAsync$3("git", args, {
3391
+ git: async (args, cwd) => (await execFileAsync$4("git", args, {
3184
3392
  cwd,
3185
3393
  encoding: "utf-8"
3186
3394
  })).stdout.trim()
@@ -3248,7 +3456,7 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3248
3456
  const normalizedMergeId = issueId.toUpperCase();
3249
3457
  _serverManagedMerges.add(normalizedMergeId);
3250
3458
  setPendingOperation(issueId, "merge");
3251
- let queueAdvanced = false;
3459
+ let queueAdvanced = false, preserveQueue = false;
3252
3460
  const advanceQueue = () => {
3253
3461
  if (queueAdvanced) return;
3254
3462
  queueAdvanced = true;
@@ -3258,8 +3466,8 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3258
3466
  try {
3259
3467
  if (request.kind === "normal" && workspaceInfo.isRemote && workspaceInfo.vmName) {
3260
3468
  console.log(`[merge] Remote workspace detected for ${issueId}, using review artifact merge...`);
3261
- const { getMergeSetSync, ensureMergeSetForIssueSync } = await import("./merge-set-bUqbm3yc.js");
3262
- const { getForgeAdapter } = await import("./forge-DXnS_YFH.js");
3469
+ const { getMergeSetSync, ensureMergeSetForIssueSync } = await import("./merge-set-DeUxFsC3.js");
3470
+ const { getForgeAdapter } = await import("./forge-B5o319qI.js");
3263
3471
  const remotePrimaryRepo = (getMergeSetSync(issueId) || ensureMergeSetForIssueSync(issueId))?.repos[0];
3264
3472
  const remoteTargetBranch = remotePrimaryRepo?.targetBranch || "main";
3265
3473
  const remoteForge = remotePrimaryRepo?.forge || "github";
@@ -3295,7 +3503,7 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3295
3503
  ...mergeCompletionStatus(request)
3296
3504
  });
3297
3505
  completePendingOperation(issueId, null);
3298
- const { postMergeLifecycle } = await import("./merge-agent-CKkgIBPB.js");
3506
+ const { postMergeLifecycle } = await import("./merge-agent-DQTXZk8z.js");
3299
3507
  await postMergeLifecycle(issueId, projectPath);
3300
3508
  return {
3301
3509
  success: true,
@@ -3321,21 +3529,30 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3321
3529
  };
3322
3530
  }
3323
3531
  }
3532
+ const projectConfig = findProjectByTeamSync(issuePrefix);
3533
+ const isPolyrepo = projectConfig?.workspace?.type === "polyrepo";
3324
3534
  if (!existsSync$1(workspacePath)) {
3325
- completePendingOperation(issueId, "Workspace does not exist");
3535
+ const error = "Workspace does not exist";
3536
+ const retryable = request.kind === "normal" && !workspaceInfo.isRemote && !isPolyrepo;
3537
+ if (retryable) setReviewStatus(issueId, {
3538
+ mergeStatus: "queued",
3539
+ mergeNotes: error
3540
+ });
3541
+ completePendingOperation(issueId, error);
3326
3542
  return {
3327
3543
  success: false,
3328
- statusCode: 400,
3329
- error: "Workspace does not exist"
3544
+ statusCode: retryable ? 500 : 400,
3545
+ error,
3546
+ ...retryable ? { retryable: true } : {}
3330
3547
  };
3331
3548
  }
3332
- const projectConfig = findProjectByTeamSync(issuePrefix);
3333
- if (projectConfig?.workspace?.type === "polyrepo" && projectConfig?.workspace?.repos) {
3549
+ if (isPolyrepo && projectConfig?.workspace?.repos) {
3334
3550
  console.log(`[merge] Polyrepo detected for ${issueId}, coordinating merge set...`);
3335
- const { getMergeSetSync, ensureMergeSetForIssueSync, upsertMergeSetSync, withRepoStateSync } = await import("./merge-set-bUqbm3yc.js");
3336
- const { runQualityGates } = await import("./validation-CC9OPqJZ.js");
3337
- const { getForgeAdapter } = await import("./forge-DXnS_YFH.js");
3338
- const { messageAgent } = await import("./agents-wi9NWzs2.js");
3551
+ const { getMergeSetSync, ensureMergeSetForIssueSync, upsertMergeSetSync, withRepoStateSync } = await import("./merge-set-DeUxFsC3.js");
3552
+ const { runQualityGates } = await import("./validation-hVOwQk8T.js");
3553
+ const { reconcileStrandedRepos } = await import("./merge-completeness-BLbB5-6n.js");
3554
+ const { getForgeAdapter } = await import("./forge-B5o319qI.js");
3555
+ const { messageAgent } = await import("./agents-ePFVoZbu.js");
3339
3556
  let mergeSet = getMergeSetSync(issueId) || ensureMergeSetForIssueSync(issueId);
3340
3557
  if (!mergeSet) {
3341
3558
  const error = `No merge set found for ${issueId}`;
@@ -3351,21 +3568,59 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3351
3568
  error
3352
3569
  };
3353
3570
  }
3354
- const activeRepos = mergeSet.repos.filter((repo) => repo.mergeStatus !== "skipped" && !!repo.artifactUrl).sort((a, b) => a.mergeOrder - b.mergeOrder);
3355
- if (activeRepos.length === 0) {
3356
- const error = `No changed repos are marked ready for coordinated merge in ${issueId}`;
3571
+ const reconciliation = await reconcileStrandedRepos(mergeSet);
3572
+ mergeSet = reconciliation.mergeSet;
3573
+ if (reconciliation.blockers.length > 0) {
3574
+ const error = reconciliation.blockers.map((blocker) => blocker.reason).join("; ");
3575
+ mergeSet = {
3576
+ ...mergeSet,
3577
+ status: "failed",
3578
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3579
+ };
3580
+ upsertMergeSetSync(mergeSet);
3357
3581
  setReviewStatus(issueId, {
3358
3582
  mergeStatus: "failed",
3359
3583
  readyForMerge: false,
3360
- mergeNotes: error
3584
+ mergeNotes: error,
3585
+ blockerReasons: reconciliation.blockers.map((blocker) => ({
3586
+ type: "unmerged_sibling_repo",
3587
+ summary: blocker.reason,
3588
+ detectedAt: (/* @__PURE__ */ new Date()).toISOString()
3589
+ }))
3361
3590
  });
3362
3591
  completePendingOperation(issueId, error);
3363
3592
  return {
3364
3593
  success: false,
3365
- statusCode: 400,
3594
+ statusCode: 409,
3366
3595
  error
3367
3596
  };
3368
3597
  }
3598
+ const activeRepos = mergeSet.repos.filter((repo) => repo.mergeStatus !== "skipped" && repo.mergeStatus !== "merged" && !!repo.artifactUrl).sort((a, b) => a.mergeOrder - b.mergeOrder);
3599
+ if (activeRepos.length === 0) {
3600
+ mergeSet = {
3601
+ ...mergeSet,
3602
+ status: "merged",
3603
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3604
+ };
3605
+ upsertMergeSetSync(mergeSet);
3606
+ setReviewStatus(issueId, {
3607
+ mergeStatus: "merged",
3608
+ mergeNotes: void 0,
3609
+ readyForMerge: false,
3610
+ ...mergeCompletionStatus(request)
3611
+ });
3612
+ completePendingOperation(issueId, null);
3613
+ const { postMergeLifecycle } = await import("./merge-agent-DQTXZk8z.js");
3614
+ advanceQueue();
3615
+ await postMergeLifecycle(issueId, projectPath);
3616
+ return {
3617
+ success: true,
3618
+ statusCode: 200,
3619
+ message: `No changed repos remain for ${issueId}`,
3620
+ mergeStatus: "merged",
3621
+ repos: []
3622
+ };
3623
+ }
3369
3624
  const agentId = `agent-${issueId.toLowerCase()}`;
3370
3625
  mergeSet = {
3371
3626
  ...mergeSet,
@@ -3428,21 +3683,24 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3428
3683
  };
3429
3684
  }
3430
3685
  const reposNeedingRebase = activeRepos.filter((repo) => !alreadyRebased.has(repo.repoKey));
3431
- if (reposNeedingRebase.length > 0 && !await Effect.runPromise(sessionExists(agentId))) {
3432
- const error = `Work agent ${agentId} is not running. Polyrepo merge requires the work agent to rebase every affected repo and push.`;
3433
- setReviewStatus(issueId, {
3434
- mergeStatus: "failed",
3435
- readyForMerge: false,
3436
- mergeNotes: error
3686
+ if (reposNeedingRebase.length > 0) {
3687
+ const prep = await prepareWorkAgentForRebase({
3688
+ issueId,
3689
+ workspacePath,
3690
+ agentId,
3691
+ rebaseMsg: `MERGE REQUESTED: The human has clicked MERGE for ${issueId}. Rebase and push every affected repo in this merge set:\n\n${reposNeedingRebase.map((repo, index) => `${index + 1}. cd ${repo.repoKey}\n git fetch origin ${repo.targetBranch}\n git rebase origin/${repo.targetBranch}\n git push --force-with-lease`).join("\n")}\n\nResolve any conflicts in the workspaces above, complete every rebase, and push all affected branches. Do NOT merge PRs/MRs yourself.`,
3692
+ scopeNote: `${reposNeedingRebase.length} repo(s)`,
3693
+ setStatus: (u) => setReviewStatus(issueId, u)
3437
3694
  });
3438
- completePendingOperation(issueId, error);
3439
- return {
3440
- success: false,
3441
- statusCode: 400,
3442
- error
3443
- };
3695
+ if (!prep.ok) {
3696
+ completePendingOperation(issueId, prep.error);
3697
+ return {
3698
+ success: false,
3699
+ statusCode: 400,
3700
+ error: prep.error
3701
+ };
3702
+ }
3444
3703
  }
3445
- if (reposNeedingRebase.length > 0) await messageAgent(agentId, `MERGE REQUESTED: The human has clicked MERGE for ${issueId}. Rebase and push every affected repo in this merge set:\n\n${reposNeedingRebase.map((repo, index) => `${index + 1}. cd ${repo.repoKey}\n git fetch origin ${repo.targetBranch}\n git rebase origin/${repo.targetBranch}\n git push --force-with-lease`).join("\n")}\n\nResolve any conflicts in the workspaces above, complete every rebase, and push all affected branches. Do NOT merge PRs/MRs yourself.`);
3446
3704
  const REBASE_TIMEOUT_MS = 1800 * 1e3;
3447
3705
  const POLL_INTERVAL_MS = 5e3;
3448
3706
  const pushedRepos = new Set(alreadyRebased);
@@ -3606,7 +3864,7 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3606
3864
  ...mergeCompletionStatus(request)
3607
3865
  });
3608
3866
  completePendingOperation(issueId, null);
3609
- const { postMergeLifecycle } = await import("./merge-agent-CKkgIBPB.js");
3867
+ const { postMergeLifecycle } = await import("./merge-agent-DQTXZk8z.js");
3610
3868
  advanceQueue();
3611
3869
  await postMergeLifecycle(issueId, projectPath);
3612
3870
  return {
@@ -3617,8 +3875,8 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3617
3875
  repos: mergeResults
3618
3876
  };
3619
3877
  }
3620
- const { getMergeSetSync, ensureMergeSetForIssueSync } = await import("./merge-set-bUqbm3yc.js");
3621
- const { getForgeAdapter } = await import("./forge-DXnS_YFH.js");
3878
+ const { getMergeSetSync, ensureMergeSetForIssueSync } = await import("./merge-set-DeUxFsC3.js");
3879
+ const { getForgeAdapter } = await import("./forge-B5o319qI.js");
3622
3880
  const primaryRepo = (getMergeSetSync(issueId) || ensureMergeSetForIssueSync(issueId))?.repos[0];
3623
3881
  const targetBranch = primaryRepo?.targetBranch || "main";
3624
3882
  const primaryForge = primaryRepo?.forge || "github";
@@ -3659,10 +3917,12 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3659
3917
  error
3660
3918
  };
3661
3919
  }
3920
+ let preMergePrState;
3662
3921
  if (githubPrRef) try {
3663
- const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-ClZ2lk8D.js");
3922
+ const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-Bmg4R9mv.js");
3664
3923
  if (isGitHubAppConfigured()) {
3665
3924
  const prState = await Effect.runPromise(getPullRequestState(githubPrRef.owner, githubPrRef.repo, githubPrRef.number));
3925
+ preMergePrState = prState;
3666
3926
  if (prState.state !== "OPEN" && !prState.merged) {
3667
3927
  const error = `PR #${githubPrRef.number} is ${prState.state} (not OPEN). Overdeck state is out of sync — likely a cancel-flow left a stale prUrl. Re-open the work agent to create a fresh PR, or reset review state.`;
3668
3928
  console.error(`[merge] ${error}`);
@@ -3722,7 +3982,7 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3722
3982
  ...mergeCompletionStatus(request)
3723
3983
  });
3724
3984
  completePendingOperation(issueId, null);
3725
- const { postMergeLifecycle } = await import("./merge-agent-CKkgIBPB.js");
3985
+ const { postMergeLifecycle } = await import("./merge-agent-DQTXZk8z.js");
3726
3986
  await postMergeLifecycle(issueId, projectPath, branchName);
3727
3987
  return {
3728
3988
  success: true,
@@ -3736,83 +3996,56 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3736
3996
  } catch (prStateErr) {
3737
3997
  console.warn(`[merge] Pre-merge PR state check failed for ${issueId}: ${prStateErr.message} — proceeding (check is best-effort)`);
3738
3998
  }
3739
- const { postMergeLifecycle } = await import("./merge-agent-CKkgIBPB.js");
3740
- const agentId = request.kind === "strike" ? request.recoveryTarget : `agent-${issueId.toLowerCase()}`;
3741
- const rebaseMsg = request.kind === "strike" ? `STRIKE LANDING REQUEST: Rebase ${branchName} onto ${targetBranch}, resolve conflicts, run the full quality gates, push ${branchName}, then run pan strike-ready ${issueId} to persist the new HEAD. Do NOT merge or push main.` : `MERGE REQUESTED: The human has clicked MERGE for ${issueId}. Please rebase onto ${targetBranch} and push:\n\n1. git fetch origin ${targetBranch}\n2. git rebase origin/${targetBranch}\n3. If conflicts: resolve them, git add, git rebase --continue\n4. git push --force-with-lease\n\nAfter pushing, the server will handle verification and merge automatically. Do NOT run gh pr merge yourself.`;
3742
- setReviewStatus(issueId, { mergeStep: "rebasing" });
3743
- console.log(`[merge] Rebasing ${branchName} onto ${targetBranch} for ${issueId} (agent=${await Effect.runPromise(sessionExists(agentId)) ? "running" : "stopped"})...`);
3744
- {
3745
- const { beginShipLog, appendShipLog } = await import("./ship-log-D9MlVzYU.js");
3746
- beginShipLog(issueId);
3747
- appendShipLog(issueId, `Ship started: rebasing ${branchName} onto ${targetBranch}…`, "rebasing");
3748
- }
3999
+ const { postMergeLifecycle } = await import("./merge-agent-DQTXZk8z.js");
4000
+ const { beginShipLog, appendShipLog } = await import("./ship-log-7kJfjUX2.js");
3749
4001
  let rebaseResult;
3750
- const { alreadyRebased, currentHead } = await isBranchAlreadyRebased(workspacePath, branchName, targetBranch);
3751
- if (alreadyRebased && currentHead) {
3752
- console.log(`[merge] ${branchName} already contains origin/${targetBranch} — skipping rebase request for ${issueId}`);
4002
+ if (preMergePrState?.mergeable === true && preMergePrState.mergeableState === "clean" && !preMergePrState.checksFailed && !preMergePrState.checksPending && !preMergePrState.draft && !preMergePrState.merged) {
4003
+ console.log(`[merge] PR is CLEAN — merging directly without rebase for ${issueId}`);
3753
4004
  rebaseResult = {
3754
4005
  success: true,
3755
- newHead: currentHead
4006
+ newHead: preMergePrState.headSha
3756
4007
  };
3757
- } else try {
3758
- const recovery = await ensureAgentReadyForMerge(issueId, workspacePath, rebaseMsg, {
4008
+ } else {
4009
+ const agentId = request.kind === "strike" ? request.recoveryTarget : `agent-${issueId.toLowerCase()}`;
4010
+ const rebaseMsg = request.kind === "strike" ? `STRIKE LANDING REQUEST: Rebase ${branchName} onto ${targetBranch}, resolve conflicts, run the full quality gates, push ${branchName}, then run pan strike-ready ${issueId} to persist the new HEAD. Do NOT merge or push main.` : `MERGE REQUESTED: The human has clicked MERGE for ${issueId}. Please rebase onto ${targetBranch} and push:\n\n1. git fetch origin ${targetBranch}\n2. git rebase origin/${targetBranch}\n3. If conflicts: resolve them, git add, git rebase --continue\n4. git push --force-with-lease\n\nAfter pushing, the server will handle verification and merge automatically. Do NOT run gh pr merge yourself.`;
4011
+ setReviewStatus(issueId, { mergeStep: "rebasing" });
4012
+ console.log(`[merge] Rebasing ${branchName} onto ${targetBranch} for ${issueId} (agent=${await Effect.runPromise(sessionExists(agentId)) ? "running" : "stopped"})...`);
4013
+ beginShipLog(issueId);
4014
+ appendShipLog(issueId, `Ship started: rebasing ${branchName} onto ${targetBranch}…`, "rebasing");
4015
+ const { alreadyRebased, currentHead } = await isBranchAlreadyRebased(workspacePath, branchName, targetBranch);
4016
+ if (alreadyRebased && currentHead) {
4017
+ console.log(`[merge] ${branchName} already contains origin/${targetBranch} — skipping rebase request for ${issueId}`);
4018
+ rebaseResult = {
4019
+ success: true,
4020
+ newHead: currentHead
4021
+ };
4022
+ } else rebaseResult = await rebaseWithAgentFallback({
4023
+ issueId,
4024
+ workspacePath,
4025
+ branchName,
4026
+ targetBranch,
3759
4027
  agentId,
3760
- allowFreshStart: request.kind !== "strike"
3761
- });
3762
- console.log(`[merge] ${recovery.detail}`);
3763
- const { stdout: headBefore } = await execAsync$5(`git rev-parse origin/${branchName} 2>/dev/null || echo NONE`, {
3764
- cwd: workspacePath,
3765
- encoding: "utf-8",
3766
- timeout: 1e4
4028
+ rebaseMsg,
4029
+ allowFreshStart: request.kind !== "strike",
4030
+ setStatus: (update) => setReviewStatus(issueId, update)
3767
4031
  });
3768
- const REBASE_TIMEOUT_MS = 1800 * 1e3;
3769
- const POLL_INTERVAL_MS = 5e3;
3770
- const startTime = Date.now();
3771
- let newHead = null;
3772
- while (Date.now() - startTime < REBASE_TIMEOUT_MS) {
3773
- await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
3774
- try {
3775
- await execAsync$5("git fetch origin", {
3776
- cwd: workspacePath,
3777
- encoding: "utf-8",
3778
- timeout: 15e3
3779
- });
3780
- const { stdout: headNow } = await execAsync$5(`git rev-parse origin/${branchName}`, {
3781
- cwd: workspacePath,
3782
- encoding: "utf-8",
3783
- timeout: 5e3
3784
- });
3785
- if (headNow.trim() !== headBefore.trim()) {
3786
- newHead = headNow.trim();
3787
- console.log(`[merge] Work agent pushed rebased branch for ${issueId} (new HEAD: ${newHead.slice(0, 8)})`);
3788
- break;
3789
- }
3790
- } catch {}
3791
- if (!await Effect.runPromise(sessionExists(agentId))) {
3792
- console.log(`[merge] Work agent ${agentId} stopped during rebase`);
3793
- break;
3794
- }
3795
- }
3796
- if (newHead) rebaseResult = {
3797
- success: true,
3798
- newHead
3799
- };
3800
- else if (!await Effect.runPromise(sessionExists(agentId))) rebaseResult = {
3801
- success: false,
3802
- reason: `Work agent ${agentId} stopped before completing the rebase onto ${targetBranch}`
3803
- };
3804
- else rebaseResult = {
3805
- success: false,
3806
- reason: `Work agent did not push the rebased branch within ${REBASE_TIMEOUT_MS / 6e4} minutes`
3807
- };
3808
- } catch (recoveryErr) {
3809
- rebaseResult = {
3810
- success: false,
3811
- reason: recoveryErr.message || `Work agent ${agentId} could not be prepared for merge`
3812
- };
3813
4032
  }
4033
+ if (!rebaseResult) throw new Error(`Rebase escalation produced no result for ${issueId}`);
3814
4034
  if (!rebaseResult.success) {
3815
4035
  const error = rebaseResult.reason || "Rebase failed";
4036
+ if (rebaseResult.retryable) {
4037
+ setReviewStatus(issueId, {
4038
+ mergeStatus: "queued",
4039
+ mergeNotes: error
4040
+ });
4041
+ completePendingOperation(issueId, error);
4042
+ return {
4043
+ success: false,
4044
+ statusCode: 500,
4045
+ error,
4046
+ retryable: true
4047
+ };
4048
+ }
3816
4049
  setReviewStatus(issueId, {
3817
4050
  mergeStatus: "failed",
3818
4051
  mergeNotes: error,
@@ -3873,7 +4106,7 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3873
4106
  });
3874
4107
  let skipLocalVerification = false;
3875
4108
  if (primaryForge === "github" && artifactUrl) try {
3876
- const { parsePullRequestRef, getCiCheckRunsStatePromise, isGitHubAppConfigured } = await import("./github-app-ClZ2lk8D.js");
4109
+ const { parsePullRequestRef, getCiCheckRunsStatePromise, isGitHubAppConfigured } = await import("./github-app-Bmg4R9mv.js");
3877
4110
  if (isGitHubAppConfigured()) {
3878
4111
  const ref = parsePullRequestRef({ url: artifactUrl });
3879
4112
  if (ref) {
@@ -3894,17 +4127,27 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3894
4127
  } catch (ciErr) {
3895
4128
  console.warn(`[merge] CI-state check failed (${ciErr.message?.slice(0, 120)}) — falling back to local verification for ${issueId}`);
3896
4129
  }
3897
- const { appendShipLog } = await import("./ship-log-D9MlVzYU.js");
3898
4130
  if (skipLocalVerification) appendShipLog(issueId, "✓ Local verification skipped — CI already green on this exact commit", "verifying");
3899
4131
  const verifyResult = skipLocalVerification ? { outcome: "passed" } : await (async () => {
3900
4132
  console.log(`[merge] Running post-rebase verification for ${issueId}...`);
3901
4133
  appendShipLog(issueId, "Running post-rebase verification (full quality-gate suite)…", "verifying");
3902
- const { runVerificationForIssue } = await import("./verification-runner-BW4HOKAz.js");
4134
+ const { runVerificationForIssue } = await import("./verification-runner-Bc3cJvpC.js");
3903
4135
  return Effect.runPromise(runVerificationForIssue(issueId, workspacePath, { isRemote: false }, "merge-verify", {
3904
4136
  ...mergeVerificationOptions(request),
3905
4137
  onGateLog: (line) => appendShipLog(issueId, line, "verifying")
3906
4138
  }));
3907
4139
  })();
4140
+ const verificationDeferral = handlePostRebaseVerificationDeferral(issueId, verifyResult, reviewStatus, {
4141
+ appendShipLog,
4142
+ setReviewStatus,
4143
+ completePendingOperation
4144
+ });
4145
+ if (verificationDeferral) {
4146
+ markMergeProcessing(projectKey, normalizedId, false);
4147
+ _serverManagedMerges.delete(normalizedMergeId);
4148
+ preserveQueue = true;
4149
+ return verificationDeferral;
4150
+ }
3908
4151
  if (verifyResult.outcome === "failed") {
3909
4152
  const error = `Post-rebase verification failed at ${verifyResult.failedCheck}`;
3910
4153
  console.log(`[merge] ${error}`);
@@ -3930,9 +4173,10 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3930
4173
  };
3931
4174
  }
3932
4175
  console.log(`[merge] Post-rebase verification ${verifyResult.outcome} for ${issueId}`);
4176
+ if (skipLocalVerification) await recordCiGreenVerificationVerdict(issueId, workspacePath);
3933
4177
  setReviewStatus(issueId, { mergeStep: "reporting-statuses" });
3934
4178
  try {
3935
- const { getPullRequestState, isGitHubAppConfigured, reportCommitStatus } = await import("./github-app-ClZ2lk8D.js");
4179
+ const { getPullRequestState, isGitHubAppConfigured, reportCommitStatus } = await import("./github-app-Bmg4R9mv.js");
3936
4180
  if (githubPrRef && isGitHubAppConfigured()) {
3937
4181
  const sha = (await Effect.runPromise(getPullRequestState(githubPrRef.owner, githubPrRef.repo, githubPrRef.number))).headSha.trim();
3938
4182
  if (sha) {
@@ -3960,7 +4204,7 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
3960
4204
  } catch (prMergeErr) {
3961
4205
  console.error(`[merge] Review artifact merge threw for ${issueId}:`, prMergeErr);
3962
4206
  try {
3963
- const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-ClZ2lk8D.js");
4207
+ const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-Bmg4R9mv.js");
3964
4208
  if (githubPrRef && isGitHubAppConfigured()) {
3965
4209
  artifactMerged = (await Effect.runPromise(getPullRequestState(githubPrRef.owner, githubPrRef.repo, githubPrRef.number))).merged;
3966
4210
  if (artifactMerged) console.log(`[merge] Race-detected: PR #${githubPrRef.number} for ${issueId} was already merged despite thrown error; proceeding`);
@@ -4055,7 +4299,7 @@ async function triggerMerge(issueId, request = { kind: "normal" }) {
4055
4299
  error: error.message
4056
4300
  };
4057
4301
  } finally {
4058
- advanceQueue();
4302
+ if (!preserveQueue) advanceQueue();
4059
4303
  }
4060
4304
  }
4061
4305
  setMergeQueueTriggerHandler(triggerMerge);
@@ -4079,8 +4323,8 @@ const postForgeApproveRoute = HttpRouter.add("POST", "/api/issues/:issueId/forge
4079
4323
  if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
4080
4324
  if (!/^[A-Z]+-\d+$/i.test(issueId)) return jsonResponse({ error: "Invalid issue ID format" }, { status: 400 });
4081
4325
  return yield* Effect.promise(async () => {
4082
- const { getMergeSetSync, upsertMergeSetSync, withRepoArtifactUrlSync, withRepoStateSync } = await import("./merge-set-bUqbm3yc.js");
4083
- const { getForgeAdapter } = await import("./forge-DXnS_YFH.js");
4326
+ const { getMergeSetSync, upsertMergeSetSync, withRepoArtifactUrlSync, withRepoStateSync } = await import("./merge-set-DeUxFsC3.js");
4327
+ const { getForgeAdapter } = await import("./forge-B5o319qI.js");
4084
4328
  let mergeSet = getMergeSetSync(issueId);
4085
4329
  if (!mergeSet) return jsonResponse({ error: `No merge set found for ${issueId}` }, { status: 404 });
4086
4330
  const results = [];
@@ -4141,7 +4385,7 @@ const postForgeApproveRoute = HttpRouter.add("POST", "/api/issues/:issueId/forge
4141
4385
  }
4142
4386
  }
4143
4387
  if (results.filter((r) => r.approved).length > 0) {
4144
- const { emitActivityEntrySync, emitActivityTtsSync } = await import("./activity-logger-OEUBdfZ8.js");
4388
+ const { emitActivityEntrySync, emitActivityTtsSync } = await import("./activity-logger-CMthG6Vd.js");
4145
4389
  emitActivityEntrySync({
4146
4390
  source: "dashboard",
4147
4391
  level: "success",
@@ -4168,8 +4412,9 @@ const postForgeMergeRoute = HttpRouter.add("POST", "/api/issues/:issueId/forge-m
4168
4412
  if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
4169
4413
  if (!/^[A-Z]+-\d+$/i.test(issueId)) return jsonResponse({ error: "Invalid issue ID format" }, { status: 400 });
4170
4414
  return yield* Effect.promise(async () => {
4171
- const { getMergeSetSync, upsertMergeSetSync, withRepoArtifactUrlSync, withRepoStateSync } = await import("./merge-set-bUqbm3yc.js");
4172
- const { getForgeAdapter } = await import("./forge-DXnS_YFH.js");
4415
+ const { getMergeSetSync, upsertMergeSetSync, withRepoArtifactUrlSync, withRepoStateSync } = await import("./merge-set-DeUxFsC3.js");
4416
+ const { getForgeAdapter } = await import("./forge-B5o319qI.js");
4417
+ const { assessRepoMergeCompleteness } = await import("./merge-completeness-BLbB5-6n.js");
4173
4418
  let mergeSet = getMergeSetSync(issueId);
4174
4419
  if (!mergeSet) return jsonResponse({ error: `No merge set found for ${issueId}` }, { status: 404 });
4175
4420
  const results = [];
@@ -4185,34 +4430,44 @@ const postForgeMergeRoute = HttpRouter.add("POST", "/api/issues/:issueId/forge-m
4185
4430
  const workspacePath = mergeSet.workspaceType === "polyrepo" ? join(mergeSet.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`, repo.repoKey) : join(mergeSet.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
4186
4431
  let artifactUrl = repo.artifactUrl;
4187
4432
  let artifactId = repo.artifactId;
4188
- if (!artifactUrl && !artifactId) try {
4189
- const discovered = await adapter.discoverArtifact({
4190
- sourceBranch: repo.sourceBranch,
4191
- cwd: existsSync$1(workspacePath) ? workspacePath : repo.repoPath
4192
- });
4193
- if (discovered?.url || discovered?.id) {
4194
- artifactUrl = discovered.url;
4195
- artifactId = discovered.id;
4433
+ if (!artifactUrl && !artifactId) {
4434
+ try {
4435
+ const discovered = await adapter.discoverArtifact({
4436
+ sourceBranch: repo.sourceBranch,
4437
+ cwd: existsSync$1(workspacePath) ? workspacePath : repo.repoPath
4438
+ });
4439
+ artifactUrl = discovered?.url;
4440
+ artifactId = discovered?.id;
4441
+ } catch {}
4442
+ if (artifactUrl || artifactId) {
4196
4443
  mergeSet = withRepoArtifactUrlSync(mergeSet, repo.repoKey, artifactUrl ?? "", artifactId);
4197
4444
  upsertMergeSetSync(mergeSet);
4198
4445
  console.log(`[forge-merge] Discovered artifact for ${issueId}/${repo.repoKey}: ${artifactUrl}`);
4199
4446
  } else {
4200
- mergeSet = withRepoStateSync(mergeSet, repo.repoKey, { mergeStatus: "skipped" });
4447
+ const classification = await assessRepoMergeCompleteness(repo);
4448
+ if (classification.state === "merged") {
4449
+ mergeSet = withRepoStateSync(mergeSet, repo.repoKey, { mergeStatus: "merged" });
4450
+ results.push({
4451
+ repoKey: repo.repoKey,
4452
+ merged: true
4453
+ });
4454
+ } else if (classification.state === "no-changes") {
4455
+ mergeSet = withRepoStateSync(mergeSet, repo.repoKey, { mergeStatus: "skipped" });
4456
+ results.push({
4457
+ repoKey: repo.repoKey,
4458
+ merged: true
4459
+ });
4460
+ } else {
4461
+ mergeSet = withRepoStateSync(mergeSet, repo.repoKey, { mergeStatus: "blocked" });
4462
+ results.push({
4463
+ repoKey: repo.repoKey,
4464
+ merged: false,
4465
+ error: classification.reason
4466
+ });
4467
+ }
4201
4468
  upsertMergeSetSync(mergeSet);
4202
- results.push({
4203
- repoKey: repo.repoKey,
4204
- merged: true
4205
- });
4206
4469
  continue;
4207
4470
  }
4208
- } catch {
4209
- mergeSet = withRepoStateSync(mergeSet, repo.repoKey, { mergeStatus: "skipped" });
4210
- upsertMergeSetSync(mergeSet);
4211
- results.push({
4212
- repoKey: repo.repoKey,
4213
- merged: true
4214
- });
4215
- continue;
4216
4471
  }
4217
4472
  try {
4218
4473
  await adapter.mergeReviewArtifact({
@@ -4237,7 +4492,7 @@ const postForgeMergeRoute = HttpRouter.add("POST", "/api/issues/:issueId/forge-m
4237
4492
  }
4238
4493
  }
4239
4494
  if (results.filter((r) => r.merged).length > 0) {
4240
- const { emitActivityEntrySync, emitActivityTtsSync } = await import("./activity-logger-OEUBdfZ8.js");
4495
+ const { emitActivityEntrySync, emitActivityTtsSync } = await import("./activity-logger-CMthG6Vd.js");
4241
4496
  emitActivityEntrySync({
4242
4497
  source: "dashboard",
4243
4498
  level: "success",
@@ -4362,7 +4617,7 @@ const postWorkspaceApproveRoute = HttpRouter.add("POST", "/api/issues/:issueId/a
4362
4617
  console.log(`[approve] Starting role pipeline for ${issueId}...`);
4363
4618
  let reviewResult;
4364
4619
  try {
4365
- const { spawnReviewRoleForIssue } = await import("./review-agent-DNboMyW4.js");
4620
+ const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
4366
4621
  reviewResult = await Effect.runPromise(spawnReviewRoleForIssue({
4367
4622
  issueId,
4368
4623
  workspace: workspacePath,
@@ -4409,7 +4664,7 @@ const postWorkspaceApproveRoute = HttpRouter.add("POST", "/api/issues/:issueId/a
4409
4664
  }
4410
4665
  console.log(`[approve] Step 3/3: Running server-side rebase for ${issueId}...`);
4411
4666
  try {
4412
- const { rebaseFeatureBranch } = await import("./merge-rebase-BfaTyXsw.js");
4667
+ const { rebaseFeatureBranch } = await import("./merge-rebase-CJJVAJuz.js");
4413
4668
  const workspacePathForRebase = join(projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
4414
4669
  const rebaseResult = await Effect.runPromise(rebaseFeatureBranch(workspacePathForRebase, branchName, "main", issueId));
4415
4670
  if (!rebaseResult.success) {
@@ -4429,7 +4684,7 @@ const postWorkspaceApproveRoute = HttpRouter.add("POST", "/api/issues/:issueId/a
4429
4684
  completePendingOperation(issueId, pushResult.error);
4430
4685
  return jsonResponse({ error: pushResult.error }, { status: pushResult.httpStatus });
4431
4686
  }
4432
- const { approve: lifecycleApprove } = await import("./lifecycle-xmBfK2GJ.js");
4687
+ const { approve: lifecycleApprove } = await import("./lifecycle-B3s4sM1G.js");
4433
4688
  const ghResolved = resolveGitHubIssueSync(issueId);
4434
4689
  const isGitHubIssueFlag = ghResolved.isGitHub;
4435
4690
  const lifecycleCtx = {
@@ -4463,7 +4718,7 @@ const getMergeQueueRoute = HttpRouter.add("GET", "/api/merge-queue", httpHandler
4463
4718
  })));
4464
4719
  const postInternalPipelineNotifyRoute = HttpRouter.add("POST", "/api/internal/pipeline/notify", httpHandler(Effect.gen(function* () {
4465
4720
  const request = yield* HttpServerRequest.HttpServerRequest;
4466
- const { INTERNAL_TOKEN_HEADER, getInternalTokenSync } = yield* Effect.promise(() => import("./internal-token-BrcU6qfe.js"));
4721
+ const { INTERNAL_TOKEN_HEADER, getInternalTokenSync } = yield* Effect.promise(() => import("./internal-token-Ias7N8Kg.js"));
4467
4722
  const expected = getInternalTokenSync();
4468
4723
  if (!expected) return jsonResponse({
4469
4724
  ok: false,
@@ -4477,7 +4732,7 @@ const postInternalPipelineNotifyRoute = HttpRouter.add("POST", "/api/internal/pi
4477
4732
  }, 403);
4478
4733
  const event = yield* readJsonBody;
4479
4734
  const type = event.type;
4480
- const { notifyPipelineSync } = yield* Effect.promise(() => import("./pipeline-notifier-BJr8gQX6.js"));
4735
+ const { notifyPipelineSync } = yield* Effect.promise(() => import("./pipeline-notifier-DT6xLFao.js"));
4481
4736
  switch (type) {
4482
4737
  case "status_changed": {
4483
4738
  const issueId = event.issueId;
@@ -4645,7 +4900,7 @@ init_types$1();
4645
4900
  init_review_context();
4646
4901
  init_tldr_daemon();
4647
4902
  const execAsync$4 = promisify(exec);
4648
- const execFileAsync$2 = promisify(execFile);
4903
+ const execFileAsync$3 = promisify(execFile);
4649
4904
  function getWorkspaceLocation(issueId) {
4650
4905
  try {
4651
4906
  const meta = loadWorkspaceMetadataSync(issueId);
@@ -4704,7 +4959,7 @@ async function getRepoGitStatusAsync(workspacePath) {
4704
4959
  }
4705
4960
  async function getMrUrlAsync(issueId, workspacePath) {
4706
4961
  try {
4707
- const { stdout } = await execFileAsync$2("gh", [
4962
+ const { stdout } = await execFileAsync$3("gh", [
4708
4963
  "pr",
4709
4964
  "view",
4710
4965
  `feature/${issueId.toLowerCase()}`,
@@ -5252,7 +5507,7 @@ const patchWorkspaceTieredExecutionRoute = HttpRouter.add("PATCH", "/api/workspa
5252
5507
  if (override !== "on" && override !== "off" && override !== null && override !== void 0) return jsonResponse({ error: "Invalid tiered-execution override" }, { status: 400 });
5253
5508
  const project = getProjectSync(extractPrefixSync(issueId) ?? issueId.split("-")[0]);
5254
5509
  if (!project) return jsonResponse({ error: "Project not found" }, { status: 404 });
5255
- yield* Effect.promise(() => import("./record-CN0pj4_5.js").then((m) => m.writeRecordTieredExecutionOverride(project, issueId, override)));
5510
+ yield* Effect.promise(() => import("./record-BTwWhtBb.js").then((m) => m.writeRecordTieredExecutionOverride(project, issueId, override)));
5256
5511
  const projectPath = project.path;
5257
5512
  const location = yield* resolvePlanLocation(projectPath, issueId);
5258
5513
  if (!location) return jsonResponse({ error: "No xBRIEF plan found for this workspace" }, { status: 404 });
@@ -5540,6 +5795,48 @@ const postWorkspaceCleanRoute = HttpRouter.add("POST", "/api/workspaces/:issueId
5540
5795
  })));
5541
5796
  const stashCleanRouteLayer = Layer.mergeAll(getWorkspaceStashesRoute, postWorkspaceRecoverStashRoute, deleteWorkspaceStashRoute, getWorkspaceCleanPreviewRoute, postWorkspaceCleanRoute);
5542
5797
  //#endregion
5798
+ //#region ../../lib/cloister/review-branch-push.ts
5799
+ init_project_repos();
5800
+ const execFileAsync$2 = promisify(execFile);
5801
+ const REVIEW_PUSH_TIMEOUT_MS = 3e4;
5802
+ async function runReviewGit(args, options) {
5803
+ await execFileAsync$2("git", args, options);
5804
+ }
5805
+ function reviewGitOptions(cwd) {
5806
+ return {
5807
+ cwd,
5808
+ timeout: REVIEW_PUSH_TIMEOUT_MS,
5809
+ killSignal: "SIGKILL",
5810
+ env: {
5811
+ ...process.env,
5812
+ GIT_TERMINAL_PROMPT: "0",
5813
+ GIT_ASKPASS: "true",
5814
+ SSH_ASKPASS: "true"
5815
+ }
5816
+ };
5817
+ }
5818
+ async function pushLocalReviewBranches(issueId, workspacePath, dependencies = {}) {
5819
+ const roots = (dependencies.resolveRoots ?? resolveWorkspaceRepoRootsSync)(issueId, workspacePath);
5820
+ const runGit = dependencies.runGit ?? runReviewGit;
5821
+ for (const root of roots) {
5822
+ try {
5823
+ await runGit([
5824
+ "rev-parse",
5825
+ "--verify",
5826
+ "--quiet",
5827
+ `refs/heads/${root.sourceBranch}`
5828
+ ], reviewGitOptions(root.dir));
5829
+ } catch {
5830
+ continue;
5831
+ }
5832
+ await runGit([
5833
+ "push",
5834
+ "origin",
5835
+ root.sourceBranch
5836
+ ], reviewGitOptions(root.dir));
5837
+ }
5838
+ }
5839
+ //#endregion
5543
5840
  //#region ../../lib/cloister/request-review-pipeline.ts
5544
5841
  init_in_flight_guard();
5545
5842
  /**
@@ -5560,6 +5857,10 @@ function createRequestReviewPipeline() {
5560
5857
  await deps.onVerificationError(outcome);
5561
5858
  return;
5562
5859
  }
5860
+ if (outcome.outcome === "deferred") {
5861
+ await deps.onVerificationDeferred?.(outcome);
5862
+ return;
5863
+ }
5563
5864
  await deps.pushBranch();
5564
5865
  await deps.dispatchReview();
5565
5866
  }, deps.onError);
@@ -5569,6 +5870,92 @@ function createRequestReviewPipeline() {
5569
5870
  }
5570
5871
  };
5571
5872
  }
5873
+ /** Shared host-side pipeline so HTTP requests and durable intent recovery coalesce. */
5874
+ const requestReviewPipeline = createRequestReviewPipeline();
5875
+ //#endregion
5876
+ //#region services/durable-review-pipeline.ts
5877
+ init_durable_review_pipeline();
5878
+ init_projects();
5879
+ async function startDashboardDurableReviewPipeline(input, dependencies) {
5880
+ const { issueId, prUrl, setReviewPending, dispatchReview } = input;
5881
+ const resolved = dependencies.resolveWorkspace(issueId);
5882
+ if (!resolved) return false;
5883
+ const { workspacePath, workspaceInfo, branchName } = resolved;
5884
+ return requestReviewPipeline.start(issueId, {
5885
+ verify: () => dependencies.verify ? dependencies.verify(issueId, workspacePath, workspaceInfo) : Effect.runPromise(runVerificationForIssue(issueId, workspacePath, workspaceInfo, "durable-review")),
5886
+ onVerificationFailed: (outcome) => {
5887
+ setReviewPending({
5888
+ reviewStatus: "pending",
5889
+ reviewNotes: `Verification failed at ${outcome.failedCheck} — fix and resubmit`
5890
+ });
5891
+ },
5892
+ onVerificationError: (outcome) => {
5893
+ setReviewPending({
5894
+ reviewStatus: "pending",
5895
+ reviewNotes: `Verification infrastructure error: ${outcome.message}`
5896
+ });
5897
+ },
5898
+ onVerificationDeferred: (outcome) => {
5899
+ setReviewPending({
5900
+ reviewStatus: "pending",
5901
+ reviewNotes: outcome.reason
5902
+ });
5903
+ console.log(`[review-status] durable review verification deferred for ${issueId}: ${outcome.reason}`);
5904
+ },
5905
+ pushBranch: () => dependencies.pushBranch(resolved),
5906
+ dispatchReview: async () => {
5907
+ const result = await dispatchReview({
5908
+ issueId,
5909
+ workspace: workspacePath,
5910
+ branch: branchName,
5911
+ ...prUrl ? { prUrl } : {}
5912
+ });
5913
+ if (!result.success) {
5914
+ setReviewPending({
5915
+ reviewStatus: "pending",
5916
+ reviewNotes: result.error || result.message || "Failed to dispatch review"
5917
+ });
5918
+ return;
5919
+ }
5920
+ const message = result.message?.startsWith("Review already in progress") ? "already in progress — no-op" : "auto-dispatched from durable journal intent";
5921
+ console.log(`[review-status] review dispatch for ${issueId}: ${message} (host-side)`);
5922
+ },
5923
+ onError: (error) => {
5924
+ const detail = error instanceof Error ? error.message : String(error);
5925
+ setReviewPending({
5926
+ reviewStatus: "pending",
5927
+ reviewNotes: `Review pipeline error: ${detail}`
5928
+ });
5929
+ console.warn(`[review-status] host-side durable review pipeline for ${issueId} failed (non-fatal): ${detail}`);
5930
+ }
5931
+ });
5932
+ }
5933
+ async function pushDashboardReviewBranch(workspace, dependencies) {
5934
+ if (workspace.workspaceInfo.isRemote && workspace.workspaceInfo.vmName) {
5935
+ await dependencies.pushRemote(workspace.workspaceInfo.vmName, workspace.workspacePath, workspace.branchName);
5936
+ return;
5937
+ }
5938
+ await pushLocalReviewBranches(workspace.issueId, workspace.workspacePath);
5939
+ }
5940
+ function registerDashboardDurableReviewPipeline(dependencies) {
5941
+ registerDurableReviewPipelineHandler((input) => startDashboardDurableReviewPipeline(input, {
5942
+ resolveWorkspace: (issueId) => {
5943
+ const workspaceInfo = dependencies.getWorkspaceInfo(issueId);
5944
+ if (!workspaceInfo.exists) return null;
5945
+ const resolved = resolveProjectFromIssueSync(issueId);
5946
+ if (!resolved) return null;
5947
+ const workspacePath = workspaceInfo.isRemote ? workspaceInfo.remotePath : workspaceInfo.localPath || join(resolved.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
5948
+ if (!workspacePath) return null;
5949
+ return {
5950
+ issueId,
5951
+ workspacePath,
5952
+ workspaceInfo,
5953
+ branchName: `feature/${issueId.toLowerCase()}`
5954
+ };
5955
+ },
5956
+ pushBranch: (workspace) => pushDashboardReviewBranch(workspace, dependencies)
5957
+ }));
5958
+ }
5572
5959
  //#endregion
5573
5960
  //#region routes/workspaces/review-pipeline.ts
5574
5961
  /**
@@ -5596,7 +5983,16 @@ init_conflict_gate();
5596
5983
  init_agents();
5597
5984
  const execAsync$2 = promisify(exec);
5598
5985
  const MAX_AUTO_REQUEUE = 25;
5599
- const requestReviewPipeline = createRequestReviewPipeline();
5986
+ const pushRemoteReviewBranch = async (vmName, workspacePath, branchName) => {
5987
+ await execAsync$2(flyExecCmd(vmName, `cd ${workspacePath} && GIT_TERMINAL_PROMPT=0 GIT_ASKPASS=true SSH_ASKPASS=true git push origin ${branchName}`), {
5988
+ encoding: "utf-8",
5989
+ timeout: 3e4
5990
+ });
5991
+ };
5992
+ registerDashboardDurableReviewPipeline({
5993
+ getWorkspaceInfo: getWorkspaceInfoForIssue,
5994
+ pushRemote: pushRemoteReviewBranch
5995
+ });
5600
5996
  /** Safe `.message` read for caught values of unknown shape. */
5601
5997
  const errorMessage = (e) => e instanceof Error ? e.message : void 0;
5602
5998
  /**
@@ -5610,21 +6006,7 @@ const errorMessage = (e) => e instanceof Error ? e.message : void 0;
5610
6006
  * the workspace path, preserving the previous behavior.
5611
6007
  */
5612
6008
  async function pushFeatureBranches(issueId, workspacePath) {
5613
- const { resolveWorkspaceRepoRootsSync } = await import("./project-repos-DXKQsc_m.js");
5614
- for (const root of resolveWorkspaceRepoRootsSync(issueId, workspacePath)) {
5615
- try {
5616
- await execAsync$2(`git rev-parse --verify --quiet refs/heads/${root.sourceBranch}`, {
5617
- cwd: root.dir,
5618
- encoding: "utf-8"
5619
- });
5620
- } catch {
5621
- continue;
5622
- }
5623
- await execAsync$2(`git push origin ${root.sourceBranch}`, {
5624
- cwd: root.dir,
5625
- encoding: "utf-8"
5626
- });
5627
- }
6009
+ await pushLocalReviewBranches(issueId, workspacePath);
5628
6010
  }
5629
6011
  function shouldTreatAsRerun(status) {
5630
6012
  if (!status) return false;
@@ -5742,7 +6124,7 @@ const postWorkspaceReviewRoute = HttpRouter.add("POST", "/api/review/:issueId/tr
5742
6124
  console.log(`Feature branch push note: ${errorMessage(pushErr)}`);
5743
6125
  }
5744
6126
  try {
5745
- const { createReviewArtifactsForIssue } = await import("./review-artifacts-nRDPuMxd.js");
6127
+ const { createReviewArtifactsForIssue } = await import("./review-artifacts-BNmw8dWE.js");
5746
6128
  const artifactResult = await Effect.runPromise(createReviewArtifactsForIssue(issueId, workspacePath));
5747
6129
  const primaryArtifact = artifactResult.mergeSet?.repos.find((repo) => !!repo.artifactUrl);
5748
6130
  artifactResult.mergeSet?.repos.find((repo) => repo.mergeStatus !== "skipped")?.targetBranch;
@@ -5797,7 +6179,12 @@ const postWorkspaceReviewRoute = HttpRouter.add("POST", "/api/review/:issueId/tr
5797
6179
  } catch {}
5798
6180
  return;
5799
6181
  }
5800
- const { spawnReviewRoleForIssue } = await import("./review-agent-DNboMyW4.js");
6182
+ if (verifyOutcome.outcome === "deferred") {
6183
+ console.log(`[review] Verification deferred for ${issueId}: ${verifyOutcome.reason}`);
6184
+ completePendingOperation(issueId, verifyOutcome.reason);
6185
+ return;
6186
+ }
6187
+ const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
5801
6188
  const prUrl = getReviewStatusSync(issueId)?.prUrl;
5802
6189
  const reviewResult = await Effect.runPromise(spawnReviewRoleForIssue({
5803
6190
  issueId,
@@ -5933,7 +6320,7 @@ const postWorkspaceRequestReviewRoute = HttpRouter.add("POST", "/api/review/:iss
5933
6320
  console.log(`[request-review] Feature branch push note: ${errorMessage(pushErr)}`);
5934
6321
  }
5935
6322
  const prUrl = getReviewStatusSync(issueId)?.prUrl;
5936
- const { spawnReviewRoleForIssue } = await import("./review-agent-DNboMyW4.js");
6323
+ const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
5937
6324
  const result = await Effect.runPromise(spawnReviewRoleForIssue({
5938
6325
  issueId,
5939
6326
  workspace: workspacePathRerun,
@@ -5983,7 +6370,7 @@ const postWorkspaceRequestReviewRoute = HttpRouter.add("POST", "/api/review/:iss
5983
6370
  });
5984
6371
  } else {
5985
6372
  const workspacePath = join(resolved.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
5986
- const { spawnRun } = yield* Effect.promise(() => import("./agents-wi9NWzs2.js"));
6373
+ const { spawnRun } = yield* Effect.promise(() => import("./agents-ePFVoZbu.js"));
5987
6374
  try {
5988
6375
  const testRun = yield* Effect.promise(() => spawnRun(issueId, "test", { workspace: workspacePath }));
5989
6376
  setReviewStatus(issueId, { testStatus: "testing" });
@@ -6060,6 +6447,7 @@ const postWorkspaceRequestReviewRoute = HttpRouter.add("POST", "/api/review/:iss
6060
6447
  verificationStatus: "pending",
6061
6448
  reviewNotes
6062
6449
  });
6450
+ clearFeedbackDeliveryStuck(canonicalIssueId);
6063
6451
  if (!requestReviewPipeline.start(canonicalIssueId, {
6064
6452
  verify: () => Effect.runPromise(runVerificationForIssue(issueId, workspacePath, workspaceInfo, "request-review")),
6065
6453
  onVerificationFailed: (outcome) => {
@@ -6078,9 +6466,17 @@ const postWorkspaceRequestReviewRoute = HttpRouter.add("POST", "/api/review/:iss
6078
6466
  autoRequeueCount: currentCount
6079
6467
  });
6080
6468
  },
6469
+ onVerificationDeferred: (outcome) => {
6470
+ console.log(`[request-review] Verification deferred for ${issueId}: ${outcome.reason}`);
6471
+ completePendingOperation(issueId, outcome.reason);
6472
+ },
6081
6473
  pushBranch: async () => {
6082
- if (workspaceInfo.isRemote && workspaceInfo.vmName) await execAsync$2(flyExecCmd(workspaceInfo.vmName, `cd ${workspacePath} && git push origin ${branchName}`), { encoding: "utf-8" });
6083
- else await pushFeatureBranches(issueId, workspacePath);
6474
+ await pushDashboardReviewBranch({
6475
+ issueId,
6476
+ workspacePath,
6477
+ workspaceInfo,
6478
+ branchName
6479
+ }, { pushRemote: pushRemoteReviewBranch });
6084
6480
  console.log(`[request-review] Pushed verified branch ${branchName} for ${issueId}`);
6085
6481
  },
6086
6482
  dispatchReview: async () => {
@@ -6089,7 +6485,7 @@ const postWorkspaceRequestReviewRoute = HttpRouter.add("POST", "/api/review/:iss
6089
6485
  testStatus: "pending",
6090
6486
  reviewNotes
6091
6487
  });
6092
- const { spawnReviewRoleForIssue } = await import("./review-agent-DNboMyW4.js");
6488
+ const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
6093
6489
  const result = await Effect.runPromise(spawnReviewRoleForIssue({
6094
6490
  issueId,
6095
6491
  workspace: workspacePath,
@@ -6176,12 +6572,12 @@ const reviewPipelineRouteLayer = Layer.mergeAll(postWorkspaceReviewRoute, postWo
6176
6572
  * stay owned by ../workspaces.js.
6177
6573
  */
6178
6574
  init_issue_id();
6179
- init_archive_planning();
6180
6575
  init_projects();
6181
6576
  init_review_status();
6182
6577
  init_agents();
6183
6578
  init_model_validation();
6184
6579
  init_config_yaml();
6580
+ init_pipeline_notifier();
6185
6581
  const execAsync$1 = promisify(exec);
6186
6582
  function resolveConfiguredReviewModel() {
6187
6583
  try {
@@ -6191,6 +6587,32 @@ function resolveConfiguredReviewModel() {
6191
6587
  }
6192
6588
  }
6193
6589
  /**
6590
+ * Read and re-emit canonical review status without mutating it. This is the
6591
+ * operator escape hatch for PAN-2988-style lost review.status_changed events.
6592
+ */
6593
+ function processResyncReviewStatus(issueId) {
6594
+ const status = getReviewStatusSync(issueId);
6595
+ if (!status) return {
6596
+ httpStatus: 404,
6597
+ body: {
6598
+ ok: false,
6599
+ error: `no review status found for ${issueId}`
6600
+ }
6601
+ };
6602
+ notifyPipelineSync({
6603
+ type: "status_changed",
6604
+ issueId,
6605
+ status
6606
+ });
6607
+ return {
6608
+ httpStatus: 200,
6609
+ body: {
6610
+ ok: true,
6611
+ status
6612
+ }
6613
+ };
6614
+ }
6615
+ /**
6194
6616
  * Core logic for POST /api/review/:issueId/reset (synchronous, testable).
6195
6617
  *
6196
6618
  * Resets the specialist pipeline state (review / test / merge / verification) for
@@ -6338,7 +6760,8 @@ function processUnstickRequest(issueId, workspaceExists, currentStatus, gitRepai
6338
6760
  stuckDetails: void 0,
6339
6761
  reviewedAtCommit: void 0,
6340
6762
  reviewRetryCount: 0,
6341
- recoveryStartedAt: void 0
6763
+ recoveryStartedAt: void 0,
6764
+ ...currentStatus.stuckReason === "review-not-converging" && { reviewCycleHistory: void 0 }
6342
6765
  });
6343
6766
  console.log(`[unstick] Cleared stuck flag and reset lifecycle for ${issueId} (was: ${currentStatus.stuckReason ?? "unknown"})`);
6344
6767
  return {
@@ -6398,7 +6821,7 @@ const postWorkspaceResetReviewRoute = HttpRouter.add("POST", "/api/review/:issue
6398
6821
  const result = processResetReviewPipeline(issueId, resetWorkspace.exists);
6399
6822
  if (result.httpStatus !== 200) return jsonResponse(result.body, { status: result.httpStatus });
6400
6823
  try {
6401
- const { resetPostMergeState } = yield* Effect.promise(() => import("./merge-agent-CKkgIBPB.js"));
6824
+ const { resetPostMergeState } = yield* Effect.promise(() => import("./merge-agent-DQTXZk8z.js"));
6402
6825
  resetPostMergeState(issueId);
6403
6826
  } catch (err) {
6404
6827
  console.warn(`[reset-review] resetPostMergeState best-effort failed for ${issueId}:`, err);
@@ -6407,7 +6830,7 @@ const postWorkspaceResetReviewRoute = HttpRouter.add("POST", "/api/review/:issue
6407
6830
  const rerun = body?.rerun === true;
6408
6831
  if (rerun) try {
6409
6832
  yield* Effect.promise(async () => {
6410
- const { spawnReviewRoleForIssue } = await import("./review-agent-DNboMyW4.js");
6833
+ const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
6411
6834
  const dispatchArgs = buildReviewRedispatchArgs(issueId, resetWorkspace, workspaceInfo, resolved);
6412
6835
  if (dispatchArgs) {
6413
6836
  const result = await Effect.runPromise(spawnReviewRoleForIssue({
@@ -6433,10 +6856,16 @@ const postWorkspaceResetReviewRoute = HttpRouter.add("POST", "/api/review/:issue
6433
6856
  rerun
6434
6857
  });
6435
6858
  })));
6859
+ const postReviewResyncRoute = HttpRouter.add("POST", "/api/review/:issueId/resync", httpHandler(Effect.gen(function* () {
6860
+ const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
6861
+ if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
6862
+ const result = processResyncReviewStatus(issueId.toUpperCase());
6863
+ return jsonResponse(result.body, { status: result.httpStatus });
6864
+ })));
6436
6865
  const postWorkspaceReviewPurgeRoute = HttpRouter.add("POST", "/api/review/:issueId/purge", httpHandler(Effect.gen(function* () {
6437
6866
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
6438
6867
  if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
6439
- const { purgeReviewAgentsForIssue } = yield* Effect.promise(() => import("./review-agent-DNboMyW4.js"));
6868
+ const { purgeReviewAgentsForIssue } = yield* Effect.promise(() => import("./review-agent-BTCNkq2h.js"));
6440
6869
  const projectKey = resolveProjectFromIssueSync(issueId)?.projectKey;
6441
6870
  const purge = yield* Effect.promise(() => purgeReviewAgentsForIssue(projectKey, issueId));
6442
6871
  const workspaceInfo = getWorkspaceInfoForIssue(issueId);
@@ -6466,8 +6895,8 @@ const postWorkspaceAbortReviewRoute = HttpRouter.add("POST", "/api/review/:issue
6466
6895
  success: false,
6467
6896
  error: "Workspace does not exist"
6468
6897
  }, { status: 400 });
6469
- const { resolveProjectFromIssueSync } = yield* Effect.promise(() => import("./projects-vjjcmiN8.js"));
6470
- const { killAllReviewerSessions } = yield* Effect.promise(() => import("./review-agent-DNboMyW4.js"));
6898
+ const { resolveProjectFromIssueSync } = yield* Effect.promise(() => import("./projects-_n3Zui6K.js"));
6899
+ const { killAllReviewerSessions } = yield* Effect.promise(() => import("./review-agent-BTCNkq2h.js"));
6471
6900
  const { killed, failed } = yield* killAllReviewerSessions(resolveProjectFromIssueSync(issueId)?.projectKey, issueId);
6472
6901
  setReviewStatus(issueId, {
6473
6902
  reviewStatus: "pending",
@@ -6539,8 +6968,8 @@ const getReviewConfigRoute = HttpRouter.add("GET", "/api/review/:issueId/config"
6539
6968
  const issueId = ((yield* HttpRouter.params)["issueId"] ?? "").toUpperCase();
6540
6969
  if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
6541
6970
  return jsonResponse(yield* Effect.promise(async () => {
6542
- const { readIssueRecordSync, resolveProjectForIssue } = await import("./record-CN0pj4_5.js");
6543
- const { resolveReviewMode, resolveReReviewScope } = await import("./review-agent-DNboMyW4.js");
6971
+ const { readIssueRecordSync, resolveProjectForIssue } = await import("./record-BTwWhtBb.js");
6972
+ const { resolveReviewMode, resolveReReviewScope } = await import("./review-agent-BTCNkq2h.js");
6544
6973
  const project = resolveProjectForIssue(issueId);
6545
6974
  const record = project ? readIssueRecordSync(project, issueId) : null;
6546
6975
  return {
@@ -6575,9 +7004,9 @@ const postReviewConfigRoute = HttpRouter.add("POST", "/api/review/:issueId/confi
6575
7004
  return jsonResponse({ error: error instanceof Error ? error.message : String(error) }, { status: 400 });
6576
7005
  }
6577
7006
  return jsonResponse(yield* Effect.promise(async () => {
6578
- const { resolveProjectForIssue } = await import("./record-CN0pj4_5.js");
6579
- const { updateIssueRecord } = await import("./record-update-bLJxAXH4.js");
6580
- const { resolveReviewMode, resolveReReviewScope } = await import("./review-agent-DNboMyW4.js");
7007
+ const { resolveProjectForIssue } = await import("./record-BTwWhtBb.js");
7008
+ const { updateIssueRecord } = await import("./record-update-DhI7eySG.js");
7009
+ const { resolveReviewMode, resolveReReviewScope } = await import("./review-agent-BTCNkq2h.js");
6581
7010
  const record = await updateIssueRecord(resolveProjectForIssue(issueId), issueId, (current) => {
6582
7011
  if (hasMode) if (body.reviewMode === null) delete current.reviewMode;
6583
7012
  else current.reviewMode = body.reviewMode;
@@ -6602,7 +7031,7 @@ const postReviewConfigRoute = HttpRouter.add("POST", "/api/review/:issueId/confi
6602
7031
  };
6603
7032
  }));
6604
7033
  })));
6605
- const reviewControlRouteLayer = Layer.mergeAll(postWorkspaceResetReviewRoute, postWorkspaceReviewPurgeRoute, postWorkspaceAbortReviewRoute, postWorkspaceUnstickRoute, postWorkspaceDeaconIgnoreRoute, postWorkspaceAutoMergeRoute, deleteWorkspacePendingRoute, getReviewConfigRoute, postReviewConfigRoute);
7034
+ const reviewControlRouteLayer = Layer.mergeAll(postWorkspaceResetReviewRoute, postReviewResyncRoute, postWorkspaceReviewPurgeRoute, postWorkspaceAbortReviewRoute, postWorkspaceUnstickRoute, postWorkspaceDeaconIgnoreRoute, postWorkspaceAutoMergeRoute, deleteWorkspacePendingRoute, getReviewConfigRoute, postReviewConfigRoute);
6606
7035
  //#endregion
6607
7036
  //#region routes/workspaces/uat-stack-actions.ts
6608
7037
  init_activity_logger();
@@ -7010,7 +7439,7 @@ async function readWorkspacePlanningMarkdown(issueId, fileName) {
7010
7439
  */
7011
7440
  async function readWorkspaceContinueFile(_projectPath, workspacePath, issueId) {
7012
7441
  try {
7013
- const { readRecordContinueViewSync, getProjectConfigFromWorkspacePath, resolveProjectForIssue } = await import("./record-CN0pj4_5.js");
7442
+ const { readRecordContinueViewSync, getProjectConfigFromWorkspacePath, resolveProjectForIssue } = await import("./record-BTwWhtBb.js");
7014
7443
  const recordView = readRecordContinueViewSync(resolveProjectForIssue(issueId) ?? getProjectConfigFromWorkspacePath(workspacePath), issueId);
7015
7444
  return recordView ? JSON.stringify(recordView, null, 2) : null;
7016
7445
  } catch {
@@ -7208,7 +7637,11 @@ function spawnPanCommand(args, description, cwd, options) {
7208
7637
  "ignore",
7209
7638
  "pipe",
7210
7639
  "pipe"
7211
- ]
7640
+ ],
7641
+ env: {
7642
+ ...process.env,
7643
+ ...options?.env
7644
+ }
7212
7645
  });
7213
7646
  attachPanOutputStreams(child, activityId);
7214
7647
  child.on("close", (code) => {
@@ -7227,7 +7660,11 @@ function spawnPanCommand(args, description, cwd, options) {
7227
7660
  "ignore",
7228
7661
  "pipe",
7229
7662
  "pipe"
7230
- ]
7663
+ ],
7664
+ env: {
7665
+ ...process.env,
7666
+ ...options?.env
7667
+ }
7231
7668
  });
7232
7669
  attachPanOutputStreams(next, activityId);
7233
7670
  next.on("close", (nextCode) => finalize(nextCode, `pan ${chain.args.join(" ")}`));
@@ -7525,7 +7962,16 @@ const postWorkspaceRebuildRoute = HttpRouter.add("POST", "/api/workspaces/:issue
7525
7962
  });
7526
7963
  })));
7527
7964
  const postWorkspaceRebuildAndStartRoute = HttpRouter.add("POST", "/api/workspaces/:issueId/rebuild-and-start", httpHandler(Effect.gen(function* () {
7965
+ const request = yield* HttpServerRequest.HttpServerRequest;
7528
7966
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
7967
+ const body = yield* readJsonBody;
7968
+ const internalRequest = yield* Effect.promise(() => isInternalAgentRequest(request));
7969
+ let startedBy;
7970
+ try {
7971
+ startedBy = resolveRequestedStartedBy(body?.startedBy, internalRequest);
7972
+ } catch (error) {
7973
+ return jsonResponse({ error: error instanceof Error ? error.message : String(error) }, { status: 400 });
7974
+ }
7529
7975
  if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
7530
7976
  const projectPath = getProjectPath(void 0, extractPrefixSync(issueId) ?? issueId.split("-")[0]);
7531
7977
  const activityId = spawnPanCommand([
@@ -7538,6 +7984,10 @@ const postWorkspaceRebuildAndStartRoute = HttpRouter.add("POST", "/api/workspace
7538
7984
  chainOnSuccess: {
7539
7985
  args: ["start", issueId],
7540
7986
  phaseLabel: `Stack rebuilt — starting agent for ${issueId.toUpperCase()}`
7987
+ },
7988
+ env: {
7989
+ OVERDECK_AGENT_STARTED_BY: startedBy,
7990
+ OVERDECK_AUTO_SPAWN_CONSENT_REQUIRED: internalRequest && body?.autoSpawnConsentRequired === true ? "1" : "0"
7541
7991
  }
7542
7992
  });
7543
7993
  return jsonResponse({
@@ -7769,7 +8219,7 @@ const getWorkspaceReviewStatusRoute = HttpRouter.add("GET", "/api/review/:issueI
7769
8219
  if (queuePosition === null) try {
7770
8220
  const resolved = resolveProjectFromIssueSync(issueId);
7771
8221
  if (resolved) {
7772
- const { getQueueForProject } = yield* Effect.promise(() => import("./merge-B1DiziGU.js"));
8222
+ const { getQueueForProject } = yield* Effect.promise(() => import("./merge-sr8Nrnmi.js"));
7773
8223
  const mergePos = findPositionInQueueSync(issueId, getQueueForProject(resolved.projectKey).map((e) => ({
7774
8224
  id: String(e.id),
7775
8225
  type: "task",
@@ -7807,10 +8257,10 @@ const postWorkspaceReviewStatusRoute = HttpRouter.add("POST", "/api/review/:issu
7807
8257
  const workspaceInfo = getWorkspaceInfoForIssue(issueId);
7808
8258
  if (workspaceInfo.exists && workspaceInfo.localPath) {
7809
8259
  const localPath = workspaceInfo.localPath;
7810
- const { getWorkspaceGitInfo } = yield* Effect.promise(() => import("./git-utils-D0_yhCgF.js"));
8260
+ const { snapshotWorkspaceHeadsPromise } = yield* Effect.promise(() => import("./git-utils-Xg4PFN45.js"));
7811
8261
  try {
7812
- const gitInfo = yield* getWorkspaceGitInfo(localPath);
7813
- if (gitInfo.HEAD) update.reviewedAtCommit = gitInfo.HEAD;
8262
+ const headAnchor = yield* Effect.promise(() => snapshotWorkspaceHeadsPromise(issueId, localPath));
8263
+ if (headAnchor) update.reviewedAtCommit = headAnchor;
7814
8264
  } catch {}
7815
8265
  }
7816
8266
  }
@@ -7822,7 +8272,7 @@ const postWorkspaceReviewStatusRoute = HttpRouter.add("POST", "/api/review/:issu
7822
8272
  if (verificationStatus) update.verificationStatus = verificationStatus;
7823
8273
  if (readyForMerge !== void 0) update.readyForMerge = readyForMerge;
7824
8274
  const status = setReviewStatus(issueId, update);
7825
- const { getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8275
+ const { getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7826
8276
  const projectKey = resolveProjectFromIssueSync(issueId)?.projectKey;
7827
8277
  if (reviewStatus && [
7828
8278
  "passed",
@@ -7840,7 +8290,7 @@ const postWorkspaceReviewStatusRoute = HttpRouter.add("POST", "/api/review/:issu
7840
8290
  const agentId = `agent-${issueId.toLowerCase()}`;
7841
8291
  const feedbackBody = `CODE REVIEW ${reviewStatus.toUpperCase()} for ${issueId}:\n\n${reviewNotes}\n\n## REQUIRED: Fix ALL issues above, then invoke the /rebase-and-submit skill\n\n1. Read each blocking issue carefully\n2. Fix the code for EVERY issue listed\n3. Run tests locally to verify your fixes\n4. Commit every change\n5. Invoke the /rebase-and-submit skill for ${issueId} — this is an atomic task that runs pan done (which handles rebase + push + re-submit internally)\n\nDo NOT stop between steps. Do NOT run git push manually — the skill handles it. Do NOT stop until pan done has completed successfully.`;
7842
8292
  try {
7843
- const { writeFeedbackFile } = yield* Effect.promise(() => import("./feedback-writer-D3a22RCd.js"));
8293
+ const { writeFeedbackFile } = yield* Effect.promise(() => import("./feedback-writer-CoB9Z6aU.js"));
7844
8294
  const wsInfo = getWorkspaceInfoForIssue(issueId);
7845
8295
  const fileResult = yield* Effect.promise(() => writeFeedbackFile({
7846
8296
  issueId,
@@ -7904,7 +8354,7 @@ const postWorkspaceReviewStatusRoute = HttpRouter.add("POST", "/api/review/:issu
7904
8354
  const agentId = `agent-${issueId.toLowerCase()}`;
7905
8355
  const feedbackBody = `TESTS FAILED for ${issueId}:\n\n${testNotes}\n\n## REQUIRED: Fix ALL test failures, then invoke the /rebase-and-submit skill\n\n1. Read each test failure carefully\n2. Fix the code causing EVERY failure\n3. Run the test suite locally to verify your fixes pass\n4. Commit every change\n5. Invoke the /rebase-and-submit skill for ${issueId} — this is an atomic task that runs pan done (which handles rebase + push + re-submit internally)\n\nDo NOT stop between steps. Do NOT run git push manually — the skill handles it. Do NOT stop until pan done has completed successfully.`;
7906
8356
  try {
7907
- const { writeFeedbackFile } = yield* Effect.promise(() => import("./feedback-writer-D3a22RCd.js"));
8357
+ const { writeFeedbackFile } = yield* Effect.promise(() => import("./feedback-writer-CoB9Z6aU.js"));
7908
8358
  const wsInfo = getWorkspaceInfoForIssue(issueId);
7909
8359
  const fileResult = yield* Effect.promise(() => writeFeedbackFile({
7910
8360
  issueId,
@@ -7937,14 +8387,14 @@ const postWorkspaceReviewStatusRoute = HttpRouter.add("POST", "/api/review/:issu
7937
8387
  });
7938
8388
  yield* Effect.promise(async () => {
7939
8389
  try {
7940
- const { resolveProjectFromIssueSync, getProjectSync } = await import("./projects-vjjcmiN8.js");
8390
+ const { resolveProjectFromIssueSync, getProjectSync } = await import("./projects-_n3Zui6K.js");
7941
8391
  const project = resolveProjectFromIssueSync(issueId);
7942
8392
  const repo = (project ? getProjectSync(project.projectKey) : null)?.github_repo;
7943
8393
  if (!repo || !repo.includes("/")) return;
7944
8394
  const [owner, name] = repo.split("/");
7945
8395
  const wsInfo = getWorkspaceInfoForIssue(issueId);
7946
8396
  if (!wsInfo?.localPath) return;
7947
- const { postOverdeckTestsStatus } = await import("./github-app-ClZ2lk8D.js");
8397
+ const { postOverdeckTestsStatus } = await import("./github-app-Bmg4R9mv.js");
7948
8398
  await postOverdeckTestsStatus(wsInfo.localPath, owner, name, "success", "Test specialist passed");
7949
8399
  } catch (err) {
7950
8400
  console.warn(`[review-status] Failed to post overdeck/tests for ${issueId}: ${err.message}`);
@@ -7986,7 +8436,7 @@ const postWorkspaceRefreshTokenRoute = HttpRouter.add("POST", "/api/workspaces/:
7986
8436
  if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
7987
8437
  const issueLower = issueId.toLowerCase();
7988
8438
  const workspacePath = join(getProjectPath(void 0, extractPrefixSync(issueId) ?? issueId.split("-")[0]), "workspaces", `feature-${issueLower}`);
7989
- const { refreshWorkspaceToken, isGitHubAppConfigured } = yield* Effect.promise(() => import("./github-app-ClZ2lk8D.js"));
8439
+ const { refreshWorkspaceToken, isGitHubAppConfigured } = yield* Effect.promise(() => import("./github-app-Bmg4R9mv.js"));
7990
8440
  if (!isGitHubAppConfigured()) return jsonResponse({
7991
8441
  success: false,
7992
8442
  error: "GitHub App not configured"
@@ -8001,4 +8451,4 @@ const workspacesRouteLayer = Layer.mergeAll(workspaceDataRouteLayer, postWorkspa
8001
8451
  //#endregion
8002
8452
  export { getWorkspacePathForIssue as C, stopAgentOutputService as E, resolveIssueHeadlineCost as S, startAgentOutputService as T, getCostsForIssueSync as _, pushApproveMain as a, processPendingFeedbackDeliveries as b, triggerMerge as c, resumeQueuedMerges as d, syncWalFromAllProjects as f, migrateAllSessionsSync as g, reclassifyUnknownCostEventsSync as h, mergeOpsRouteLayer as i, internalEventsRouteLayer as l, reconcilePiTranscripts as m, buildRichPRBody as n, reconcileGitHubMergeStatus as o, reconcile as p, isBranchAlreadyRebased as r, shouldBlockApproveForDirtyStatus as s, workspacesRouteLayer as t, eventsRouteLayer as u, rebuildCacheSync as v, retainAgentOutputInterest as w, getCachedRunningAgents as x, syncCacheSync as y };
8003
8453
 
8004
- //# sourceMappingURL=workspaces-Do_9J0LQ.js.map
8454
+ //# sourceMappingURL=workspaces-CRBJikLp.js.map