@overdeck/core 0.50.3 → 0.50.4

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 (208) hide show
  1. package/dist/agents-DNMRPC8n.js.map +1 -1
  2. package/dist/{build-info-BJuEVWOh.js → build-info-ioRdOmqT.js} +3 -3
  3. package/dist/{build-info-BJuEVWOh.js.map → build-info-ioRdOmqT.js.map} +1 -1
  4. package/dist/build-info-kMMitDOP.js +2 -0
  5. package/dist/cli/index.js +4 -4
  6. package/dist/conversation-compaction-GFfO5UZL.js.map +1 -1
  7. package/dist/dashboard/{advancing-selfheal-Bq8V0QUa.js → advancing-selfheal-Dp5_Gai3.js} +3 -3
  8. package/dist/dashboard/{advancing-selfheal-Bq8V0QUa.js.map → advancing-selfheal-Dp5_Gai3.js.map} +1 -1
  9. package/dist/dashboard/{agent-gc-Coz8zQt_.js → agent-gc-JzoSs5Pi.js} +3 -3
  10. package/dist/dashboard/{agent-gc-Coz8zQt_.js.map → agent-gc-JzoSs5Pi.js.map} +1 -1
  11. package/dist/dashboard/{agent-idle-CAwB-K6M.js → agent-idle-D-Qy5BN_.js} +2 -2
  12. package/dist/dashboard/{agent-idle-CAwB-K6M.js.map → agent-idle-D-Qy5BN_.js.map} +1 -1
  13. package/dist/dashboard/{agent-state-Ci6PhjOE.js → agent-state-B196fj1h.js} +38 -16
  14. package/dist/dashboard/agent-state-B196fj1h.js.map +1 -0
  15. package/dist/dashboard/{agent-state-CbUEwUEQ.js → agent-state-IpWnw8lv.js} +1 -1
  16. package/dist/dashboard/{agent-state-service-D6IVrX3B.js → agent-state-service-CCo5-9DR.js} +3 -3
  17. package/dist/dashboard/{agent-state-service-D6IVrX3B.js.map → agent-state-service-CCo5-9DR.js.map} +1 -1
  18. package/dist/dashboard/{agent-state-service-DcN1j6eK.js → agent-state-service-D_F3VZ23.js} +1 -1
  19. package/dist/dashboard/{agents-BVvL4o_4.js → agents-CkGhnAmu.js} +1 -1
  20. package/dist/dashboard/{backlog-auto-trigger-BuSBqG2V.js → backlog-auto-trigger-B5Z2zBtC.js} +2 -2
  21. package/dist/dashboard/{backlog-auto-trigger-BuSBqG2V.js.map → backlog-auto-trigger-B5Z2zBtC.js.map} +1 -1
  22. package/dist/dashboard/build-info-BTjOB0Xr.js +2 -0
  23. package/dist/dashboard/{build-info-Cj3Y0K87.js → build-info-D0EJNj6C.js} +3 -3
  24. package/dist/dashboard/{build-info-Cj3Y0K87.js.map → build-info-D0EJNj6C.js.map} +1 -1
  25. package/dist/dashboard/cli-CIznFrcE.js +2 -0
  26. package/dist/dashboard/{cli-DIhQieif.js → cli-DCbVrSsg.js} +2 -2
  27. package/dist/dashboard/{cli-DIhQieif.js.map → cli-DCbVrSsg.js.map} +1 -1
  28. package/dist/dashboard/{close-issue-CRlmrE5g.js → close-issue-Bmu9aOIx.js} +2 -2
  29. package/dist/dashboard/{close-issue-CRlmrE5g.js.map → close-issue-Bmu9aOIx.js.map} +1 -1
  30. package/dist/dashboard/{closed-issue-reaper-DrHyYgJR.js → closed-issue-reaper-COxfTtLz.js} +5 -5
  31. package/dist/dashboard/{closed-issue-reaper-DrHyYgJR.js.map → closed-issue-reaper-COxfTtLz.js.map} +1 -1
  32. package/dist/dashboard/{closed-issue-reaper-DWlw2EtL.js → closed-issue-reaper-DwMwG_Pz.js} +1 -1
  33. package/dist/dashboard/{compaction-continuation-DhYgsXmF.js → compaction-continuation-Bqc212Zm.js} +2 -2
  34. package/dist/dashboard/{compaction-continuation-DhYgsXmF.js.map → compaction-continuation-Bqc212Zm.js.map} +1 -1
  35. package/dist/dashboard/{conflict-gate-vczgdVTa.js → conflict-gate-9mPVg7-5.js} +1 -1
  36. package/dist/dashboard/{conflict-gate-Bt-lLgYf.js → conflict-gate-CGQTcR0I.js} +3 -3
  37. package/dist/dashboard/{conflict-gate-Bt-lLgYf.js.map → conflict-gate-CGQTcR0I.js.map} +1 -1
  38. package/dist/dashboard/{conversation-compaction-CsdCbcQB.js → conversation-compaction-C7P6V8Iw.js} +5 -5
  39. package/dist/dashboard/{conversation-compaction-CsdCbcQB.js.map → conversation-compaction-C7P6V8Iw.js.map} +1 -1
  40. package/dist/dashboard/{conversation-compaction-D0zgWM1f.js → conversation-compaction-Cck5oi-V.js} +1 -1
  41. package/dist/dashboard/{conversation-service-6LaymUV-.js → conversation-service-CsOpwI9Y.js} +37 -5
  42. package/dist/dashboard/{conversation-service-6LaymUV-.js.map → conversation-service-CsOpwI9Y.js.map} +1 -1
  43. package/dist/dashboard/conversation-service-plOFkoMo.js +3 -0
  44. package/dist/dashboard/dashboard-db-worker.js +1 -1
  45. package/dist/dashboard/{deacon-CU47dU7U.js → deacon-B8oMMIgN.js} +62 -62
  46. package/dist/dashboard/{deacon-CU47dU7U.js.map → deacon-B8oMMIgN.js.map} +1 -1
  47. package/dist/dashboard/{deacon-DYsOa_ss.js → deacon-b7J57Svt.js} +2 -2
  48. package/dist/dashboard/{deacon-pending-lifecycle-ijGX8wLb.js → deacon-pending-lifecycle-3NIJ7ew5.js} +2 -2
  49. package/dist/dashboard/{deacon-pending-lifecycle-ijGX8wLb.js.map → deacon-pending-lifecycle-3NIJ7ew5.js.map} +1 -1
  50. package/dist/dashboard/deacon.js +5 -5
  51. package/dist/dashboard/{delivery-DMYxIE0J.js → delivery-lnI-gQKo.js} +1 -1
  52. package/dist/dashboard/{deploy-patrol-C4eXco1S.js → deploy-patrol-u3v2krg9.js} +2 -2
  53. package/dist/dashboard/{deploy-patrol-C4eXco1S.js.map → deploy-patrol-u3v2krg9.js.map} +1 -1
  54. package/dist/dashboard/{feedback-stuck-retirement-Dd5XNrMr.js → feedback-stuck-retirement-CoFNqjCc.js} +2 -2
  55. package/dist/dashboard/{feedback-stuck-retirement-Dd5XNrMr.js.map → feedback-stuck-retirement-CoFNqjCc.js.map} +1 -1
  56. package/dist/dashboard/{feedback-target-BzdJ2wIR.js → feedback-target-BBCh3RRq.js} +1 -1
  57. package/dist/dashboard/{feedback-target-BcsA_GRV.js → feedback-target-CeCq6EhW.js} +5 -5
  58. package/dist/dashboard/{feedback-target-BcsA_GRV.js.map → feedback-target-CeCq6EhW.js.map} +1 -1
  59. package/dist/dashboard/{flywheel-Is3w2lcT.js → flywheel-DKldI63J.js} +7 -7
  60. package/dist/dashboard/{flywheel-Is3w2lcT.js.map → flywheel-DKldI63J.js.map} +1 -1
  61. package/dist/dashboard/{flywheel-D0guNqkh.js → flywheel-DpRPLErh.js} +7 -7
  62. package/dist/dashboard/{flywheel-D0guNqkh.js.map → flywheel-DpRPLErh.js.map} +1 -1
  63. package/dist/dashboard/{flywheel-B34cdfbd.js → flywheel-jeZFYvm-.js} +1 -1
  64. package/dist/dashboard/{flywheel-merge-order-6HiPR2WG.js → flywheel-merge-order-0OnoosaO.js} +1 -1
  65. package/dist/dashboard/{flywheel-merge-order-BsNPMu0S.js → flywheel-merge-order-PG5op4j7.js} +2 -2
  66. package/dist/dashboard/{flywheel-merge-order-BsNPMu0S.js.map → flywheel-merge-order-PG5op4j7.js.map} +1 -1
  67. package/dist/dashboard/{harness-resolve-CzTFVZ5l.js → harness-resolve-C0HWj3H9.js} +2 -2
  68. package/dist/dashboard/{harness-resolve-CzTFVZ5l.js.map → harness-resolve-C0HWj3H9.js.map} +1 -1
  69. package/dist/dashboard/{identity-Dc7rQLln.js → identity-Cot1Hg4G.js} +2 -2
  70. package/dist/dashboard/{identity-Dc7rQLln.js.map → identity-Cot1Hg4G.js.map} +1 -1
  71. package/dist/dashboard/{inspect-agent-CP7Bu47O.js → inspect-agent-BDmLWbGx.js} +3 -3
  72. package/dist/dashboard/{inspect-agent-CP7Bu47O.js.map → inspect-agent-BDmLWbGx.js.map} +1 -1
  73. package/dist/dashboard/inspect-agent-BcOkA-hC.js +2 -0
  74. package/dist/dashboard/{issue-lifecycle-BPbczKyy.js → issue-lifecycle-1B_v8Rf5.js} +6 -6
  75. package/dist/dashboard/{issue-lifecycle-BPbczKyy.js.map → issue-lifecycle-1B_v8Rf5.js.map} +1 -1
  76. package/dist/dashboard/{issue-lifecycle-FaugTi39.js → issue-lifecycle-CIrfbIbj.js} +1 -1
  77. package/dist/dashboard/{issue-service-singleton-Dsad9NTt.js → issue-service-singleton-BVwPzjwF.js} +1 -1
  78. package/dist/dashboard/{issue-service-singleton-BrZQJLRI.js → issue-service-singleton-KcRrOiFD.js} +2 -2
  79. package/dist/dashboard/{issue-service-singleton-BrZQJLRI.js.map → issue-service-singleton-KcRrOiFD.js.map} +1 -1
  80. package/dist/dashboard/{jsonl-resolver-DQEe0DHM.js → jsonl-resolver-jxbif7MD.js} +3 -3
  81. package/dist/dashboard/{jsonl-resolver-DQEe0DHM.js.map → jsonl-resolver-jxbif7MD.js.map} +1 -1
  82. package/dist/dashboard/{kimi-code-Cx5YUJpS.js → kimi-code-BZh3NgcN.js} +1 -1
  83. package/dist/dashboard/{lifecycle-DZFHmpGI.js → lifecycle-CvcZ4_fA.js} +4 -4
  84. package/dist/dashboard/{lifecycle-DZFHmpGI.js.map → lifecycle-CvcZ4_fA.js.map} +1 -1
  85. package/dist/dashboard/{linear-mcp-auth-DylPJABZ.js → linear-mcp-auth-CZoj_-d7.js} +1 -1
  86. package/dist/dashboard/{linear-mcp-auth-BFlpMvWh.js → linear-mcp-auth-Dx74yCAY.js} +2 -2
  87. package/dist/dashboard/{linear-mcp-auth-BFlpMvWh.js.map → linear-mcp-auth-Dx74yCAY.js.map} +1 -1
  88. package/dist/dashboard/{memory-governor-B7uDWRo9.js → memory-governor-Bv3LAqk3.js} +5 -5
  89. package/dist/dashboard/{memory-governor-B7uDWRo9.js.map → memory-governor-Bv3LAqk3.js.map} +1 -1
  90. package/dist/dashboard/{merge-agent-ddEcZDZD.js → merge-agent-1zVLl6k_.js} +1 -1
  91. package/dist/dashboard/{merge-agent-ttRY053V.js → merge-agent-8zrQu48t.js} +8 -8
  92. package/dist/dashboard/{merge-agent-ttRY053V.js.map → merge-agent-8zrQu48t.js.map} +1 -1
  93. package/dist/dashboard/merge-ops-CFJaMPLu.js +2 -0
  94. package/dist/dashboard/{merge-train-f_un38UJ.js → merge-train-BYH_cF7G.js} +2 -2
  95. package/dist/dashboard/{merge-train-f_un38UJ.js.map → merge-train-BYH_cF7G.js.map} +1 -1
  96. package/dist/dashboard/{merge-train-deps-GPlHOjK6.js → merge-train-deps-BTfXM5AR.js} +2 -2
  97. package/dist/dashboard/{merge-train-deps-GPlHOjK6.js.map → merge-train-deps-BTfXM5AR.js.map} +1 -1
  98. package/dist/dashboard/{messaging-BasbftDu.js → messaging-Bk6vGsMw.js} +1 -1
  99. package/dist/dashboard/{orphan-proposed-reconciler-DFHdQSEg.js → orphan-proposed-reconciler-B898fk26.js} +6 -6
  100. package/dist/dashboard/{orphan-proposed-reconciler-DFHdQSEg.js.map → orphan-proposed-reconciler-B898fk26.js.map} +1 -1
  101. package/dist/dashboard/{orphan-proposed-reconciler-DzAxrM99.js → orphan-proposed-reconciler-Bx_aWS4B.js} +1 -1
  102. package/dist/dashboard/{parked-residue-DMtbxJml.js → parked-residue-q2kzrYSm.js} +9 -9
  103. package/dist/dashboard/{parked-residue-DMtbxJml.js.map → parked-residue-q2kzrYSm.js.map} +1 -1
  104. package/dist/dashboard/{post-merge-lifecycle-worker-jzN2g_EY.js → post-merge-lifecycle-worker-Cl7-uf4g.js} +2 -2
  105. package/dist/dashboard/{post-merge-lifecycle-worker-jzN2g_EY.js.map → post-merge-lifecycle-worker-Cl7-uf4g.js.map} +1 -1
  106. package/dist/dashboard/{project-resource-refresh-queue-cqOeJ0fB.js → project-resource-refresh-queue-O_dRfPHn.js} +1 -1
  107. package/dist/dashboard/{project-resource-refresh-queue-DebwjPPA.js → project-resource-refresh-queue-se3T9IYP.js} +4 -4
  108. package/dist/dashboard/{project-resource-refresh-queue-DebwjPPA.js.map → project-resource-refresh-queue-se3T9IYP.js.map} +1 -1
  109. package/dist/dashboard/{reconstruct-cache-Bb2Jg2DZ.js → reconstruct-cache-XpWC9L0F.js} +2 -2
  110. package/dist/dashboard/{reconstruct-cache-Bb2Jg2DZ.js.map → reconstruct-cache-XpWC9L0F.js.map} +1 -1
  111. package/dist/dashboard/{release-engine-78iCajIc.js → release-engine-BuzxOamf.js} +2 -2
  112. package/dist/dashboard/{release-engine-78iCajIc.js.map → release-engine-BuzxOamf.js.map} +1 -1
  113. package/dist/dashboard/{remote-completion-D5wzZCte.js → remote-completion-BCZgeKPS.js} +3 -3
  114. package/dist/dashboard/{remote-completion-D5wzZCte.js.map → remote-completion-BCZgeKPS.js.map} +1 -1
  115. package/dist/dashboard/{resolver-BGZh3lXA.js → resolver-BeNrqNou.js} +5 -5
  116. package/dist/dashboard/{resolver-BGZh3lXA.js.map → resolver-BeNrqNou.js.map} +1 -1
  117. package/dist/dashboard/{resource-pressure-patrol-Bg23rPV-.js → resource-pressure-patrol-Ccg_aCgO.js} +3 -3
  118. package/dist/dashboard/{resource-pressure-patrol-Bg23rPV-.js.map → resource-pressure-patrol-Ccg_aCgO.js.map} +1 -1
  119. package/dist/dashboard/{resume-BKyB4hA1.js → resume-KGCrn0DV.js} +1 -1
  120. package/dist/dashboard/{review-agent-ZdP-HmwY.js → review-agent-BmM6YMZW.js} +1 -1
  121. package/dist/dashboard/{review-agent-DHs-JngN.js → review-agent-DRWVU8fP.js} +13 -13
  122. package/dist/dashboard/{review-agent-DHs-JngN.js.map → review-agent-DRWVU8fP.js.map} +1 -1
  123. package/dist/dashboard/{review-convoy-liveness-BTMvU4CA.js → review-convoy-liveness-EvCDv8Q_.js} +3 -3
  124. package/dist/dashboard/{review-convoy-liveness-BTMvU4CA.js.map → review-convoy-liveness-EvCDv8Q_.js.map} +1 -1
  125. package/dist/dashboard/{review-run-recovery-BYalQzbh.js → review-run-recovery-Ctm48Snt.js} +1 -1
  126. package/dist/dashboard/{review-run-recovery-BvVG3oUr.js → review-run-recovery-DNDI58cM.js} +2 -2
  127. package/dist/dashboard/{review-run-recovery-BvVG3oUr.js.map → review-run-recovery-DNDI58cM.js.map} +1 -1
  128. package/dist/dashboard/{review-status-DXTFzCmR.js → review-status-FnlvQuPI.js} +1 -1
  129. package/dist/dashboard/{review-status-emit-C9YW6SQL.js → review-status-emit-CeMS31DX.js} +2 -2
  130. package/dist/dashboard/{review-status-emit-C9YW6SQL.js.map → review-status-emit-CeMS31DX.js.map} +1 -1
  131. package/dist/dashboard/{review-status-BegAr86G.js → review-status-yY5qt7Rl.js} +5 -5
  132. package/dist/dashboard/{review-status-BegAr86G.js.map → review-status-yY5qt7Rl.js.map} +1 -1
  133. package/dist/dashboard/{review-verdict-feedback-qlVBi19-.js → review-verdict-feedback-BNgRj1e3.js} +4 -4
  134. package/dist/dashboard/{review-verdict-feedback-qlVBi19-.js.map → review-verdict-feedback-BNgRj1e3.js.map} +1 -1
  135. package/dist/dashboard/{review-verdict-feedback-Dp139Lmv.js → review-verdict-feedback-D39cuSV1.js} +1 -1
  136. package/dist/dashboard/{review-verdict-writer-CJr_Ob0Y.js → review-verdict-writer-DvFfKAn-.js} +2 -2
  137. package/dist/dashboard/{review-verdict-writer-CJr_Ob0Y.js.map → review-verdict-writer-DvFfKAn-.js.map} +1 -1
  138. package/dist/dashboard/{review-verdict-writer-BVco3WoI.js → review-verdict-writer-PcGBkvJ4.js} +1 -1
  139. package/dist/dashboard/{sequence-io-iljWlslY.js → sequence-io-DZyschsf.js} +2 -2
  140. package/dist/dashboard/{sequence-io-iljWlslY.js.map → sequence-io-DZyschsf.js.map} +1 -1
  141. package/dist/dashboard/{sequencer-agent-BGGVKxtw.js → sequencer-agent-BXDw5cNx.js} +5 -5
  142. package/dist/dashboard/{sequencer-agent-BGGVKxtw.js.map → sequencer-agent-BXDw5cNx.js.map} +1 -1
  143. package/dist/dashboard/server.js +79 -72
  144. package/dist/dashboard/server.js.map +1 -1
  145. package/dist/dashboard/{service-kzhN0DLg.js → service-DP50Omvn.js} +33 -33
  146. package/dist/dashboard/{service-kzhN0DLg.js.map → service-DP50Omvn.js.map} +1 -1
  147. package/dist/dashboard/{smart-compaction-owKHJDbL.js → smart-compaction-944GL8PN.js} +1 -1
  148. package/dist/dashboard/{smart-compaction-C96F2aFQ.js → smart-compaction-BzDfF6yb.js} +2 -2
  149. package/dist/dashboard/{smart-compaction-C96F2aFQ.js.map → smart-compaction-BzDfF6yb.js.map} +1 -1
  150. package/dist/dashboard/{spawn-planning-session-CiJdOHTD.js → spawn-planning-session-BcVnHJjm.js} +1 -1
  151. package/dist/dashboard/{spawn-planning-session-FmJa6PCS.js → spawn-planning-session-CH8IYli7.js} +3 -3
  152. package/dist/dashboard/{spawn-planning-session-FmJa6PCS.js.map → spawn-planning-session-CH8IYli7.js.map} +1 -1
  153. package/dist/dashboard/{specialist-context-_ootmzn2.js → specialist-context-DhDTXVht.js} +3 -3
  154. package/dist/dashboard/{specialist-context-_ootmzn2.js.map → specialist-context-DhDTXVht.js.map} +1 -1
  155. package/dist/dashboard/{specialist-logs-BbAX221-.js → specialist-logs-C1bcnZ-G.js} +2 -2
  156. package/dist/dashboard/{specialist-logs-BbAX221-.js.map → specialist-logs-C1bcnZ-G.js.map} +1 -1
  157. package/dist/dashboard/{specialists-COZoYaiz.js → specialists-BKmReEWT.js} +53 -53
  158. package/dist/dashboard/{specialists-COZoYaiz.js.map → specialists-BKmReEWT.js.map} +1 -1
  159. package/dist/dashboard/{specialists-RPLJnYc1.js → specialists-Bvrvt0br.js} +12 -12
  160. package/dist/dashboard/{specialists-RPLJnYc1.js.map → specialists-Bvrvt0br.js.map} +1 -1
  161. package/dist/dashboard/{specialists-DTAOVZpU.js → specialists-CD6GEKXk.js} +1 -1
  162. package/dist/dashboard/{specialists-D8sYZnPb.js → specialists-eFWpJRBc.js} +1 -1
  163. package/dist/dashboard/{stall-sweeper-9bRBZhrQ.js → stall-sweeper-D3fZvg7O.js} +3 -3
  164. package/dist/dashboard/{stall-sweeper-9bRBZhrQ.js.map → stall-sweeper-D3fZvg7O.js.map} +1 -1
  165. package/dist/dashboard/{state-migrate-J3tFJnbd.js → state-migrate-KZ2goscQ.js} +2 -2
  166. package/dist/dashboard/{state-migrate-J3tFJnbd.js.map → state-migrate-KZ2goscQ.js.map} +1 -1
  167. package/dist/dashboard/{stuck-remediation-BvTK_NYN.js → stuck-remediation-Cb2V1roj.js} +1 -1
  168. package/dist/dashboard/{stuck-remediation-4Rf_xMEb.js → stuck-remediation-CnoV0kcv.js} +5 -5
  169. package/dist/dashboard/{stuck-remediation-4Rf_xMEb.js.map → stuck-remediation-CnoV0kcv.js.map} +1 -1
  170. package/dist/dashboard/{summary-fork-PLcckTRE.js → summary-fork-CxuNBM0F.js} +2 -2
  171. package/dist/dashboard/{summary-fork-D-cylknJ.js → summary-fork-lC2vMXly.js} +4 -4
  172. package/dist/dashboard/{summary-fork-D-cylknJ.js.map → summary-fork-lC2vMXly.js.map} +1 -1
  173. package/dist/dashboard/{teardown-workspace-CTL16rnG.js → teardown-workspace-C-9murBw.js} +4 -4
  174. package/dist/dashboard/{teardown-workspace-CTL16rnG.js.map → teardown-workspace-C-9murBw.js.map} +1 -1
  175. package/dist/dashboard/{test-agent-queue-CMgYZiR_.js → test-agent-queue-YCBRzaAB.js} +3 -3
  176. package/dist/dashboard/{test-agent-queue-CMgYZiR_.js.map → test-agent-queue-YCBRzaAB.js.map} +1 -1
  177. package/dist/dashboard/{uat-failure-feedback-DS6W9X3I.js → uat-failure-feedback-B-1mL8Zp.js} +3 -3
  178. package/dist/dashboard/{uat-failure-feedback-DS6W9X3I.js.map → uat-failure-feedback-B-1mL8Zp.js.map} +1 -1
  179. package/dist/dashboard/{uat-promote-verification-CRsIHE_q.js → uat-promote-verification-BEBPcpPg.js} +2 -2
  180. package/dist/dashboard/{uat-promote-verification-CRsIHE_q.js.map → uat-promote-verification-BEBPcpPg.js.map} +1 -1
  181. package/dist/dashboard/{uat-train-BoA9r6_I.js → uat-train-BFo3OQUB.js} +1 -1
  182. package/dist/dashboard/{uat-train-Cd8CJeNe.js → uat-train-COgoJomz.js} +8 -8
  183. package/dist/dashboard/{uat-train-Cd8CJeNe.js.map → uat-train-COgoJomz.js.map} +1 -1
  184. package/dist/dashboard/{validate-BdmvTIym.js → validate-069_N1e2.js} +2 -2
  185. package/dist/dashboard/{validate-BdmvTIym.js.map → validate-069_N1e2.js.map} +1 -1
  186. package/dist/dashboard/{verification-runner-BO0K3xNA.js → verification-runner-CQnZyC5A.js} +1 -1
  187. package/dist/dashboard/{verification-runner-fEY1Qj-l.js → verification-runner-fy3wNrWn.js} +4 -4
  188. package/dist/dashboard/{verification-runner-fEY1Qj-l.js.map → verification-runner-fy3wNrWn.js.map} +1 -1
  189. package/dist/dashboard/workflows-Bk6Kt0ZQ.js +2 -0
  190. package/dist/dashboard/{workflows-CxVnygYU.js → workflows-N4QMkDzN.js} +10 -10
  191. package/dist/dashboard/{workflows-CxVnygYU.js.map → workflows-N4QMkDzN.js.map} +1 -1
  192. package/dist/dashboard/{workspaces-Cpz0xJWQ.js → workspaces-DmoyfHoU.js} +33 -33
  193. package/dist/dashboard/{workspaces-Cpz0xJWQ.js.map → workspaces-DmoyfHoU.js.map} +1 -1
  194. package/dist/{lifecycle-C6k0HWEO.js → lifecycle-DCFcjg7y.js} +1 -1
  195. package/dist/{lifecycle-D5oRpvvB.js → lifecycle-GkaHQJNK.js} +2 -2
  196. package/dist/{lifecycle-D5oRpvvB.js.map → lifecycle-GkaHQJNK.js.map} +1 -1
  197. package/dist/{merge-agent-Drufc7tU.js → merge-agent-CogNFasY.js} +2 -2
  198. package/dist/{merge-agent-Drufc7tU.js.map → merge-agent-CogNFasY.js.map} +1 -1
  199. package/dist/{merge-agent-CBOVY_eC.js → merge-agent-eteKQ9Rb.js} +1 -1
  200. package/package.json +1 -1
  201. package/dist/build-info-BgrwLUy6.js +0 -2
  202. package/dist/dashboard/agent-state-Ci6PhjOE.js.map +0 -1
  203. package/dist/dashboard/build-info-CYlxvZSQ.js +0 -2
  204. package/dist/dashboard/cli-ZAS502uC.js +0 -2
  205. package/dist/dashboard/conversation-service-Dlks_hSS.js +0 -3
  206. package/dist/dashboard/inspect-agent-DTuSg95i.js +0 -2
  207. package/dist/dashboard/merge-ops-Bgc-EScO.js +0 -2
  208. package/dist/dashboard/workflows-CgGNyl1z.js +0 -2
@@ -0,0 +1,2 @@
1
+ import { l as triggerMerge } from "./workspaces-DmoyfHoU.js";
2
+ export { triggerMerge };
@@ -72,9 +72,9 @@ async function runMergeTrainReconcile(mergedIssueId, opts = {}) {
72
72
  if (!config) return false;
73
73
  return isMergeTrainEnabledForProject(config);
74
74
  }))()) return [];
75
- return reconcileStaleSiblings(mergedIssueId, opts.deps ?? (await import("./merge-train-deps-GPlHOjK6.js")).buildRealReconcileDeps());
75
+ return reconcileStaleSiblings(mergedIssueId, opts.deps ?? (await import("./merge-train-deps-BTfXM5AR.js")).buildRealReconcileDeps());
76
76
  }
77
77
  //#endregion
78
78
  export { runMergeTrainReconcile };
79
79
 
80
- //# sourceMappingURL=merge-train-f_un38UJ.js.map
80
+ //# sourceMappingURL=merge-train-BYH_cF7G.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"merge-train-f_un38UJ.js","names":[],"sources":["../../src/lib/cloister/merge-train-reconciler.ts","../../src/lib/cloister/merge-train.ts"],"sourcesContent":["/**\n * Merge-train reconciler (PAN-1691).\n *\n * When a feature merges to main, every *other* ready-for-merge branch is now\n * behind main. Left alone they go stale / CONFLICTING and strand — the cause of\n * PAN-1240 / PAN-1215 / PAN-1213 / PAN-1658. This reconciler is the automatic\n * janitor that runs right after a merge lands: rebase each ready sibling onto\n * the new main, re-verify the clean ones, and hand the genuinely-conflicting\n * ones to a resolving *agent* (never a human — the agent must understand what\n * BOTH features intended across BOTH changesets).\n *\n * The orchestration here is pure and dependency-injected so it is unit-testable\n * without touching git, the DB, or spawning agents. The real wiring + the\n * default-off `merge_train` flag live at the call site (the post-merge path).\n */\n\nexport type SiblingOutcome =\n /** Branch was already up to date with main — nothing to do. */\n | { issueId: string; result: 'unaffected' }\n /** Clean rebase onto the new main — re-verification was dispatched. */\n | { issueId: string; result: 'rebased' }\n /** Genuine conflict — a resolver agent was dispatched. */\n | { issueId: string; result: 'conflict' }\n /** Something failed for this sibling; the rest still proceed. */\n | { issueId: string; result: 'error'; error: string };\n\nexport type RebaseStatus = 'up-to-date' | 'clean' | 'conflict';\n\nexport interface ReconcileDeps {\n /** Ready-for-merge sibling issue IDs (excluding the one that just merged). */\n getReadySiblings: (mergedIssueId: string) => Promise<string[]> | string[];\n /** Rebase this sibling's feature branch onto the updated main. */\n rebaseSibling: (issueId: string) => Promise<{ status: RebaseStatus }>;\n /** Re-run review/test verification on a cleanly-rebased sibling. */\n reDispatchVerification: (issueId: string) => Promise<void> | void;\n /**\n * Dispatch an agent to resolve a rebase conflict. The agent must load and\n * reconcile what BOTH features intended — `mergedIssueId` is the feature that\n * just landed and conflicts with `issueId`.\n */\n dispatchConflictResolver: (issueId: string, mergedIssueId: string) => Promise<void> | void;\n log?: (msg: string) => void;\n}\n\n/**\n * Reconcile every ready sibling after `mergedIssueId` landed on main. Processes\n * siblings sequentially (one git rebase at a time, no contention) and never\n * throws — a failure on one sibling becomes an `error` outcome and the rest\n * proceed.\n */\nexport async function reconcileStaleSiblings(\n mergedIssueId: string,\n deps: ReconcileDeps,\n): Promise<SiblingOutcome[]> {\n const log = deps.log ?? (() => {});\n const siblings = await deps.getReadySiblings(mergedIssueId);\n const outcomes: SiblingOutcome[] = [];\n\n for (const issueId of siblings) {\n try {\n const { status } = await deps.rebaseSibling(issueId);\n if (status === 'up-to-date') {\n outcomes.push({ issueId, result: 'unaffected' });\n } else if (status === 'clean') {\n await deps.reDispatchVerification(issueId);\n log(`[merge-train] ${issueId} rebased clean onto main(+${mergedIssueId}); re-verifying`);\n outcomes.push({ issueId, result: 'rebased' });\n } else {\n await deps.dispatchConflictResolver(issueId, mergedIssueId);\n log(`[merge-train] ${issueId} conflicts with ${mergedIssueId}; dispatched resolver agent`);\n outcomes.push({ issueId, result: 'conflict' });\n }\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n log(`[merge-train] ${issueId} reconcile failed: ${error}`);\n outcomes.push({ issueId, result: 'error', error });\n }\n }\n\n return outcomes;\n}\n","/**\n * Merge-train entry point (PAN-1691, PAN-1696).\n *\n * Called from the post-merge path after a feature lands on main. Gated by the\n * default-off `merge_train.enabled` flag (or per-project override in projects.yaml)\n * — when off this is a no-op, so nothing git-mutating runs until an operator\n * deliberately enables it.\n *\n * The real git/spawn deps are lazy-loaded only when the flag is on, so importing\n * this module (and unit-testing the gating) stays light and never pulls in the\n * agent-spawn machinery.\n */\nimport { isMergeTrainEnabledForProject } from '../overdeck/merge-sync.js';\nimport { getProjectSync, resolveProjectFromIssueSync, type ProjectConfig } from '../projects.js';\nimport { reconcileStaleSiblings, type ReconcileDeps, type SiblingOutcome } from './merge-train-reconciler.js';\n\nexport interface RunMergeTrainOptions {\n /** Override the flag check (tests). Defaults to checking the per-project override or global flag. */\n enabled?: () => boolean;\n /** Inject reconcile deps (tests). Defaults to the real git/spawn wiring. */\n deps?: ReconcileDeps;\n}\n\n/**\n * Run the merge-train reconciler for the issue that just merged. No-op (returns\n * `[]`) when the merge-train flag is off — the safe default. Respects per-project\n * overrides in projects.yaml.\n */\nexport async function runMergeTrainReconcile(\n mergedIssueId: string,\n opts: RunMergeTrainOptions = {},\n): Promise<SiblingOutcome[]> {\n const enabledCheck = opts.enabled ?? (() => {\n const resolved = resolveProjectFromIssueSync(mergedIssueId);\n // Fail closed: if project resolution fails, return false (don't mutate git).\n // This prevents unrecognized issue IDs from triggering cross-project rebase.\n if (!resolved) return false;\n\n const config = getProjectSync(resolved.projectKey);\n // Also fail closed if project config lookup fails\n if (!config) return false;\n\n return isMergeTrainEnabledForProject(config);\n });\n\n if (!enabledCheck()) return [];\n\n const deps = opts.deps ?? (await import('./merge-train-deps.js')).buildRealReconcileDeps();\n return reconcileStaleSiblings(mergedIssueId, deps);\n}\n"],"mappings":";;;;;;;;;;;AAkDA,eAAA,uBAAA,eAAA,MAAA;;;;AAQE,MAAA,MAAA,WAAA,SAAA,KAAA;;AAGI,MAAA,WAAA,aAAA,UAAA,KAAA;;;;;AAGE,SAAA,KAAA,uBAAA,QAAA;AACA,OAAA,iBAAA,QAAA,4BAAA,cAAA,iBAAA;AACA,YAAA,KAAA;;;;;AAEA,SAAA,KAAA,yBAAA,SAAA,cAAA;AACA,OAAA,iBAAA,QAAA,kBAAA,cAAA,6BAAA;AACA,YAAA,KAAA;;;;;;;AAIF,MAAA,iBAAA,QAAA,qBAAA,QAAA;AACA,WAAA,KAAA;;;;;;AAIJ,QAAA;;;;;;;;;;;;;;;;;;;;;ACnDF,eAAsB,uBACpB,eACA,OAA6B,EAAE,EACJ;AAc3B,KAAI,EAbiB,KAAK,kBAAkB;EAC1C,MAAM,WAAW,4BAA4B,cAAc;AAG3D,MAAI,CAAC,SAAU,QAAO;EAEtB,MAAM,SAAS,eAAe,SAAS,WAAW;AAElD,MAAI,CAAC,OAAQ,QAAO;AAEpB,SAAO,8BAA8B,OAAO;MAG3B,CAAE,QAAO,EAAE;AAG9B,QAAO,uBAAuB,eADjB,KAAK,SAAS,MAAM,OAAO,mCAA0B,wBAAwB,CACxC"}
1
+ {"version":3,"file":"merge-train-BYH_cF7G.js","names":[],"sources":["../../src/lib/cloister/merge-train-reconciler.ts","../../src/lib/cloister/merge-train.ts"],"sourcesContent":["/**\n * Merge-train reconciler (PAN-1691).\n *\n * When a feature merges to main, every *other* ready-for-merge branch is now\n * behind main. Left alone they go stale / CONFLICTING and strand — the cause of\n * PAN-1240 / PAN-1215 / PAN-1213 / PAN-1658. This reconciler is the automatic\n * janitor that runs right after a merge lands: rebase each ready sibling onto\n * the new main, re-verify the clean ones, and hand the genuinely-conflicting\n * ones to a resolving *agent* (never a human — the agent must understand what\n * BOTH features intended across BOTH changesets).\n *\n * The orchestration here is pure and dependency-injected so it is unit-testable\n * without touching git, the DB, or spawning agents. The real wiring + the\n * default-off `merge_train` flag live at the call site (the post-merge path).\n */\n\nexport type SiblingOutcome =\n /** Branch was already up to date with main — nothing to do. */\n | { issueId: string; result: 'unaffected' }\n /** Clean rebase onto the new main — re-verification was dispatched. */\n | { issueId: string; result: 'rebased' }\n /** Genuine conflict — a resolver agent was dispatched. */\n | { issueId: string; result: 'conflict' }\n /** Something failed for this sibling; the rest still proceed. */\n | { issueId: string; result: 'error'; error: string };\n\nexport type RebaseStatus = 'up-to-date' | 'clean' | 'conflict';\n\nexport interface ReconcileDeps {\n /** Ready-for-merge sibling issue IDs (excluding the one that just merged). */\n getReadySiblings: (mergedIssueId: string) => Promise<string[]> | string[];\n /** Rebase this sibling's feature branch onto the updated main. */\n rebaseSibling: (issueId: string) => Promise<{ status: RebaseStatus }>;\n /** Re-run review/test verification on a cleanly-rebased sibling. */\n reDispatchVerification: (issueId: string) => Promise<void> | void;\n /**\n * Dispatch an agent to resolve a rebase conflict. The agent must load and\n * reconcile what BOTH features intended — `mergedIssueId` is the feature that\n * just landed and conflicts with `issueId`.\n */\n dispatchConflictResolver: (issueId: string, mergedIssueId: string) => Promise<void> | void;\n log?: (msg: string) => void;\n}\n\n/**\n * Reconcile every ready sibling after `mergedIssueId` landed on main. Processes\n * siblings sequentially (one git rebase at a time, no contention) and never\n * throws — a failure on one sibling becomes an `error` outcome and the rest\n * proceed.\n */\nexport async function reconcileStaleSiblings(\n mergedIssueId: string,\n deps: ReconcileDeps,\n): Promise<SiblingOutcome[]> {\n const log = deps.log ?? (() => {});\n const siblings = await deps.getReadySiblings(mergedIssueId);\n const outcomes: SiblingOutcome[] = [];\n\n for (const issueId of siblings) {\n try {\n const { status } = await deps.rebaseSibling(issueId);\n if (status === 'up-to-date') {\n outcomes.push({ issueId, result: 'unaffected' });\n } else if (status === 'clean') {\n await deps.reDispatchVerification(issueId);\n log(`[merge-train] ${issueId} rebased clean onto main(+${mergedIssueId}); re-verifying`);\n outcomes.push({ issueId, result: 'rebased' });\n } else {\n await deps.dispatchConflictResolver(issueId, mergedIssueId);\n log(`[merge-train] ${issueId} conflicts with ${mergedIssueId}; dispatched resolver agent`);\n outcomes.push({ issueId, result: 'conflict' });\n }\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n log(`[merge-train] ${issueId} reconcile failed: ${error}`);\n outcomes.push({ issueId, result: 'error', error });\n }\n }\n\n return outcomes;\n}\n","/**\n * Merge-train entry point (PAN-1691, PAN-1696).\n *\n * Called from the post-merge path after a feature lands on main. Gated by the\n * default-off `merge_train.enabled` flag (or per-project override in projects.yaml)\n * — when off this is a no-op, so nothing git-mutating runs until an operator\n * deliberately enables it.\n *\n * The real git/spawn deps are lazy-loaded only when the flag is on, so importing\n * this module (and unit-testing the gating) stays light and never pulls in the\n * agent-spawn machinery.\n */\nimport { isMergeTrainEnabledForProject } from '../overdeck/merge-sync.js';\nimport { getProjectSync, resolveProjectFromIssueSync, type ProjectConfig } from '../projects.js';\nimport { reconcileStaleSiblings, type ReconcileDeps, type SiblingOutcome } from './merge-train-reconciler.js';\n\nexport interface RunMergeTrainOptions {\n /** Override the flag check (tests). Defaults to checking the per-project override or global flag. */\n enabled?: () => boolean;\n /** Inject reconcile deps (tests). Defaults to the real git/spawn wiring. */\n deps?: ReconcileDeps;\n}\n\n/**\n * Run the merge-train reconciler for the issue that just merged. No-op (returns\n * `[]`) when the merge-train flag is off — the safe default. Respects per-project\n * overrides in projects.yaml.\n */\nexport async function runMergeTrainReconcile(\n mergedIssueId: string,\n opts: RunMergeTrainOptions = {},\n): Promise<SiblingOutcome[]> {\n const enabledCheck = opts.enabled ?? (() => {\n const resolved = resolveProjectFromIssueSync(mergedIssueId);\n // Fail closed: if project resolution fails, return false (don't mutate git).\n // This prevents unrecognized issue IDs from triggering cross-project rebase.\n if (!resolved) return false;\n\n const config = getProjectSync(resolved.projectKey);\n // Also fail closed if project config lookup fails\n if (!config) return false;\n\n return isMergeTrainEnabledForProject(config);\n });\n\n if (!enabledCheck()) return [];\n\n const deps = opts.deps ?? (await import('./merge-train-deps.js')).buildRealReconcileDeps();\n return reconcileStaleSiblings(mergedIssueId, deps);\n}\n"],"mappings":";;;;;;;;;;;AAkDA,eAAA,uBAAA,eAAA,MAAA;;;;AAQE,MAAA,MAAA,WAAA,SAAA,KAAA;;AAGI,MAAA,WAAA,aAAA,UAAA,KAAA;;;;;AAGE,SAAA,KAAA,uBAAA,QAAA;AACA,OAAA,iBAAA,QAAA,4BAAA,cAAA,iBAAA;AACA,YAAA,KAAA;;;;;AAEA,SAAA,KAAA,yBAAA,SAAA,cAAA;AACA,OAAA,iBAAA,QAAA,kBAAA,cAAA,6BAAA;AACA,YAAA,KAAA;;;;;;;AAIF,MAAA,iBAAA,QAAA,qBAAA,QAAA;AACA,WAAA,KAAA;;;;;;AAIJ,QAAA;;;;;;;;;;;;;;;;;;;;;ACnDF,eAAsB,uBACpB,eACA,OAA6B,EAAE,EACJ;AAc3B,KAAI,EAbiB,KAAK,kBAAkB;EAC1C,MAAM,WAAW,4BAA4B,cAAc;AAG3D,MAAI,CAAC,SAAU,QAAO;EAEtB,MAAM,SAAS,eAAe,SAAS,WAAW;AAElD,MAAI,CAAC,OAAQ,QAAO;AAEpB,SAAO,8BAA8B,OAAO;MAG3B,CAAE,QAAO,EAAE;AAG9B,QAAO,uBAAuB,eADjB,KAAK,SAAS,MAAM,OAAO,mCAA0B,wBAAwB,CACxC"}
@@ -1,5 +1,5 @@
1
1
  import { On as resolveProjectFromIssueSync, fn as init_projects } from "./config-yaml-Dce9VUd6.js";
2
- import { ln as spawnRun, q as init_agents } from "./agent-state-Ci6PhjOE.js";
2
+ import { ln as spawnRun, q as init_agents } from "./agent-state-B196fj1h.js";
3
3
  import { i as getAllReviewStatusesFromDb, l as init_review_status_sync } from "./review-status-sync-CHt0oq_3.js";
4
4
  import { join } from "path";
5
5
  import { exec } from "child_process";
@@ -72,4 +72,4 @@ function buildRealReconcileDeps() {
72
72
  //#endregion
73
73
  export { buildRealReconcileDeps };
74
74
 
75
- //# sourceMappingURL=merge-train-deps-GPlHOjK6.js.map
75
+ //# sourceMappingURL=merge-train-deps-BTfXM5AR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"merge-train-deps-GPlHOjK6.js","names":[],"sources":["../../src/lib/cloister/merge-train-deps.ts"],"sourcesContent":["/**\n * Real wiring for the merge-train reconciler (PAN-1691). Lazy-loaded from\n * merge-train.ts only when the `flywheel.merge_train_enabled` flag is on, so it\n * is never imported during normal operation or the gating unit tests.\n *\n * This is pure I/O — git rebase/force-push and agent spawn — and is exercised\n * only with the flag on against a real merge, so it is not unit-tested. The\n * decision logic it feeds (`reconcileStaleSiblings`) and the flag gating\n * (`runMergeTrainReconcile`) are.\n */\nimport { join } from 'path';\nimport { promisify } from 'util';\nimport { exec } from 'child_process';\nimport { getAllReviewStatusesFromDb } from '../overdeck/review-status-sync.js';\nimport { resolveProjectFromIssueSync } from '../projects.js';\nimport { spawnRun } from '../agents.js';\nimport type { ReconcileDeps, RebaseStatus } from './merge-train-reconciler.js';\n\nconst execAsync = promisify(exec);\n\nfunction workspacePathFor(issueId: string): string | null {\n const project = resolveProjectFromIssueSync(issueId);\n if (!project) return null;\n return join(project.projectPath, 'workspaces', `feature-${issueId.toLowerCase()}`);\n}\n\nexport function buildRealReconcileDeps(): ReconcileDeps {\n return {\n getReadySiblings: (mergedIssueId) => {\n const merged = mergedIssueId.toUpperCase();\n return Object.values(getAllReviewStatusesFromDb())\n .filter(\n (rs) =>\n rs.readyForMerge === true &&\n rs.mergeStatus !== 'merged' &&\n rs.issueId.toUpperCase() !== merged,\n )\n .map((rs) => rs.issueId);\n },\n\n rebaseSibling: async (issueId): Promise<{ status: RebaseStatus }> => {\n const ws = workspacePathFor(issueId);\n if (!ws) return { status: 'up-to-date' };\n const run = (cmd: string) => execAsync(cmd, { cwd: ws });\n\n await run('git fetch origin main');\n const { stdout } = await run('git rev-list --count HEAD..origin/main');\n if (stdout.trim() === '0') return { status: 'up-to-date' };\n\n try {\n await run('git rebase origin/main');\n await run('git push --force-with-lease');\n return { status: 'clean' };\n } catch {\n await run('git rebase --abort').catch(() => {});\n return { status: 'conflict' };\n }\n },\n\n reDispatchVerification: async (issueId) => {\n // The branch HEAD moved after the rebase — re-run review on the new HEAD.\n await spawnRun(issueId, 'review', {\n prompt:\n 'Your branch was automatically rebased onto the latest main after another feature merged. ' +\n 'Re-review on the new HEAD and confirm the issue is still correct and ready to merge.',\n startedBy: 'merge-train:verification',\n });\n },\n\n dispatchConflictResolver: async (issueId, mergedIssueId) => {\n await spawnRun(issueId, 'work', {\n prompt: [\n `Your feature branch could not be cleanly rebased onto the latest main because ${mergedIssueId} just merged and conflicts with your changes.`,\n '',\n `Resolve the rebase conflict WITHOUT degrading either feature:`,\n `1. Read what ${mergedIssueId} changed (git log/diff on origin/main) AND what your issue (${issueId}) intended.`,\n `2. Rebase your branch onto origin/main and resolve each conflict so BOTH features' intent is preserved.`,\n `3. Build, run tests, commit, and push, then re-request review.`,\n '',\n `Do not blindly accept one side of a conflict — understand both changesets first.`,\n ].join('\\n'),\n startedBy: 'merge-train:conflict-resolver',\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;yBAa+E;eAClB;aACrB;AAGxC,MAAM,YAAY,UAAU,KAAK;AAEjC,SAAS,iBAAiB,SAAgC;CACxD,MAAM,UAAU,4BAA4B,QAAQ;AACpD,KAAI,CAAC,QAAS,QAAO;AACrB,QAAO,KAAK,QAAQ,aAAa,cAAc,WAAW,QAAQ,aAAa,GAAG;;AAGpF,SAAgB,yBAAwC;AACtD,QAAO;EACL,mBAAmB,kBAAkB;GACnC,MAAM,SAAS,cAAc,aAAa;AAC1C,UAAO,OAAO,OAAO,4BAA4B,CAAC,CAC/C,QACE,OACC,GAAG,kBAAkB,QACrB,GAAG,gBAAgB,YACnB,GAAG,QAAQ,aAAa,KAAK,OAChC,CACA,KAAK,OAAO,GAAG,QAAQ;;EAG5B,eAAe,OAAO,YAA+C;GACnE,MAAM,KAAK,iBAAiB,QAAQ;AACpC,OAAI,CAAC,GAAI,QAAO,EAAE,QAAQ,cAAc;GACxC,MAAM,OAAO,QAAgB,UAAU,KAAK,EAAE,KAAK,IAAI,CAAC;AAExD,SAAM,IAAI,wBAAwB;GAClC,MAAM,EAAE,WAAW,MAAM,IAAI,yCAAyC;AACtE,OAAI,OAAO,MAAM,KAAK,IAAK,QAAO,EAAE,QAAQ,cAAc;AAE1D,OAAI;AACF,UAAM,IAAI,yBAAyB;AACnC,UAAM,IAAI,8BAA8B;AACxC,WAAO,EAAE,QAAQ,SAAS;WACpB;AACN,UAAM,IAAI,qBAAqB,CAAC,YAAY,GAAG;AAC/C,WAAO,EAAE,QAAQ,YAAY;;;EAIjC,wBAAwB,OAAO,YAAY;AAEzC,SAAM,SAAS,SAAS,UAAU;IAChC,QACE;IAEF,WAAW;IACZ,CAAC;;EAGJ,0BAA0B,OAAO,SAAS,kBAAkB;AAC1D,SAAM,SAAS,SAAS,QAAQ;IAC9B,QAAQ;KACN,iFAAiF,cAAc;KAC/F;KACA;KACA,gBAAgB,cAAc,8DAA8D,QAAQ;KACpG;KACA;KACA;KACA;KACD,CAAC,KAAK,KAAK;IACZ,WAAW;IACZ,CAAC;;EAEL"}
1
+ {"version":3,"file":"merge-train-deps-BTfXM5AR.js","names":[],"sources":["../../src/lib/cloister/merge-train-deps.ts"],"sourcesContent":["/**\n * Real wiring for the merge-train reconciler (PAN-1691). Lazy-loaded from\n * merge-train.ts only when the `flywheel.merge_train_enabled` flag is on, so it\n * is never imported during normal operation or the gating unit tests.\n *\n * This is pure I/O — git rebase/force-push and agent spawn — and is exercised\n * only with the flag on against a real merge, so it is not unit-tested. The\n * decision logic it feeds (`reconcileStaleSiblings`) and the flag gating\n * (`runMergeTrainReconcile`) are.\n */\nimport { join } from 'path';\nimport { promisify } from 'util';\nimport { exec } from 'child_process';\nimport { getAllReviewStatusesFromDb } from '../overdeck/review-status-sync.js';\nimport { resolveProjectFromIssueSync } from '../projects.js';\nimport { spawnRun } from '../agents.js';\nimport type { ReconcileDeps, RebaseStatus } from './merge-train-reconciler.js';\n\nconst execAsync = promisify(exec);\n\nfunction workspacePathFor(issueId: string): string | null {\n const project = resolveProjectFromIssueSync(issueId);\n if (!project) return null;\n return join(project.projectPath, 'workspaces', `feature-${issueId.toLowerCase()}`);\n}\n\nexport function buildRealReconcileDeps(): ReconcileDeps {\n return {\n getReadySiblings: (mergedIssueId) => {\n const merged = mergedIssueId.toUpperCase();\n return Object.values(getAllReviewStatusesFromDb())\n .filter(\n (rs) =>\n rs.readyForMerge === true &&\n rs.mergeStatus !== 'merged' &&\n rs.issueId.toUpperCase() !== merged,\n )\n .map((rs) => rs.issueId);\n },\n\n rebaseSibling: async (issueId): Promise<{ status: RebaseStatus }> => {\n const ws = workspacePathFor(issueId);\n if (!ws) return { status: 'up-to-date' };\n const run = (cmd: string) => execAsync(cmd, { cwd: ws });\n\n await run('git fetch origin main');\n const { stdout } = await run('git rev-list --count HEAD..origin/main');\n if (stdout.trim() === '0') return { status: 'up-to-date' };\n\n try {\n await run('git rebase origin/main');\n await run('git push --force-with-lease');\n return { status: 'clean' };\n } catch {\n await run('git rebase --abort').catch(() => {});\n return { status: 'conflict' };\n }\n },\n\n reDispatchVerification: async (issueId) => {\n // The branch HEAD moved after the rebase — re-run review on the new HEAD.\n await spawnRun(issueId, 'review', {\n prompt:\n 'Your branch was automatically rebased onto the latest main after another feature merged. ' +\n 'Re-review on the new HEAD and confirm the issue is still correct and ready to merge.',\n startedBy: 'merge-train:verification',\n });\n },\n\n dispatchConflictResolver: async (issueId, mergedIssueId) => {\n await spawnRun(issueId, 'work', {\n prompt: [\n `Your feature branch could not be cleanly rebased onto the latest main because ${mergedIssueId} just merged and conflicts with your changes.`,\n '',\n `Resolve the rebase conflict WITHOUT degrading either feature:`,\n `1. Read what ${mergedIssueId} changed (git log/diff on origin/main) AND what your issue (${issueId}) intended.`,\n `2. Rebase your branch onto origin/main and resolve each conflict so BOTH features' intent is preserved.`,\n `3. Build, run tests, commit, and push, then re-request review.`,\n '',\n `Do not blindly accept one side of a conflict — understand both changesets first.`,\n ].join('\\n'),\n startedBy: 'merge-train:conflict-resolver',\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;yBAa+E;eAClB;aACrB;AAGxC,MAAM,YAAY,UAAU,KAAK;AAEjC,SAAS,iBAAiB,SAAgC;CACxD,MAAM,UAAU,4BAA4B,QAAQ;AACpD,KAAI,CAAC,QAAS,QAAO;AACrB,QAAO,KAAK,QAAQ,aAAa,cAAc,WAAW,QAAQ,aAAa,GAAG;;AAGpF,SAAgB,yBAAwC;AACtD,QAAO;EACL,mBAAmB,kBAAkB;GACnC,MAAM,SAAS,cAAc,aAAa;AAC1C,UAAO,OAAO,OAAO,4BAA4B,CAAC,CAC/C,QACE,OACC,GAAG,kBAAkB,QACrB,GAAG,gBAAgB,YACnB,GAAG,QAAQ,aAAa,KAAK,OAChC,CACA,KAAK,OAAO,GAAG,QAAQ;;EAG5B,eAAe,OAAO,YAA+C;GACnE,MAAM,KAAK,iBAAiB,QAAQ;AACpC,OAAI,CAAC,GAAI,QAAO,EAAE,QAAQ,cAAc;GACxC,MAAM,OAAO,QAAgB,UAAU,KAAK,EAAE,KAAK,IAAI,CAAC;AAExD,SAAM,IAAI,wBAAwB;GAClC,MAAM,EAAE,WAAW,MAAM,IAAI,yCAAyC;AACtE,OAAI,OAAO,MAAM,KAAK,IAAK,QAAO,EAAE,QAAQ,cAAc;AAE1D,OAAI;AACF,UAAM,IAAI,yBAAyB;AACnC,UAAM,IAAI,8BAA8B;AACxC,WAAO,EAAE,QAAQ,SAAS;WACpB;AACN,UAAM,IAAI,qBAAqB,CAAC,YAAY,GAAG;AAC/C,WAAO,EAAE,QAAQ,YAAY;;;EAIjC,wBAAwB,OAAO,YAAY;AAEzC,SAAM,SAAS,SAAS,UAAU;IAChC,QACE;IAEF,WAAW;IACZ,CAAC;;EAGJ,0BAA0B,OAAO,SAAS,kBAAkB;AAC1D,SAAM,SAAS,SAAS,QAAQ;IAC9B,QAAQ;KACN,iFAAiF,cAAc;KAC/F;KACA;KACA,gBAAgB,cAAc,8DAA8D,QAAQ;KACpG;KACA;KACA;KACA;KACD,CAAC,KAAK,KAAK;IACZ,WAAW;IACZ,CAAC;;EAEL"}
@@ -1,3 +1,3 @@
1
- import { Gt as messageAgent, Wt as init_messaging } from "./agent-state-Ci6PhjOE.js";
1
+ import { Gt as messageAgent, Wt as init_messaging } from "./agent-state-B196fj1h.js";
2
2
  init_messaging();
3
3
  export { messageAgent };
@@ -3,21 +3,21 @@ import { On as resolveProjectFromIssueSync, fn as init_projects, gn as listProje
3
3
  import { l as init_activity_logger, o as emitActivityEntrySync } from "./activity-logger-DNYDzAOU.js";
4
4
  import { C as init_tmux, j as listSessionNames } from "./tmux-l-yvNWhg.js";
5
5
  import { c as init_control_settings, f as isFlywheelAutoPickupBacklog } from "./control-settings-BkaVFRdm.js";
6
- import { m as getAgentState, q as init_agents } from "./agent-state-Ci6PhjOE.js";
6
+ import { m as getAgentState, q as init_agents } from "./agent-state-B196fj1h.js";
7
7
  import { o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-Ci0LxMIq.js";
8
8
  import { a as readAutoSpawnOnFinalizeFlagAsync } from "./auto-spawn-consent-CJeQM5e0.js";
9
9
  import { o as init_lifecycle, s as isXBriefFilename } from "./lifecycle-BSQIQ1Sq.js";
10
10
  import { C as init_specs, N as getProjectPanPaths, P as init_paths, S as findSpecByIssue, f as readPlanSync, i as findPlanSync, s as init_io } from "./io-Cm4Sf_6P.js";
11
11
  import { i as loadCloisterConfig, r as init_config } from "./config-B-MLcKSo.js";
12
12
  import { n as resolveGitHubIssueSync, t as init_tracker_utils } from "./tracker-utils-McMENyKj.js";
13
- import { i as issue_service_singleton_exports, n as init_issue_service_singleton } from "./issue-service-singleton-BrZQJLRI.js";
14
- import { d as getReviewStatusSync, p as init_review_status } from "./review-status-BegAr86G.js";
13
+ import { i as issue_service_singleton_exports, n as init_issue_service_singleton } from "./issue-service-singleton-KcRrOiFD.js";
14
+ import { d as getReviewStatusSync, p as init_review_status } from "./review-status-yY5qt7Rl.js";
15
15
  import { f as init_github_app, p as isGitHubAppConfigured, v as listPullRequestsForHead } from "./github-app-BINlfWAA.js";
16
16
  import { h as init_pickup, r as LEGACY_PARKED_LABELS } from "./pickup-TwHZNJn4.js";
17
- import { r as activeOrderBookIssues } from "./flywheel-Is3w2lcT.js";
17
+ import { r as activeOrderBookIssues } from "./flywheel-DKldI63J.js";
18
18
  import { n as init_issue_closed, r as isIssueClosed } from "./issue-closed-D7aMUeMq.js";
19
19
  import { t as recordDeadEndNeedsYou } from "./dead-end-trip-B-zvz8Rw.js";
20
- import "./spawn-planning-session-FmJa6PCS.js";
20
+ import "./spawn-planning-session-CH8IYli7.js";
21
21
  import { n as spawnWorkAgentThroughAgentsEndpoint, t as init_work_agent_start } from "./work-agent-start-DA3P_ABv.js";
22
22
  import { Effect } from "effect";
23
23
  import { existsSync, readdirSync } from "fs";
@@ -654,4 +654,4 @@ async function reconcileOrphanProposedSpecs(options = {}) {
654
654
  //#endregion
655
655
  export { triggerRebuildAndStart as a, reconcileOrphanProposedSpecs as i, handleOrphanProposedSpec as n, decideAutonomousWorkDispatch as o, hasReviewPipelinePresence as r, gatherAutonomousWorkDispatchInput as s, findOrphanProposedSpecsForReconciler as t };
656
656
 
657
- //# sourceMappingURL=orphan-proposed-reconciler-DFHdQSEg.js.map
657
+ //# sourceMappingURL=orphan-proposed-reconciler-B898fk26.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"orphan-proposed-reconciler-DFHdQSEg.js","names":[],"sources":["../../src/lib/cloister/autonomous-work-dispatch.ts","../../src/lib/cloister/orphan-proposed-reconciler.ts"],"sourcesContent":["import { Effect } from 'effect';\nimport {\n EPIC_LABEL,\n LEGACY_PARKED_LABELS,\n OBJECTION_LABEL,\n PARKED_LABEL,\n READY_LABEL,\n RELEASED_LABEL,\n VETOED_LABEL,\n} from '../backlog/pickup.js';\nimport { isFlywheelAutoPickupBacklog } from '../overdeck/control-settings.js';\nimport { findSpecByIssue } from '../pan-dir/specs.js';\nimport { readAutoSpawnOnFinalizeFlagAsync } from '../planning/spawn-planning-session.js';\nimport { resolveProjectFromIssueSync } from '../projects.js';\nimport { activeOrderBookIssues } from './flywheel.js';\n\nexport interface AutonomousWorkDispatchInput {\n labels: readonly string[] | null;\n planned: boolean;\n autoPickupBacklog: boolean;\n activeBookMember: boolean;\n autoSpawnOnFinalizeConsent: boolean;\n}\n\ntype PlannedState = { status: string; itemCount: number } | null;\n\nexport interface AutonomousWorkDispatchDeps {\n getIssues?: () => Array<Record<string, unknown>>;\n isAutoPickupBacklog?: () => boolean | Promise<boolean>;\n resolveProject?: typeof resolveProjectFromIssueSync;\n activeBookIssues?: typeof activeOrderBookIssues;\n readAutoSpawnConsent?: (issueId: string) => boolean | Promise<boolean>;\n findPlannedState?: (projectRoot: string, issueId: string) => Promise<PlannedState>;\n knownPlanned?: boolean;\n now?: () => number;\n}\n\nexport type AutonomousWorkReleaseSource =\n | 'released-label'\n | 'auto-pickup'\n | 'active-order-book'\n | 'planning-consent';\n\nexport type AutonomousWorkDispatchDecision =\n | { allow: true; releaseSource: AutonomousWorkReleaseSource }\n | {\n allow: false;\n code:\n | 'not-ready'\n | 'not-planned'\n | 'not-released'\n | 'parked'\n | 'vetoed'\n | 'objection'\n | 'epic'\n | 'labels-unavailable';\n reason: string;\n };\n\nconst RELEASE_CONTEXT_CACHE_MS = 5_000;\nlet autoPickupCache: { expiresAt: number; value: boolean } | null = null;\nconst activeBookCache = new Map<string, { expiresAt: number; value: ReadonlySet<string> }>();\n\nexport function clearAutonomousWorkDispatchCaches(): void {\n autoPickupCache = null;\n activeBookCache.clear();\n}\n\nfunction getSharedIssues(): Array<Record<string, unknown>> {\n // Keep this lazy require aligned with autonomous-plan-dispatch: a static\n // import creates a lib → dashboard layering edge.\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { getSharedIssueService } = require('../../dashboard/server/services/issue-service-singleton.js') as typeof import('../../dashboard/server/services/issue-service-singleton.js');\n return getSharedIssueService().getIssues() as Array<Record<string, unknown>>;\n}\n\nasync function defaultFindPlannedState(projectRoot: string, issueId: string): Promise<PlannedState> {\n const entry = await Effect.runPromise(\n findSpecByIssue(projectRoot, issueId).pipe(Effect.catch(() => Effect.succeed(null))),\n );\n if (!entry) return null;\n return {\n status: entry.status,\n itemCount: Array.isArray(entry.document.plan?.items) ? entry.document.plan.items.length : 0,\n };\n}\n\nfunction isPlannedState(state: PlannedState): boolean {\n return state !== null\n && (state.status === 'proposed' || state.status === 'active')\n && state.itemCount > 0;\n}\n\nasync function cachedAutoPickup(deps: AutonomousWorkDispatchDeps, now: number): Promise<boolean> {\n if (deps.isAutoPickupBacklog) return deps.isAutoPickupBacklog();\n if (autoPickupCache && autoPickupCache.expiresAt > now) return autoPickupCache.value;\n const value = isFlywheelAutoPickupBacklog();\n autoPickupCache = { value, expiresAt: now + RELEASE_CONTEXT_CACHE_MS };\n return value;\n}\n\nasync function cachedActiveBookIssues(\n projectRoot: string,\n deps: AutonomousWorkDispatchDeps,\n now: number,\n): Promise<ReadonlySet<string>> {\n if (deps.activeBookIssues) return deps.activeBookIssues(projectRoot);\n const cached = activeBookCache.get(projectRoot);\n if (cached && cached.expiresAt > now) return cached.value;\n const value = await activeOrderBookIssues(projectRoot);\n activeBookCache.set(projectRoot, { value, expiresAt: now + RELEASE_CONTEXT_CACHE_MS });\n return value;\n}\n\nfunction emptyInput(labels: readonly string[] | null, planned = false): AutonomousWorkDispatchInput {\n return {\n labels,\n planned,\n autoPickupBacklog: false,\n activeBookMember: false,\n autoSpawnOnFinalizeConsent: false,\n };\n}\n\nexport async function gatherAutonomousWorkDispatchInput(\n issueId: string,\n deps: AutonomousWorkDispatchDeps = {},\n): Promise<AutonomousWorkDispatchInput> {\n const normalizedIssueId = issueId.trim().toUpperCase();\n let labels: readonly string[] | null = null;\n\n try {\n const issue = (deps.getIssues ?? getSharedIssues)()\n .find((candidate) => (\n typeof candidate['identifier'] === 'string'\n && candidate['identifier'].toUpperCase() === normalizedIssueId\n ));\n if (issue) {\n const rawLabels = Array.isArray(issue['labels']) ? issue['labels'] as unknown[] : [];\n labels = rawLabels\n .map((label) => (\n typeof label === 'string' ? label : ((label as { name?: string })?.name ?? '')\n ))\n .filter((label): label is string => Boolean(label));\n }\n } catch {\n // Autonomous dispatch fails closed when tracker labels cannot be read.\n }\n\n const labelDecision = decideAutonomousWorkDispatch({ ...emptyInput(labels, true) });\n if (!labelDecision.allow && labelDecision.code !== 'not-released') return emptyInput(labels);\n\n let project: ReturnType<typeof resolveProjectFromIssueSync> = null;\n let planned = deps.knownPlanned === true;\n if (!planned) {\n try {\n project = (deps.resolveProject ?? resolveProjectFromIssueSync)(normalizedIssueId);\n planned = Boolean(project && isPlannedState(\n await (deps.findPlannedState ?? defaultFindPlannedState)(project.projectPath, normalizedIssueId),\n ));\n } catch {\n planned = false;\n }\n }\n if (!planned) return emptyInput(labels);\n\n const normalizedLabels = new Set(labels?.map((label) => label.toLowerCase()));\n if (normalizedLabels.has(RELEASED_LABEL)) return emptyInput(labels, true);\n\n if (!project) {\n try {\n project = (deps.resolveProject ?? resolveProjectFromIssueSync)(normalizedIssueId);\n } catch {\n project = null;\n }\n }\n const now = (deps.now ?? Date.now)();\n const [autoPickupBacklog, activeIssues, autoSpawnOnFinalizeConsent] = await Promise.all([\n cachedAutoPickup(deps, now).catch(() => false),\n project ? cachedActiveBookIssues(project.projectPath, deps, now).catch(() => new Set<string>()) : new Set<string>(),\n Promise.resolve((deps.readAutoSpawnConsent ?? readAutoSpawnOnFinalizeFlagAsync)(normalizedIssueId)).catch(() => false),\n ]);\n\n return {\n labels,\n planned: true,\n autoPickupBacklog,\n activeBookMember: activeIssues.has(normalizedIssueId),\n autoSpawnOnFinalizeConsent,\n };\n}\n\nexport function decideAutonomousWorkDispatch(\n input: AutonomousWorkDispatchInput,\n): AutonomousWorkDispatchDecision {\n if (input.labels === null) {\n return {\n allow: false,\n code: 'labels-unavailable',\n reason:\n 'Autonomous work dispatch was refused because tracker labels are unavailable, so ready, released, parked, vetoed, objection, and epic state cannot be verified. Restore label access or run pan start manually.',\n };\n }\n\n const labels = new Set(input.labels.map((label) => label.toLowerCase()));\n const hasLabel = (label: string): boolean => labels.has(label);\n\n if (hasLabel(PARKED_LABEL) || LEGACY_PARKED_LABELS.some(hasLabel)) {\n return {\n allow: false,\n code: 'parked',\n reason:\n 'Autonomous work dispatch was refused because the issue is parked. Remove the parked label before allowing autonomous work, or run pan start manually.',\n };\n }\n\n if (hasLabel(VETOED_LABEL)) {\n return {\n allow: false,\n code: 'vetoed',\n reason:\n 'Autonomous work dispatch was refused because the issue is vetoed. Remove the veto before allowing autonomous work, or run pan start manually.',\n };\n }\n\n if (hasLabel(OBJECTION_LABEL)) {\n return {\n allow: false,\n code: 'objection',\n reason:\n 'Autonomous work dispatch was refused because the issue has an open objection. Resolve the objection before allowing autonomous work, or run pan start manually.',\n };\n }\n\n if (hasLabel(EPIC_LABEL)) {\n return {\n allow: false,\n code: 'epic',\n reason:\n 'Autonomous work dispatch was refused because the issue is an epic container. Start one of its child issues instead.',\n };\n }\n\n if (!hasLabel(READY_LABEL)) {\n return {\n allow: false,\n code: 'not-ready',\n reason:\n 'Autonomous work dispatch was refused because the issue is not ready. Add the ready label before allowing autonomous work, or run pan start manually.',\n };\n }\n\n if (!input.planned) {\n return {\n allow: false,\n code: 'not-planned',\n reason:\n 'Autonomous work dispatch was refused because no active implementation plan with work items is available. Complete planning or run pan start manually.',\n };\n }\n\n const releaseSource: AutonomousWorkReleaseSource | null = hasLabel(RELEASED_LABEL)\n ? 'released-label'\n : input.autoPickupBacklog\n ? 'auto-pickup'\n : input.activeBookMember\n ? 'active-order-book'\n : input.autoSpawnOnFinalizeConsent\n ? 'planning-consent'\n : null;\n if (!releaseSource) {\n return {\n allow: false,\n code: 'not-released',\n reason:\n 'Autonomous work dispatch was refused because the issue is not released and no release override applies. Add the released label, enable auto-pickup, include the issue in the active order book, or launch planning with auto-start; alternatively, run pan start manually.',\n };\n }\n\n return { allow: true, releaseSource };\n}\n","/**\n * Reconciles proposed specs only after the shared autonomous-work pickup gate\n * passes; explicit planning auto-start consent is a release source, not a bypass\n * for readiness, tracker-label availability, or blocker labels.\n */\nimport { exec } from 'child_process';\nimport { existsSync } from 'fs';\nimport { readdir, readFile } from 'fs/promises';\nimport { readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { promisify } from 'util';\nimport { Effect } from 'effect';\n\nimport { getAgentState, type AgentState } from '../agents.js';\nimport { emitActivityEntrySync } from '../activity-logger.js';\nimport { getInternalTokenSync, INTERNAL_TOKEN_HEADER } from '../internal-token.js';\nimport { getProjectPanPaths } from '../pan-dir/paths.js';\nimport { listProjects, resolveProjectFromIssueSync, type ProjectConfig } from '../projects.js';\nimport { getReviewStatusSync, type ReviewStatus } from '../review-status.js';\nimport { listSessionNames } from '../tmux.js';\nimport { findPlanSync, readPlanSync } from '../xbrief/io.js';\nimport { isXBriefFilename } from '../xbrief/lifecycle.js';\nimport type { XBriefDocument } from '../xbrief/types.js';\nimport { isGitHubAppConfigured, listPullRequestsForHead } from '../github-app.js';\nimport { resolveGitHubIssueSync } from '../tracker-utils.js';\nimport {\n decideAutonomousWorkDispatch,\n gatherAutonomousWorkDispatchInput,\n type AutonomousWorkDispatchDecision,\n} from './autonomous-work-dispatch.js';\nimport { loadCloisterConfig } from './config.js';\nimport { recordDeadEndNeedsYou } from './dead-end-trip.js';\nimport { clearIssueClosedCache, isIssueClosed } from './issue-closed.js';\nimport {\n spawnWorkAgentThroughAgentsEndpoint,\n type SpawnWorkAgentResult,\n} from './work-agent-start.js';\n\nexport { spawnWorkAgentThroughAgentsEndpoint };\nexport type { SpawnWorkAgentResult };\n\nconst DEFAULT_ATTEMPT_INTERVAL_MS = 5 * 60 * 1000;\nconst MAX_PICKUP_REFUSAL_REASONS = 512;\nconst execAsync = promisify(exec);\nconst attemptCooldowns = new Map<string, number>();\nconst pickupRefusalReasons = new Map<string, string>();\nconst terminalClosedIssueIds = new Set<string>();\nlet scanInFlight = false;\n\nexport interface OrphanProposedReconcilerConfig {\n enabled?: boolean;\n minAttemptIntervalMs?: number;\n}\n\ntype ProjectEntry = { key: string; config: Pick<ProjectConfig, 'name' | 'path'> };\n\ntype ProposedSpecState = {\n plan?: {\n id?: unknown;\n status?: unknown;\n items?: unknown;\n };\n};\n\nexport type ReviewPipelinePresenceStatus = Pick<ReviewStatus,\n 'reviewStatus' | 'testStatus' | 'mergeStatus' | 'readyForMerge' | 'prNumber' | 'prUrl'\n>;\n\nexport function hasReviewPipelinePresence(status: ReviewPipelinePresenceStatus | null): boolean {\n if (!status) return false;\n if (status.reviewStatus !== 'pending') return true;\n if (status.testStatus !== 'pending') return true;\n if (status.mergeStatus && status.mergeStatus !== 'pending') return true;\n if (status.readyForMerge === true) return true;\n if (status.prNumber != null) return true;\n if (typeof status.prUrl === 'string' && status.prUrl.trim().length > 0) return true;\n return false;\n}\n\nexport interface OrphanProposedCandidate {\n projectKey: string;\n projectName: string;\n projectPath: string;\n issueId: string;\n specPath: string;\n taskCount: number;\n planItemCount: number;\n}\n\nexport interface FindOrphanProposedOptions {\n projects?: ProjectEntry[];\n tmuxSessionNames?: readonly string[];\n getAgentStateForIssue?: (agentId: string) => Promise<Pick<AgentState, 'status' | 'paused' | 'troubled'> | null>;\n getReviewStatusForIssue?: (issueId: string) => ReviewPipelinePresenceStatus | null;\n closedIssueIds?: Set<string>;\n}\n\nexport interface ReconcileOrphanProposedOptions extends FindOrphanProposedOptions {\n now?: Date;\n config?: OrphanProposedReconcilerConfig;\n spawnWorkAgent?: (issueId: string, autoSpawnConsentRequired: boolean) => Promise<SpawnWorkAgentResult>;\n hasOpenPrForBranch?: (projectPath: string, issueId: string) => Promise<boolean>;\n evaluatePickupGate?: (issueId: string) => Promise<AutonomousWorkDispatchDecision>;\n dashboardOrigin?: string;\n}\n\nexport interface HandleOrphanProposedSpecOptions {\n spawnWorkAgent?: (issueId: string, autoSpawnConsentRequired: boolean) => Promise<SpawnWorkAgentResult>;\n hasOpenPrForBranch?: (projectPath: string, issueId: string) => Promise<boolean>;\n evaluatePickupGate?: (issueId: string) => Promise<AutonomousWorkDispatchDecision>;\n dashboardOrigin?: string;\n config?: OrphanProposedReconcilerConfig;\n /** Project override for tests / callers that already resolved the issue. */\n project?: { projectKey: string; projectPath: string };\n /** Spec override so the safety net does not re-read the file. */\n spec?: { path: string; doc: XBriefDocument };\n /** Liveness overrides for deterministic scans that already captured a snapshot. */\n tmuxSessionNames?: readonly string[];\n getAgentStateForIssue?: (agentId: string) => Promise<Pick<AgentState, 'status' | 'paused' | 'troubled'> | null>;\n closedIssueIds?: Set<string>;\n}\n\nasync function findSpecPathForIssue(projectPath: string, issueId: string): Promise<string | null> {\n const specsDir = getProjectPanPaths(projectPath).specsDir;\n if (!existsSync(specsDir)) return null;\n let filenames: string[];\n try {\n filenames = readdirSync(specsDir);\n } catch {\n return null;\n }\n for (const filename of filenames) {\n if (!isXBriefFilename(filename)) continue;\n const specPath = join(specsDir, filename);\n try {\n const doc = readPlanSync(specPath);\n if (normalizeIssueId(doc.plan?.id) === issueId.toUpperCase()) {\n return specPath;\n }\n } catch {\n // ignore unreadable specs\n }\n }\n return null;\n}\n\nfunction normalizeIssueId(value: unknown): string | null {\n return typeof value === 'string' && /^[A-Za-z]+-\\d+$/.test(value.trim())\n ? value.trim().toUpperCase()\n : null;\n}\n\nasync function readJsonFile<T>(path: string): Promise<T | null> {\n try {\n return JSON.parse(await readFile(path, 'utf-8')) as T;\n } catch {\n return null;\n }\n}\n\nasync function defaultGetAgentState(agentId: string): Promise<Pick<AgentState, 'status' | 'paused' | 'troubled'> | null> {\n return Effect.runPromise(getAgentState(agentId).pipe(Effect.catch(() => Effect.succeed(null))));\n}\n\nasync function loadProjectsForScan(projects?: ProjectEntry[]): Promise<ProjectEntry[]> {\n if (projects) return projects;\n return Effect.runPromise(listProjects().pipe(Effect.catch(() => Effect.succeed([]))));\n}\n\nasync function loadTmuxSessionNames(tmuxSessionNames?: readonly string[]): Promise<readonly string[]> {\n if (tmuxSessionNames) return tmuxSessionNames;\n return Effect.runPromise(listSessionNames().pipe(Effect.catch(() => Effect.succeed([]))));\n}\n\nfunction hasIssueScopedSession(tmuxSessionNames: readonly string[], agentId: string): boolean {\n return tmuxSessionNames.some((sessionName) => sessionName === agentId || sessionName.startsWith(`${agentId}-`));\n}\n\nasync function defaultHasOpenPrForBranch(projectPath: string, issueId: string): Promise<boolean> {\n const branch = `feature/${issueId.toLowerCase()}`;\n\n try {\n const resolved = resolveGitHubIssueSync(issueId);\n if (!resolved.isGitHub) {\n // Linear/GitLab-tracked issue: there is no GitHub PR to probe, and `gh`\n // would fail anyway — a polyrepo wrapper projectPath is not a git repo\n // (\"fatal: not a git repository\", PAN-3042).\n logReconcilerDiagnostic('open-pr-check-skipped', { projectPath, issueId, branch, reason: 'non-github-tracker' });\n return false;\n }\n if (isGitHubAppConfigured()) {\n return (await Effect.runPromise(listPullRequestsForHead(resolved.owner, resolved.repo, branch, 'open'))).length > 0;\n }\n\n // `--repo` keeps the probe independent of cwd: gh otherwise resolves the\n // repo from git remotes, which fails when projectPath has no git repo or no\n // origin (the polyrepo wrapper case).\n const result = await execAsync(`gh pr list --repo ${resolved.owner}/${resolved.repo} --head ${branch} --state open --json number --limit 1`, { cwd: projectPath }) as { stdout?: string } | string;\n const stdout = typeof result === 'string' ? result : result.stdout;\n const prs = JSON.parse(stdout ?? '[]') as unknown;\n return Array.isArray(prs) && prs.length > 0;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logReconcilerDiagnostic('open-pr-check-failed', { projectPath, issueId, branch, error: message });\n return false;\n }\n}\n\nexport async function findOrphanProposedSpecsForReconciler(options: FindOrphanProposedOptions = {}): Promise<OrphanProposedCandidate[]> {\n const projects = await loadProjectsForScan(options.projects);\n const tmuxSessionNames = await loadTmuxSessionNames(options.tmuxSessionNames);\n const getState = options.getAgentStateForIssue ?? defaultGetAgentState;\n const getReviewStatus = options.getReviewStatusForIssue ?? getReviewStatusSync;\n const candidates: OrphanProposedCandidate[] = [];\n\n for (const { key, config } of projects) {\n const specsDir = getProjectPanPaths(config.path).specsDir;\n if (!existsSync(specsDir)) continue;\n\n const entries = await readdir(specsDir, { withFileTypes: true }).catch(() => []);\n for (const entry of entries) {\n if (!entry.isFile() || !isXBriefFilename(entry.name)) continue;\n\n const specPath = join(specsDir, entry.name);\n const spec = await readJsonFile<ProposedSpecState>(specPath);\n if (spec?.plan?.status !== 'proposed') continue;\n\n const issueId = normalizeIssueId(spec.plan?.id);\n if (!issueId) continue;\n\n const agentId = `agent-${issueId.toLowerCase()}`;\n const state = await getState(agentId);\n if (hasIssueScopedSession(tmuxSessionNames, agentId)) continue;\n if (state?.status === 'starting' || state?.status === 'running') continue;\n if (state?.paused === true || state?.troubled === true) continue;\n if (hasReviewPipelinePresence(getReviewStatus(issueId))) {\n logReconcilerDiagnostic('candidate-excluded', { issueId, reason: 'review-pipeline-presence' });\n continue;\n }\n if (terminalClosedIssueIds.has(issueId)) continue;\n if (await isIssueClosed(issueId, options.closedIssueIds)) continue;\n\n const planItems = Array.isArray(spec.plan.items) ? spec.plan.items : [];\n const planItemCount = planItems.length;\n if (planItemCount === 0) continue;\n\n candidates.push({\n projectKey: key,\n projectName: config.name,\n projectPath: config.path,\n issueId,\n specPath,\n taskCount: planItemCount,\n planItemCount,\n });\n }\n }\n\n return candidates;\n}\n\nfunction internalDashboardOrigin(): string {\n const port = Number.parseInt(process.env['API_PORT'] ?? process.env['PORT'] ?? '3011', 10);\n return process.env['OVERDECK_INTERNAL_DASHBOARD_URL'] ?? `http://127.0.0.1:${port}`;\n}\n\nexport interface RebuildAndStartResult {\n triggered: boolean;\n error?: string;\n}\n\n/**\n * PAN-2520: trigger the `rebuild-and-start` recovery for a workspace whose Docker\n * stack is unhealthy — the same path the dashboard \"Rebuild & start\" button uses\n * (`POST /api/workspaces/:issueId/rebuild-and-start`, workspaces.ts). It rebuilds\n * the stack, then `pan start`s the work agent once the stack is healthy. Used by\n * the deacon dead-end recovery when a PAN-2209 respawn defers on `stack-unhealthy`\n * (which would otherwise loop forever, since nothing else rebuilds the stack).\n */\nexport async function triggerRebuildAndStart(\n issueId: string,\n dashboardOrigin = internalDashboardOrigin(),\n): Promise<RebuildAndStartResult> {\n const internalToken = getInternalTokenSync();\n const response = await fetch(\n new URL(`/api/workspaces/${encodeURIComponent(issueId)}/rebuild-and-start`, dashboardOrigin),\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n origin: dashboardOrigin,\n ...(internalToken ? { [INTERNAL_TOKEN_HEADER]: internalToken } : {}),\n },\n body: JSON.stringify({ startedBy: 'workspace-rebuild-recovery' }),\n },\n );\n const body = await response.json().catch(() => ({})) as Record<string, unknown>;\n if (response.ok && body['success'] !== false) {\n return { triggered: true };\n }\n return {\n triggered: false,\n error: typeof body['error'] === 'string'\n ? body['error']\n : `rebuild-and-start returned HTTP ${response.status}`,\n };\n}\n\n/**\n * Surface a real, actioned reconciler outcome in the dashboard activity feed.\n * Use this ONLY when something actually happened that a human should see — a\n * work agent was started, or a start genuinely failed. `message` must read as a\n * plain sentence (it is what the feed shows), not a machine event name.\n */\nfunction emitReconcilerActivity(\n level: 'info' | 'warn' | 'error' | 'success',\n message: string,\n details: Record<string, unknown> = {},\n issueId = 'ALL',\n): void {\n const eventIssueId = issueId.toUpperCase();\n emitActivityEntrySync({\n source: 'cloister',\n level,\n issueId: eventIssueId,\n message,\n details: JSON.stringify({\n ...details,\n issueId: eventIssueId,\n timestamp: new Date().toISOString(),\n }),\n });\n}\n\n/**\n * Per-cycle diagnostic trail — console only, never the user activity feed.\n * The reconciler scans on every patrol (~60s); scan-start / orphan-detected /\n * cooldown-skip chatter was flooding the feed and reading as cryptic machine\n * codes (PAN-1626). Those belong in logs, not in front of the operator.\n */\nfunction logReconcilerDiagnostic(kind: string, info: Record<string, unknown> = {}): void {\n console.debug(`[orphan-proposed-reconciler] ${kind}`, info);\n}\n\nasync function recordPickupRefusal(\n issueId: string,\n now: number,\n decision: Extract<AutonomousWorkDispatchDecision, { allow: false }>,\n): Promise<string[]> {\n const reason = `pickup-gate:${decision.code}`;\n logReconcilerDiagnostic('spawn-skipped', { issueId, reason });\n attemptCooldowns.set(issueId, now);\n if (pickupRefusalReasons.get(issueId) !== decision.reason) {\n if (!pickupRefusalReasons.has(issueId) && pickupRefusalReasons.size >= MAX_PICKUP_REFUSAL_REASONS) {\n const oldestIssueId = pickupRefusalReasons.keys().next().value;\n if (oldestIssueId) pickupRefusalReasons.delete(oldestIssueId);\n }\n pickupRefusalReasons.set(issueId, decision.reason);\n await recordDeadEndNeedsYou(issueId, 'orphan-proposed-pickup-gate', 'proposed', decision.reason);\n }\n return [`Skipped orphan proposed spec ${issueId}: ${reason}`];\n}\n\nasync function defaultEvaluatePickupGate(issueId: string): Promise<AutonomousWorkDispatchDecision> {\n return decideAutonomousWorkDispatch(await gatherAutonomousWorkDispatchInput(issueId, { knownPlanned: true }));\n}\n\n/**\n * PAN-1908: reactive orphan-proposed handler. When a spec reaches `proposed`,\n * the autonomous-work pickup gate allows it, and no work agent is\n * running/starting, spawn a work agent without scanning all project specs.\n */\nexport async function handleOrphanProposedSpec(\n issueId: string,\n options: HandleOrphanProposedSpecOptions = {},\n): Promise<string[]> {\n const upperIssueId = issueId.trim().toUpperCase();\n if (!upperIssueId) return [];\n\n const loadedConfig = options.config ?? await Effect.runPromise(\n loadCloisterConfig().pipe(\n Effect.map(config => config.orphanProposedReconciler ?? { enabled: true, minAttemptIntervalMs: DEFAULT_ATTEMPT_INTERVAL_MS }),\n Effect.catch(() => Effect.succeed({ enabled: true, minAttemptIntervalMs: DEFAULT_ATTEMPT_INTERVAL_MS })),\n ),\n );\n if (loadedConfig.enabled === false) return [];\n\n const now = Date.now();\n const minAttemptIntervalMs = Math.max(loadedConfig.minAttemptIntervalMs ?? DEFAULT_ATTEMPT_INTERVAL_MS, DEFAULT_ATTEMPT_INTERVAL_MS);\n const lastAttempt = attemptCooldowns.get(upperIssueId);\n if (lastAttempt !== undefined && now - lastAttempt < minAttemptIntervalMs) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'cooldown' });\n return [];\n }\n\n const resolved = options.project ?? resolveProjectFromIssueSync(upperIssueId);\n if (!resolved) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'no-project' });\n return [];\n }\n const projectPath = resolved.projectPath;\n const projectKey = resolved.projectKey;\n\n const issueLower = upperIssueId.toLowerCase();\n\n let planDoc: XBriefDocument;\n let planPath: string | null;\n if (options.spec) {\n planPath = options.spec.path;\n planDoc = options.spec.doc;\n } else {\n const workspacePath = join(projectPath, 'workspaces', `feature-${issueLower}`);\n planPath = findPlanSync(workspacePath) ?? await findSpecPathForIssue(projectPath, upperIssueId);\n if (!planPath) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'no-spec' });\n return [];\n }\n\n try {\n planDoc = readPlanSync(planPath);\n } catch {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'spec-unreadable' });\n return [];\n }\n }\n\n if (planDoc.plan?.status !== 'proposed') {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'not-proposed', status: planDoc.plan?.status });\n return [];\n }\n\n let pickupGate: AutonomousWorkDispatchDecision;\n try {\n pickupGate = await (options.evaluatePickupGate ?? defaultEvaluatePickupGate)(upperIssueId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n pickupGate = {\n allow: false,\n code: 'labels-unavailable',\n reason: `Autonomous work dispatch was refused because pickup evaluation failed: ${message}`,\n };\n }\n if (!pickupGate.allow) return recordPickupRefusal(upperIssueId, now, pickupGate);\n pickupRefusalReasons.delete(upperIssueId);\n\n const agentId = `agent-${issueLower}`;\n\n // PAN-1908: prefer agents-table state (fast) but fall back to state.json.\n const agentState = options.getAgentStateForIssue\n ? await options.getAgentStateForIssue(agentId)\n : await Effect.runPromise(getAgentState(agentId).pipe(Effect.catch(() => Effect.succeed(null))));\n if (agentState?.status === 'starting' || agentState?.status === 'running') {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'agent-active' });\n return [];\n }\n if (agentState?.paused === true || agentState?.troubled === true) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: agentState.paused ? 'paused' : 'troubled' });\n return [];\n }\n\n // Any tmux session for the issue means the pipeline is active here.\n const sessions = options.tmuxSessionNames\n ?? await Effect.runPromise(listSessionNames().pipe(Effect.catch(() => Effect.succeed([]))));\n if (hasIssueScopedSession(sessions, agentId)) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'issue-scoped-session' });\n return [];\n }\n\n if (hasReviewPipelinePresence(getReviewStatusSync(upperIssueId))) {\n logReconcilerDiagnostic('candidate-excluded', { issueId: upperIssueId, reason: 'review-pipeline-presence' });\n return [];\n }\n\n if (terminalClosedIssueIds.has(upperIssueId)) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'terminal-closed' });\n return [];\n }\n if (await isIssueClosed(upperIssueId, options.closedIssueIds)) {\n terminalClosedIssueIds.add(upperIssueId);\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'closed' });\n return [];\n }\n\n const planItems = Array.isArray(planDoc.plan?.items) ? planDoc.plan.items : [];\n const planItemCount = planItems.length;\n if (planItemCount === 0) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'empty-plan', planItemCount });\n return [];\n }\n\n try {\n if (await (options.hasOpenPrForBranch ?? defaultHasOpenPrForBranch)(projectPath, upperIssueId)) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'open-pr' });\n return [`Skipped orphan proposed spec ${upperIssueId}: open-pr`];\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logReconcilerDiagnostic('open-pr-check-failed', { issueId: upperIssueId, error: message });\n }\n\n attemptCooldowns.set(upperIssueId, now);\n\n try {\n const autoSpawnConsentRequired = pickupGate.releaseSource === 'planning-consent';\n const spawn = await (options.spawnWorkAgent\n ?? ((id, required) => spawnWorkAgentThroughAgentsEndpoint(id, options.dashboardOrigin, required)))(\n upperIssueId,\n autoSpawnConsentRequired,\n );\n if (spawn.spawned) {\n emitReconcilerActivity(\n 'success',\n spawn.queued\n ? `Queued container startup for ${upperIssueId} before work-agent spawn`\n : `Started work agent for ${upperIssueId} — proposed spec had tasks but no running agent`,\n { issueId: upperIssueId, agentId: spawn.agentId, queued: spawn.queued === true, projectKey, projectPath },\n upperIssueId,\n );\n return [spawn.queued\n ? `Queued container startup for orphan proposed spec ${upperIssueId}`\n : `Spawned work agent for orphan proposed spec ${upperIssueId}`];\n }\n\n const reason = spawn.skippedReason ?? 'spawn-failed';\n if (reason === 'closed-issue') {\n terminalClosedIssueIds.add(upperIssueId);\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason, error: spawn.error });\n return [`Skipped orphan proposed spec ${upperIssueId}: ${reason}`];\n }\n emitReconcilerActivity(\n 'warn',\n `Couldn't start work agent for ${upperIssueId}: ${reason}`,\n { issueId: upperIssueId, error: spawn.error, projectKey, projectPath },\n upperIssueId,\n );\n return [`Skipped orphan proposed spec ${upperIssueId}: ${reason}`];\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n emitReconcilerActivity(\n 'error',\n `Couldn't start work agent for ${upperIssueId}: ${message}`,\n { issueId: upperIssueId, projectKey, projectPath },\n upperIssueId,\n );\n return [`Skipped orphan proposed spec ${upperIssueId}: spawn-failed`];\n }\n}\n\n/**\n * PAN-1908: thin dropped-event safety net for orphan proposed specs. The\n * primary path is reactive via handleOrphanProposedSpec on\n * issue.statusChanged(todo). This net finds candidate issueIds and delegates\n * to the same handler so the eligibility logic lives in one place.\n */\nexport async function reconcileOrphanProposedSpecs(options: ReconcileOrphanProposedOptions = {}): Promise<string[]> {\n const loadedConfig = options.config ?? await Effect.runPromise(\n loadCloisterConfig().pipe(\n Effect.map(config => config.orphanProposedReconciler ?? { enabled: true, minAttemptIntervalMs: DEFAULT_ATTEMPT_INTERVAL_MS }),\n Effect.catch(() => Effect.succeed({ enabled: true, minAttemptIntervalMs: DEFAULT_ATTEMPT_INTERVAL_MS })),\n ),\n );\n if (loadedConfig.enabled === false) return [];\n if (scanInFlight) {\n logReconcilerDiagnostic('scan-skipped', { reason: 'previous scan still running' });\n return [];\n }\n\n scanInFlight = true;\n try {\n const actions: string[] = [];\n const candidates = await findOrphanProposedSpecsForReconciler(options);\n const liveCandidateIds = new Set(candidates.map(candidate => candidate.issueId));\n for (const issueId of pickupRefusalReasons.keys()) {\n if (!liveCandidateIds.has(issueId)) pickupRefusalReasons.delete(issueId);\n }\n\n for (const candidate of candidates) {\n let planDoc: XBriefDocument;\n try {\n planDoc = readPlanSync(candidate.specPath);\n } catch {\n logReconcilerDiagnostic('spawn-skipped', { issueId: candidate.issueId, reason: 'spec-unreadable' });\n continue;\n }\n\n const result = await handleOrphanProposedSpec(candidate.issueId, {\n spawnWorkAgent: options.spawnWorkAgent,\n hasOpenPrForBranch: options.hasOpenPrForBranch,\n evaluatePickupGate: options.evaluatePickupGate,\n dashboardOrigin: options.dashboardOrigin,\n config: { enabled: true, minAttemptIntervalMs: loadedConfig.minAttemptIntervalMs },\n project: { projectKey: candidate.projectKey, projectPath: candidate.projectPath },\n spec: { path: candidate.specPath, doc: planDoc },\n tmuxSessionNames: options.tmuxSessionNames,\n getAgentStateForIssue: options.getAgentStateForIssue,\n closedIssueIds: options.closedIssueIds,\n });\n actions.push(...result);\n }\n\n return actions;\n } finally {\n scanInFlight = false;\n }\n}\n\nexport function clearOrphanProposedAttemptCooldowns(): void {\n attemptCooldowns.clear();\n pickupRefusalReasons.clear();\n terminalClosedIssueIds.clear();\n clearIssueClosedCache();\n scanInFlight = false;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"orphan-proposed-reconciler-B898fk26.js","names":[],"sources":["../../src/lib/cloister/autonomous-work-dispatch.ts","../../src/lib/cloister/orphan-proposed-reconciler.ts"],"sourcesContent":["import { Effect } from 'effect';\nimport {\n EPIC_LABEL,\n LEGACY_PARKED_LABELS,\n OBJECTION_LABEL,\n PARKED_LABEL,\n READY_LABEL,\n RELEASED_LABEL,\n VETOED_LABEL,\n} from '../backlog/pickup.js';\nimport { isFlywheelAutoPickupBacklog } from '../overdeck/control-settings.js';\nimport { findSpecByIssue } from '../pan-dir/specs.js';\nimport { readAutoSpawnOnFinalizeFlagAsync } from '../planning/spawn-planning-session.js';\nimport { resolveProjectFromIssueSync } from '../projects.js';\nimport { activeOrderBookIssues } from './flywheel.js';\n\nexport interface AutonomousWorkDispatchInput {\n labels: readonly string[] | null;\n planned: boolean;\n autoPickupBacklog: boolean;\n activeBookMember: boolean;\n autoSpawnOnFinalizeConsent: boolean;\n}\n\ntype PlannedState = { status: string; itemCount: number } | null;\n\nexport interface AutonomousWorkDispatchDeps {\n getIssues?: () => Array<Record<string, unknown>>;\n isAutoPickupBacklog?: () => boolean | Promise<boolean>;\n resolveProject?: typeof resolveProjectFromIssueSync;\n activeBookIssues?: typeof activeOrderBookIssues;\n readAutoSpawnConsent?: (issueId: string) => boolean | Promise<boolean>;\n findPlannedState?: (projectRoot: string, issueId: string) => Promise<PlannedState>;\n knownPlanned?: boolean;\n now?: () => number;\n}\n\nexport type AutonomousWorkReleaseSource =\n | 'released-label'\n | 'auto-pickup'\n | 'active-order-book'\n | 'planning-consent';\n\nexport type AutonomousWorkDispatchDecision =\n | { allow: true; releaseSource: AutonomousWorkReleaseSource }\n | {\n allow: false;\n code:\n | 'not-ready'\n | 'not-planned'\n | 'not-released'\n | 'parked'\n | 'vetoed'\n | 'objection'\n | 'epic'\n | 'labels-unavailable';\n reason: string;\n };\n\nconst RELEASE_CONTEXT_CACHE_MS = 5_000;\nlet autoPickupCache: { expiresAt: number; value: boolean } | null = null;\nconst activeBookCache = new Map<string, { expiresAt: number; value: ReadonlySet<string> }>();\n\nexport function clearAutonomousWorkDispatchCaches(): void {\n autoPickupCache = null;\n activeBookCache.clear();\n}\n\nfunction getSharedIssues(): Array<Record<string, unknown>> {\n // Keep this lazy require aligned with autonomous-plan-dispatch: a static\n // import creates a lib → dashboard layering edge.\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { getSharedIssueService } = require('../../dashboard/server/services/issue-service-singleton.js') as typeof import('../../dashboard/server/services/issue-service-singleton.js');\n return getSharedIssueService().getIssues() as Array<Record<string, unknown>>;\n}\n\nasync function defaultFindPlannedState(projectRoot: string, issueId: string): Promise<PlannedState> {\n const entry = await Effect.runPromise(\n findSpecByIssue(projectRoot, issueId).pipe(Effect.catch(() => Effect.succeed(null))),\n );\n if (!entry) return null;\n return {\n status: entry.status,\n itemCount: Array.isArray(entry.document.plan?.items) ? entry.document.plan.items.length : 0,\n };\n}\n\nfunction isPlannedState(state: PlannedState): boolean {\n return state !== null\n && (state.status === 'proposed' || state.status === 'active')\n && state.itemCount > 0;\n}\n\nasync function cachedAutoPickup(deps: AutonomousWorkDispatchDeps, now: number): Promise<boolean> {\n if (deps.isAutoPickupBacklog) return deps.isAutoPickupBacklog();\n if (autoPickupCache && autoPickupCache.expiresAt > now) return autoPickupCache.value;\n const value = isFlywheelAutoPickupBacklog();\n autoPickupCache = { value, expiresAt: now + RELEASE_CONTEXT_CACHE_MS };\n return value;\n}\n\nasync function cachedActiveBookIssues(\n projectRoot: string,\n deps: AutonomousWorkDispatchDeps,\n now: number,\n): Promise<ReadonlySet<string>> {\n if (deps.activeBookIssues) return deps.activeBookIssues(projectRoot);\n const cached = activeBookCache.get(projectRoot);\n if (cached && cached.expiresAt > now) return cached.value;\n const value = await activeOrderBookIssues(projectRoot);\n activeBookCache.set(projectRoot, { value, expiresAt: now + RELEASE_CONTEXT_CACHE_MS });\n return value;\n}\n\nfunction emptyInput(labels: readonly string[] | null, planned = false): AutonomousWorkDispatchInput {\n return {\n labels,\n planned,\n autoPickupBacklog: false,\n activeBookMember: false,\n autoSpawnOnFinalizeConsent: false,\n };\n}\n\nexport async function gatherAutonomousWorkDispatchInput(\n issueId: string,\n deps: AutonomousWorkDispatchDeps = {},\n): Promise<AutonomousWorkDispatchInput> {\n const normalizedIssueId = issueId.trim().toUpperCase();\n let labels: readonly string[] | null = null;\n\n try {\n const issue = (deps.getIssues ?? getSharedIssues)()\n .find((candidate) => (\n typeof candidate['identifier'] === 'string'\n && candidate['identifier'].toUpperCase() === normalizedIssueId\n ));\n if (issue) {\n const rawLabels = Array.isArray(issue['labels']) ? issue['labels'] as unknown[] : [];\n labels = rawLabels\n .map((label) => (\n typeof label === 'string' ? label : ((label as { name?: string })?.name ?? '')\n ))\n .filter((label): label is string => Boolean(label));\n }\n } catch {\n // Autonomous dispatch fails closed when tracker labels cannot be read.\n }\n\n const labelDecision = decideAutonomousWorkDispatch({ ...emptyInput(labels, true) });\n if (!labelDecision.allow && labelDecision.code !== 'not-released') return emptyInput(labels);\n\n let project: ReturnType<typeof resolveProjectFromIssueSync> = null;\n let planned = deps.knownPlanned === true;\n if (!planned) {\n try {\n project = (deps.resolveProject ?? resolveProjectFromIssueSync)(normalizedIssueId);\n planned = Boolean(project && isPlannedState(\n await (deps.findPlannedState ?? defaultFindPlannedState)(project.projectPath, normalizedIssueId),\n ));\n } catch {\n planned = false;\n }\n }\n if (!planned) return emptyInput(labels);\n\n const normalizedLabels = new Set(labels?.map((label) => label.toLowerCase()));\n if (normalizedLabels.has(RELEASED_LABEL)) return emptyInput(labels, true);\n\n if (!project) {\n try {\n project = (deps.resolveProject ?? resolveProjectFromIssueSync)(normalizedIssueId);\n } catch {\n project = null;\n }\n }\n const now = (deps.now ?? Date.now)();\n const [autoPickupBacklog, activeIssues, autoSpawnOnFinalizeConsent] = await Promise.all([\n cachedAutoPickup(deps, now).catch(() => false),\n project ? cachedActiveBookIssues(project.projectPath, deps, now).catch(() => new Set<string>()) : new Set<string>(),\n Promise.resolve((deps.readAutoSpawnConsent ?? readAutoSpawnOnFinalizeFlagAsync)(normalizedIssueId)).catch(() => false),\n ]);\n\n return {\n labels,\n planned: true,\n autoPickupBacklog,\n activeBookMember: activeIssues.has(normalizedIssueId),\n autoSpawnOnFinalizeConsent,\n };\n}\n\nexport function decideAutonomousWorkDispatch(\n input: AutonomousWorkDispatchInput,\n): AutonomousWorkDispatchDecision {\n if (input.labels === null) {\n return {\n allow: false,\n code: 'labels-unavailable',\n reason:\n 'Autonomous work dispatch was refused because tracker labels are unavailable, so ready, released, parked, vetoed, objection, and epic state cannot be verified. Restore label access or run pan start manually.',\n };\n }\n\n const labels = new Set(input.labels.map((label) => label.toLowerCase()));\n const hasLabel = (label: string): boolean => labels.has(label);\n\n if (hasLabel(PARKED_LABEL) || LEGACY_PARKED_LABELS.some(hasLabel)) {\n return {\n allow: false,\n code: 'parked',\n reason:\n 'Autonomous work dispatch was refused because the issue is parked. Remove the parked label before allowing autonomous work, or run pan start manually.',\n };\n }\n\n if (hasLabel(VETOED_LABEL)) {\n return {\n allow: false,\n code: 'vetoed',\n reason:\n 'Autonomous work dispatch was refused because the issue is vetoed. Remove the veto before allowing autonomous work, or run pan start manually.',\n };\n }\n\n if (hasLabel(OBJECTION_LABEL)) {\n return {\n allow: false,\n code: 'objection',\n reason:\n 'Autonomous work dispatch was refused because the issue has an open objection. Resolve the objection before allowing autonomous work, or run pan start manually.',\n };\n }\n\n if (hasLabel(EPIC_LABEL)) {\n return {\n allow: false,\n code: 'epic',\n reason:\n 'Autonomous work dispatch was refused because the issue is an epic container. Start one of its child issues instead.',\n };\n }\n\n if (!hasLabel(READY_LABEL)) {\n return {\n allow: false,\n code: 'not-ready',\n reason:\n 'Autonomous work dispatch was refused because the issue is not ready. Add the ready label before allowing autonomous work, or run pan start manually.',\n };\n }\n\n if (!input.planned) {\n return {\n allow: false,\n code: 'not-planned',\n reason:\n 'Autonomous work dispatch was refused because no active implementation plan with work items is available. Complete planning or run pan start manually.',\n };\n }\n\n const releaseSource: AutonomousWorkReleaseSource | null = hasLabel(RELEASED_LABEL)\n ? 'released-label'\n : input.autoPickupBacklog\n ? 'auto-pickup'\n : input.activeBookMember\n ? 'active-order-book'\n : input.autoSpawnOnFinalizeConsent\n ? 'planning-consent'\n : null;\n if (!releaseSource) {\n return {\n allow: false,\n code: 'not-released',\n reason:\n 'Autonomous work dispatch was refused because the issue is not released and no release override applies. Add the released label, enable auto-pickup, include the issue in the active order book, or launch planning with auto-start; alternatively, run pan start manually.',\n };\n }\n\n return { allow: true, releaseSource };\n}\n","/**\n * Reconciles proposed specs only after the shared autonomous-work pickup gate\n * passes; explicit planning auto-start consent is a release source, not a bypass\n * for readiness, tracker-label availability, or blocker labels.\n */\nimport { exec } from 'child_process';\nimport { existsSync } from 'fs';\nimport { readdir, readFile } from 'fs/promises';\nimport { readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { promisify } from 'util';\nimport { Effect } from 'effect';\n\nimport { getAgentState, type AgentState } from '../agents.js';\nimport { emitActivityEntrySync } from '../activity-logger.js';\nimport { getInternalTokenSync, INTERNAL_TOKEN_HEADER } from '../internal-token.js';\nimport { getProjectPanPaths } from '../pan-dir/paths.js';\nimport { listProjects, resolveProjectFromIssueSync, type ProjectConfig } from '../projects.js';\nimport { getReviewStatusSync, type ReviewStatus } from '../review-status.js';\nimport { listSessionNames } from '../tmux.js';\nimport { findPlanSync, readPlanSync } from '../xbrief/io.js';\nimport { isXBriefFilename } from '../xbrief/lifecycle.js';\nimport type { XBriefDocument } from '../xbrief/types.js';\nimport { isGitHubAppConfigured, listPullRequestsForHead } from '../github-app.js';\nimport { resolveGitHubIssueSync } from '../tracker-utils.js';\nimport {\n decideAutonomousWorkDispatch,\n gatherAutonomousWorkDispatchInput,\n type AutonomousWorkDispatchDecision,\n} from './autonomous-work-dispatch.js';\nimport { loadCloisterConfig } from './config.js';\nimport { recordDeadEndNeedsYou } from './dead-end-trip.js';\nimport { clearIssueClosedCache, isIssueClosed } from './issue-closed.js';\nimport {\n spawnWorkAgentThroughAgentsEndpoint,\n type SpawnWorkAgentResult,\n} from './work-agent-start.js';\n\nexport { spawnWorkAgentThroughAgentsEndpoint };\nexport type { SpawnWorkAgentResult };\n\nconst DEFAULT_ATTEMPT_INTERVAL_MS = 5 * 60 * 1000;\nconst MAX_PICKUP_REFUSAL_REASONS = 512;\nconst execAsync = promisify(exec);\nconst attemptCooldowns = new Map<string, number>();\nconst pickupRefusalReasons = new Map<string, string>();\nconst terminalClosedIssueIds = new Set<string>();\nlet scanInFlight = false;\n\nexport interface OrphanProposedReconcilerConfig {\n enabled?: boolean;\n minAttemptIntervalMs?: number;\n}\n\ntype ProjectEntry = { key: string; config: Pick<ProjectConfig, 'name' | 'path'> };\n\ntype ProposedSpecState = {\n plan?: {\n id?: unknown;\n status?: unknown;\n items?: unknown;\n };\n};\n\nexport type ReviewPipelinePresenceStatus = Pick<ReviewStatus,\n 'reviewStatus' | 'testStatus' | 'mergeStatus' | 'readyForMerge' | 'prNumber' | 'prUrl'\n>;\n\nexport function hasReviewPipelinePresence(status: ReviewPipelinePresenceStatus | null): boolean {\n if (!status) return false;\n if (status.reviewStatus !== 'pending') return true;\n if (status.testStatus !== 'pending') return true;\n if (status.mergeStatus && status.mergeStatus !== 'pending') return true;\n if (status.readyForMerge === true) return true;\n if (status.prNumber != null) return true;\n if (typeof status.prUrl === 'string' && status.prUrl.trim().length > 0) return true;\n return false;\n}\n\nexport interface OrphanProposedCandidate {\n projectKey: string;\n projectName: string;\n projectPath: string;\n issueId: string;\n specPath: string;\n taskCount: number;\n planItemCount: number;\n}\n\nexport interface FindOrphanProposedOptions {\n projects?: ProjectEntry[];\n tmuxSessionNames?: readonly string[];\n getAgentStateForIssue?: (agentId: string) => Promise<Pick<AgentState, 'status' | 'paused' | 'troubled'> | null>;\n getReviewStatusForIssue?: (issueId: string) => ReviewPipelinePresenceStatus | null;\n closedIssueIds?: Set<string>;\n}\n\nexport interface ReconcileOrphanProposedOptions extends FindOrphanProposedOptions {\n now?: Date;\n config?: OrphanProposedReconcilerConfig;\n spawnWorkAgent?: (issueId: string, autoSpawnConsentRequired: boolean) => Promise<SpawnWorkAgentResult>;\n hasOpenPrForBranch?: (projectPath: string, issueId: string) => Promise<boolean>;\n evaluatePickupGate?: (issueId: string) => Promise<AutonomousWorkDispatchDecision>;\n dashboardOrigin?: string;\n}\n\nexport interface HandleOrphanProposedSpecOptions {\n spawnWorkAgent?: (issueId: string, autoSpawnConsentRequired: boolean) => Promise<SpawnWorkAgentResult>;\n hasOpenPrForBranch?: (projectPath: string, issueId: string) => Promise<boolean>;\n evaluatePickupGate?: (issueId: string) => Promise<AutonomousWorkDispatchDecision>;\n dashboardOrigin?: string;\n config?: OrphanProposedReconcilerConfig;\n /** Project override for tests / callers that already resolved the issue. */\n project?: { projectKey: string; projectPath: string };\n /** Spec override so the safety net does not re-read the file. */\n spec?: { path: string; doc: XBriefDocument };\n /** Liveness overrides for deterministic scans that already captured a snapshot. */\n tmuxSessionNames?: readonly string[];\n getAgentStateForIssue?: (agentId: string) => Promise<Pick<AgentState, 'status' | 'paused' | 'troubled'> | null>;\n closedIssueIds?: Set<string>;\n}\n\nasync function findSpecPathForIssue(projectPath: string, issueId: string): Promise<string | null> {\n const specsDir = getProjectPanPaths(projectPath).specsDir;\n if (!existsSync(specsDir)) return null;\n let filenames: string[];\n try {\n filenames = readdirSync(specsDir);\n } catch {\n return null;\n }\n for (const filename of filenames) {\n if (!isXBriefFilename(filename)) continue;\n const specPath = join(specsDir, filename);\n try {\n const doc = readPlanSync(specPath);\n if (normalizeIssueId(doc.plan?.id) === issueId.toUpperCase()) {\n return specPath;\n }\n } catch {\n // ignore unreadable specs\n }\n }\n return null;\n}\n\nfunction normalizeIssueId(value: unknown): string | null {\n return typeof value === 'string' && /^[A-Za-z]+-\\d+$/.test(value.trim())\n ? value.trim().toUpperCase()\n : null;\n}\n\nasync function readJsonFile<T>(path: string): Promise<T | null> {\n try {\n return JSON.parse(await readFile(path, 'utf-8')) as T;\n } catch {\n return null;\n }\n}\n\nasync function defaultGetAgentState(agentId: string): Promise<Pick<AgentState, 'status' | 'paused' | 'troubled'> | null> {\n return Effect.runPromise(getAgentState(agentId).pipe(Effect.catch(() => Effect.succeed(null))));\n}\n\nasync function loadProjectsForScan(projects?: ProjectEntry[]): Promise<ProjectEntry[]> {\n if (projects) return projects;\n return Effect.runPromise(listProjects().pipe(Effect.catch(() => Effect.succeed([]))));\n}\n\nasync function loadTmuxSessionNames(tmuxSessionNames?: readonly string[]): Promise<readonly string[]> {\n if (tmuxSessionNames) return tmuxSessionNames;\n return Effect.runPromise(listSessionNames().pipe(Effect.catch(() => Effect.succeed([]))));\n}\n\nfunction hasIssueScopedSession(tmuxSessionNames: readonly string[], agentId: string): boolean {\n return tmuxSessionNames.some((sessionName) => sessionName === agentId || sessionName.startsWith(`${agentId}-`));\n}\n\nasync function defaultHasOpenPrForBranch(projectPath: string, issueId: string): Promise<boolean> {\n const branch = `feature/${issueId.toLowerCase()}`;\n\n try {\n const resolved = resolveGitHubIssueSync(issueId);\n if (!resolved.isGitHub) {\n // Linear/GitLab-tracked issue: there is no GitHub PR to probe, and `gh`\n // would fail anyway — a polyrepo wrapper projectPath is not a git repo\n // (\"fatal: not a git repository\", PAN-3042).\n logReconcilerDiagnostic('open-pr-check-skipped', { projectPath, issueId, branch, reason: 'non-github-tracker' });\n return false;\n }\n if (isGitHubAppConfigured()) {\n return (await Effect.runPromise(listPullRequestsForHead(resolved.owner, resolved.repo, branch, 'open'))).length > 0;\n }\n\n // `--repo` keeps the probe independent of cwd: gh otherwise resolves the\n // repo from git remotes, which fails when projectPath has no git repo or no\n // origin (the polyrepo wrapper case).\n const result = await execAsync(`gh pr list --repo ${resolved.owner}/${resolved.repo} --head ${branch} --state open --json number --limit 1`, { cwd: projectPath }) as { stdout?: string } | string;\n const stdout = typeof result === 'string' ? result : result.stdout;\n const prs = JSON.parse(stdout ?? '[]') as unknown;\n return Array.isArray(prs) && prs.length > 0;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logReconcilerDiagnostic('open-pr-check-failed', { projectPath, issueId, branch, error: message });\n return false;\n }\n}\n\nexport async function findOrphanProposedSpecsForReconciler(options: FindOrphanProposedOptions = {}): Promise<OrphanProposedCandidate[]> {\n const projects = await loadProjectsForScan(options.projects);\n const tmuxSessionNames = await loadTmuxSessionNames(options.tmuxSessionNames);\n const getState = options.getAgentStateForIssue ?? defaultGetAgentState;\n const getReviewStatus = options.getReviewStatusForIssue ?? getReviewStatusSync;\n const candidates: OrphanProposedCandidate[] = [];\n\n for (const { key, config } of projects) {\n const specsDir = getProjectPanPaths(config.path).specsDir;\n if (!existsSync(specsDir)) continue;\n\n const entries = await readdir(specsDir, { withFileTypes: true }).catch(() => []);\n for (const entry of entries) {\n if (!entry.isFile() || !isXBriefFilename(entry.name)) continue;\n\n const specPath = join(specsDir, entry.name);\n const spec = await readJsonFile<ProposedSpecState>(specPath);\n if (spec?.plan?.status !== 'proposed') continue;\n\n const issueId = normalizeIssueId(spec.plan?.id);\n if (!issueId) continue;\n\n const agentId = `agent-${issueId.toLowerCase()}`;\n const state = await getState(agentId);\n if (hasIssueScopedSession(tmuxSessionNames, agentId)) continue;\n if (state?.status === 'starting' || state?.status === 'running') continue;\n if (state?.paused === true || state?.troubled === true) continue;\n if (hasReviewPipelinePresence(getReviewStatus(issueId))) {\n logReconcilerDiagnostic('candidate-excluded', { issueId, reason: 'review-pipeline-presence' });\n continue;\n }\n if (terminalClosedIssueIds.has(issueId)) continue;\n if (await isIssueClosed(issueId, options.closedIssueIds)) continue;\n\n const planItems = Array.isArray(spec.plan.items) ? spec.plan.items : [];\n const planItemCount = planItems.length;\n if (planItemCount === 0) continue;\n\n candidates.push({\n projectKey: key,\n projectName: config.name,\n projectPath: config.path,\n issueId,\n specPath,\n taskCount: planItemCount,\n planItemCount,\n });\n }\n }\n\n return candidates;\n}\n\nfunction internalDashboardOrigin(): string {\n const port = Number.parseInt(process.env['API_PORT'] ?? process.env['PORT'] ?? '3011', 10);\n return process.env['OVERDECK_INTERNAL_DASHBOARD_URL'] ?? `http://127.0.0.1:${port}`;\n}\n\nexport interface RebuildAndStartResult {\n triggered: boolean;\n error?: string;\n}\n\n/**\n * PAN-2520: trigger the `rebuild-and-start` recovery for a workspace whose Docker\n * stack is unhealthy — the same path the dashboard \"Rebuild & start\" button uses\n * (`POST /api/workspaces/:issueId/rebuild-and-start`, workspaces.ts). It rebuilds\n * the stack, then `pan start`s the work agent once the stack is healthy. Used by\n * the deacon dead-end recovery when a PAN-2209 respawn defers on `stack-unhealthy`\n * (which would otherwise loop forever, since nothing else rebuilds the stack).\n */\nexport async function triggerRebuildAndStart(\n issueId: string,\n dashboardOrigin = internalDashboardOrigin(),\n): Promise<RebuildAndStartResult> {\n const internalToken = getInternalTokenSync();\n const response = await fetch(\n new URL(`/api/workspaces/${encodeURIComponent(issueId)}/rebuild-and-start`, dashboardOrigin),\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n origin: dashboardOrigin,\n ...(internalToken ? { [INTERNAL_TOKEN_HEADER]: internalToken } : {}),\n },\n body: JSON.stringify({ startedBy: 'workspace-rebuild-recovery' }),\n },\n );\n const body = await response.json().catch(() => ({})) as Record<string, unknown>;\n if (response.ok && body['success'] !== false) {\n return { triggered: true };\n }\n return {\n triggered: false,\n error: typeof body['error'] === 'string'\n ? body['error']\n : `rebuild-and-start returned HTTP ${response.status}`,\n };\n}\n\n/**\n * Surface a real, actioned reconciler outcome in the dashboard activity feed.\n * Use this ONLY when something actually happened that a human should see — a\n * work agent was started, or a start genuinely failed. `message` must read as a\n * plain sentence (it is what the feed shows), not a machine event name.\n */\nfunction emitReconcilerActivity(\n level: 'info' | 'warn' | 'error' | 'success',\n message: string,\n details: Record<string, unknown> = {},\n issueId = 'ALL',\n): void {\n const eventIssueId = issueId.toUpperCase();\n emitActivityEntrySync({\n source: 'cloister',\n level,\n issueId: eventIssueId,\n message,\n details: JSON.stringify({\n ...details,\n issueId: eventIssueId,\n timestamp: new Date().toISOString(),\n }),\n });\n}\n\n/**\n * Per-cycle diagnostic trail — console only, never the user activity feed.\n * The reconciler scans on every patrol (~60s); scan-start / orphan-detected /\n * cooldown-skip chatter was flooding the feed and reading as cryptic machine\n * codes (PAN-1626). Those belong in logs, not in front of the operator.\n */\nfunction logReconcilerDiagnostic(kind: string, info: Record<string, unknown> = {}): void {\n console.debug(`[orphan-proposed-reconciler] ${kind}`, info);\n}\n\nasync function recordPickupRefusal(\n issueId: string,\n now: number,\n decision: Extract<AutonomousWorkDispatchDecision, { allow: false }>,\n): Promise<string[]> {\n const reason = `pickup-gate:${decision.code}`;\n logReconcilerDiagnostic('spawn-skipped', { issueId, reason });\n attemptCooldowns.set(issueId, now);\n if (pickupRefusalReasons.get(issueId) !== decision.reason) {\n if (!pickupRefusalReasons.has(issueId) && pickupRefusalReasons.size >= MAX_PICKUP_REFUSAL_REASONS) {\n const oldestIssueId = pickupRefusalReasons.keys().next().value;\n if (oldestIssueId) pickupRefusalReasons.delete(oldestIssueId);\n }\n pickupRefusalReasons.set(issueId, decision.reason);\n await recordDeadEndNeedsYou(issueId, 'orphan-proposed-pickup-gate', 'proposed', decision.reason);\n }\n return [`Skipped orphan proposed spec ${issueId}: ${reason}`];\n}\n\nasync function defaultEvaluatePickupGate(issueId: string): Promise<AutonomousWorkDispatchDecision> {\n return decideAutonomousWorkDispatch(await gatherAutonomousWorkDispatchInput(issueId, { knownPlanned: true }));\n}\n\n/**\n * PAN-1908: reactive orphan-proposed handler. When a spec reaches `proposed`,\n * the autonomous-work pickup gate allows it, and no work agent is\n * running/starting, spawn a work agent without scanning all project specs.\n */\nexport async function handleOrphanProposedSpec(\n issueId: string,\n options: HandleOrphanProposedSpecOptions = {},\n): Promise<string[]> {\n const upperIssueId = issueId.trim().toUpperCase();\n if (!upperIssueId) return [];\n\n const loadedConfig = options.config ?? await Effect.runPromise(\n loadCloisterConfig().pipe(\n Effect.map(config => config.orphanProposedReconciler ?? { enabled: true, minAttemptIntervalMs: DEFAULT_ATTEMPT_INTERVAL_MS }),\n Effect.catch(() => Effect.succeed({ enabled: true, minAttemptIntervalMs: DEFAULT_ATTEMPT_INTERVAL_MS })),\n ),\n );\n if (loadedConfig.enabled === false) return [];\n\n const now = Date.now();\n const minAttemptIntervalMs = Math.max(loadedConfig.minAttemptIntervalMs ?? DEFAULT_ATTEMPT_INTERVAL_MS, DEFAULT_ATTEMPT_INTERVAL_MS);\n const lastAttempt = attemptCooldowns.get(upperIssueId);\n if (lastAttempt !== undefined && now - lastAttempt < minAttemptIntervalMs) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'cooldown' });\n return [];\n }\n\n const resolved = options.project ?? resolveProjectFromIssueSync(upperIssueId);\n if (!resolved) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'no-project' });\n return [];\n }\n const projectPath = resolved.projectPath;\n const projectKey = resolved.projectKey;\n\n const issueLower = upperIssueId.toLowerCase();\n\n let planDoc: XBriefDocument;\n let planPath: string | null;\n if (options.spec) {\n planPath = options.spec.path;\n planDoc = options.spec.doc;\n } else {\n const workspacePath = join(projectPath, 'workspaces', `feature-${issueLower}`);\n planPath = findPlanSync(workspacePath) ?? await findSpecPathForIssue(projectPath, upperIssueId);\n if (!planPath) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'no-spec' });\n return [];\n }\n\n try {\n planDoc = readPlanSync(planPath);\n } catch {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'spec-unreadable' });\n return [];\n }\n }\n\n if (planDoc.plan?.status !== 'proposed') {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'not-proposed', status: planDoc.plan?.status });\n return [];\n }\n\n let pickupGate: AutonomousWorkDispatchDecision;\n try {\n pickupGate = await (options.evaluatePickupGate ?? defaultEvaluatePickupGate)(upperIssueId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n pickupGate = {\n allow: false,\n code: 'labels-unavailable',\n reason: `Autonomous work dispatch was refused because pickup evaluation failed: ${message}`,\n };\n }\n if (!pickupGate.allow) return recordPickupRefusal(upperIssueId, now, pickupGate);\n pickupRefusalReasons.delete(upperIssueId);\n\n const agentId = `agent-${issueLower}`;\n\n // PAN-1908: prefer agents-table state (fast) but fall back to state.json.\n const agentState = options.getAgentStateForIssue\n ? await options.getAgentStateForIssue(agentId)\n : await Effect.runPromise(getAgentState(agentId).pipe(Effect.catch(() => Effect.succeed(null))));\n if (agentState?.status === 'starting' || agentState?.status === 'running') {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'agent-active' });\n return [];\n }\n if (agentState?.paused === true || agentState?.troubled === true) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: agentState.paused ? 'paused' : 'troubled' });\n return [];\n }\n\n // Any tmux session for the issue means the pipeline is active here.\n const sessions = options.tmuxSessionNames\n ?? await Effect.runPromise(listSessionNames().pipe(Effect.catch(() => Effect.succeed([]))));\n if (hasIssueScopedSession(sessions, agentId)) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'issue-scoped-session' });\n return [];\n }\n\n if (hasReviewPipelinePresence(getReviewStatusSync(upperIssueId))) {\n logReconcilerDiagnostic('candidate-excluded', { issueId: upperIssueId, reason: 'review-pipeline-presence' });\n return [];\n }\n\n if (terminalClosedIssueIds.has(upperIssueId)) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'terminal-closed' });\n return [];\n }\n if (await isIssueClosed(upperIssueId, options.closedIssueIds)) {\n terminalClosedIssueIds.add(upperIssueId);\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'closed' });\n return [];\n }\n\n const planItems = Array.isArray(planDoc.plan?.items) ? planDoc.plan.items : [];\n const planItemCount = planItems.length;\n if (planItemCount === 0) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'empty-plan', planItemCount });\n return [];\n }\n\n try {\n if (await (options.hasOpenPrForBranch ?? defaultHasOpenPrForBranch)(projectPath, upperIssueId)) {\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason: 'open-pr' });\n return [`Skipped orphan proposed spec ${upperIssueId}: open-pr`];\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logReconcilerDiagnostic('open-pr-check-failed', { issueId: upperIssueId, error: message });\n }\n\n attemptCooldowns.set(upperIssueId, now);\n\n try {\n const autoSpawnConsentRequired = pickupGate.releaseSource === 'planning-consent';\n const spawn = await (options.spawnWorkAgent\n ?? ((id, required) => spawnWorkAgentThroughAgentsEndpoint(id, options.dashboardOrigin, required)))(\n upperIssueId,\n autoSpawnConsentRequired,\n );\n if (spawn.spawned) {\n emitReconcilerActivity(\n 'success',\n spawn.queued\n ? `Queued container startup for ${upperIssueId} before work-agent spawn`\n : `Started work agent for ${upperIssueId} — proposed spec had tasks but no running agent`,\n { issueId: upperIssueId, agentId: spawn.agentId, queued: spawn.queued === true, projectKey, projectPath },\n upperIssueId,\n );\n return [spawn.queued\n ? `Queued container startup for orphan proposed spec ${upperIssueId}`\n : `Spawned work agent for orphan proposed spec ${upperIssueId}`];\n }\n\n const reason = spawn.skippedReason ?? 'spawn-failed';\n if (reason === 'closed-issue') {\n terminalClosedIssueIds.add(upperIssueId);\n logReconcilerDiagnostic('spawn-skipped', { issueId: upperIssueId, reason, error: spawn.error });\n return [`Skipped orphan proposed spec ${upperIssueId}: ${reason}`];\n }\n emitReconcilerActivity(\n 'warn',\n `Couldn't start work agent for ${upperIssueId}: ${reason}`,\n { issueId: upperIssueId, error: spawn.error, projectKey, projectPath },\n upperIssueId,\n );\n return [`Skipped orphan proposed spec ${upperIssueId}: ${reason}`];\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n emitReconcilerActivity(\n 'error',\n `Couldn't start work agent for ${upperIssueId}: ${message}`,\n { issueId: upperIssueId, projectKey, projectPath },\n upperIssueId,\n );\n return [`Skipped orphan proposed spec ${upperIssueId}: spawn-failed`];\n }\n}\n\n/**\n * PAN-1908: thin dropped-event safety net for orphan proposed specs. The\n * primary path is reactive via handleOrphanProposedSpec on\n * issue.statusChanged(todo). This net finds candidate issueIds and delegates\n * to the same handler so the eligibility logic lives in one place.\n */\nexport async function reconcileOrphanProposedSpecs(options: ReconcileOrphanProposedOptions = {}): Promise<string[]> {\n const loadedConfig = options.config ?? await Effect.runPromise(\n loadCloisterConfig().pipe(\n Effect.map(config => config.orphanProposedReconciler ?? { enabled: true, minAttemptIntervalMs: DEFAULT_ATTEMPT_INTERVAL_MS }),\n Effect.catch(() => Effect.succeed({ enabled: true, minAttemptIntervalMs: DEFAULT_ATTEMPT_INTERVAL_MS })),\n ),\n );\n if (loadedConfig.enabled === false) return [];\n if (scanInFlight) {\n logReconcilerDiagnostic('scan-skipped', { reason: 'previous scan still running' });\n return [];\n }\n\n scanInFlight = true;\n try {\n const actions: string[] = [];\n const candidates = await findOrphanProposedSpecsForReconciler(options);\n const liveCandidateIds = new Set(candidates.map(candidate => candidate.issueId));\n for (const issueId of pickupRefusalReasons.keys()) {\n if (!liveCandidateIds.has(issueId)) pickupRefusalReasons.delete(issueId);\n }\n\n for (const candidate of candidates) {\n let planDoc: XBriefDocument;\n try {\n planDoc = readPlanSync(candidate.specPath);\n } catch {\n logReconcilerDiagnostic('spawn-skipped', { issueId: candidate.issueId, reason: 'spec-unreadable' });\n continue;\n }\n\n const result = await handleOrphanProposedSpec(candidate.issueId, {\n spawnWorkAgent: options.spawnWorkAgent,\n hasOpenPrForBranch: options.hasOpenPrForBranch,\n evaluatePickupGate: options.evaluatePickupGate,\n dashboardOrigin: options.dashboardOrigin,\n config: { enabled: true, minAttemptIntervalMs: loadedConfig.minAttemptIntervalMs },\n project: { projectKey: candidate.projectKey, projectPath: candidate.projectPath },\n spec: { path: candidate.specPath, doc: planDoc },\n tmuxSessionNames: options.tmuxSessionNames,\n getAgentStateForIssue: options.getAgentStateForIssue,\n closedIssueIds: options.closedIssueIds,\n });\n actions.push(...result);\n }\n\n return actions;\n } finally {\n scanInFlight = false;\n }\n}\n\nexport function clearOrphanProposedAttemptCooldowns(): void {\n attemptCooldowns.clear();\n pickupRefusalReasons.clear();\n terminalClosedIssueIds.clear();\n clearIssueClosedCache();\n scanInFlight = false;\n}\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { n as handleOrphanProposedSpec } from "./orphan-proposed-reconciler-DFHdQSEg.js";
1
+ import { n as handleOrphanProposedSpec } from "./orphan-proposed-reconciler-B898fk26.js";
2
2
  import "./work-agent-start-DA3P_ABv.js";
3
3
  export { handleOrphanProposedSpec };
@@ -1,14 +1,14 @@
1
1
  import { Ht as init_state_read_home, On as resolveProjectFromIssueSync, Ri as init_paths, Wt as resolveStateReadHomeSync, Y as init_record, di as AGENTS_DIR, fn as init_projects, j as RECORD_DIRNAME } from "./config-yaml-Dce9VUd6.js";
2
2
  import { l as init_activity_logger, o as emitActivityEntrySync } from "./activity-logger-DNYDzAOU.js";
3
3
  import { B as sendKeys, C as init_tmux, W as sessionExistsSync } from "./tmux-l-yvNWhg.js";
4
- import { Rn as listRunningAgentsSync, W as getAgentRuntimeStateSync, _ as init_agent_state, a as clearAgentOperatorGatesForIssuesSync, g as getAgentStateSync, q as init_agents } from "./agent-state-Ci6PhjOE.js";
4
+ import { Rn as listRunningAgentsSync, W as getAgentRuntimeStateSync, _ as init_agent_state, a as clearAgentOperatorGatesForIssuesSync, g as getAgentStateSync, q as init_agents } from "./agent-state-B196fj1h.js";
5
5
  import { i as loadCloisterConfig, r as init_config } from "./config-B-MLcKSo.js";
6
6
  import { n as resolveGitHubIssueSync, t as init_tracker_utils } from "./tracker-utils-McMENyKj.js";
7
7
  import { _ as markMerged, c as init_merge_sync, f as listActiveAutoMerges, m as listProblemAutoMerges, t as cancelPending } from "./merge-sync-CTGkR1_m.js";
8
8
  import { i as init_merge_set, r as getMergeSetSync } from "./merge-set-DRPWriK9.js";
9
- import { U as reviewGatesPassedSync, Y as init_review_status_record_sync, Z as readJournalStatusSync, h as loadReviewStatuses, p as init_review_status, w as setReviewStatusSync } from "./review-status-BegAr86G.js";
9
+ import { U as reviewGatesPassedSync, Y as init_review_status_record_sync, Z as readJournalStatusSync, h as loadReviewStatuses, p as init_review_status, w as setReviewStatusSync } from "./review-status-yY5qt7Rl.js";
10
10
  import { M as withConcurrencyLimit, j as init_concurrency } from "./github-app-BINlfWAA.js";
11
- import { r as isAgentIdleForNudge } from "./agent-idle-CAwB-K6M.js";
11
+ import { r as isAgentIdleForNudge } from "./agent-idle-D-Qy5BN_.js";
12
12
  import { n as sweepAutoCloseOutCache, t as getAutoCloseOutCanonicalState } from "./deacon-canonical-state-wi63RApC.js";
13
13
  import { n as getForgeAdapter } from "./forge-CEe3eFjh.js";
14
14
  import { i as observeForgeMergeState } from "./merge-completeness-YQbhKLPk.js";
@@ -158,7 +158,7 @@ async function reconcileStuckMergingStates() {
158
158
  reviewGatesPassed: reviewGatesPassedSync,
159
159
  setReviewStatus: setReviewStatusSync,
160
160
  enqueuePostMerge: async (issueId, projectPath, branch) => {
161
- const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-jzN2g_EY.js");
161
+ const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-Cl7-uf4g.js");
162
162
  return enqueuePostMergeLifecycle(issueId, projectPath, branch);
163
163
  },
164
164
  warn: (message) => console.warn(message)
@@ -408,7 +408,7 @@ async function reconcileStaleMergeStatus() {
408
408
  } catch {}
409
409
  const branch = `feature/${issueId.toLowerCase()}`;
410
410
  if (postMergeIncomplete) {
411
- const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-jzN2g_EY.js");
411
+ const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-Cl7-uf4g.js");
412
412
  const action = enqueuePostMergeLifecycle(issueId, project.projectPath, branch);
413
413
  if (action) actions.push(action);
414
414
  continue;
@@ -447,7 +447,7 @@ async function reconcileStaleMergeStatus() {
447
447
  const msg = `Reconciled stale mergeStatus for ${issueId} — branch ${branch} is merged to main`;
448
448
  actions.push(msg);
449
449
  console.log(`[deacon] ${msg}`);
450
- const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-jzN2g_EY.js");
450
+ const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-Cl7-uf4g.js");
451
451
  const action = enqueuePostMergeLifecycle(issueId, project.projectPath, branch);
452
452
  if (action) actions.push(action);
453
453
  }
@@ -590,7 +590,7 @@ async function reconcileStaleMergeBlockers(gatherEligibility = async (ids) => (a
590
590
  }) {
591
591
  const actions = [];
592
592
  try {
593
- const { resolveConflictGate, buildRealConflictGateDeps } = await import("./conflict-gate-vczgdVTa.js");
593
+ const { resolveConflictGate, buildRealConflictGateDeps } = await import("./conflict-gate-9mPVg7-5.js");
594
594
  const statuses = loadReviewStatuses();
595
595
  const now = Date.now();
596
596
  const deps = buildRealConflictGateDeps();
@@ -899,7 +899,7 @@ async function autoCloseOut(now = /* @__PURE__ */ new Date()) {
899
899
  } } : {}
900
900
  };
901
901
  try {
902
- const { closeOut } = await import("./workflows-CgGNyl1z.js");
902
+ const { closeOut } = await import("./workflows-Bk6Kt0ZQ.js");
903
903
  const result = await Effect.runPromise(closeOut(ctx));
904
904
  if (!result.success) {
905
905
  const failed = result.steps.find((step) => !step.success && !step.skipped);
@@ -1130,4 +1130,4 @@ async function reconcileTerminalIssueResidue(projects, deps = defaultDeps()) {
1130
1130
  //#endregion
1131
1131
  export { checkFailedMergeRetry as a, ciRetryMap as c, reconcileMergedButReviewing as d, reconcileStaleMergeBlockers as f, reconcileStuckMergingStates as g, reconcileAutoMergeRows as h, autoCloseOut as i, reconcileClosedPrReadyForMerge as l, reconcileStuckReadyForMerge as m, reconcileTerminalIssueResidue as n, checkFirstCompletionAgents as o, reconcileStaleMergeStatus as p, listIssueRecords as r, checkReadyForMergeStuck as s, isRecordPipelineTerminal as t, reconcileFalseMerged as u };
1132
1132
 
1133
- //# sourceMappingURL=parked-residue-DMtbxJml.js.map
1133
+ //# sourceMappingURL=parked-residue-q2kzrYSm.js.map