@overdeck/core 0.45.10 → 0.45.11

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 (219) hide show
  1. package/dist/{agent-state-KVbJEG5f.js → agent-state-RLhS7ckO.js} +1 -1
  2. package/dist/{agents-pp8FO7Uj.js → agents-By3u_fQ8.js} +1 -1
  3. package/dist/{agents-CQHK0CSA.js → agents-CgVr77Qq.js} +12 -12
  4. package/dist/{agents-CQHK0CSA.js.map → agents-CgVr77Qq.js.map} +1 -1
  5. package/dist/{backlog-auto-trigger-CyuoS0nl.js → backlog-auto-trigger-B_-1tk4e.js} +5 -5
  6. package/dist/{backlog-auto-trigger-CyuoS0nl.js.map → backlog-auto-trigger-B_-1tk4e.js.map} +1 -1
  7. package/dist/cli/index.js +45 -45
  8. package/dist/{cli-Cewlu3yU.js → cli-DGeSW85B.js} +2 -2
  9. package/dist/{cli-Cewlu3yU.js.map → cli-DGeSW85B.js.map} +1 -1
  10. package/dist/cli-MTB9IOoR.js +3 -0
  11. package/dist/{close-issue-BJGX9_z7.js → close-issue-Djajb6Sv.js} +2 -2
  12. package/dist/{close-issue-BJGX9_z7.js.map → close-issue-Djajb6Sv.js.map} +1 -1
  13. package/dist/{concurrency-Ca-fC7tA.js → concurrency-4rzjHAQA.js} +1 -1
  14. package/dist/{conversation-compaction-B_6s9EvM.js → conversation-compaction-BQvZh09I.js} +4 -4
  15. package/dist/{conversation-compaction-B_6s9EvM.js.map → conversation-compaction-BQvZh09I.js.map} +1 -1
  16. package/dist/dashboard/{advancing-selfheal-CMlGznKv.js → advancing-selfheal-BezNfM3P.js} +3 -3
  17. package/dist/dashboard/{advancing-selfheal-CMlGznKv.js.map → advancing-selfheal-BezNfM3P.js.map} +1 -1
  18. package/dist/dashboard/{agent-state-xk_G8t90.js → agent-state-BUANcaA7.js} +1 -1
  19. package/dist/dashboard/{agent-state-service-C1iUF9Ft.js → agent-state-service-DmFpIMbP.js} +1 -1
  20. package/dist/dashboard/{agent-state-service-5ge9xxhx.js → agent-state-service-tXUdp6UF.js} +2 -2
  21. package/dist/dashboard/{agent-state-service-5ge9xxhx.js.map → agent-state-service-tXUdp6UF.js.map} +1 -1
  22. package/dist/dashboard/{agents-BIggLvi_.js → agents-C-vqmKDi.js} +1 -1
  23. package/dist/dashboard/{agents-DHvsjsuP.js → agents-C7V4odQ6.js} +11 -11
  24. package/dist/dashboard/{agents-DHvsjsuP.js.map → agents-C7V4odQ6.js.map} +1 -1
  25. package/dist/dashboard/{backlog-auto-trigger-COm_R96V.js → backlog-auto-trigger-Cb8PR-5w.js} +2 -2
  26. package/dist/dashboard/{backlog-auto-trigger-COm_R96V.js.map → backlog-auto-trigger-Cb8PR-5w.js.map} +1 -1
  27. package/dist/dashboard/{cli-CvK9xuSS.js → cli-BgzbB6h3.js} +2 -2
  28. package/dist/dashboard/{cli-CvK9xuSS.js.map → cli-BgzbB6h3.js.map} +1 -1
  29. package/dist/dashboard/cli-DCqy_wFa.js +3 -0
  30. package/dist/dashboard/{close-issue-BnpErnD1.js → close-issue-BWf3pxn4.js} +2 -2
  31. package/dist/dashboard/{close-issue-BnpErnD1.js.map → close-issue-BWf3pxn4.js.map} +1 -1
  32. package/dist/dashboard/{closed-issue-reaper-DRqK5k39.js → closed-issue-reaper-D7XPq5pY.js} +4 -4
  33. package/dist/dashboard/{closed-issue-reaper-DRqK5k39.js.map → closed-issue-reaper-D7XPq5pY.js.map} +1 -1
  34. package/dist/dashboard/{closed-issue-reaper-BLCQwTpF.js → closed-issue-reaper-VSTSTROK.js} +1 -1
  35. package/dist/dashboard/{conflict-gate-JdFuhKuF.js → conflict-gate-DwOslTij.js} +1 -1
  36. package/dist/dashboard/{conflict-gate-BhKvrPxn.js → conflict-gate-FFEvTDVA.js} +3 -3
  37. package/dist/dashboard/{conflict-gate-BhKvrPxn.js.map → conflict-gate-FFEvTDVA.js.map} +1 -1
  38. package/dist/dashboard/{conversation-compaction-C5o_eKEm.js → conversation-compaction-CCqN4hWk.js} +4 -4
  39. package/dist/dashboard/{conversation-compaction-C5o_eKEm.js.map → conversation-compaction-CCqN4hWk.js.map} +1 -1
  40. package/dist/dashboard/{conversation-compaction-Ba5aZdrb.js → conversation-compaction-CL5Ti4j4.js} +1 -1
  41. package/dist/dashboard/{deacon-j3qSZ7--.js → deacon-CGHl90eC.js} +107 -50
  42. package/dist/dashboard/{deacon-j3qSZ7--.js.map → deacon-CGHl90eC.js.map} +1 -1
  43. package/dist/dashboard/{deacon-Cv2RMfHs.js → deacon-DMPh40Im.js} +2 -2
  44. package/dist/dashboard/deacon-swarm-CVTiNL0N.js +2 -0
  45. package/dist/dashboard/{deacon-swarm-DadWNi5J.js → deacon-swarm-aMMJTq6t.js} +4 -4
  46. package/dist/dashboard/{deacon-swarm-DadWNi5J.js.map → deacon-swarm-aMMJTq6t.js.map} +1 -1
  47. package/dist/dashboard/deacon.js +4 -4
  48. package/dist/dashboard/{feedback-target-oE4-Esxl.js → feedback-target-dJjFfITP.js} +4 -4
  49. package/dist/dashboard/{feedback-target-oE4-Esxl.js.map → feedback-target-dJjFfITP.js.map} +1 -1
  50. package/dist/dashboard/{feedback-target-C4DaDSZ8.js → feedback-target-nQSM6ygL.js} +1 -1
  51. package/dist/dashboard/{flywheel-ClMjGW_u.js → flywheel-BLoVNtJV.js} +6 -6
  52. package/dist/dashboard/{flywheel-ClMjGW_u.js.map → flywheel-BLoVNtJV.js.map} +1 -1
  53. package/dist/dashboard/{flywheel-DefHRzY4.js → flywheel-Cqf8vu7N.js} +6 -6
  54. package/dist/dashboard/{flywheel-DefHRzY4.js.map → flywheel-Cqf8vu7N.js.map} +1 -1
  55. package/dist/dashboard/{flywheel-BqDdGvrQ.js → flywheel-PJsbrXNY.js} +1 -1
  56. package/dist/dashboard/{flywheel-merge-order-CuDcqTRJ.js → flywheel-merge-order-B7BH8mZ3.js} +2 -2
  57. package/dist/dashboard/{flywheel-merge-order-CuDcqTRJ.js.map → flywheel-merge-order-B7BH8mZ3.js.map} +1 -1
  58. package/dist/dashboard/{flywheel-merge-order-B6YDSElh.js → flywheel-merge-order-CCwF60b-.js} +1 -1
  59. package/dist/dashboard/{harness-resolve-DKeSVsJL.js → harness-resolve-B3f9G1Kp.js} +2 -2
  60. package/dist/dashboard/{harness-resolve-DKeSVsJL.js.map → harness-resolve-B3f9G1Kp.js.map} +1 -1
  61. package/dist/dashboard/{inspect-agent-BKKc0XnB.js → inspect-agent-CKF5-SJr.js} +3 -3
  62. package/dist/dashboard/{inspect-agent-BKKc0XnB.js.map → inspect-agent-CKF5-SJr.js.map} +1 -1
  63. package/dist/dashboard/inspect-agent-CqpEWGWy.js +2 -0
  64. package/dist/dashboard/{issue-lifecycle-DnhQgddB.js → issue-lifecycle-5LbOcATP.js} +7 -7
  65. package/dist/dashboard/{issue-lifecycle-DnhQgddB.js.map → issue-lifecycle-5LbOcATP.js.map} +1 -1
  66. package/dist/dashboard/{issue-lifecycle-nY4esZn8.js → issue-lifecycle-CjYqQ669.js} +1 -1
  67. package/dist/dashboard/{issue-service-singleton-Bnqv1uaa.js → issue-service-singleton-B8iu_TKV.js} +1 -1
  68. package/dist/dashboard/{issue-service-singleton-_AquSBTl.js → issue-service-singleton-CDGt__oQ.js} +2 -2
  69. package/dist/dashboard/{issue-service-singleton-_AquSBTl.js.map → issue-service-singleton-CDGt__oQ.js.map} +1 -1
  70. package/dist/dashboard/{lifecycle-CGKm7doE.js → lifecycle-CEg4sHZH.js} +4 -4
  71. package/dist/dashboard/{lifecycle-CGKm7doE.js.map → lifecycle-CEg4sHZH.js.map} +1 -1
  72. package/dist/dashboard/{merge-agent-Dh8Y9PDO.js → merge-agent-7nBiCytp.js} +1 -1
  73. package/dist/dashboard/{merge-agent-BcgAYStl.js → merge-agent-C81xPIGd.js} +6 -6
  74. package/dist/dashboard/{merge-agent-BcgAYStl.js.map → merge-agent-C81xPIGd.js.map} +1 -1
  75. package/dist/dashboard/merge-ops-DE_6CnmZ.js +2 -0
  76. package/dist/dashboard/{merge-train-DmxlYbEo.js → merge-train-D3qzRccL.js} +2 -2
  77. package/dist/dashboard/{merge-train-DmxlYbEo.js.map → merge-train-D3qzRccL.js.map} +1 -1
  78. package/dist/dashboard/{merge-train-deps-DBHsOWt9.js → merge-train-deps-Be5ElC_P.js} +2 -2
  79. package/dist/dashboard/{merge-train-deps-DBHsOWt9.js.map → merge-train-deps-Be5ElC_P.js.map} +1 -1
  80. package/dist/dashboard/{orphan-proposed-reconciler-Db8tUhce.js → orphan-proposed-reconciler-Boq_XaRe.js} +3 -3
  81. package/dist/dashboard/{orphan-proposed-reconciler-Db8tUhce.js.map → orphan-proposed-reconciler-Boq_XaRe.js.map} +1 -1
  82. package/dist/dashboard/{orphan-proposed-reconciler-mXV--tcB.js → orphan-proposed-reconciler-C0sPnDq_.js} +1 -1
  83. package/dist/dashboard/{reconstruct-cache-_tDZ2D72.js → reconstruct-cache-C2pCltOq.js} +3 -3
  84. package/dist/dashboard/{reconstruct-cache-_tDZ2D72.js.map → reconstruct-cache-C2pCltOq.js.map} +1 -1
  85. package/dist/dashboard/{remote-completion-Bklh6loJ.js → remote-completion-BmxD5UMQ.js} +3 -3
  86. package/dist/dashboard/{remote-completion-Bklh6loJ.js.map → remote-completion-BmxD5UMQ.js.map} +1 -1
  87. package/dist/dashboard/resume-C-nxu9Y4.js +3 -0
  88. package/dist/dashboard/{review-agent-phzqNqIs.js → review-agent-D6P6d3pz.js} +26 -17
  89. package/dist/dashboard/review-agent-D6P6d3pz.js.map +1 -0
  90. package/dist/dashboard/review-agent-DTINEffB.js +3 -0
  91. package/dist/dashboard/{review-context-CCq56O_Y.js → review-context-Dyo0tsBa.js} +2 -2
  92. package/dist/dashboard/{review-context-CCq56O_Y.js.map → review-context-Dyo0tsBa.js.map} +1 -1
  93. package/dist/dashboard/{review-status-BQjqQXZG.js → review-status-B5ZASOo4.js} +18 -5
  94. package/dist/dashboard/review-status-B5ZASOo4.js.map +1 -0
  95. package/dist/dashboard/{review-status-bBkqUj5i.js → review-status-h7BXIA4z.js} +1 -1
  96. package/dist/dashboard/{review-verdict-feedback-wqnikhMK.js → review-verdict-feedback-B70VbfRL.js} +4 -4
  97. package/dist/dashboard/{review-verdict-feedback-wqnikhMK.js.map → review-verdict-feedback-B70VbfRL.js.map} +1 -1
  98. package/dist/dashboard/{review-verdict-feedback-cZh9Wi9G.js → review-verdict-feedback-CorgH49f.js} +1 -1
  99. package/dist/dashboard/{sequence-io-B2GmilSI.js → sequence-io-6YP8fVpH.js} +2 -2
  100. package/dist/dashboard/{sequence-io-B2GmilSI.js.map → sequence-io-6YP8fVpH.js.map} +1 -1
  101. package/dist/dashboard/{sequencer-agent-D8pW2aU_.js → sequencer-agent-ja-nkEc1.js} +5 -5
  102. package/dist/dashboard/{sequencer-agent-D8pW2aU_.js.map → sequencer-agent-ja-nkEc1.js.map} +1 -1
  103. package/dist/dashboard/server.js +66 -55
  104. package/dist/dashboard/server.js.map +1 -1
  105. package/dist/dashboard/{service-CILd-uOt.js → service-HKDrIy0h.js} +24 -24
  106. package/dist/dashboard/{service-CILd-uOt.js.map → service-HKDrIy0h.js.map} +1 -1
  107. package/dist/dashboard/{smart-compaction-Bgp_gwcA.js → smart-compaction-L0LSnF0_.js} +1 -1
  108. package/dist/dashboard/{smart-compaction-CrP90OFE.js → smart-compaction-uke1npUz.js} +2 -2
  109. package/dist/dashboard/{smart-compaction-CrP90OFE.js.map → smart-compaction-uke1npUz.js.map} +1 -1
  110. package/dist/dashboard/{spawn-planning-session-D15KbPOy.js → spawn-planning-session-CSMWco8B.js} +1 -1
  111. package/dist/dashboard/{spawn-planning-session-BmJWHSCu.js → spawn-planning-session-CXc0NkwV.js} +3 -3
  112. package/dist/dashboard/{spawn-planning-session-BmJWHSCu.js.map → spawn-planning-session-CXc0NkwV.js.map} +1 -1
  113. package/dist/dashboard/{specialist-context-CwKkcXL9.js → specialist-context-BGCJ24LH.js} +3 -3
  114. package/dist/dashboard/{specialist-context-CwKkcXL9.js.map → specialist-context-BGCJ24LH.js.map} +1 -1
  115. package/dist/dashboard/{specialist-logs-CvDxquV_.js → specialist-logs--Uz-r8ia.js} +2 -2
  116. package/dist/dashboard/{specialist-logs-CvDxquV_.js.map → specialist-logs--Uz-r8ia.js.map} +1 -1
  117. package/dist/dashboard/{specialists-BCjcG4uE.js → specialists-Ca9XSBCS.js} +1 -1
  118. package/dist/dashboard/{specialists-D07ybnam.js → specialists-DEfrAbWs.js} +36 -36
  119. package/dist/dashboard/{specialists-D07ybnam.js.map → specialists-DEfrAbWs.js.map} +1 -1
  120. package/dist/dashboard/{specialists-F2uMO4QS.js → specialists-DeZx9xom.js} +1 -1
  121. package/dist/dashboard/{specialists-BYi0k8CZ.js → specialists-nZ0mRwpZ.js} +12 -12
  122. package/dist/dashboard/{specialists-BYi0k8CZ.js.map → specialists-nZ0mRwpZ.js.map} +1 -1
  123. package/dist/dashboard/{summary-fork-DedqguZb.js → summary-fork-2a1L2DIU.js} +2 -2
  124. package/dist/dashboard/{summary-fork-EjvOkEPl.js → summary-fork-Xn0QUNmb.js} +3 -3
  125. package/dist/dashboard/{summary-fork-EjvOkEPl.js.map → summary-fork-Xn0QUNmb.js.map} +1 -1
  126. package/dist/dashboard/{teardown-workspace-5LCVbjfq.js → teardown-workspace-DhA6oAIK.js} +2 -2
  127. package/dist/dashboard/{teardown-workspace-5LCVbjfq.js.map → teardown-workspace-DhA6oAIK.js.map} +1 -1
  128. package/dist/dashboard/{test-agent-queue-qfsq6uaC.js → test-agent-queue-B_ukPyIK.js} +3 -3
  129. package/dist/dashboard/{test-agent-queue-qfsq6uaC.js.map → test-agent-queue-B_ukPyIK.js.map} +1 -1
  130. package/dist/dashboard/{uat-train-CtNGgXxj.js → uat-train-BLBAbJ8Y.js} +10 -10
  131. package/dist/dashboard/{uat-train-CtNGgXxj.js.map → uat-train-BLBAbJ8Y.js.map} +1 -1
  132. package/dist/dashboard/{uat-train-C3hWXtip.js → uat-train-DPfGR9_I.js} +1 -1
  133. package/dist/dashboard/{verification-runner-DuZRHjPU.js → verification-runner-KTGTNugM.js} +1 -1
  134. package/dist/dashboard/{verification-runner-BPAhPWR7.js → verification-runner-R2-4XgMO.js} +4 -4
  135. package/dist/dashboard/{verification-runner-BPAhPWR7.js.map → verification-runner-R2-4XgMO.js.map} +1 -1
  136. package/dist/dashboard/{workflows-H-COJ84X.js → workflows-CSKX5MhC.js} +7 -7
  137. package/dist/dashboard/{workflows-H-COJ84X.js.map → workflows-CSKX5MhC.js.map} +1 -1
  138. package/dist/dashboard/workflows-DVwXauef.js +2 -0
  139. package/dist/dashboard/{workspaces-CRU9_vRn.js → workspaces-DXLDgXo2.js} +32 -32
  140. package/dist/dashboard/{workspaces-CRU9_vRn.js.map → workspaces-DXLDgXo2.js.map} +1 -1
  141. package/dist/docs-index.sqlite +0 -0
  142. package/dist/{feedback-target-DTGAhFkM.js → feedback-target-BsKN4Tr_.js} +4 -4
  143. package/dist/{feedback-target-DTGAhFkM.js.map → feedback-target-BsKN4Tr_.js.map} +1 -1
  144. package/dist/{feedback-target-DutF088V.js → feedback-target-DM1WzOKy.js} +1 -1
  145. package/dist/{harness-resolve-Bz1prk6B.js → harness-resolve-B-YDNwNW.js} +2 -2
  146. package/dist/{harness-resolve-Bz1prk6B.js.map → harness-resolve-B-YDNwNW.js.map} +1 -1
  147. package/dist/{issue-lifecycle-fVqvCdKM.js → issue-lifecycle-Bc1l3U9f.js} +7 -7
  148. package/dist/{issue-lifecycle-fVqvCdKM.js.map → issue-lifecycle-Bc1l3U9f.js.map} +1 -1
  149. package/dist/{issue-service-singleton-CZm8p6Rj.js → issue-service-singleton-D-8Q6tdT.js} +1 -1
  150. package/dist/{issue-service-singleton-Cr73JAaR.js → issue-service-singleton-D1433I7n.js} +2 -2
  151. package/dist/{issue-service-singleton-Cr73JAaR.js.map → issue-service-singleton-D1433I7n.js.map} +1 -1
  152. package/dist/{lifecycle-CR6tZfl1.js → lifecycle-SmrqysDf.js} +7 -7
  153. package/dist/{lifecycle-CR6tZfl1.js.map → lifecycle-SmrqysDf.js.map} +1 -1
  154. package/dist/{lifecycle-D_EWiUjk.js → lifecycle-mRMyiIXs.js} +2 -2
  155. package/dist/{merge-agent-LM4avOtA.js → merge-agent-B9hIZ6Z0.js} +6 -6
  156. package/dist/{merge-agent-LM4avOtA.js.map → merge-agent-B9hIZ6Z0.js.map} +1 -1
  157. package/dist/{merge-agent-Bj046HE1.js → merge-agent-DUj22cXL.js} +1 -1
  158. package/dist/{merge-fulfillment-DrnC1Kmg.js → merge-fulfillment-__P4WE-T.js} +3 -3
  159. package/dist/{merge-fulfillment-DrnC1Kmg.js.map → merge-fulfillment-__P4WE-T.js.map} +1 -1
  160. package/dist/{reconstruct-cache-NPqoAUg-.js → reconstruct-cache-9SWp82SQ.js} +3 -3
  161. package/dist/{reconstruct-cache-NPqoAUg-.js.map → reconstruct-cache-9SWp82SQ.js.map} +1 -1
  162. package/dist/{records-BIkN1LQ4.js → records-CTmvuRzz.js} +14 -1
  163. package/dist/{records-BIkN1LQ4.js.map → records-CTmvuRzz.js.map} +1 -1
  164. package/dist/records-backfill-BQcmTmwF.js +2 -0
  165. package/dist/{records-backfill-HM0Pln6N.js → records-backfill-BrNsv_zT.js} +2 -2
  166. package/dist/{records-backfill-HM0Pln6N.js.map → records-backfill-BrNsv_zT.js.map} +1 -1
  167. package/dist/resume-Bn4kDk9x.js +3 -0
  168. package/dist/{review-agent-DFosQzCG.js → review-agent-PhqOhpx3.js} +24 -16
  169. package/dist/{review-agent-DFosQzCG.js.map → review-agent-PhqOhpx3.js.map} +1 -1
  170. package/dist/review-agent-hLbRRxZF.js +3 -0
  171. package/dist/{review-status-iJwfEoNX.js → review-status-B_XXomV0.js} +6 -6
  172. package/dist/{review-status-iJwfEoNX.js.map → review-status-B_XXomV0.js.map} +1 -1
  173. package/dist/{review-status-BbNVlXh1.js → review-status-Bo-EFVKh.js} +1 -1
  174. package/dist/{review-verdict-feedback-BGPw3z1X.js → review-verdict-feedback-CXHkoiKZ.js} +1 -1
  175. package/dist/{review-verdict-feedback-CCZ05atV.js → review-verdict-feedback-DGV13LDb.js} +4 -4
  176. package/dist/{review-verdict-feedback-CCZ05atV.js.map → review-verdict-feedback-DGV13LDb.js.map} +1 -1
  177. package/dist/{sequence-io-CcxZNHcD.js → sequence-io-Cg4NHAco.js} +1 -1
  178. package/dist/{sequence-io-Cx1usxG3.js → sequence-io-CyxvNHfA.js} +2 -2
  179. package/dist/{sequence-io-Cx1usxG3.js.map → sequence-io-CyxvNHfA.js.map} +1 -1
  180. package/dist/{smart-compaction-ByUEgQkF.js → smart-compaction-ByKXTQNy.js} +2 -2
  181. package/dist/{smart-compaction-ByUEgQkF.js.map → smart-compaction-ByKXTQNy.js.map} +1 -1
  182. package/dist/{smart-compaction-DfLe_CtH.js → smart-compaction-U6e_uB1E.js} +1 -1
  183. package/dist/{specialist-context-McuGkaeR.js → specialist-context-BUTadO-U.js} +3 -3
  184. package/dist/{specialist-context-McuGkaeR.js.map → specialist-context-BUTadO-U.js.map} +1 -1
  185. package/dist/{specialist-logs-CUUJ4eiB.js → specialist-logs-pEMCTtGZ.js} +2 -2
  186. package/dist/{specialist-logs-CUUJ4eiB.js.map → specialist-logs-pEMCTtGZ.js.map} +1 -1
  187. package/dist/{specialists-BSrylD1S.js → specialists-BGFnrQ8n.js} +1 -1
  188. package/dist/{specialists-B0elgInc.js → specialists-DeTkkp8b.js} +12 -12
  189. package/dist/{specialists-B0elgInc.js.map → specialists-DeTkkp8b.js.map} +1 -1
  190. package/dist/{summary-fork-DskMRnyb.js → summary-fork-CgzThE2-.js} +2 -2
  191. package/dist/{summary-fork-CPUTKcAT.js → summary-fork-Dx1RMuvU.js} +3 -3
  192. package/dist/{summary-fork-CPUTKcAT.js.map → summary-fork-Dx1RMuvU.js.map} +1 -1
  193. package/dist/{sync-BiNVQHBf.js → sync-Bsww9tuj.js} +2 -2
  194. package/dist/{sync-BiNVQHBf.js.map → sync-Bsww9tuj.js.map} +1 -1
  195. package/dist/sync-CylE_SjB.js +2 -0
  196. package/dist/{verdict-restore-DQiV7_fe.js → verdict-restore-DGpX0ZOJ.js} +5 -5
  197. package/dist/{verdict-restore-DQiV7_fe.js.map → verdict-restore-DGpX0ZOJ.js.map} +1 -1
  198. package/dist/{webhook-handlers-DHBSEDEm.js → webhook-handlers-BjsfIL7u.js} +3 -3
  199. package/dist/{webhook-handlers-DHBSEDEm.js.map → webhook-handlers-BjsfIL7u.js.map} +1 -1
  200. package/dist/{workspace-migrate-duUsWNpd.js → workspace-migrate-BBQ8nAnP.js} +2 -2
  201. package/dist/{workspace-migrate-duUsWNpd.js.map → workspace-migrate-BBQ8nAnP.js.map} +1 -1
  202. package/dist/{workspace-reap-DLCIoJmn.js → workspace-reap-12O9354k.js} +2 -2
  203. package/dist/{workspace-reap-DLCIoJmn.js.map → workspace-reap-12O9354k.js.map} +1 -1
  204. package/package.json +1 -1
  205. package/scripts/file-size-baseline.txt +1 -1
  206. package/dist/cli-DBWG12XK.js +0 -3
  207. package/dist/dashboard/cli-CJDWXE_Y.js +0 -3
  208. package/dist/dashboard/deacon-swarm-D1iAUX-P.js +0 -2
  209. package/dist/dashboard/inspect-agent-vm88mLYr.js +0 -2
  210. package/dist/dashboard/merge-ops-QdBiQ8XB.js +0 -2
  211. package/dist/dashboard/resume-DnIsmIgC.js +0 -3
  212. package/dist/dashboard/review-agent-DgySDb-G.js +0 -3
  213. package/dist/dashboard/review-agent-phzqNqIs.js.map +0 -1
  214. package/dist/dashboard/review-status-BQjqQXZG.js.map +0 -1
  215. package/dist/dashboard/workflows-Cz8OtiB4.js +0 -2
  216. package/dist/records-backfill-DEgtRyKL.js +0 -2
  217. package/dist/resume-DGymuXZM.js +0 -3
  218. package/dist/review-agent-DjVadURa.js +0 -3
  219. package/dist/sync-4jqukkxz.js +0 -2
@@ -2,14 +2,14 @@ import { E as OVERDECK_HOME, et as init_paths, t as AGENTS_DIR } from "./paths-3
2
2
  import { n as extractPrefixSync, r as init_issue_id, t as extractNumberSync } from "./issue-id-DfZZfSZC.js";
3
3
  import { c as getProjectConfigFromWorkspacePath, l as init_record, u as markRecordPipelineClosedOutSync } from "./record-osVNNpoC.js";
4
4
  import { A as sessionExists, w as listSessionNames, x as killSession, y as init_tmux } from "./tmux-Ceg1ulra.js";
5
- import { $ as loadCloisterConfig, Q as init_config } from "./agents-CQHK0CSA.js";
5
+ import { $ as loadCloisterConfig, Q as init_config } from "./agents-CgVr77Qq.js";
6
6
  import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population-5MWfsQI_.js";
7
7
  import { a as init_agents, o as listAllAgentsSync, s as removeAgentSync } from "./agents-BURDseV4.js";
8
8
  import { i as init_workspace_manager, r as getContainersReferencingWorkspacePath } from "./workspace-manager-CxoFBq_Y.js";
9
9
  import { r as init_devcontainer_renderer, t as DEVCONTAINER_DIRNAME } from "./devcontainer-renderer-B2oacvw2.js";
10
10
  import { a as init_archive_planning, i as findWorkspacePath, r as findAllWorkspacePaths, t as archivePlanning } from "./archive-planning-6uw521Do.js";
11
11
  import { a as stepSkipped, i as stepOk, n as init_types, r as stepFailed, t as getLinearApiKey } from "./types-D112L62U.js";
12
- import { n as closeIssue } from "./close-issue-BJGX9_z7.js";
12
+ import { n as closeIssue } from "./close-issue-Djajb6Sv.js";
13
13
  import { n as init_compact_beads } from "./compact-beads-BrBt37Xm.js";
14
14
  import { Effect } from "effect";
15
15
  import { existsSync } from "fs";
@@ -612,7 +612,7 @@ function pruneSpecialistRegistry(issueId) {
612
612
  return Effect.tryPromise({
613
613
  try: async () => {
614
614
  const step = "teardown:specialist-registry";
615
- const { pruneSpecialistRegistryEntriesForIssue } = await import("./specialists-BSrylD1S.js");
615
+ const { pruneSpecialistRegistryEntriesForIssue } = await import("./specialists-BGFnrQ8n.js");
616
616
  const removed = pruneSpecialistRegistryEntriesForIssue(issueId);
617
617
  return removed > 0 ? stepOk(step, [`Pruned ${removed} specialist registry entr${removed === 1 ? "y" : "ies"} for ${issueId}`]) : stepSkipped(step, [`No specialist registry entries for ${issueId}`]);
618
618
  },
@@ -866,7 +866,7 @@ async function verifyBranchMergedImpl(ctx) {
866
866
  const branchName = `feature/${ctx.issueId.toLowerCase()}`;
867
867
  try {
868
868
  try {
869
- const { loadReviewStatuses } = await import("./review-status-BbNVlXh1.js");
869
+ const { loadReviewStatuses } = await import("./review-status-Bo-EFVKh.js");
870
870
  if (loadReviewStatuses()[ctx.issueId.toUpperCase()]?.mergeStatus === "merged") return stepOk(step, ["Merge specialist confirmed merge completed"]);
871
871
  } catch {}
872
872
  const { stdout: branchExists } = await execAsync(`git branch --list "${branchName}" 2>/dev/null || true`, {
@@ -1069,7 +1069,7 @@ async function resetIssueToTodoImpl(ctx) {
1069
1069
  */
1070
1070
  async function resetPostMergeStateForIssue(issueId) {
1071
1071
  try {
1072
- const { resetPostMergeState } = await import("./merge-agent-Bj046HE1.js");
1072
+ const { resetPostMergeState } = await import("./merge-agent-DUj22cXL.js");
1073
1073
  resetPostMergeState(issueId);
1074
1074
  resetPostMergeState(issueId.toUpperCase());
1075
1075
  } catch {
@@ -1085,7 +1085,7 @@ function clearReviewStatusStep(issueId) {
1085
1085
  async function clearReviewStatusStepImpl(issueId) {
1086
1086
  const step = "clear-review-status";
1087
1087
  try {
1088
- const { clearReviewStatus } = await import("./review-status-BbNVlXh1.js");
1088
+ const { clearReviewStatus } = await import("./review-status-Bo-EFVKh.js");
1089
1089
  clearReviewStatus(issueId.toUpperCase());
1090
1090
  return stepOk(step, ["Review status cleared"]);
1091
1091
  } catch {
@@ -1112,4 +1112,4 @@ init_compact_beads();
1112
1112
  //#endregion
1113
1113
  export { resetToTodo as n, teardownWorkspace as r, closeOut as t };
1114
1114
 
1115
- //# sourceMappingURL=lifecycle-CR6tZfl1.js.map
1115
+ //# sourceMappingURL=lifecycle-SmrqysDf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-CR6tZfl1.js","names":["execAsync"],"sources":["../src/lib/lifecycle/teardown-workspace.ts","../src/lib/cloister/agent-gc.ts","../src/lib/lifecycle/workflows.ts","../src/lib/lifecycle/index.ts"],"sourcesContent":["/**\n * teardown-workspace — Full workspace cleanup.\n *\n * Consolidates workspace teardown from close-out.ts and workspace-manager.ts.\n * Handles: tmux sessions, TLDR daemon, Docker containers, git worktrees,\n * agent state directories, and (optionally) git branches.\n *\n * The workspace-manager's removeWorkspace() handles additional project-specific\n * cleanup (DNS, tunnels, Hume, ports) that this module does not cover.\n * In Phase 2, removeWorkspace() will delegate to this module for the common steps.\n */\n\nimport { existsSync } from 'fs';\nimport { appendFile, readFile, rm, writeFile } from 'fs/promises';\nimport { join, basename, dirname } from 'path';\nimport { homedir } from 'os';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { Effect } from 'effect';\nimport { AGENTS_DIR } from '../paths.js';\nimport { killSession, sessionExists, listSessionNames } from '../tmux.js';\nimport type { LifecycleContext, StepResult, TeardownOptions } from './types.js';\nimport { stepOk, stepSkipped, stepFailed } from './types.js';\nimport { findAllWorkspacePaths, findWorkspacePath } from './archive-planning.js';\nimport { getContainersReferencingWorkspacePath } from '../workspace-manager.js';\nimport { DEVCONTAINER_DIRNAME } from '../workspace/devcontainer-renderer.js';\n\nconst execAsync = promisify(exec);\n\n/**\n * Kill tmux sessions associated with an issue.\n */\nfunction killTmuxSessions(issueLower: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => killTmuxSessionsImpl(issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:tmux-sessions', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function killTmuxSessionsImpl(issueLower: string): Promise<StepResult> {\n const step = 'teardown:tmux-sessions';\n let killed = 0;\n\n // Exact-match sessions (agent, test, merge, planning, strike).\n const exactPatterns = [\n `agent-${issueLower}`,\n `test-${issueLower}`,\n `merge-${issueLower}`,\n `planning-${issueLower}`,\n `strike-${issueLower}`,\n ];\n for (const session of exactPatterns) {\n if (await Effect.runPromise(sessionExists(session))) {\n try {\n await Effect.runPromise(killSession(session));\n killed++;\n } catch {\n // session may have died between check and kill\n }\n }\n }\n\n // Pattern-match sessions for review coordinators, review specialists, and\n // canonical specialists. Today's naming uses the UPPER issue ID (PAN-1024)\n // not the lower form, and includes session families that the prior\n // single-regex didn't cover. PAN-1024 close-out left\n // `review-coordinator-PAN-1024-...` and\n // `specialist-overdeck-PAN-1024-test-agent` alive (2026-05-09).\n //\n // Patterns we now match (case-insensitive on the issue ID):\n // - review-coordinator-<ISSUE>-<timestamp>\n // - review-<ISSUE>-<timestamp>-<role> (legacy)\n // - specialist-<projectKey>-<ISSUE>-<role> (canonical PAN-830/915)\n try {\n const allSessions = await Effect.runPromise(listSessionNames());\n const escapedLower = issueLower.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const escapedUpper = issueLower.toUpperCase().replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const issuePart = `(${escapedLower}|${escapedUpper})`;\n const patterns: RegExp[] = [\n new RegExp(`^review-coordinator-${issuePart}-\\\\d+`),\n new RegExp(`^review-${issuePart}-\\\\d+`),\n new RegExp(`^specialist-[^-]+(?:-[^-]+)*?-${issuePart}-`),\n ];\n const matchedSessions = allSessions.filter(s => patterns.some(p => p.test(s)));\n for (const session of matchedSessions) {\n try {\n await Effect.runPromise(killSession(session));\n killed++;\n } catch {\n // session may have died between check and kill\n }\n }\n } catch {\n // Session listing may fail if tmux server is not running\n }\n\n // NOTE: Per-project ephemeral specialists (specialist-{project}-{type}) are NOT killed here.\n // They belong to the project, not the issue, and accumulate context across issues via --resume.\n // Their grace period / idle timeout handles cleanup when no new work arrives.\n\n if (killed > 0) {\n return stepOk(step, [`Killed ${killed} tmux session(s)`]);\n }\n return stepSkipped(step, ['No tmux sessions found']);\n}\n\n/**\n * Stop TLDR daemon if workspace has a .venv.\n */\nfunction stopTldrDaemon(workspacePath: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => stopTldrDaemonImpl(workspacePath),\n catch: (err) => err,\n }).pipe(\n Effect.catch(() =>\n Effect.succeed(stepSkipped('teardown:tldr-daemon', ['TLDR daemon not running or failed to stop (non-fatal)'])),\n ),\n );\n}\n\nasync function stopTldrDaemonImpl(workspacePath: string): Promise<StepResult> {\n const step = 'teardown:tldr-daemon';\n const venvPath = join(workspacePath, '.venv');\n if (!existsSync(venvPath)) {\n return stepSkipped(step, ['No .venv found']);\n }\n try {\n const { getTldrDaemonServiceSync } = await import('../tldr-daemon.js');\n const tldrService = getTldrDaemonServiceSync(workspacePath, venvPath);\n await tldrService.stop();\n return stepOk(step, ['Stopped TLDR daemon']);\n } catch {\n return stepSkipped(step, ['TLDR daemon not running or failed to stop (non-fatal)']);\n }\n}\n\n/**\n * Stop Docker containers for the workspace.\n */\nfunction stopDocker(\n workspacePath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => stopDockerImpl(workspacePath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch(() =>\n Effect.succeed(stepSkipped('teardown:docker', ['Docker cleanup skipped (not running or failed)'])),\n ),\n );\n}\n\nasync function stopDockerImpl(\n workspacePath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:docker';\n try {\n const { stopWorkspaceDocker } = await import('../workspace-manager.js');\n await Effect.runPromise(stopWorkspaceDocker(workspacePath, issueLower));\n return stepOk(step, ['Stopped Docker containers']);\n } catch {\n return stepSkipped(step, ['Docker cleanup skipped (not running or failed)']);\n }\n}\n\n/**\n * Detect whether a PID belongs to a process running inside a Docker container.\n * Container processes appear in host lsof output when paths are bind-mounted.\n */\nasync function isDockerContainerProcess(pid: string): Promise<boolean> {\n try {\n const cgroup = await readFile(`/proc/${pid}/cgroup`, 'utf-8');\n return cgroup.includes('/docker-') || cgroup.includes('/docker/');\n } catch {\n return false;\n }\n}\n\n/**\n * Kill orphaned host processes for a workspace.\n */\nfunction killOrphanedProcesses(workspacePath: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => killOrphanedProcessesImpl(workspacePath),\n catch: (err) => err,\n }).pipe(\n Effect.catch(() =>\n Effect.succeed(stepSkipped('teardown:orphaned-processes', ['Orphaned process cleanup failed (non-fatal)'])),\n ),\n );\n}\n\nasync function killOrphanedProcessesImpl(workspacePath: string): Promise<StepResult> {\n const step = 'teardown:orphaned-processes';\n try {\n // Find PIDs with cwd matching the workspace path\n const { stdout } = await execAsync(\n `lsof +D \"${workspacePath}\" -t 2>/dev/null || true`,\n { encoding: 'utf-8', timeout: 10000 },\n );\n const pids = stdout.trim().split('\\n').filter(Boolean).map(p => p.trim()).filter(p => /^\\d+$/.test(p));\n\n if (pids.length === 0) {\n return stepSkipped(step, ['No orphaned processes found']);\n }\n\n // Don't kill our own process or the dashboard\n const myPid = String(process.pid);\n const safePids = pids.filter(p => p !== myPid);\n\n if (safePids.length === 0) {\n return stepSkipped(step, ['No orphaned processes to kill']);\n }\n\n // Filter out Docker container processes — they appear in host lsof due to bind mounts\n const hostPids: string[] = [];\n for (const pid of safePids) {\n if (!(await isDockerContainerProcess(pid))) {\n hostPids.push(pid);\n }\n }\n\n if (hostPids.length === 0) {\n return stepSkipped(step, ['No orphaned host processes to kill (all were container processes)']);\n }\n\n await execAsync(`kill ${hostPids.join(' ')} 2>/dev/null || true`, { encoding: 'utf-8', timeout: 5000 });\n return stepOk(step, [`Killed ${hostPids.length} orphaned process(es)`]);\n } catch {\n return stepSkipped(step, ['Orphaned process cleanup failed (non-fatal)']);\n }\n}\n\n/**\n * Sync workspace beads to the project-root beads database before workspace deletion.\n */\nfunction syncWorkspaceBeads(\n projectPath: string,\n workspacePath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => syncWorkspaceBeadsImpl(projectPath, workspacePath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:sync-beads', `Failed to sync workspace beads: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function syncWorkspaceBeadsImpl(\n projectPath: string,\n workspacePath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:sync-beads';\n const workspaceBeadsDir = join(workspacePath, '.beads');\n\n if (!existsSync(workspaceBeadsDir)) {\n return stepSkipped(step, ['No .beads directory in workspace']);\n }\n\n try {\n // Export workspace beads to JSONL\n // 120s: bd export cold-starts a dolt server per workspace .beads and can\n // block on the global bd lock; a timeout kill bypasses `|| true` and\n // aborts the whole close-out ceremony (observed at 15s, 14/32 closes).\n await execAsync(\n 'bd export --output .beads/issues-export.jsonl 2>&1 || true',\n { cwd: workspacePath, encoding: 'utf-8', timeout: 120000 }\n );\n\n const exportPath = join(workspacePath, '.beads', 'issues-export.jsonl');\n if (!existsSync(exportPath)) {\n await execAsync('bd export --output .beads/issues.jsonl 2>&1 || true', { cwd: workspacePath, encoding: 'utf-8', timeout: 120000 });\n }\n\n // Import workspace beads into project-root database\n // Use bd import if available, otherwise copy JSONL entries\n try {\n await execAsync(\n `bd import \"${join(workspacePath, '.beads', 'issues.jsonl')}\" 2>&1 || true`,\n { cwd: projectPath, encoding: 'utf-8', timeout: 120000 }\n );\n return stepOk(step, [`Synced workspace beads to project root for ${issueLower}`]);\n } catch {\n // bd import may not exist — try manual JSONL merge\n const wsJsonl = join(workspacePath, '.beads', 'issues.jsonl');\n const projJsonl = join(projectPath, '.beads', 'issues.jsonl');\n\n if (existsSync(wsJsonl) && existsSync(projJsonl)) {\n const wsContent = await readFile(wsJsonl, 'utf-8');\n const issuePattern = issueLower.replace('-', '[-_]');\n const relevantLines = wsContent.split('\\n').filter(\n line => line.trim() && new RegExp(issuePattern, 'i').test(line)\n );\n if (relevantLines.length > 0) {\n await appendFile(projJsonl, '\\n' + relevantLines.join('\\n'));\n return stepOk(step, [`Appended ${relevantLines.length} beads entries for ${issueLower} to project JSONL`]);\n }\n }\n return stepSkipped(step, ['No beads to sync or import not available']);\n }\n } catch (err) {\n return stepFailed(step, `Failed to sync workspace beads: ${(err as Error).message}`);\n }\n}\n\n/**\n * Clear beads for this issue from the project-root .beads/issues.jsonl.\n */\nfunction clearProjectBeads(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => clearProjectBeadsImpl(projectPath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:clear-beads', `Failed to clear beads: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function clearProjectBeadsImpl(\n projectPath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:clear-beads';\n const projJsonl = join(projectPath, '.beads', 'issues.jsonl');\n\n if (!existsSync(projJsonl)) {\n return stepSkipped(step, ['No .beads/issues.jsonl in project root']);\n }\n\n try {\n const content = await readFile(projJsonl, 'utf-8');\n const lines = content.split('\\n');\n const issueUpper = issueLower.toUpperCase();\n const before = lines.length;\n // Remove lines that reference this issue (by ID in the title or issue field)\n const filtered = lines.filter(line => {\n if (!line.trim()) return true; // keep blank lines\n try {\n const entry = JSON.parse(line);\n const title = (entry.title || '').toUpperCase();\n const issue = (entry.issue || '').toUpperCase();\n return !title.includes(issueUpper) && issue !== issueUpper;\n } catch {\n return true; // keep unparseable lines\n }\n });\n const removed = before - filtered.length;\n if (removed > 0) {\n await writeFile(projJsonl, filtered.join('\\n'));\n return stepOk(step, [`Removed ${removed} beads entries for ${issueLower} from project JSONL`]);\n }\n return stepSkipped(step, [`No beads entries found for ${issueLower}`]);\n } catch (err) {\n return stepFailed(step, `Failed to clear beads: ${(err as Error).message}`);\n }\n}\n\n/**\n * Remove git worktree for the workspace.\n */\nfunction removeWorktree(\n projectPath: string,\n workspacePath: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => removeWorktreeImpl(projectPath, workspacePath),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:worktree', `Failed to remove workspace: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function removeWorktreeImpl(\n projectPath: string,\n workspacePath: string,\n): Promise<StepResult> {\n const step = 'teardown:worktree';\n if (!existsSync(workspacePath)) {\n return stepSkipped(step, ['Workspace directory does not exist']);\n }\n\n // Guard: never delete workspace (and its `.devcontainer/`) while containers\n // still reference compose paths inside it.\n const orphanedContainers = await Effect.runPromise(getContainersReferencingWorkspacePath(workspacePath));\n if (orphanedContainers.length > 0) {\n return stepFailed(\n step,\n `Cannot remove workspace: ${orphanedContainers.length} Docker container(s) still reference compose paths in ${DEVCONTAINER_DIRNAME}/. ` +\n `Run workspace Docker cleanup first or stop the containers manually.`,\n );\n }\n\n try {\n await execAsync(`git worktree remove \"${workspacePath}\" --force`, { cwd: projectPath });\n return stepOk(step, ['Removed git worktree']);\n } catch {\n // worktree remove failed — try direct removal\n try {\n await rm(workspacePath, { recursive: true, force: true });\n return stepOk(step, ['Removed workspace directory after worktree removal failed']);\n } catch (err) {\n return stepFailed(step, `Failed to remove workspace: ${(err as Error).message}`);\n }\n }\n}\n\n/**\n * Remove every agent state directory tied to an issue.\n */\nfunction removeAgentState(issueLower: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => removeAgentStateImpl(issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:agent-state', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function removeAgentStateImpl(issueLower: string): Promise<StepResult> {\n const step = 'teardown:agent-state';\n const { readdir, rm } = await import('fs/promises');\n\n let entries: string[];\n try {\n entries = await readdir(AGENTS_DIR);\n } catch {\n return stepSkipped(step, ['Agents directory not present']);\n }\n\n const work = `agent-${issueLower}`;\n const planner = `planning-${issueLower}`;\n const strike = `strike-${issueLower}`;\n const specialistPrefix = `agent-${issueLower}-`;\n const targets = entries.filter(name =>\n name === work || name === planner || name === strike || name.startsWith(specialistPrefix),\n );\n\n let removed = 0;\n for (const name of targets) {\n try {\n await rm(join(AGENTS_DIR, name), { recursive: true, force: true });\n removed++;\n } catch { /* non-fatal */ }\n }\n\n if (removed > 0) {\n return stepOk(step, [`Removed ${removed} agent state director${removed === 1 ? 'y' : 'ies'}`]);\n }\n return stepSkipped(step, ['No agent state directories found']);\n}\n\n/**\n * Delete feature branches (local + remote).\n */\nfunction deleteBranches(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => deleteBranchesImpl(projectPath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:branches', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function deleteBranchesImpl(\n projectPath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:branches';\n const branchName = `feature/${issueLower}`;\n const details: string[] = [];\n const localSlots = await execAsync(`git for-each-ref --format=\"%(refname:short)\" \"refs/heads/feature/${issueLower}-slot-*\"`, { cwd: projectPath, encoding: 'utf-8' })\n .then(({ stdout }) => stdout.trim().split('\\n').filter(Boolean)).catch(() => [] as string[]);\n const remoteSlots = await execAsync(`git ls-remote --heads origin \"feature/${issueLower}-slot-*\"`, { cwd: projectPath, encoding: 'utf-8' })\n .then(({ stdout }) => stdout.trim().split('\\n').map(line => line.split('refs/heads/')[1]).filter((name): name is string => Boolean(name))).catch(() => [] as string[]);\n\n // Delete local branch\n try {\n await execAsync(`git branch -D \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted local branch ${branchName}`);\n } catch {\n details.push(`Local branch ${branchName} not found (already deleted)`);\n }\n\n for (const slotBranch of localSlots) {\n try {\n await execAsync(`git branch -D ${JSON.stringify(slotBranch)}`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted local branch ${slotBranch}`);\n } catch { details.push(`Failed to delete local branch ${slotBranch}`); }\n }\n\n // Delete remote branch\n try {\n await execAsync(`git push origin --delete \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted remote branch ${branchName}`);\n } catch {\n details.push(`Remote branch ${branchName} not found (already deleted)`);\n }\n\n for (const slotBranch of remoteSlots) {\n try {\n await execAsync(`git push origin --delete ${JSON.stringify(slotBranch)}`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted remote branch ${slotBranch}`);\n } catch { details.push(`Failed to delete remote branch ${slotBranch}`); }\n }\n\n return stepOk(step, details);\n}\n\n/**\n * Whether a local branch exists and is fully merged into main.\n */\nasync function localBranchMergedState(\n projectPath: string,\n branchName: string,\n): Promise<{ exists: boolean; merged: boolean }> {\n try {\n await execAsync(`git show-ref --verify --quiet \"refs/heads/${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n } catch {\n return { exists: false, merged: false };\n }\n try {\n await execAsync(`git merge-base --is-ancestor \"${branchName}\" main`, { cwd: projectPath, encoding: 'utf-8' });\n return { exists: true, merged: true };\n } catch {\n return { exists: true, merged: false };\n }\n}\n\n/**\n * Delete the strike branch (local + remote) once it is merged into main.\n *\n * Strike work (`pan strike`) lands on main directly, so a merged\n * `strike/<issue>` branch is pure residue — it is deleted on every teardown,\n * not just when `deleteBranches` is requested (PAN-1721). An UNMERGED strike\n * branch may hold the only copy of an aborted strike's work, so it is\n * preserved and reported instead.\n */\nfunction deleteStrikeBranch(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => deleteStrikeBranchImpl(projectPath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:strike-branch', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function deleteStrikeBranchImpl(\n projectPath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:strike-branch';\n const branchName = `strike/${issueLower}`;\n const details: string[] = [];\n\n // Local branch\n const local = await localBranchMergedState(projectPath, branchName);\n if (local.exists) {\n if (local.merged) {\n try {\n await execAsync(`git branch -D \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted local branch ${branchName}`);\n } catch (err) {\n details.push(`Failed to delete local branch ${branchName}: ${(err as Error).message}`);\n }\n } else {\n details.push(`Preserved local branch ${branchName} — not merged to main`);\n }\n }\n\n // Remote branch\n try {\n const { stdout: remoteRef } = await execAsync(\n `git ls-remote --heads origin \"${branchName}\" 2>/dev/null || true`,\n { cwd: projectPath, encoding: 'utf-8' },\n );\n if (remoteRef.trim()) {\n let remoteMerged = false;\n try {\n await execAsync(`git fetch origin \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n await execAsync('git merge-base --is-ancestor FETCH_HEAD main', { cwd: projectPath, encoding: 'utf-8' });\n remoteMerged = true;\n } catch {\n remoteMerged = false;\n }\n if (remoteMerged) {\n await execAsync(`git push origin --delete \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted remote branch ${branchName}`);\n } else {\n details.push(`Preserved remote branch ${branchName} — not merged to main`);\n }\n }\n } catch {\n // remote check/delete failed — non-fatal\n }\n\n if (details.length === 0) {\n return stepSkipped(step, [`No strike branch ${branchName} found`]);\n }\n return details.some(d => d.startsWith('Failed'))\n ? stepFailed(step, details.join('; '))\n : stepOk(step, details);\n}\n\n/**\n * Remove leftover strike worktrees (`workspaces/feature-<issue>-strike`).\n *\n * Runs when the regular worktree removal is gated off (remove_workspace=false\n * at close-out): a strike worktree has no post-close purpose once the strike\n * branch is merged or gone, and leaving it keeps the closed issue alive in\n * resource discovery (PAN-1721). Worktrees whose strike branch has unmerged\n * commits are preserved alongside the branch.\n */\nfunction removeStrikeWorktrees(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => removeStrikeWorktreesImpl(projectPath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:strike-worktree', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function removeStrikeWorktreesImpl(\n projectPath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:strike-worktree';\n const strikePaths = findAllWorkspacePaths(projectPath, issueLower).filter(p => p.endsWith('-strike'));\n if (strikePaths.length === 0) {\n return stepSkipped(step, ['No strike worktree found']);\n }\n\n const branch = await localBranchMergedState(projectPath, `strike/${issueLower}`);\n if (branch.exists && !branch.merged) {\n return stepSkipped(step, [`Preserved strike worktree — strike/${issueLower} not merged to main`]);\n }\n\n const details: string[] = [];\n for (const p of strikePaths) {\n const result = await removeWorktreeImpl(projectPath, p);\n details.push(...(result.details ?? [result.error ?? result.step]));\n if (!result.success && !result.skipped) {\n return stepFailed(step, `Failed to remove strike worktree ${p}: ${result.error ?? 'unknown error'}`);\n }\n }\n return stepOk(step, details);\n}\n\n/**\n * Clear shadow state for an issue.\n */\nfunction clearShadowState(issueId: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => clearShadowStateImpl(issueId),\n catch: (err) => err,\n }).pipe(\n Effect.catch(() =>\n Effect.succeed(stepSkipped('teardown:shadow-state', ['Shadow state cleanup skipped (non-fatal)'])),\n ),\n );\n}\n\nasync function clearShadowStateImpl(issueId: string): Promise<StepResult> {\n const step = 'teardown:shadow-state';\n try {\n const { removeShadowState } = await import('../shadow-state.js');\n const result = removeShadowState(issueId);\n if (result.success) {\n return stepOk(step, [`Cleared shadow state for ${issueId}`]);\n }\n return stepSkipped(step, ['No shadow state found']);\n } catch {\n return stepSkipped(step, ['Shadow state cleanup skipped (non-fatal)']);\n }\n}\n\n/**\n * Remove legacy .planning/<issue>/ directory from project root.\n */\nfunction clearLegacyPlanningDir(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const step = 'teardown:legacy-planning-dir';\n const legacyDir = join(projectPath, '.planning', issueLower);\n if (!existsSync(legacyDir)) {\n return stepSkipped(step, ['No legacy planning directory found']);\n }\n await rm(legacyDir, { recursive: true, force: true });\n return stepOk(step, [`Deleted legacy planning dir: ${legacyDir}`]);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:legacy-planning-dir', `Failed to delete legacy planning dir: ${(err as Error).message}`)),\n ),\n );\n}\n\n/**\n * Build template placeholders for project-specific cleanup (tunnel, Hume).\n */\nfunction buildPlaceholders(\n ctx: LifecycleContext,\n opts: TeardownOptions,\n workspacePath: string,\n) {\n const issueLower = ctx.issueId.toLowerCase();\n const featureFolder = `feature-${issueLower}`;\n const projName = opts.projectName || ctx.projectName || basename(ctx.projectPath);\n const domain = opts.workspaceConfig?.dns?.domain || 'localhost';\n return {\n FEATURE_NAME: issueLower,\n FEATURE_FOLDER: featureFolder,\n BRANCH_NAME: `feature/${issueLower}`,\n COMPOSE_PROJECT: `${projName}-${featureFolder}`,\n DOMAIN: domain,\n PROJECT_NAME: projName,\n PROJECT_PATH: ctx.projectPath,\n WORKSPACE_PATH: workspacePath,\n };\n}\n\n/**\n * Remove Cloudflare tunnel ingress for workspace.\n */\nfunction removeTunnelConfig(\n tunnelConfig: any,\n placeholders: Record<string, string>,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const { removeTunnelIngress } = await import('../tunnel.js');\n const result = await Effect.runPromise(removeTunnelIngress(tunnelConfig, placeholders as any));\n return stepOk('teardown:tunnel', result.steps || ['Removed tunnel ingress']);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped('teardown:tunnel', [`Tunnel cleanup warning: ${(err as Error).message}`])),\n ),\n );\n}\n\n/**\n * Remove Hume EVI config for workspace.\n */\nfunction removeHumeEviConfig(\n humeConfig: any,\n placeholders: Record<string, string>,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const { deleteHumeConfig } = await import('../hume.js');\n const result = await Effect.runPromise(deleteHumeConfig(humeConfig, placeholders as any));\n return stepOk('teardown:hume', result.steps || ['Removed Hume EVI config']);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped('teardown:hume', [`Hume cleanup warning: ${(err as Error).message}`])),\n ),\n );\n}\n\n/**\n * Full workspace teardown.\n */\nexport function teardownWorkspace(\n ctx: LifecycleContext,\n opts: TeardownOptions = {},\n): Effect.Effect<StepResult[]> {\n return Effect.gen(function* () {\n const issueLower = ctx.issueId.toLowerCase();\n const workspacePath = findWorkspacePath(ctx.projectPath, issueLower);\n const shouldDeleteWorkspace = opts.deleteWorkspace !== false; // default true\n const results: StepResult[] = [];\n\n // 1. Kill tmux sessions\n results.push(yield* killTmuxSessions(issueLower));\n\n // 2. Clear shadow state (always runs)\n results.push(yield* clearShadowState(ctx.issueId));\n\n // 3. Clear legacy planning directory (always runs)\n results.push(yield* clearLegacyPlanningDir(ctx.projectPath, issueLower));\n\n // 4-9: Workspace-specific cleanup\n if (workspacePath && existsSync(workspacePath)) {\n // 4. Stop TLDR daemon (only if deleting workspace)\n if (shouldDeleteWorkspace) {\n results.push(yield* stopTldrDaemon(workspacePath));\n }\n\n // 5. Stop Docker containers (only if deleting workspace)\n if (shouldDeleteWorkspace && !opts.skipDocker) {\n results.push(yield* stopDocker(workspacePath, issueLower));\n }\n\n // 5b. Kill orphaned host processes (Vite, node) that survive Docker teardown\n if (shouldDeleteWorkspace) {\n results.push(yield* killOrphanedProcesses(workspacePath));\n }\n\n // 6. Beads lifecycle: sync or clear depending on context (PAN-412)\n if (opts.clearBeads) {\n results.push(yield* clearProjectBeads(ctx.projectPath, issueLower));\n } else if (shouldDeleteWorkspace) {\n results.push(yield* syncWorkspaceBeads(ctx.projectPath, workspacePath, issueLower));\n }\n\n // 7-8: Project-specific cleanup (tunnel, Hume)\n if (shouldDeleteWorkspace && (opts.workspaceConfig?.tunnel || opts.workspaceConfig?.hume)) {\n const placeholders = buildPlaceholders(ctx, opts, workspacePath);\n\n if (opts.workspaceConfig.tunnel) {\n results.push(yield* removeTunnelConfig(opts.workspaceConfig.tunnel, placeholders));\n }\n if (opts.workspaceConfig.hume) {\n results.push(yield* removeHumeEviConfig(opts.workspaceConfig.hume, placeholders));\n }\n }\n\n // 9. Remove worktree + workspace directory (only if deleting workspace).\n if (shouldDeleteWorkspace) {\n const allPaths = findAllWorkspacePaths(ctx.projectPath, issueLower);\n for (const p of allPaths) {\n results.push(yield* removeWorktree(ctx.projectPath, p));\n }\n }\n } else {\n results.push(stepSkipped('teardown:workspace', ['No workspace found to clean up']));\n }\n\n // 9b. Strike worktrees are residue once the strike branch is merged —\n // remove them even when deleteWorkspace is gated off (PAN-1721). When\n // shouldDeleteWorkspace is true the loop above already removed them via\n // findAllWorkspacePaths.\n if (!shouldDeleteWorkspace) {\n results.push(yield* removeStrikeWorktrees(ctx.projectPath, issueLower));\n }\n\n // 10. Remove agent state\n results.push(yield* removeAgentState(issueLower));\n\n // 11. Delete branches. Feature branches only if explicitly requested;\n // the strike branch is always a candidate once merged to main (PAN-1721).\n results.push(yield* deleteStrikeBranch(ctx.projectPath, issueLower));\n if (opts.deleteBranches) {\n results.push(yield* deleteBranches(ctx.projectPath, issueLower));\n }\n\n // 12. Prune checkpoint refs for this issue's agents.\n results.push(yield* pruneCheckpointRefs(ctx.projectPath, issueLower));\n\n // 13. Prune specialist registry entries for this issue.\n results.push(yield* pruneSpecialistRegistry(ctx.issueId));\n\n return results;\n });\n}\n\nfunction pruneSpecialistRegistry(issueId: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const step = 'teardown:specialist-registry';\n const { pruneSpecialistRegistryEntriesForIssue } = await import('../cloister/specialists.js');\n const removed = pruneSpecialistRegistryEntriesForIssue(issueId);\n return removed > 0\n ? stepOk(step, [`Pruned ${removed} specialist registry entr${removed === 1 ? 'y' : 'ies'} for ${issueId}`])\n : stepSkipped(step, [`No specialist registry entries for ${issueId}`]);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped('teardown:specialist-registry', [`Specialist registry prune failed (non-fatal): ${(err as Error).message}`])),\n ),\n );\n}\n\nfunction pruneCheckpointRefs(projectPath: string, issueLower: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const step = 'teardown:checkpoint-refs';\n const { pruneCheckpointRefsForAgents } = await import('../checkpoint/checkpoint-manager.js');\n const agentIds = [`agent-${issueLower}`, `planning-${issueLower}`, `strike-${issueLower}`];\n const pruned = await Effect.runPromise(pruneCheckpointRefsForAgents(projectPath, agentIds));\n return stepOk(step, [`Pruned ${pruned} checkpoint ref(s) for ${agentIds.join(', ')}`]);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:checkpoint-refs', `Checkpoint prune failed: ${(err as Error).message}`)),\n ),\n );\n}\n","import { listAllAgentsSync, removeAgentSync } from '../overdeck/agents.js';\nimport { readIssueRecordForWorkspaceSync } from '../pan-dir/record.js';\n\nexport interface AgentGcResult { removed: string[]; preserved: string[] }\nexport interface AgentGcRow { id: string; issueId: string; status: string; workspace?: string | null }\n\nexport function pruneStoppedAgentsForIssue(\n issueId: string,\n agents: AgentGcRow[] = listAllAgentsSync(),\n remove: (id: string) => void = removeAgentSync,\n): AgentGcResult {\n const issue = issueId.toUpperCase();\n const scoped = agents.filter(agent => agent.issueId.toUpperCase() === issue);\n const removed = scoped.filter(agent => agent.status === 'stopped').map(agent => agent.id);\n const preserved = scoped.filter(agent => agent.status !== 'stopped').map(agent => agent.id);\n for (const id of removed) remove(id);\n return { removed, preserved };\n}\n\nexport function pruneTerminalStoppedAgents(): AgentGcResult {\n const agents = listAllAgentsSync();\n const terminal = agents.filter(agent => agent.status === 'stopped' && agent.workspace\n && readIssueRecordForWorkspaceSync(agent.workspace, agent.issueId)?.pipeline?.closedOut === true);\n const removed = terminal.map(agent => agent.id);\n for (const id of removed) removeAgentSync(id);\n return { removed, preserved: [] };\n}\n","/**\n * Lifecycle workflows — Compose atomic operations into complete workflows.\n *\n * approve() — Post-merge: archive + close + teardown + compact-beads\n * close() — Simple close: close-issue + teardown\n * closeOut() — Full ceremony: verify-merged + archive + teardown + close + label + clear-status\n * deepWipe() — Destructive: teardown(deleteBranches) + delete agent state + reset issue\n */\n\nimport { existsSync } from 'fs';\nimport { copyFile, readFile, writeFile } from 'fs/promises';\nimport { join } from 'path';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { Effect } from 'effect';\nimport { OVERDECK_HOME } from '../paths.js';\nimport type {\n LifecycleContext,\n WorkflowResult,\n StepResult,\n ApproveOptions,\n DeepWipeOptions,\n ArchiveOptions,\n} from './types.js';\nimport { stepOk, stepSkipped, stepFailed, getLinearApiKey } from './types.js';\nimport { archivePlanning, findWorkspacePath } from './archive-planning.js';\nimport { closeIssue, type CloseIssueOptions } from './close-issue.js';\nimport { teardownWorkspace } from './teardown-workspace.js';\nimport { compactBeads } from './compact-beads.js';\nimport { loadCloisterConfig } from '../cloister/config.js';\nimport { extractNumberSync, extractPrefixSync } from '../issue-id.js';\nimport { recordFeatureRegistryLifecycle } from '../registry/feature-registry-population.js';\nimport { getProjectConfigFromWorkspacePath, markRecordPipelineClosedOutSync } from '../pan-dir/record.js';\nimport { pruneStoppedAgentsForIssue } from '../cloister/agent-gc.js';\n\nconst execAsync = promisify(exec);\n\nfunction trackerName(ctx: LifecycleContext, fallback: string): string {\n const name = ctx.tracker?.name ?? fallback;\n return name.charAt(0).toUpperCase() + name.slice(1);\n}\n\n/**\n * Build a WorkflowResult from collected steps.\n */\nfunction buildResult(\n workflow: WorkflowResult['workflow'],\n issueId: string,\n steps: StepResult[],\n startTime: number,\n): WorkflowResult {\n return {\n workflow,\n issueId,\n success: steps.every(s => s.success),\n steps,\n duration: Date.now() - startTime,\n };\n}\n\nfunction hasBlockingFailure(steps: StepResult[]): boolean {\n return steps.some(s => !s.success && !s.skipped);\n}\n\n/**\n * approve() — Post-merge lifecycle.\n */\nexport function approve(\n ctx: LifecycleContext,\n opts: ApproveOptions & CloseIssueOptions & ArchiveOptions = {},\n): Effect.Effect<WorkflowResult> {\n return Effect.gen(function* () {\n const start = Date.now();\n const allSteps: StepResult[] = [];\n\n // 1. Archive planning\n const archiveSteps = yield* archivePlanning(ctx, opts);\n allSteps.push(...archiveSteps);\n\n // If archive failed, stop — don't destroy unarchived artifacts\n const archiveFailed = archiveSteps.some(s => !s.success && !s.skipped);\n if (archiveFailed) {\n allSteps.push(stepFailed('approve:abort', 'Stopped — archiving failed, workspace preserved'));\n return buildResult('approve', ctx.issueId, allSteps, start);\n }\n\n // 2. Close issue\n const closeSteps = yield* closeIssue(ctx, {\n tracker: opts.tracker,\n comment: 'Merged to main via Overdeck lifecycle',\n applyLabel: true,\n });\n allSteps.push(...closeSteps);\n\n // 3. Teardown workspace (delete branches — merge is complete)\n const teardownSteps = yield* teardownWorkspace(ctx, { deleteBranches: true });\n allSteps.push(...teardownSteps);\n\n // 4. Compact beads (non-blocking — failure doesn't affect workflow success)\n if (!opts.skipBeadsCompaction) {\n const beadsResult = yield* compactBeads(ctx);\n allSteps.push(beadsResult);\n }\n\n // 5. Clear review status\n const clearResult = yield* clearReviewStatusStep(ctx.issueId);\n allSteps.push(clearResult);\n\n return buildResult('approve', ctx.issueId, allSteps, start);\n });\n}\n\n/**\n * close() — Simple issue close with teardown.\n */\nexport function close(\n ctx: LifecycleContext,\n opts: CloseIssueOptions = {},\n): Effect.Effect<WorkflowResult> {\n return Effect.gen(function* () {\n const start = Date.now();\n const allSteps: StepResult[] = [];\n\n // 1. Close issue\n const closeSteps = yield* closeIssue(ctx, {\n tracker: opts.tracker,\n reason: opts.reason,\n applyLabel: false,\n });\n allSteps.push(...closeSteps);\n\n // 2. Teardown workspace\n const teardownSteps = yield* teardownWorkspace(ctx);\n allSteps.push(...teardownSteps);\n\n // 3. Clear review status\n const clearResult = yield* clearReviewStatusStep(ctx.issueId);\n allSteps.push(clearResult);\n\n return buildResult('close', ctx.issueId, allSteps, start);\n });\n}\n\n/**\n * closeOut() — Full close-out ceremony.\n *\n * This is the human-gated verification and cleanup workflow.\n * Replaces the monolithic executeCloseOut() function.\n *\n * 1. Verify branch merged (hard fail if not — must pass before any cleanup)\n * 2. Move PRD + archive workspace artifacts (hard fail if archiving fails)\n * 3. Mark vBRIEF completed\n * 4. Clean up workspace (tmux, TLDR, Docker, worktree)\n * 5. Clean up agent state\n * 6. Close issue on tracker\n * 7. Apply closed-out label\n * 8. Clear review status\n */\nexport function closeOut(\n ctx: LifecycleContext,\n opts: CloseIssueOptions & ArchiveOptions = {},\n): Effect.Effect<WorkflowResult> {\n return Effect.gen(function* () {\n const start = Date.now();\n const allSteps: StepResult[] = [];\n\n // 1. Verify branch merged (hard fail — must pass before we archive or clean up)\n const mergeVerify = yield* verifyBranchMerged(ctx);\n allSteps.push(mergeVerify);\n if (!mergeVerify.success && !mergeVerify.skipped) {\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 2. Move PRD + archive workspace artifacts\n const archiveSteps = yield* archivePlanning(ctx, opts);\n allSteps.push(...archiveSteps);\n\n // Hard fail on archive failure — don't destroy unarchived artifacts\n const archiveFailed = archiveSteps.some(s => !s.success && !s.skipped);\n if (archiveFailed) {\n allSteps.push(stepFailed('close-out:abort', 'Stopped — archiving failed, workspace preserved'));\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 3. Mark the vBRIEF completed on main before teardown removes local state.\n const vbriefStep = yield* Effect.promise(() => completeVBriefStep(ctx));\n allSteps.push(vbriefStep);\n if (!vbriefStep.success && !vbriefStep.skipped) {\n allSteps.push(stepFailed('close-out:abort', 'Stopped — vBRIEF completion failed, workspace preserved'));\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 4+5. Teardown workspace + agent state\n const closeOutConfig = (yield* Effect.promise(() => Effect.runPromise(loadCloisterConfig()))).close_out;\n const teardownSteps = yield* teardownWorkspace(ctx, {\n deleteWorkspace: closeOutConfig?.remove_workspace ?? false,\n deleteBranches: closeOutConfig?.delete_feature_branch ?? false,\n });\n allSteps.push(...teardownSteps);\n if (hasBlockingFailure(teardownSteps)) {\n allSteps.push(stepFailed('close-out:abort', 'Stopped — teardown failed, tracker issue and review status preserved'));\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 6+7. Close issue + apply label\n const closeSteps = yield* closeIssue(ctx, {\n tracker: opts.tracker,\n comment: ctx.auto ? 'Closed via automatic close-out ceremony' : 'Closed via close-out ceremony',\n applyLabel: true,\n });\n allSteps.push(...closeSteps);\n if (hasBlockingFailure(closeSteps)) {\n allSteps.push(stepFailed('close-out:abort', 'Stopped — issue close failed, review status preserved'));\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 8. Mark durable pipeline terminal before clearing the DB cache.\n const markTerminal = yield* markPipelineClosedOutStep(ctx);\n allSteps.push(markTerminal);\n if (markTerminal.success) {\n const pruned = pruneStoppedAgentsForIssue(ctx.issueId);\n allSteps.push(pruned.preserved.length > 0\n ? stepSkipped('close-out:prune-agent-rows', [`WARNING: preserved live/non-stopped agents: ${pruned.preserved.join(', ')}`])\n : stepOk('close-out:prune-agent-rows', [`Pruned ${pruned.removed.length} stopped agent row(s)`]));\n }\n\n // 9. Clear review status\n const clearResult = yield* clearReviewStatusStep(ctx.issueId);\n allSteps.push(clearResult);\n\n yield* Effect.promise(() => resetPostMergeStateForIssue(ctx.issueId));\n yield* Effect.promise(() => recordFeatureRegistryLifecycle({ issueId: ctx.issueId, status: 'archived' }));\n\n return buildResult('close-out', ctx.issueId, allSteps, start);\n });\n}\n\nfunction markPipelineClosedOutStep(ctx: LifecycleContext): Effect.Effect<StepResult> {\n const step = 'close-out:mark-pipeline-terminal';\n return Effect.try({\n try: () => {\n const project = getProjectConfigFromWorkspacePath(ctx.projectPath);\n markRecordPipelineClosedOutSync(project, ctx.issueId.toUpperCase());\n return stepOk(step, ['Marked durable pipeline journal closed-out']);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped(step, [`Pipeline terminal marker failed (non-fatal): ${(err as Error).message ?? String(err)}`])),\n ),\n );\n}\n\n/**\n * deepWipe() — Destructive cleanup for abandoned workspaces.\n */\nfunction destructiveResetWorkflow(\n workflow: 'deep-wipe' | 'reset' | 'cancel',\n ctx: LifecycleContext,\n opts: DeepWipeOptions,\n resetStep: (ctx: LifecycleContext) => Effect.Effect<StepResult>,\n progressLabel: string,\n progressSuccessDetail: string,\n): Effect.Effect<WorkflowResult> {\n return Effect.gen(function* () {\n const start = Date.now();\n const allSteps: StepResult[] = [];\n const { deleteWorkspace = true, deleteBranches = true, resetIssue = true, onProgress } = opts;\n const resetContext = opts.tracker ? { ...ctx, tracker: opts.tracker } : ctx;\n\n const TOTAL_STEPS = 3 + (resetIssue ? 1 : 0);\n let stepNum = 0;\n\n const progress = (label: string, detail: string, status: 'active' | 'complete' | 'error' = 'active') => {\n onProgress?.({ step: stepNum, total: TOTAL_STEPS, label, detail, status });\n };\n\n stepNum = 1;\n\n // Preserve PRD before workspace teardown so it survives reset/cancel.\n const issueLower = ctx.issueId.toLowerCase();\n const workspacePath = findWorkspacePath(ctx.projectPath, issueLower);\n if (workspacePath && existsSync(workspacePath)) {\n const prdPath = join(workspacePath, '.pan', 'prd.md');\n if (existsSync(prdPath)) {\n yield* Effect.tryPromise({\n try: async () => {\n const activeDir = join(ctx.projectPath, 'docs', 'prds', 'active', issueLower);\n const { mkdir } = await import('fs/promises');\n await mkdir(activeDir, { recursive: true });\n await copyFile(prdPath, join(activeDir, 'prd.md'));\n },\n catch: () => null,\n }).pipe(Effect.catch(() => Effect.void));\n }\n }\n\n progress('Tearing down workspace', 'Killing agents, stopping services, removing files');\n const teardownSteps = yield* teardownWorkspace(ctx, {\n deleteWorkspace,\n deleteBranches,\n clearBeads: true,\n workspaceConfig: opts.workspaceConfig,\n projectName: opts.projectName,\n });\n allSteps.push(...teardownSteps);\n const teardownFailed = teardownSteps.some(s => !s.success && !s.skipped);\n progress('Tearing down workspace', teardownFailed ? 'Some steps failed' : 'Workspace torn down', teardownFailed ? 'error' : 'complete');\n\n stepNum = 2;\n progress('Deleting git branches', `feature/${ctx.issueId.toLowerCase()}`);\n progress('Deleting git branches', deleteBranches ? 'Branches removed' : 'Skipped', 'complete');\n\n if (resetIssue) {\n stepNum = 3;\n progress(progressLabel, `${ctx.issueId}`);\n const resetResult = yield* resetStep(resetContext);\n allSteps.push(resetResult);\n progress(progressLabel, resetResult.success ? progressSuccessDetail : (resetResult.error || 'Failed'), resetResult.success ? 'complete' : 'error');\n }\n\n stepNum = resetIssue ? 4 : 3;\n progress('Clearing review status', 'Removing specialist state');\n const clearResult = yield* clearReviewStatusStep(ctx.issueId);\n allSteps.push(clearResult);\n progress('Clearing review status', 'Review status cleared', 'complete');\n\n return buildResult(workflow, ctx.issueId, allSteps, start);\n });\n}\n\nexport function deepWipe(\n ctx: LifecycleContext,\n opts: DeepWipeOptions = {},\n): Effect.Effect<WorkflowResult> {\n return destructiveResetWorkflow(\n 'deep-wipe',\n ctx,\n opts,\n resetIssueToTodo,\n 'Resetting issue status',\n 'Issue reset to Todo',\n );\n}\n\nexport function resetToTodo(\n ctx: LifecycleContext,\n opts: DeepWipeOptions = {},\n): Effect.Effect<WorkflowResult> {\n return destructiveResetWorkflow(\n 'reset',\n ctx,\n opts,\n resetIssueToTodo,\n 'Resetting issue status',\n 'Issue reset to Todo',\n );\n}\n\nexport function cancelIssueWorkflow(\n ctx: LifecycleContext,\n opts: DeepWipeOptions = {},\n): Effect.Effect<WorkflowResult> {\n return destructiveResetWorkflow(\n 'cancel',\n ctx,\n opts,\n resetIssueToCanceled,\n 'Canceling issue',\n 'Issue moved to Canceled',\n );\n}\n\n// --- Internal helpers ---\n\nasync function completeVBriefStep(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'close-out:vbrief-completed';\n try {\n const { transitionVBriefOnMain } = await import('../vbrief/lifecycle-io.js');\n const result = await Effect.runPromise(transitionVBriefOnMain(\n ctx.projectPath,\n ctx.issueId,\n 'completed',\n 'completed',\n `scope: complete ${ctx.issueId.toUpperCase()} vBRIEF`,\n ));\n const details = [\n result.moved ? 'Updated vBRIEF lifecycle to completed' : 'vBRIEF lifecycle already completed',\n result.statusUpdated ? 'Updated plan.status to completed' : 'plan.status already completed',\n ];\n if (result.committed) details.push('Committed vBRIEF completion on main');\n return stepOk(step, details);\n } catch (err) {\n const cause = (err as { cause?: unknown }).cause ?? err;\n const message = cause instanceof Error ? cause.message : String(cause);\n if (message.includes('No vBRIEF found')) {\n return stepSkipped(step, [`No vBRIEF found for ${ctx.issueId}`]);\n }\n return stepFailed(step, `vBRIEF completion failed: ${message}`);\n }\n}\n\n/**\n * Verify feature branch is merged into main.\n */\nfunction verifyBranchMerged(ctx: LifecycleContext): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => verifyBranchMergedImpl(ctx),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('close-out:verify-merged', `Could not verify merge: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function verifyBranchMergedImpl(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'close-out:verify-merged';\n const issueLower = ctx.issueId.toLowerCase();\n const branchName = `feature/${issueLower}`;\n\n try {\n // Check review-status first — the merge specialist validates before marking merged\n try {\n const { loadReviewStatuses } = await import('../review-status.js');\n const statuses = loadReviewStatuses();\n const issueKey = ctx.issueId.toUpperCase();\n if (statuses[issueKey]?.mergeStatus === 'merged') {\n return stepOk(step, ['Merge specialist confirmed merge completed']);\n }\n } catch {\n // review-status.json may not exist, continue with git checks\n }\n\n\n // Check if branch exists locally\n const { stdout: branchExists } = await execAsync(\n `git branch --list \"${branchName}\" 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n\n if (branchExists.trim()) {\n // Use merge-base --is-ancestor: checks if the branch tip is reachable from main\n try {\n await execAsync(\n `git merge-base --is-ancestor ${branchName} main`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const remoteCheck = await verifyRemoteBranchIfPresent(ctx, branchName);\n if (remoteCheck && !remoteCheck.success) return remoteCheck;\n return stepOk(step, [\n 'All commits merged to main',\n ...(remoteCheck?.details ?? []),\n ]);\n } catch {\n // --is-ancestor fails for squash merges where the branch still exists.\n try {\n const { stdout: codeDiff } = await execAsync(\n `git diff main...${branchName} -- ':!.planning' ':!docs/prds' ':!.overdeck/prompts' 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (!codeDiff.trim()) {\n const remoteCheck = await verifyRemoteBranchIfPresent(ctx, branchName);\n if (remoteCheck && !remoteCheck.success) return remoteCheck;\n return stepOk(step, [\n 'Code changes squash-merged to main (only planning artifacts remain on branch)',\n ...(remoteCheck?.details ?? []),\n ]);\n }\n } catch {\n // diff failed — fall through to unmerged report\n }\n\n const githubMerged = await verifySquashMergedPrByBranch(ctx, branchName, branchName);\n if (githubMerged?.success) {\n const remoteCheck = await verifyRemoteBranchIfPresent(ctx, branchName);\n if (remoteCheck && !remoteCheck.success) return remoteCheck;\n return stepOk(step, [\n ...(githubMerged.details ?? []),\n ...(remoteCheck?.details ?? []),\n ]);\n }\n if (githubMerged) return githubMerged;\n\n const { stdout: unmerged } = await execAsync(\n `git log main..${branchName} --oneline 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const count = unmerged.trim() ? unmerged.trim().split('\\n').length : 0;\n\n if (ctx.github) {\n try {\n const { stdout: issueState } = await execAsync(\n `gh issue view ${ctx.github.number} --repo ${ctx.github.owner}/${ctx.github.repo} --json state --jq '.state'`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (issueState.trim().toUpperCase() === 'CLOSED') {\n return stepSkipped(step, [`Issue already closed on GitHub; ${count} unmerged commit(s) remain on ${branchName}`]);\n }\n } catch {\n // gh check failed — fall through to hard fail\n }\n }\n\n return stepFailed(step, `${count} unmerged commit(s) on ${branchName}. Merge before closing out.`);\n }\n }\n\n // Check remote\n const { stdout: remoteBranch } = await execAsync(\n `git ls-remote --heads origin \"${branchName}\" 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n\n if (remoteBranch.trim()) {\n await execAsync(`git fetch origin ${branchName}`, { cwd: ctx.projectPath }).catch(() => {});\n const remoteCheck = await verifyRemoteBranchIfPresent(ctx, branchName);\n if (remoteCheck) return remoteCheck;\n }\n\n // No branch at all — assume squash-merged and branch deleted\n return stepOk(step, ['Branch already cleaned up (squash-merged)']);\n } catch (err) {\n return stepFailed(step, `Could not verify merge: ${(err as Error).message}`);\n }\n}\n\ntype GitHubMergedPr = {\n number?: number;\n mergedAt?: string | null;\n headRefOid?: string | null;\n url?: string | null;\n};\n\nasync function verifyRemoteBranchIfPresent(\n ctx: LifecycleContext,\n branchName: string,\n): Promise<StepResult | null> {\n const step = 'close-out:verify-merged';\n const remoteRef = `origin/${branchName}`;\n\n const { stdout: remoteBranch } = await execAsync(\n `git ls-remote --heads origin \"${branchName}\" 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (!remoteBranch.trim()) return null;\n\n await execAsync(`git fetch origin ${branchName}`, { cwd: ctx.projectPath }).catch(() => {});\n\n try {\n await execAsync(\n `git merge-base --is-ancestor ${remoteRef} main`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n return stepOk(step, ['Remote branch fully merged']);\n } catch {\n // Squash-merge detection for remote branch\n try {\n const { stdout: codeDiff } = await execAsync(\n `git diff main...${remoteRef} -- ':!.planning' ':!docs/prds' ':!.overdeck/prompts' 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (!codeDiff.trim()) {\n return stepOk(step, ['Remote code changes squash-merged to main (only planning artifacts remain on branch)']);\n }\n } catch {\n // diff failed — fall through\n }\n\n const githubMerged = await verifySquashMergedPrByBranch(ctx, branchName, remoteRef);\n if (githubMerged) return githubMerged;\n\n const { stdout: remoteUnmerged } = await execAsync(\n `git log main..${remoteRef} --oneline 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const count = remoteUnmerged.trim() ? remoteUnmerged.trim().split('\\n').length : 0;\n\n if (ctx.github) {\n try {\n const { stdout: issueState } = await execAsync(\n `gh issue view ${ctx.github.number} --repo ${ctx.github.owner}/${ctx.github.repo} --json state --jq '.state'`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (issueState.trim().toUpperCase() === 'CLOSED') {\n return stepSkipped(step, [`Issue already closed on GitHub; ${count} unmerged commit(s) remain on remote ${branchName}`]);\n }\n } catch {\n // gh check failed — fall through to hard fail\n }\n }\n\n return stepFailed(step, `${count} unmerged commit(s) on remote ${branchName}.`);\n }\n}\n\nasync function verifySquashMergedPrByBranch(\n ctx: LifecycleContext,\n branchName: string,\n branchRef: string,\n): Promise<StepResult | null> {\n if (!ctx.github) return null;\n\n const step = 'close-out:verify-merged';\n const { owner, repo } = ctx.github;\n\n try {\n const { stdout: prJson } = await execAsync(\n `gh pr list --repo ${owner}/${repo} --state merged --head ${JSON.stringify(branchName)} --json number,mergedAt,headRefOid,url`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const prs = JSON.parse(prJson) as GitHubMergedPr[];\n const mergedPr = prs\n .filter((pr) => (\n typeof pr.mergedAt === 'string'\n && pr.mergedAt.length > 0\n && typeof pr.headRefOid === 'string'\n && pr.headRefOid.length > 0\n ))\n .sort((a, b) => Date.parse(String(b.mergedAt)) - Date.parse(String(a.mergedAt)))[0];\n if (!mergedPr?.headRefOid) return null;\n\n const { stdout: tipShaRaw } = await execAsync(\n `git rev-parse ${branchRef} 2>/dev/null`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const tipSha = tipShaRaw.trim();\n if (!tipSha) return null;\n\n if (tipSha === mergedPr.headRefOid) {\n const prLabel = typeof mergedPr.number === 'number' ? `PR #${mergedPr.number}` : 'GitHub PR';\n return stepOk(step, [`${prLabel} is squash-merged and ${branchRef} matches the merged PR head`]);\n }\n\n // PAN-2406 / state-plane policy rule 3: commits after the merged head that\n // touch ONLY state-plane paths (.pan/, .beads/) are pipeline exhaust —\n // e.g. 'chore: record merge status' — and must not block close-out.\n try {\n const { stdout: deltaRaw } = await execAsync(\n `git diff --name-only ${mergedPr.headRefOid}..${tipSha}`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n let deltaFiles = deltaRaw.split('\\n').map((f) => f.trim()).filter(Boolean);\n let statePlaneOnly = deltaFiles.length > 0 && deltaFiles.every((f) =>\n f.startsWith('.pan/') || f.startsWith('.beads/'));\n if (!statePlaneOnly) {\n // Branch may have merged main INTO itself after the PR merged — the\n // two-dot delta then contains main's own files. Judge only changes\n // UNIQUE to the branch (three-dot vs origin/main): if those are\n // state-plane-only, everything real is already on main.\n const { stdout: uniqueRaw } = await execAsync(\n `git diff --name-only origin/main...${tipSha}`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n deltaFiles = uniqueRaw.split('\\n').map((f) => f.trim()).filter(Boolean);\n statePlaneOnly = deltaFiles.every((f) =>\n f.startsWith('.pan/') || f.startsWith('.beads/'));\n }\n if (statePlaneOnly) {\n const prLabel = typeof mergedPr.number === 'number' ? `PR #${mergedPr.number}` : 'GitHub PR';\n return stepOk(step, [\n `${prLabel} is squash-merged; ${branchRef} is ahead only by state-plane commits (${deltaFiles.length} file(s): .pan/.beads) — accepted per state-plane policy`,\n ]);\n }\n } catch { /* diff failure falls through to the strict rejection below */ }\n\n const prLabel = typeof mergedPr.number === 'number' ? `PR #${mergedPr.number}` : 'merged GitHub PR';\n return stepFailed(step, `${branchRef} does not match the head commit of merged ${prLabel}; inspect before closing out.`);\n } catch {\n return null;\n }\n}\n\n/**\n * Reset issue back to open/backlog state (for destructive reset).\n */\nfunction resetIssueToTodo(ctx: LifecycleContext): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => resetIssueToTodoImpl(ctx),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('reset:reset-issue', `Failed to reset issue: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function resetIssueToTodoImpl(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'reset:reset-issue';\n try {\n if (ctx.github) {\n const { owner, repo, number } = ctx.github;\n // Reopen the issue\n await execAsync(\n `gh issue reopen ${number} --repo ${owner}/${repo}`,\n { encoding: 'utf-8' },\n ).catch(() => {}); // May already be open\n // Remove lifecycle labels\n const labelsToRemove = ['in-review', 'in-progress', 'planned', 'planning', 'Review: Approved', 'Review: Failed', 'ready-for-merge'];\n for (const label of labelsToRemove) {\n await execAsync(\n `gh issue edit ${number} --repo ${owner}/${repo} --remove-label \"${label}\"`,\n { encoding: 'utf-8' },\n ).catch(() => {}); // Label may not exist\n }\n return stepOk(step, [`Reset GitHub issue #${number}: reopened and cleared labels`]);\n }\n\n // Linear: reopen to Todo\n const linearApiKey = await getLinearApiKey();\n if (linearApiKey) {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey: linearApiKey });\n const issueNum = extractNumberSync(ctx.issueId);\n const teamKey = extractPrefixSync(ctx.issueId);\n if (issueNum === null || teamKey === null) {\n return stepFailed(step, `Could not parse issue ID: ${ctx.issueId}`);\n }\n const results = await client.issues({\n filter: {\n number: { eq: issueNum },\n team: { key: { eq: teamKey } },\n },\n first: 1,\n });\n if (results.nodes.length > 0) {\n const issue = results.nodes[0];\n const team = await issue.team;\n if (team) {\n const states = await team.states();\n const todoState = states.nodes.find(s => s.type === 'unstarted' && s.name === 'Todo') ||\n states.nodes.find(s => s.type === 'unstarted');\n if (todoState) {\n await issue.update({ stateId: todoState.id });\n }\n }\n }\n return stepOk(step, [`Reset ${trackerName(ctx, 'linear')} issue ${ctx.issueId} to Todo`]);\n }\n\n return stepSkipped(step, ['No tracker available to reset issue']);\n } catch (err) {\n return stepFailed(step, `Failed to reset issue: ${(err as Error).message}`);\n }\n}\n\n/**\n * Clear review status for an issue.\n */\nasync function resetPostMergeStateForIssue(issueId: string): Promise<void> {\n try {\n const { resetPostMergeState } = await import('../cloister/merge-agent.js');\n resetPostMergeState(issueId);\n resetPostMergeState(issueId.toUpperCase());\n } catch {\n return;\n }\n}\n\nfunction clearReviewStatusStep(issueId: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => clearReviewStatusStepImpl(issueId),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped('clear-review-status', [`Failed to clear review status (non-fatal): ${(err as Error).message}`])),\n ),\n );\n}\n\nasync function clearReviewStatusStepImpl(issueId: string): Promise<StepResult> {\n const step = 'clear-review-status';\n try {\n const { clearReviewStatus } = await import('../review-status.js');\n clearReviewStatus(issueId.toUpperCase());\n return stepOk(step, ['Review status cleared']);\n } catch {\n // Fallback: direct file manipulation\n try {\n const statusFile = join(OVERDECK_HOME, 'review-status.json');\n if (existsSync(statusFile)) {\n const data = JSON.parse(await readFile(statusFile, 'utf-8'));\n const upperKey = issueId.toUpperCase();\n if (data[upperKey]) {\n delete data[upperKey];\n await writeFile(statusFile, JSON.stringify(data, null, 2));\n }\n }\n return stepOk(step, ['Review status cleared (direct)']);\n } catch (innerErr) {\n return stepSkipped(step, [`Failed to clear review status (non-fatal): ${(innerErr as Error).message}`]);\n }\n }\n}\n\nexport const __testInternals = {\n completeVBriefStep,\n verifyBranchMerged,\n};\n\nfunction resetIssueToCanceled(ctx: LifecycleContext): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => resetIssueToCanceledImpl(ctx),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('cancel:reset-issue', `Failed to cancel issue: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function resetIssueToCanceledImpl(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'cancel:reset-issue';\n try {\n if (ctx.github) {\n const { owner, repo, number } = ctx.github;\n await execAsync(\n `gh issue edit ${number} --repo ${owner}/${repo} --add-label \"wontfix\"`,\n { encoding: 'utf-8' },\n ).catch(() => {});\n return stepOk(step, [`Marked GitHub issue #${number} as canceled/wontfix`]);\n }\n\n const linearApiKey = await getLinearApiKey();\n if (linearApiKey) {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey: linearApiKey });\n const issueNum = extractNumberSync(ctx.issueId);\n const teamKey = extractPrefixSync(ctx.issueId);\n if (issueNum === null || teamKey === null) {\n return stepFailed(step, `Could not parse issue ID: ${ctx.issueId}`);\n }\n const results = await client.issues({\n filter: {\n number: { eq: issueNum },\n team: { key: { eq: teamKey } },\n },\n first: 1,\n });\n if (results.nodes.length > 0) {\n const issue = results.nodes[0];\n const team = await issue.team;\n if (team) {\n const states = await team.states();\n const canceledState = states.nodes.find(s => s.type === 'canceled') ||\n states.nodes.find(s => s.name.toLowerCase() === 'canceled');\n if (canceledState) {\n await issue.update({ stateId: canceledState.id });\n }\n }\n }\n return stepOk(step, [`Reset ${trackerName(ctx, 'linear')} issue ${ctx.issueId} to Canceled`]);\n }\n\n return stepSkipped(step, ['No tracker available to cancel issue']);\n } catch (err) {\n return stepFailed(step, `Failed to cancel issue: ${(err as Error).message}`);\n }\n}\n","/**\n * Lifecycle — Composable, idempotent post-merge operations.\n *\n * Atomic operations:\n * archive-planning — PRD active→completed + workspace .pan/ preservation\n * close-issue — IssueTracker transition + label management\n * teardown-workspace — Full workspace cleanup (agent, worktree, Docker, tmux)\n * compact-beads — Beads compaction + git commit/push\n *\n * Workflows (compose the above):\n * approve() — merge + close + archive + teardown + compact\n * close() — close + teardown\n * closeOut() — verify-merged + archive + teardown + close + label + clear-status\n * deepWipe() — teardown(deleteBranches) + delete agent state + reset issue\n */\n\n// Types\nexport type {\n StepResult,\n WorkflowResult,\n LifecycleContext,\n TeardownOptions,\n ArchiveOptions,\n ApproveOptions,\n DeepWipeOptions,\n} from './types.js';\n\nexport { stepOk, stepSkipped, stepFailed } from './types.js';\n\n// Atomic operations\nexport { archivePlanning } from './archive-planning.js';\nexport { closeIssue } from './close-issue.js';\nexport { teardownWorkspace } from './teardown-workspace.js';\nexport { compactBeads } from './compact-beads.js';\n\n// Workflows\nexport { approve, close, closeOut, deepWipe, resetToTodo, cancelIssueWorkflow } from './workflows.js';\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecycle-SmrqysDf.js","names":["execAsync"],"sources":["../src/lib/lifecycle/teardown-workspace.ts","../src/lib/cloister/agent-gc.ts","../src/lib/lifecycle/workflows.ts","../src/lib/lifecycle/index.ts"],"sourcesContent":["/**\n * teardown-workspace — Full workspace cleanup.\n *\n * Consolidates workspace teardown from close-out.ts and workspace-manager.ts.\n * Handles: tmux sessions, TLDR daemon, Docker containers, git worktrees,\n * agent state directories, and (optionally) git branches.\n *\n * The workspace-manager's removeWorkspace() handles additional project-specific\n * cleanup (DNS, tunnels, Hume, ports) that this module does not cover.\n * In Phase 2, removeWorkspace() will delegate to this module for the common steps.\n */\n\nimport { existsSync } from 'fs';\nimport { appendFile, readFile, rm, writeFile } from 'fs/promises';\nimport { join, basename, dirname } from 'path';\nimport { homedir } from 'os';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { Effect } from 'effect';\nimport { AGENTS_DIR } from '../paths.js';\nimport { killSession, sessionExists, listSessionNames } from '../tmux.js';\nimport type { LifecycleContext, StepResult, TeardownOptions } from './types.js';\nimport { stepOk, stepSkipped, stepFailed } from './types.js';\nimport { findAllWorkspacePaths, findWorkspacePath } from './archive-planning.js';\nimport { getContainersReferencingWorkspacePath } from '../workspace-manager.js';\nimport { DEVCONTAINER_DIRNAME } from '../workspace/devcontainer-renderer.js';\n\nconst execAsync = promisify(exec);\n\n/**\n * Kill tmux sessions associated with an issue.\n */\nfunction killTmuxSessions(issueLower: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => killTmuxSessionsImpl(issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:tmux-sessions', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function killTmuxSessionsImpl(issueLower: string): Promise<StepResult> {\n const step = 'teardown:tmux-sessions';\n let killed = 0;\n\n // Exact-match sessions (agent, test, merge, planning, strike).\n const exactPatterns = [\n `agent-${issueLower}`,\n `test-${issueLower}`,\n `merge-${issueLower}`,\n `planning-${issueLower}`,\n `strike-${issueLower}`,\n ];\n for (const session of exactPatterns) {\n if (await Effect.runPromise(sessionExists(session))) {\n try {\n await Effect.runPromise(killSession(session));\n killed++;\n } catch {\n // session may have died between check and kill\n }\n }\n }\n\n // Pattern-match sessions for review coordinators, review specialists, and\n // canonical specialists. Today's naming uses the UPPER issue ID (PAN-1024)\n // not the lower form, and includes session families that the prior\n // single-regex didn't cover. PAN-1024 close-out left\n // `review-coordinator-PAN-1024-...` and\n // `specialist-overdeck-PAN-1024-test-agent` alive (2026-05-09).\n //\n // Patterns we now match (case-insensitive on the issue ID):\n // - review-coordinator-<ISSUE>-<timestamp>\n // - review-<ISSUE>-<timestamp>-<role> (legacy)\n // - specialist-<projectKey>-<ISSUE>-<role> (canonical PAN-830/915)\n try {\n const allSessions = await Effect.runPromise(listSessionNames());\n const escapedLower = issueLower.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const escapedUpper = issueLower.toUpperCase().replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const issuePart = `(${escapedLower}|${escapedUpper})`;\n const patterns: RegExp[] = [\n new RegExp(`^review-coordinator-${issuePart}-\\\\d+`),\n new RegExp(`^review-${issuePart}-\\\\d+`),\n new RegExp(`^specialist-[^-]+(?:-[^-]+)*?-${issuePart}-`),\n ];\n const matchedSessions = allSessions.filter(s => patterns.some(p => p.test(s)));\n for (const session of matchedSessions) {\n try {\n await Effect.runPromise(killSession(session));\n killed++;\n } catch {\n // session may have died between check and kill\n }\n }\n } catch {\n // Session listing may fail if tmux server is not running\n }\n\n // NOTE: Per-project ephemeral specialists (specialist-{project}-{type}) are NOT killed here.\n // They belong to the project, not the issue, and accumulate context across issues via --resume.\n // Their grace period / idle timeout handles cleanup when no new work arrives.\n\n if (killed > 0) {\n return stepOk(step, [`Killed ${killed} tmux session(s)`]);\n }\n return stepSkipped(step, ['No tmux sessions found']);\n}\n\n/**\n * Stop TLDR daemon if workspace has a .venv.\n */\nfunction stopTldrDaemon(workspacePath: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => stopTldrDaemonImpl(workspacePath),\n catch: (err) => err,\n }).pipe(\n Effect.catch(() =>\n Effect.succeed(stepSkipped('teardown:tldr-daemon', ['TLDR daemon not running or failed to stop (non-fatal)'])),\n ),\n );\n}\n\nasync function stopTldrDaemonImpl(workspacePath: string): Promise<StepResult> {\n const step = 'teardown:tldr-daemon';\n const venvPath = join(workspacePath, '.venv');\n if (!existsSync(venvPath)) {\n return stepSkipped(step, ['No .venv found']);\n }\n try {\n const { getTldrDaemonServiceSync } = await import('../tldr-daemon.js');\n const tldrService = getTldrDaemonServiceSync(workspacePath, venvPath);\n await tldrService.stop();\n return stepOk(step, ['Stopped TLDR daemon']);\n } catch {\n return stepSkipped(step, ['TLDR daemon not running or failed to stop (non-fatal)']);\n }\n}\n\n/**\n * Stop Docker containers for the workspace.\n */\nfunction stopDocker(\n workspacePath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => stopDockerImpl(workspacePath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch(() =>\n Effect.succeed(stepSkipped('teardown:docker', ['Docker cleanup skipped (not running or failed)'])),\n ),\n );\n}\n\nasync function stopDockerImpl(\n workspacePath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:docker';\n try {\n const { stopWorkspaceDocker } = await import('../workspace-manager.js');\n await Effect.runPromise(stopWorkspaceDocker(workspacePath, issueLower));\n return stepOk(step, ['Stopped Docker containers']);\n } catch {\n return stepSkipped(step, ['Docker cleanup skipped (not running or failed)']);\n }\n}\n\n/**\n * Detect whether a PID belongs to a process running inside a Docker container.\n * Container processes appear in host lsof output when paths are bind-mounted.\n */\nasync function isDockerContainerProcess(pid: string): Promise<boolean> {\n try {\n const cgroup = await readFile(`/proc/${pid}/cgroup`, 'utf-8');\n return cgroup.includes('/docker-') || cgroup.includes('/docker/');\n } catch {\n return false;\n }\n}\n\n/**\n * Kill orphaned host processes for a workspace.\n */\nfunction killOrphanedProcesses(workspacePath: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => killOrphanedProcessesImpl(workspacePath),\n catch: (err) => err,\n }).pipe(\n Effect.catch(() =>\n Effect.succeed(stepSkipped('teardown:orphaned-processes', ['Orphaned process cleanup failed (non-fatal)'])),\n ),\n );\n}\n\nasync function killOrphanedProcessesImpl(workspacePath: string): Promise<StepResult> {\n const step = 'teardown:orphaned-processes';\n try {\n // Find PIDs with cwd matching the workspace path\n const { stdout } = await execAsync(\n `lsof +D \"${workspacePath}\" -t 2>/dev/null || true`,\n { encoding: 'utf-8', timeout: 10000 },\n );\n const pids = stdout.trim().split('\\n').filter(Boolean).map(p => p.trim()).filter(p => /^\\d+$/.test(p));\n\n if (pids.length === 0) {\n return stepSkipped(step, ['No orphaned processes found']);\n }\n\n // Don't kill our own process or the dashboard\n const myPid = String(process.pid);\n const safePids = pids.filter(p => p !== myPid);\n\n if (safePids.length === 0) {\n return stepSkipped(step, ['No orphaned processes to kill']);\n }\n\n // Filter out Docker container processes — they appear in host lsof due to bind mounts\n const hostPids: string[] = [];\n for (const pid of safePids) {\n if (!(await isDockerContainerProcess(pid))) {\n hostPids.push(pid);\n }\n }\n\n if (hostPids.length === 0) {\n return stepSkipped(step, ['No orphaned host processes to kill (all were container processes)']);\n }\n\n await execAsync(`kill ${hostPids.join(' ')} 2>/dev/null || true`, { encoding: 'utf-8', timeout: 5000 });\n return stepOk(step, [`Killed ${hostPids.length} orphaned process(es)`]);\n } catch {\n return stepSkipped(step, ['Orphaned process cleanup failed (non-fatal)']);\n }\n}\n\n/**\n * Sync workspace beads to the project-root beads database before workspace deletion.\n */\nfunction syncWorkspaceBeads(\n projectPath: string,\n workspacePath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => syncWorkspaceBeadsImpl(projectPath, workspacePath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:sync-beads', `Failed to sync workspace beads: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function syncWorkspaceBeadsImpl(\n projectPath: string,\n workspacePath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:sync-beads';\n const workspaceBeadsDir = join(workspacePath, '.beads');\n\n if (!existsSync(workspaceBeadsDir)) {\n return stepSkipped(step, ['No .beads directory in workspace']);\n }\n\n try {\n // Export workspace beads to JSONL\n // 120s: bd export cold-starts a dolt server per workspace .beads and can\n // block on the global bd lock; a timeout kill bypasses `|| true` and\n // aborts the whole close-out ceremony (observed at 15s, 14/32 closes).\n await execAsync(\n 'bd export --output .beads/issues-export.jsonl 2>&1 || true',\n { cwd: workspacePath, encoding: 'utf-8', timeout: 120000 }\n );\n\n const exportPath = join(workspacePath, '.beads', 'issues-export.jsonl');\n if (!existsSync(exportPath)) {\n await execAsync('bd export --output .beads/issues.jsonl 2>&1 || true', { cwd: workspacePath, encoding: 'utf-8', timeout: 120000 });\n }\n\n // Import workspace beads into project-root database\n // Use bd import if available, otherwise copy JSONL entries\n try {\n await execAsync(\n `bd import \"${join(workspacePath, '.beads', 'issues.jsonl')}\" 2>&1 || true`,\n { cwd: projectPath, encoding: 'utf-8', timeout: 120000 }\n );\n return stepOk(step, [`Synced workspace beads to project root for ${issueLower}`]);\n } catch {\n // bd import may not exist — try manual JSONL merge\n const wsJsonl = join(workspacePath, '.beads', 'issues.jsonl');\n const projJsonl = join(projectPath, '.beads', 'issues.jsonl');\n\n if (existsSync(wsJsonl) && existsSync(projJsonl)) {\n const wsContent = await readFile(wsJsonl, 'utf-8');\n const issuePattern = issueLower.replace('-', '[-_]');\n const relevantLines = wsContent.split('\\n').filter(\n line => line.trim() && new RegExp(issuePattern, 'i').test(line)\n );\n if (relevantLines.length > 0) {\n await appendFile(projJsonl, '\\n' + relevantLines.join('\\n'));\n return stepOk(step, [`Appended ${relevantLines.length} beads entries for ${issueLower} to project JSONL`]);\n }\n }\n return stepSkipped(step, ['No beads to sync or import not available']);\n }\n } catch (err) {\n return stepFailed(step, `Failed to sync workspace beads: ${(err as Error).message}`);\n }\n}\n\n/**\n * Clear beads for this issue from the project-root .beads/issues.jsonl.\n */\nfunction clearProjectBeads(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => clearProjectBeadsImpl(projectPath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:clear-beads', `Failed to clear beads: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function clearProjectBeadsImpl(\n projectPath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:clear-beads';\n const projJsonl = join(projectPath, '.beads', 'issues.jsonl');\n\n if (!existsSync(projJsonl)) {\n return stepSkipped(step, ['No .beads/issues.jsonl in project root']);\n }\n\n try {\n const content = await readFile(projJsonl, 'utf-8');\n const lines = content.split('\\n');\n const issueUpper = issueLower.toUpperCase();\n const before = lines.length;\n // Remove lines that reference this issue (by ID in the title or issue field)\n const filtered = lines.filter(line => {\n if (!line.trim()) return true; // keep blank lines\n try {\n const entry = JSON.parse(line);\n const title = (entry.title || '').toUpperCase();\n const issue = (entry.issue || '').toUpperCase();\n return !title.includes(issueUpper) && issue !== issueUpper;\n } catch {\n return true; // keep unparseable lines\n }\n });\n const removed = before - filtered.length;\n if (removed > 0) {\n await writeFile(projJsonl, filtered.join('\\n'));\n return stepOk(step, [`Removed ${removed} beads entries for ${issueLower} from project JSONL`]);\n }\n return stepSkipped(step, [`No beads entries found for ${issueLower}`]);\n } catch (err) {\n return stepFailed(step, `Failed to clear beads: ${(err as Error).message}`);\n }\n}\n\n/**\n * Remove git worktree for the workspace.\n */\nfunction removeWorktree(\n projectPath: string,\n workspacePath: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => removeWorktreeImpl(projectPath, workspacePath),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:worktree', `Failed to remove workspace: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function removeWorktreeImpl(\n projectPath: string,\n workspacePath: string,\n): Promise<StepResult> {\n const step = 'teardown:worktree';\n if (!existsSync(workspacePath)) {\n return stepSkipped(step, ['Workspace directory does not exist']);\n }\n\n // Guard: never delete workspace (and its `.devcontainer/`) while containers\n // still reference compose paths inside it.\n const orphanedContainers = await Effect.runPromise(getContainersReferencingWorkspacePath(workspacePath));\n if (orphanedContainers.length > 0) {\n return stepFailed(\n step,\n `Cannot remove workspace: ${orphanedContainers.length} Docker container(s) still reference compose paths in ${DEVCONTAINER_DIRNAME}/. ` +\n `Run workspace Docker cleanup first or stop the containers manually.`,\n );\n }\n\n try {\n await execAsync(`git worktree remove \"${workspacePath}\" --force`, { cwd: projectPath });\n return stepOk(step, ['Removed git worktree']);\n } catch {\n // worktree remove failed — try direct removal\n try {\n await rm(workspacePath, { recursive: true, force: true });\n return stepOk(step, ['Removed workspace directory after worktree removal failed']);\n } catch (err) {\n return stepFailed(step, `Failed to remove workspace: ${(err as Error).message}`);\n }\n }\n}\n\n/**\n * Remove every agent state directory tied to an issue.\n */\nfunction removeAgentState(issueLower: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => removeAgentStateImpl(issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:agent-state', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function removeAgentStateImpl(issueLower: string): Promise<StepResult> {\n const step = 'teardown:agent-state';\n const { readdir, rm } = await import('fs/promises');\n\n let entries: string[];\n try {\n entries = await readdir(AGENTS_DIR);\n } catch {\n return stepSkipped(step, ['Agents directory not present']);\n }\n\n const work = `agent-${issueLower}`;\n const planner = `planning-${issueLower}`;\n const strike = `strike-${issueLower}`;\n const specialistPrefix = `agent-${issueLower}-`;\n const targets = entries.filter(name =>\n name === work || name === planner || name === strike || name.startsWith(specialistPrefix),\n );\n\n let removed = 0;\n for (const name of targets) {\n try {\n await rm(join(AGENTS_DIR, name), { recursive: true, force: true });\n removed++;\n } catch { /* non-fatal */ }\n }\n\n if (removed > 0) {\n return stepOk(step, [`Removed ${removed} agent state director${removed === 1 ? 'y' : 'ies'}`]);\n }\n return stepSkipped(step, ['No agent state directories found']);\n}\n\n/**\n * Delete feature branches (local + remote).\n */\nfunction deleteBranches(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => deleteBranchesImpl(projectPath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:branches', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function deleteBranchesImpl(\n projectPath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:branches';\n const branchName = `feature/${issueLower}`;\n const details: string[] = [];\n const localSlots = await execAsync(`git for-each-ref --format=\"%(refname:short)\" \"refs/heads/feature/${issueLower}-slot-*\"`, { cwd: projectPath, encoding: 'utf-8' })\n .then(({ stdout }) => stdout.trim().split('\\n').filter(Boolean)).catch(() => [] as string[]);\n const remoteSlots = await execAsync(`git ls-remote --heads origin \"feature/${issueLower}-slot-*\"`, { cwd: projectPath, encoding: 'utf-8' })\n .then(({ stdout }) => stdout.trim().split('\\n').map(line => line.split('refs/heads/')[1]).filter((name): name is string => Boolean(name))).catch(() => [] as string[]);\n\n // Delete local branch\n try {\n await execAsync(`git branch -D \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted local branch ${branchName}`);\n } catch {\n details.push(`Local branch ${branchName} not found (already deleted)`);\n }\n\n for (const slotBranch of localSlots) {\n try {\n await execAsync(`git branch -D ${JSON.stringify(slotBranch)}`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted local branch ${slotBranch}`);\n } catch { details.push(`Failed to delete local branch ${slotBranch}`); }\n }\n\n // Delete remote branch\n try {\n await execAsync(`git push origin --delete \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted remote branch ${branchName}`);\n } catch {\n details.push(`Remote branch ${branchName} not found (already deleted)`);\n }\n\n for (const slotBranch of remoteSlots) {\n try {\n await execAsync(`git push origin --delete ${JSON.stringify(slotBranch)}`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted remote branch ${slotBranch}`);\n } catch { details.push(`Failed to delete remote branch ${slotBranch}`); }\n }\n\n return stepOk(step, details);\n}\n\n/**\n * Whether a local branch exists and is fully merged into main.\n */\nasync function localBranchMergedState(\n projectPath: string,\n branchName: string,\n): Promise<{ exists: boolean; merged: boolean }> {\n try {\n await execAsync(`git show-ref --verify --quiet \"refs/heads/${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n } catch {\n return { exists: false, merged: false };\n }\n try {\n await execAsync(`git merge-base --is-ancestor \"${branchName}\" main`, { cwd: projectPath, encoding: 'utf-8' });\n return { exists: true, merged: true };\n } catch {\n return { exists: true, merged: false };\n }\n}\n\n/**\n * Delete the strike branch (local + remote) once it is merged into main.\n *\n * Strike work (`pan strike`) lands on main directly, so a merged\n * `strike/<issue>` branch is pure residue — it is deleted on every teardown,\n * not just when `deleteBranches` is requested (PAN-1721). An UNMERGED strike\n * branch may hold the only copy of an aborted strike's work, so it is\n * preserved and reported instead.\n */\nfunction deleteStrikeBranch(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => deleteStrikeBranchImpl(projectPath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:strike-branch', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function deleteStrikeBranchImpl(\n projectPath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:strike-branch';\n const branchName = `strike/${issueLower}`;\n const details: string[] = [];\n\n // Local branch\n const local = await localBranchMergedState(projectPath, branchName);\n if (local.exists) {\n if (local.merged) {\n try {\n await execAsync(`git branch -D \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted local branch ${branchName}`);\n } catch (err) {\n details.push(`Failed to delete local branch ${branchName}: ${(err as Error).message}`);\n }\n } else {\n details.push(`Preserved local branch ${branchName} — not merged to main`);\n }\n }\n\n // Remote branch\n try {\n const { stdout: remoteRef } = await execAsync(\n `git ls-remote --heads origin \"${branchName}\" 2>/dev/null || true`,\n { cwd: projectPath, encoding: 'utf-8' },\n );\n if (remoteRef.trim()) {\n let remoteMerged = false;\n try {\n await execAsync(`git fetch origin \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n await execAsync('git merge-base --is-ancestor FETCH_HEAD main', { cwd: projectPath, encoding: 'utf-8' });\n remoteMerged = true;\n } catch {\n remoteMerged = false;\n }\n if (remoteMerged) {\n await execAsync(`git push origin --delete \"${branchName}\"`, { cwd: projectPath, encoding: 'utf-8' });\n details.push(`Deleted remote branch ${branchName}`);\n } else {\n details.push(`Preserved remote branch ${branchName} — not merged to main`);\n }\n }\n } catch {\n // remote check/delete failed — non-fatal\n }\n\n if (details.length === 0) {\n return stepSkipped(step, [`No strike branch ${branchName} found`]);\n }\n return details.some(d => d.startsWith('Failed'))\n ? stepFailed(step, details.join('; '))\n : stepOk(step, details);\n}\n\n/**\n * Remove leftover strike worktrees (`workspaces/feature-<issue>-strike`).\n *\n * Runs when the regular worktree removal is gated off (remove_workspace=false\n * at close-out): a strike worktree has no post-close purpose once the strike\n * branch is merged or gone, and leaving it keeps the closed issue alive in\n * resource discovery (PAN-1721). Worktrees whose strike branch has unmerged\n * commits are preserved alongside the branch.\n */\nfunction removeStrikeWorktrees(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => removeStrikeWorktreesImpl(projectPath, issueLower),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:strike-worktree', `Failed: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function removeStrikeWorktreesImpl(\n projectPath: string,\n issueLower: string,\n): Promise<StepResult> {\n const step = 'teardown:strike-worktree';\n const strikePaths = findAllWorkspacePaths(projectPath, issueLower).filter(p => p.endsWith('-strike'));\n if (strikePaths.length === 0) {\n return stepSkipped(step, ['No strike worktree found']);\n }\n\n const branch = await localBranchMergedState(projectPath, `strike/${issueLower}`);\n if (branch.exists && !branch.merged) {\n return stepSkipped(step, [`Preserved strike worktree — strike/${issueLower} not merged to main`]);\n }\n\n const details: string[] = [];\n for (const p of strikePaths) {\n const result = await removeWorktreeImpl(projectPath, p);\n details.push(...(result.details ?? [result.error ?? result.step]));\n if (!result.success && !result.skipped) {\n return stepFailed(step, `Failed to remove strike worktree ${p}: ${result.error ?? 'unknown error'}`);\n }\n }\n return stepOk(step, details);\n}\n\n/**\n * Clear shadow state for an issue.\n */\nfunction clearShadowState(issueId: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => clearShadowStateImpl(issueId),\n catch: (err) => err,\n }).pipe(\n Effect.catch(() =>\n Effect.succeed(stepSkipped('teardown:shadow-state', ['Shadow state cleanup skipped (non-fatal)'])),\n ),\n );\n}\n\nasync function clearShadowStateImpl(issueId: string): Promise<StepResult> {\n const step = 'teardown:shadow-state';\n try {\n const { removeShadowState } = await import('../shadow-state.js');\n const result = removeShadowState(issueId);\n if (result.success) {\n return stepOk(step, [`Cleared shadow state for ${issueId}`]);\n }\n return stepSkipped(step, ['No shadow state found']);\n } catch {\n return stepSkipped(step, ['Shadow state cleanup skipped (non-fatal)']);\n }\n}\n\n/**\n * Remove legacy .planning/<issue>/ directory from project root.\n */\nfunction clearLegacyPlanningDir(\n projectPath: string,\n issueLower: string,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const step = 'teardown:legacy-planning-dir';\n const legacyDir = join(projectPath, '.planning', issueLower);\n if (!existsSync(legacyDir)) {\n return stepSkipped(step, ['No legacy planning directory found']);\n }\n await rm(legacyDir, { recursive: true, force: true });\n return stepOk(step, [`Deleted legacy planning dir: ${legacyDir}`]);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:legacy-planning-dir', `Failed to delete legacy planning dir: ${(err as Error).message}`)),\n ),\n );\n}\n\n/**\n * Build template placeholders for project-specific cleanup (tunnel, Hume).\n */\nfunction buildPlaceholders(\n ctx: LifecycleContext,\n opts: TeardownOptions,\n workspacePath: string,\n) {\n const issueLower = ctx.issueId.toLowerCase();\n const featureFolder = `feature-${issueLower}`;\n const projName = opts.projectName || ctx.projectName || basename(ctx.projectPath);\n const domain = opts.workspaceConfig?.dns?.domain || 'localhost';\n return {\n FEATURE_NAME: issueLower,\n FEATURE_FOLDER: featureFolder,\n BRANCH_NAME: `feature/${issueLower}`,\n COMPOSE_PROJECT: `${projName}-${featureFolder}`,\n DOMAIN: domain,\n PROJECT_NAME: projName,\n PROJECT_PATH: ctx.projectPath,\n WORKSPACE_PATH: workspacePath,\n };\n}\n\n/**\n * Remove Cloudflare tunnel ingress for workspace.\n */\nfunction removeTunnelConfig(\n tunnelConfig: any,\n placeholders: Record<string, string>,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const { removeTunnelIngress } = await import('../tunnel.js');\n const result = await Effect.runPromise(removeTunnelIngress(tunnelConfig, placeholders as any));\n return stepOk('teardown:tunnel', result.steps || ['Removed tunnel ingress']);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped('teardown:tunnel', [`Tunnel cleanup warning: ${(err as Error).message}`])),\n ),\n );\n}\n\n/**\n * Remove Hume EVI config for workspace.\n */\nfunction removeHumeEviConfig(\n humeConfig: any,\n placeholders: Record<string, string>,\n): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const { deleteHumeConfig } = await import('../hume.js');\n const result = await Effect.runPromise(deleteHumeConfig(humeConfig, placeholders as any));\n return stepOk('teardown:hume', result.steps || ['Removed Hume EVI config']);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped('teardown:hume', [`Hume cleanup warning: ${(err as Error).message}`])),\n ),\n );\n}\n\n/**\n * Full workspace teardown.\n */\nexport function teardownWorkspace(\n ctx: LifecycleContext,\n opts: TeardownOptions = {},\n): Effect.Effect<StepResult[]> {\n return Effect.gen(function* () {\n const issueLower = ctx.issueId.toLowerCase();\n const workspacePath = findWorkspacePath(ctx.projectPath, issueLower);\n const shouldDeleteWorkspace = opts.deleteWorkspace !== false; // default true\n const results: StepResult[] = [];\n\n // 1. Kill tmux sessions\n results.push(yield* killTmuxSessions(issueLower));\n\n // 2. Clear shadow state (always runs)\n results.push(yield* clearShadowState(ctx.issueId));\n\n // 3. Clear legacy planning directory (always runs)\n results.push(yield* clearLegacyPlanningDir(ctx.projectPath, issueLower));\n\n // 4-9: Workspace-specific cleanup\n if (workspacePath && existsSync(workspacePath)) {\n // 4. Stop TLDR daemon (only if deleting workspace)\n if (shouldDeleteWorkspace) {\n results.push(yield* stopTldrDaemon(workspacePath));\n }\n\n // 5. Stop Docker containers (only if deleting workspace)\n if (shouldDeleteWorkspace && !opts.skipDocker) {\n results.push(yield* stopDocker(workspacePath, issueLower));\n }\n\n // 5b. Kill orphaned host processes (Vite, node) that survive Docker teardown\n if (shouldDeleteWorkspace) {\n results.push(yield* killOrphanedProcesses(workspacePath));\n }\n\n // 6. Beads lifecycle: sync or clear depending on context (PAN-412)\n if (opts.clearBeads) {\n results.push(yield* clearProjectBeads(ctx.projectPath, issueLower));\n } else if (shouldDeleteWorkspace) {\n results.push(yield* syncWorkspaceBeads(ctx.projectPath, workspacePath, issueLower));\n }\n\n // 7-8: Project-specific cleanup (tunnel, Hume)\n if (shouldDeleteWorkspace && (opts.workspaceConfig?.tunnel || opts.workspaceConfig?.hume)) {\n const placeholders = buildPlaceholders(ctx, opts, workspacePath);\n\n if (opts.workspaceConfig.tunnel) {\n results.push(yield* removeTunnelConfig(opts.workspaceConfig.tunnel, placeholders));\n }\n if (opts.workspaceConfig.hume) {\n results.push(yield* removeHumeEviConfig(opts.workspaceConfig.hume, placeholders));\n }\n }\n\n // 9. Remove worktree + workspace directory (only if deleting workspace).\n if (shouldDeleteWorkspace) {\n const allPaths = findAllWorkspacePaths(ctx.projectPath, issueLower);\n for (const p of allPaths) {\n results.push(yield* removeWorktree(ctx.projectPath, p));\n }\n }\n } else {\n results.push(stepSkipped('teardown:workspace', ['No workspace found to clean up']));\n }\n\n // 9b. Strike worktrees are residue once the strike branch is merged —\n // remove them even when deleteWorkspace is gated off (PAN-1721). When\n // shouldDeleteWorkspace is true the loop above already removed them via\n // findAllWorkspacePaths.\n if (!shouldDeleteWorkspace) {\n results.push(yield* removeStrikeWorktrees(ctx.projectPath, issueLower));\n }\n\n // 10. Remove agent state\n results.push(yield* removeAgentState(issueLower));\n\n // 11. Delete branches. Feature branches only if explicitly requested;\n // the strike branch is always a candidate once merged to main (PAN-1721).\n results.push(yield* deleteStrikeBranch(ctx.projectPath, issueLower));\n if (opts.deleteBranches) {\n results.push(yield* deleteBranches(ctx.projectPath, issueLower));\n }\n\n // 12. Prune checkpoint refs for this issue's agents.\n results.push(yield* pruneCheckpointRefs(ctx.projectPath, issueLower));\n\n // 13. Prune specialist registry entries for this issue.\n results.push(yield* pruneSpecialistRegistry(ctx.issueId));\n\n return results;\n });\n}\n\nfunction pruneSpecialistRegistry(issueId: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const step = 'teardown:specialist-registry';\n const { pruneSpecialistRegistryEntriesForIssue } = await import('../cloister/specialists.js');\n const removed = pruneSpecialistRegistryEntriesForIssue(issueId);\n return removed > 0\n ? stepOk(step, [`Pruned ${removed} specialist registry entr${removed === 1 ? 'y' : 'ies'} for ${issueId}`])\n : stepSkipped(step, [`No specialist registry entries for ${issueId}`]);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped('teardown:specialist-registry', [`Specialist registry prune failed (non-fatal): ${(err as Error).message}`])),\n ),\n );\n}\n\nfunction pruneCheckpointRefs(projectPath: string, issueLower: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: async () => {\n const step = 'teardown:checkpoint-refs';\n const { pruneCheckpointRefsForAgents } = await import('../checkpoint/checkpoint-manager.js');\n const agentIds = [`agent-${issueLower}`, `planning-${issueLower}`, `strike-${issueLower}`];\n const pruned = await Effect.runPromise(pruneCheckpointRefsForAgents(projectPath, agentIds));\n return stepOk(step, [`Pruned ${pruned} checkpoint ref(s) for ${agentIds.join(', ')}`]);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('teardown:checkpoint-refs', `Checkpoint prune failed: ${(err as Error).message}`)),\n ),\n );\n}\n","import { listAllAgentsSync, removeAgentSync } from '../overdeck/agents.js';\nimport { readIssueRecordForWorkspaceSync } from '../pan-dir/record.js';\n\nexport interface AgentGcResult { removed: string[]; preserved: string[] }\nexport interface AgentGcRow { id: string; issueId: string; status: string; workspace?: string | null }\n\nexport function pruneStoppedAgentsForIssue(\n issueId: string,\n agents: AgentGcRow[] = listAllAgentsSync(),\n remove: (id: string) => void = removeAgentSync,\n): AgentGcResult {\n const issue = issueId.toUpperCase();\n const scoped = agents.filter(agent => agent.issueId.toUpperCase() === issue);\n const removed = scoped.filter(agent => agent.status === 'stopped').map(agent => agent.id);\n const preserved = scoped.filter(agent => agent.status !== 'stopped').map(agent => agent.id);\n for (const id of removed) remove(id);\n return { removed, preserved };\n}\n\nexport function pruneTerminalStoppedAgents(): AgentGcResult {\n const agents = listAllAgentsSync();\n const terminal = agents.filter(agent => agent.status === 'stopped' && agent.workspace\n && readIssueRecordForWorkspaceSync(agent.workspace, agent.issueId)?.pipeline?.closedOut === true);\n const removed = terminal.map(agent => agent.id);\n for (const id of removed) removeAgentSync(id);\n return { removed, preserved: [] };\n}\n","/**\n * Lifecycle workflows — Compose atomic operations into complete workflows.\n *\n * approve() — Post-merge: archive + close + teardown + compact-beads\n * close() — Simple close: close-issue + teardown\n * closeOut() — Full ceremony: verify-merged + archive + teardown + close + label + clear-status\n * deepWipe() — Destructive: teardown(deleteBranches) + delete agent state + reset issue\n */\n\nimport { existsSync } from 'fs';\nimport { copyFile, readFile, writeFile } from 'fs/promises';\nimport { join } from 'path';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { Effect } from 'effect';\nimport { OVERDECK_HOME } from '../paths.js';\nimport type {\n LifecycleContext,\n WorkflowResult,\n StepResult,\n ApproveOptions,\n DeepWipeOptions,\n ArchiveOptions,\n} from './types.js';\nimport { stepOk, stepSkipped, stepFailed, getLinearApiKey } from './types.js';\nimport { archivePlanning, findWorkspacePath } from './archive-planning.js';\nimport { closeIssue, type CloseIssueOptions } from './close-issue.js';\nimport { teardownWorkspace } from './teardown-workspace.js';\nimport { compactBeads } from './compact-beads.js';\nimport { loadCloisterConfig } from '../cloister/config.js';\nimport { extractNumberSync, extractPrefixSync } from '../issue-id.js';\nimport { recordFeatureRegistryLifecycle } from '../registry/feature-registry-population.js';\nimport { getProjectConfigFromWorkspacePath, markRecordPipelineClosedOutSync } from '../pan-dir/record.js';\nimport { pruneStoppedAgentsForIssue } from '../cloister/agent-gc.js';\n\nconst execAsync = promisify(exec);\n\nfunction trackerName(ctx: LifecycleContext, fallback: string): string {\n const name = ctx.tracker?.name ?? fallback;\n return name.charAt(0).toUpperCase() + name.slice(1);\n}\n\n/**\n * Build a WorkflowResult from collected steps.\n */\nfunction buildResult(\n workflow: WorkflowResult['workflow'],\n issueId: string,\n steps: StepResult[],\n startTime: number,\n): WorkflowResult {\n return {\n workflow,\n issueId,\n success: steps.every(s => s.success),\n steps,\n duration: Date.now() - startTime,\n };\n}\n\nfunction hasBlockingFailure(steps: StepResult[]): boolean {\n return steps.some(s => !s.success && !s.skipped);\n}\n\n/**\n * approve() — Post-merge lifecycle.\n */\nexport function approve(\n ctx: LifecycleContext,\n opts: ApproveOptions & CloseIssueOptions & ArchiveOptions = {},\n): Effect.Effect<WorkflowResult> {\n return Effect.gen(function* () {\n const start = Date.now();\n const allSteps: StepResult[] = [];\n\n // 1. Archive planning\n const archiveSteps = yield* archivePlanning(ctx, opts);\n allSteps.push(...archiveSteps);\n\n // If archive failed, stop — don't destroy unarchived artifacts\n const archiveFailed = archiveSteps.some(s => !s.success && !s.skipped);\n if (archiveFailed) {\n allSteps.push(stepFailed('approve:abort', 'Stopped — archiving failed, workspace preserved'));\n return buildResult('approve', ctx.issueId, allSteps, start);\n }\n\n // 2. Close issue\n const closeSteps = yield* closeIssue(ctx, {\n tracker: opts.tracker,\n comment: 'Merged to main via Overdeck lifecycle',\n applyLabel: true,\n });\n allSteps.push(...closeSteps);\n\n // 3. Teardown workspace (delete branches — merge is complete)\n const teardownSteps = yield* teardownWorkspace(ctx, { deleteBranches: true });\n allSteps.push(...teardownSteps);\n\n // 4. Compact beads (non-blocking — failure doesn't affect workflow success)\n if (!opts.skipBeadsCompaction) {\n const beadsResult = yield* compactBeads(ctx);\n allSteps.push(beadsResult);\n }\n\n // 5. Clear review status\n const clearResult = yield* clearReviewStatusStep(ctx.issueId);\n allSteps.push(clearResult);\n\n return buildResult('approve', ctx.issueId, allSteps, start);\n });\n}\n\n/**\n * close() — Simple issue close with teardown.\n */\nexport function close(\n ctx: LifecycleContext,\n opts: CloseIssueOptions = {},\n): Effect.Effect<WorkflowResult> {\n return Effect.gen(function* () {\n const start = Date.now();\n const allSteps: StepResult[] = [];\n\n // 1. Close issue\n const closeSteps = yield* closeIssue(ctx, {\n tracker: opts.tracker,\n reason: opts.reason,\n applyLabel: false,\n });\n allSteps.push(...closeSteps);\n\n // 2. Teardown workspace\n const teardownSteps = yield* teardownWorkspace(ctx);\n allSteps.push(...teardownSteps);\n\n // 3. Clear review status\n const clearResult = yield* clearReviewStatusStep(ctx.issueId);\n allSteps.push(clearResult);\n\n return buildResult('close', ctx.issueId, allSteps, start);\n });\n}\n\n/**\n * closeOut() — Full close-out ceremony.\n *\n * This is the human-gated verification and cleanup workflow.\n * Replaces the monolithic executeCloseOut() function.\n *\n * 1. Verify branch merged (hard fail if not — must pass before any cleanup)\n * 2. Move PRD + archive workspace artifacts (hard fail if archiving fails)\n * 3. Mark vBRIEF completed\n * 4. Clean up workspace (tmux, TLDR, Docker, worktree)\n * 5. Clean up agent state\n * 6. Close issue on tracker\n * 7. Apply closed-out label\n * 8. Clear review status\n */\nexport function closeOut(\n ctx: LifecycleContext,\n opts: CloseIssueOptions & ArchiveOptions = {},\n): Effect.Effect<WorkflowResult> {\n return Effect.gen(function* () {\n const start = Date.now();\n const allSteps: StepResult[] = [];\n\n // 1. Verify branch merged (hard fail — must pass before we archive or clean up)\n const mergeVerify = yield* verifyBranchMerged(ctx);\n allSteps.push(mergeVerify);\n if (!mergeVerify.success && !mergeVerify.skipped) {\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 2. Move PRD + archive workspace artifacts\n const archiveSteps = yield* archivePlanning(ctx, opts);\n allSteps.push(...archiveSteps);\n\n // Hard fail on archive failure — don't destroy unarchived artifacts\n const archiveFailed = archiveSteps.some(s => !s.success && !s.skipped);\n if (archiveFailed) {\n allSteps.push(stepFailed('close-out:abort', 'Stopped — archiving failed, workspace preserved'));\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 3. Mark the vBRIEF completed on main before teardown removes local state.\n const vbriefStep = yield* Effect.promise(() => completeVBriefStep(ctx));\n allSteps.push(vbriefStep);\n if (!vbriefStep.success && !vbriefStep.skipped) {\n allSteps.push(stepFailed('close-out:abort', 'Stopped — vBRIEF completion failed, workspace preserved'));\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 4+5. Teardown workspace + agent state\n const closeOutConfig = (yield* Effect.promise(() => Effect.runPromise(loadCloisterConfig()))).close_out;\n const teardownSteps = yield* teardownWorkspace(ctx, {\n deleteWorkspace: closeOutConfig?.remove_workspace ?? false,\n deleteBranches: closeOutConfig?.delete_feature_branch ?? false,\n });\n allSteps.push(...teardownSteps);\n if (hasBlockingFailure(teardownSteps)) {\n allSteps.push(stepFailed('close-out:abort', 'Stopped — teardown failed, tracker issue and review status preserved'));\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 6+7. Close issue + apply label\n const closeSteps = yield* closeIssue(ctx, {\n tracker: opts.tracker,\n comment: ctx.auto ? 'Closed via automatic close-out ceremony' : 'Closed via close-out ceremony',\n applyLabel: true,\n });\n allSteps.push(...closeSteps);\n if (hasBlockingFailure(closeSteps)) {\n allSteps.push(stepFailed('close-out:abort', 'Stopped — issue close failed, review status preserved'));\n return buildResult('close-out', ctx.issueId, allSteps, start);\n }\n\n // 8. Mark durable pipeline terminal before clearing the DB cache.\n const markTerminal = yield* markPipelineClosedOutStep(ctx);\n allSteps.push(markTerminal);\n if (markTerminal.success) {\n const pruned = pruneStoppedAgentsForIssue(ctx.issueId);\n allSteps.push(pruned.preserved.length > 0\n ? stepSkipped('close-out:prune-agent-rows', [`WARNING: preserved live/non-stopped agents: ${pruned.preserved.join(', ')}`])\n : stepOk('close-out:prune-agent-rows', [`Pruned ${pruned.removed.length} stopped agent row(s)`]));\n }\n\n // 9. Clear review status\n const clearResult = yield* clearReviewStatusStep(ctx.issueId);\n allSteps.push(clearResult);\n\n yield* Effect.promise(() => resetPostMergeStateForIssue(ctx.issueId));\n yield* Effect.promise(() => recordFeatureRegistryLifecycle({ issueId: ctx.issueId, status: 'archived' }));\n\n return buildResult('close-out', ctx.issueId, allSteps, start);\n });\n}\n\nfunction markPipelineClosedOutStep(ctx: LifecycleContext): Effect.Effect<StepResult> {\n const step = 'close-out:mark-pipeline-terminal';\n return Effect.try({\n try: () => {\n const project = getProjectConfigFromWorkspacePath(ctx.projectPath);\n markRecordPipelineClosedOutSync(project, ctx.issueId.toUpperCase());\n return stepOk(step, ['Marked durable pipeline journal closed-out']);\n },\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped(step, [`Pipeline terminal marker failed (non-fatal): ${(err as Error).message ?? String(err)}`])),\n ),\n );\n}\n\n/**\n * deepWipe() — Destructive cleanup for abandoned workspaces.\n */\nfunction destructiveResetWorkflow(\n workflow: 'deep-wipe' | 'reset' | 'cancel',\n ctx: LifecycleContext,\n opts: DeepWipeOptions,\n resetStep: (ctx: LifecycleContext) => Effect.Effect<StepResult>,\n progressLabel: string,\n progressSuccessDetail: string,\n): Effect.Effect<WorkflowResult> {\n return Effect.gen(function* () {\n const start = Date.now();\n const allSteps: StepResult[] = [];\n const { deleteWorkspace = true, deleteBranches = true, resetIssue = true, onProgress } = opts;\n const resetContext = opts.tracker ? { ...ctx, tracker: opts.tracker } : ctx;\n\n const TOTAL_STEPS = 3 + (resetIssue ? 1 : 0);\n let stepNum = 0;\n\n const progress = (label: string, detail: string, status: 'active' | 'complete' | 'error' = 'active') => {\n onProgress?.({ step: stepNum, total: TOTAL_STEPS, label, detail, status });\n };\n\n stepNum = 1;\n\n // Preserve PRD before workspace teardown so it survives reset/cancel.\n const issueLower = ctx.issueId.toLowerCase();\n const workspacePath = findWorkspacePath(ctx.projectPath, issueLower);\n if (workspacePath && existsSync(workspacePath)) {\n const prdPath = join(workspacePath, '.pan', 'prd.md');\n if (existsSync(prdPath)) {\n yield* Effect.tryPromise({\n try: async () => {\n const activeDir = join(ctx.projectPath, 'docs', 'prds', 'active', issueLower);\n const { mkdir } = await import('fs/promises');\n await mkdir(activeDir, { recursive: true });\n await copyFile(prdPath, join(activeDir, 'prd.md'));\n },\n catch: () => null,\n }).pipe(Effect.catch(() => Effect.void));\n }\n }\n\n progress('Tearing down workspace', 'Killing agents, stopping services, removing files');\n const teardownSteps = yield* teardownWorkspace(ctx, {\n deleteWorkspace,\n deleteBranches,\n clearBeads: true,\n workspaceConfig: opts.workspaceConfig,\n projectName: opts.projectName,\n });\n allSteps.push(...teardownSteps);\n const teardownFailed = teardownSteps.some(s => !s.success && !s.skipped);\n progress('Tearing down workspace', teardownFailed ? 'Some steps failed' : 'Workspace torn down', teardownFailed ? 'error' : 'complete');\n\n stepNum = 2;\n progress('Deleting git branches', `feature/${ctx.issueId.toLowerCase()}`);\n progress('Deleting git branches', deleteBranches ? 'Branches removed' : 'Skipped', 'complete');\n\n if (resetIssue) {\n stepNum = 3;\n progress(progressLabel, `${ctx.issueId}`);\n const resetResult = yield* resetStep(resetContext);\n allSteps.push(resetResult);\n progress(progressLabel, resetResult.success ? progressSuccessDetail : (resetResult.error || 'Failed'), resetResult.success ? 'complete' : 'error');\n }\n\n stepNum = resetIssue ? 4 : 3;\n progress('Clearing review status', 'Removing specialist state');\n const clearResult = yield* clearReviewStatusStep(ctx.issueId);\n allSteps.push(clearResult);\n progress('Clearing review status', 'Review status cleared', 'complete');\n\n return buildResult(workflow, ctx.issueId, allSteps, start);\n });\n}\n\nexport function deepWipe(\n ctx: LifecycleContext,\n opts: DeepWipeOptions = {},\n): Effect.Effect<WorkflowResult> {\n return destructiveResetWorkflow(\n 'deep-wipe',\n ctx,\n opts,\n resetIssueToTodo,\n 'Resetting issue status',\n 'Issue reset to Todo',\n );\n}\n\nexport function resetToTodo(\n ctx: LifecycleContext,\n opts: DeepWipeOptions = {},\n): Effect.Effect<WorkflowResult> {\n return destructiveResetWorkflow(\n 'reset',\n ctx,\n opts,\n resetIssueToTodo,\n 'Resetting issue status',\n 'Issue reset to Todo',\n );\n}\n\nexport function cancelIssueWorkflow(\n ctx: LifecycleContext,\n opts: DeepWipeOptions = {},\n): Effect.Effect<WorkflowResult> {\n return destructiveResetWorkflow(\n 'cancel',\n ctx,\n opts,\n resetIssueToCanceled,\n 'Canceling issue',\n 'Issue moved to Canceled',\n );\n}\n\n// --- Internal helpers ---\n\nasync function completeVBriefStep(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'close-out:vbrief-completed';\n try {\n const { transitionVBriefOnMain } = await import('../vbrief/lifecycle-io.js');\n const result = await Effect.runPromise(transitionVBriefOnMain(\n ctx.projectPath,\n ctx.issueId,\n 'completed',\n 'completed',\n `scope: complete ${ctx.issueId.toUpperCase()} vBRIEF`,\n ));\n const details = [\n result.moved ? 'Updated vBRIEF lifecycle to completed' : 'vBRIEF lifecycle already completed',\n result.statusUpdated ? 'Updated plan.status to completed' : 'plan.status already completed',\n ];\n if (result.committed) details.push('Committed vBRIEF completion on main');\n return stepOk(step, details);\n } catch (err) {\n const cause = (err as { cause?: unknown }).cause ?? err;\n const message = cause instanceof Error ? cause.message : String(cause);\n if (message.includes('No vBRIEF found')) {\n return stepSkipped(step, [`No vBRIEF found for ${ctx.issueId}`]);\n }\n return stepFailed(step, `vBRIEF completion failed: ${message}`);\n }\n}\n\n/**\n * Verify feature branch is merged into main.\n */\nfunction verifyBranchMerged(ctx: LifecycleContext): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => verifyBranchMergedImpl(ctx),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('close-out:verify-merged', `Could not verify merge: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function verifyBranchMergedImpl(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'close-out:verify-merged';\n const issueLower = ctx.issueId.toLowerCase();\n const branchName = `feature/${issueLower}`;\n\n try {\n // Check review-status first — the merge specialist validates before marking merged\n try {\n const { loadReviewStatuses } = await import('../review-status.js');\n const statuses = loadReviewStatuses();\n const issueKey = ctx.issueId.toUpperCase();\n if (statuses[issueKey]?.mergeStatus === 'merged') {\n return stepOk(step, ['Merge specialist confirmed merge completed']);\n }\n } catch {\n // review-status.json may not exist, continue with git checks\n }\n\n\n // Check if branch exists locally\n const { stdout: branchExists } = await execAsync(\n `git branch --list \"${branchName}\" 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n\n if (branchExists.trim()) {\n // Use merge-base --is-ancestor: checks if the branch tip is reachable from main\n try {\n await execAsync(\n `git merge-base --is-ancestor ${branchName} main`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const remoteCheck = await verifyRemoteBranchIfPresent(ctx, branchName);\n if (remoteCheck && !remoteCheck.success) return remoteCheck;\n return stepOk(step, [\n 'All commits merged to main',\n ...(remoteCheck?.details ?? []),\n ]);\n } catch {\n // --is-ancestor fails for squash merges where the branch still exists.\n try {\n const { stdout: codeDiff } = await execAsync(\n `git diff main...${branchName} -- ':!.planning' ':!docs/prds' ':!.overdeck/prompts' 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (!codeDiff.trim()) {\n const remoteCheck = await verifyRemoteBranchIfPresent(ctx, branchName);\n if (remoteCheck && !remoteCheck.success) return remoteCheck;\n return stepOk(step, [\n 'Code changes squash-merged to main (only planning artifacts remain on branch)',\n ...(remoteCheck?.details ?? []),\n ]);\n }\n } catch {\n // diff failed — fall through to unmerged report\n }\n\n const githubMerged = await verifySquashMergedPrByBranch(ctx, branchName, branchName);\n if (githubMerged?.success) {\n const remoteCheck = await verifyRemoteBranchIfPresent(ctx, branchName);\n if (remoteCheck && !remoteCheck.success) return remoteCheck;\n return stepOk(step, [\n ...(githubMerged.details ?? []),\n ...(remoteCheck?.details ?? []),\n ]);\n }\n if (githubMerged) return githubMerged;\n\n const { stdout: unmerged } = await execAsync(\n `git log main..${branchName} --oneline 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const count = unmerged.trim() ? unmerged.trim().split('\\n').length : 0;\n\n if (ctx.github) {\n try {\n const { stdout: issueState } = await execAsync(\n `gh issue view ${ctx.github.number} --repo ${ctx.github.owner}/${ctx.github.repo} --json state --jq '.state'`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (issueState.trim().toUpperCase() === 'CLOSED') {\n return stepSkipped(step, [`Issue already closed on GitHub; ${count} unmerged commit(s) remain on ${branchName}`]);\n }\n } catch {\n // gh check failed — fall through to hard fail\n }\n }\n\n return stepFailed(step, `${count} unmerged commit(s) on ${branchName}. Merge before closing out.`);\n }\n }\n\n // Check remote\n const { stdout: remoteBranch } = await execAsync(\n `git ls-remote --heads origin \"${branchName}\" 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n\n if (remoteBranch.trim()) {\n await execAsync(`git fetch origin ${branchName}`, { cwd: ctx.projectPath }).catch(() => {});\n const remoteCheck = await verifyRemoteBranchIfPresent(ctx, branchName);\n if (remoteCheck) return remoteCheck;\n }\n\n // No branch at all — assume squash-merged and branch deleted\n return stepOk(step, ['Branch already cleaned up (squash-merged)']);\n } catch (err) {\n return stepFailed(step, `Could not verify merge: ${(err as Error).message}`);\n }\n}\n\ntype GitHubMergedPr = {\n number?: number;\n mergedAt?: string | null;\n headRefOid?: string | null;\n url?: string | null;\n};\n\nasync function verifyRemoteBranchIfPresent(\n ctx: LifecycleContext,\n branchName: string,\n): Promise<StepResult | null> {\n const step = 'close-out:verify-merged';\n const remoteRef = `origin/${branchName}`;\n\n const { stdout: remoteBranch } = await execAsync(\n `git ls-remote --heads origin \"${branchName}\" 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (!remoteBranch.trim()) return null;\n\n await execAsync(`git fetch origin ${branchName}`, { cwd: ctx.projectPath }).catch(() => {});\n\n try {\n await execAsync(\n `git merge-base --is-ancestor ${remoteRef} main`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n return stepOk(step, ['Remote branch fully merged']);\n } catch {\n // Squash-merge detection for remote branch\n try {\n const { stdout: codeDiff } = await execAsync(\n `git diff main...${remoteRef} -- ':!.planning' ':!docs/prds' ':!.overdeck/prompts' 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (!codeDiff.trim()) {\n return stepOk(step, ['Remote code changes squash-merged to main (only planning artifacts remain on branch)']);\n }\n } catch {\n // diff failed — fall through\n }\n\n const githubMerged = await verifySquashMergedPrByBranch(ctx, branchName, remoteRef);\n if (githubMerged) return githubMerged;\n\n const { stdout: remoteUnmerged } = await execAsync(\n `git log main..${remoteRef} --oneline 2>/dev/null || true`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const count = remoteUnmerged.trim() ? remoteUnmerged.trim().split('\\n').length : 0;\n\n if (ctx.github) {\n try {\n const { stdout: issueState } = await execAsync(\n `gh issue view ${ctx.github.number} --repo ${ctx.github.owner}/${ctx.github.repo} --json state --jq '.state'`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n if (issueState.trim().toUpperCase() === 'CLOSED') {\n return stepSkipped(step, [`Issue already closed on GitHub; ${count} unmerged commit(s) remain on remote ${branchName}`]);\n }\n } catch {\n // gh check failed — fall through to hard fail\n }\n }\n\n return stepFailed(step, `${count} unmerged commit(s) on remote ${branchName}.`);\n }\n}\n\nasync function verifySquashMergedPrByBranch(\n ctx: LifecycleContext,\n branchName: string,\n branchRef: string,\n): Promise<StepResult | null> {\n if (!ctx.github) return null;\n\n const step = 'close-out:verify-merged';\n const { owner, repo } = ctx.github;\n\n try {\n const { stdout: prJson } = await execAsync(\n `gh pr list --repo ${owner}/${repo} --state merged --head ${JSON.stringify(branchName)} --json number,mergedAt,headRefOid,url`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const prs = JSON.parse(prJson) as GitHubMergedPr[];\n const mergedPr = prs\n .filter((pr) => (\n typeof pr.mergedAt === 'string'\n && pr.mergedAt.length > 0\n && typeof pr.headRefOid === 'string'\n && pr.headRefOid.length > 0\n ))\n .sort((a, b) => Date.parse(String(b.mergedAt)) - Date.parse(String(a.mergedAt)))[0];\n if (!mergedPr?.headRefOid) return null;\n\n const { stdout: tipShaRaw } = await execAsync(\n `git rev-parse ${branchRef} 2>/dev/null`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n const tipSha = tipShaRaw.trim();\n if (!tipSha) return null;\n\n if (tipSha === mergedPr.headRefOid) {\n const prLabel = typeof mergedPr.number === 'number' ? `PR #${mergedPr.number}` : 'GitHub PR';\n return stepOk(step, [`${prLabel} is squash-merged and ${branchRef} matches the merged PR head`]);\n }\n\n // PAN-2406 / state-plane policy rule 3: commits after the merged head that\n // touch ONLY state-plane paths (.pan/, .beads/) are pipeline exhaust —\n // e.g. 'chore: record merge status' — and must not block close-out.\n try {\n const { stdout: deltaRaw } = await execAsync(\n `git diff --name-only ${mergedPr.headRefOid}..${tipSha}`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n let deltaFiles = deltaRaw.split('\\n').map((f) => f.trim()).filter(Boolean);\n let statePlaneOnly = deltaFiles.length > 0 && deltaFiles.every((f) =>\n f.startsWith('.pan/') || f.startsWith('.beads/'));\n if (!statePlaneOnly) {\n // Branch may have merged main INTO itself after the PR merged — the\n // two-dot delta then contains main's own files. Judge only changes\n // UNIQUE to the branch (three-dot vs origin/main): if those are\n // state-plane-only, everything real is already on main.\n const { stdout: uniqueRaw } = await execAsync(\n `git diff --name-only origin/main...${tipSha}`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n deltaFiles = uniqueRaw.split('\\n').map((f) => f.trim()).filter(Boolean);\n statePlaneOnly = deltaFiles.every((f) =>\n f.startsWith('.pan/') || f.startsWith('.beads/'));\n }\n if (statePlaneOnly) {\n const prLabel = typeof mergedPr.number === 'number' ? `PR #${mergedPr.number}` : 'GitHub PR';\n return stepOk(step, [\n `${prLabel} is squash-merged; ${branchRef} is ahead only by state-plane commits (${deltaFiles.length} file(s): .pan/.beads) — accepted per state-plane policy`,\n ]);\n }\n } catch { /* diff failure falls through to the strict rejection below */ }\n\n const prLabel = typeof mergedPr.number === 'number' ? `PR #${mergedPr.number}` : 'merged GitHub PR';\n return stepFailed(step, `${branchRef} does not match the head commit of merged ${prLabel}; inspect before closing out.`);\n } catch {\n return null;\n }\n}\n\n/**\n * Reset issue back to open/backlog state (for destructive reset).\n */\nfunction resetIssueToTodo(ctx: LifecycleContext): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => resetIssueToTodoImpl(ctx),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('reset:reset-issue', `Failed to reset issue: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function resetIssueToTodoImpl(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'reset:reset-issue';\n try {\n if (ctx.github) {\n const { owner, repo, number } = ctx.github;\n // Reopen the issue\n await execAsync(\n `gh issue reopen ${number} --repo ${owner}/${repo}`,\n { encoding: 'utf-8' },\n ).catch(() => {}); // May already be open\n // Remove lifecycle labels\n const labelsToRemove = ['in-review', 'in-progress', 'planned', 'planning', 'Review: Approved', 'Review: Failed', 'ready-for-merge'];\n for (const label of labelsToRemove) {\n await execAsync(\n `gh issue edit ${number} --repo ${owner}/${repo} --remove-label \"${label}\"`,\n { encoding: 'utf-8' },\n ).catch(() => {}); // Label may not exist\n }\n return stepOk(step, [`Reset GitHub issue #${number}: reopened and cleared labels`]);\n }\n\n // Linear: reopen to Todo\n const linearApiKey = await getLinearApiKey();\n if (linearApiKey) {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey: linearApiKey });\n const issueNum = extractNumberSync(ctx.issueId);\n const teamKey = extractPrefixSync(ctx.issueId);\n if (issueNum === null || teamKey === null) {\n return stepFailed(step, `Could not parse issue ID: ${ctx.issueId}`);\n }\n const results = await client.issues({\n filter: {\n number: { eq: issueNum },\n team: { key: { eq: teamKey } },\n },\n first: 1,\n });\n if (results.nodes.length > 0) {\n const issue = results.nodes[0];\n const team = await issue.team;\n if (team) {\n const states = await team.states();\n const todoState = states.nodes.find(s => s.type === 'unstarted' && s.name === 'Todo') ||\n states.nodes.find(s => s.type === 'unstarted');\n if (todoState) {\n await issue.update({ stateId: todoState.id });\n }\n }\n }\n return stepOk(step, [`Reset ${trackerName(ctx, 'linear')} issue ${ctx.issueId} to Todo`]);\n }\n\n return stepSkipped(step, ['No tracker available to reset issue']);\n } catch (err) {\n return stepFailed(step, `Failed to reset issue: ${(err as Error).message}`);\n }\n}\n\n/**\n * Clear review status for an issue.\n */\nasync function resetPostMergeStateForIssue(issueId: string): Promise<void> {\n try {\n const { resetPostMergeState } = await import('../cloister/merge-agent.js');\n resetPostMergeState(issueId);\n resetPostMergeState(issueId.toUpperCase());\n } catch {\n return;\n }\n}\n\nfunction clearReviewStatusStep(issueId: string): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => clearReviewStatusStepImpl(issueId),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepSkipped('clear-review-status', [`Failed to clear review status (non-fatal): ${(err as Error).message}`])),\n ),\n );\n}\n\nasync function clearReviewStatusStepImpl(issueId: string): Promise<StepResult> {\n const step = 'clear-review-status';\n try {\n const { clearReviewStatus } = await import('../review-status.js');\n clearReviewStatus(issueId.toUpperCase());\n return stepOk(step, ['Review status cleared']);\n } catch {\n // Fallback: direct file manipulation\n try {\n const statusFile = join(OVERDECK_HOME, 'review-status.json');\n if (existsSync(statusFile)) {\n const data = JSON.parse(await readFile(statusFile, 'utf-8'));\n const upperKey = issueId.toUpperCase();\n if (data[upperKey]) {\n delete data[upperKey];\n await writeFile(statusFile, JSON.stringify(data, null, 2));\n }\n }\n return stepOk(step, ['Review status cleared (direct)']);\n } catch (innerErr) {\n return stepSkipped(step, [`Failed to clear review status (non-fatal): ${(innerErr as Error).message}`]);\n }\n }\n}\n\nexport const __testInternals = {\n completeVBriefStep,\n verifyBranchMerged,\n};\n\nfunction resetIssueToCanceled(ctx: LifecycleContext): Effect.Effect<StepResult> {\n return Effect.tryPromise({\n try: () => resetIssueToCanceledImpl(ctx),\n catch: (err) => err,\n }).pipe(\n Effect.catch((err) =>\n Effect.succeed(stepFailed('cancel:reset-issue', `Failed to cancel issue: ${(err as Error).message}`)),\n ),\n );\n}\n\nasync function resetIssueToCanceledImpl(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'cancel:reset-issue';\n try {\n if (ctx.github) {\n const { owner, repo, number } = ctx.github;\n await execAsync(\n `gh issue edit ${number} --repo ${owner}/${repo} --add-label \"wontfix\"`,\n { encoding: 'utf-8' },\n ).catch(() => {});\n return stepOk(step, [`Marked GitHub issue #${number} as canceled/wontfix`]);\n }\n\n const linearApiKey = await getLinearApiKey();\n if (linearApiKey) {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey: linearApiKey });\n const issueNum = extractNumberSync(ctx.issueId);\n const teamKey = extractPrefixSync(ctx.issueId);\n if (issueNum === null || teamKey === null) {\n return stepFailed(step, `Could not parse issue ID: ${ctx.issueId}`);\n }\n const results = await client.issues({\n filter: {\n number: { eq: issueNum },\n team: { key: { eq: teamKey } },\n },\n first: 1,\n });\n if (results.nodes.length > 0) {\n const issue = results.nodes[0];\n const team = await issue.team;\n if (team) {\n const states = await team.states();\n const canceledState = states.nodes.find(s => s.type === 'canceled') ||\n states.nodes.find(s => s.name.toLowerCase() === 'canceled');\n if (canceledState) {\n await issue.update({ stateId: canceledState.id });\n }\n }\n }\n return stepOk(step, [`Reset ${trackerName(ctx, 'linear')} issue ${ctx.issueId} to Canceled`]);\n }\n\n return stepSkipped(step, ['No tracker available to cancel issue']);\n } catch (err) {\n return stepFailed(step, `Failed to cancel issue: ${(err as Error).message}`);\n }\n}\n","/**\n * Lifecycle — Composable, idempotent post-merge operations.\n *\n * Atomic operations:\n * archive-planning — PRD active→completed + workspace .pan/ preservation\n * close-issue — IssueTracker transition + label management\n * teardown-workspace — Full workspace cleanup (agent, worktree, Docker, tmux)\n * compact-beads — Beads compaction + git commit/push\n *\n * Workflows (compose the above):\n * approve() — merge + close + archive + teardown + compact\n * close() — close + teardown\n * closeOut() — verify-merged + archive + teardown + close + label + clear-status\n * deepWipe() — teardown(deleteBranches) + delete agent state + reset issue\n */\n\n// Types\nexport type {\n StepResult,\n WorkflowResult,\n LifecycleContext,\n TeardownOptions,\n ArchiveOptions,\n ApproveOptions,\n DeepWipeOptions,\n} from './types.js';\n\nexport { stepOk, stepSkipped, stepFailed } from './types.js';\n\n// Atomic operations\nexport { archivePlanning } from './archive-planning.js';\nexport { closeIssue } from './close-issue.js';\nexport { teardownWorkspace } from './teardown-workspace.js';\nexport { compactBeads } from './compact-beads.js';\n\n// Workflows\nexport { approve, close, closeOut, deepWipe, resetToTodo, cancelIssueWorkflow } from './workflows.js';\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import "./archive-planning-6uw521Do.js";
2
2
  import "./types-D112L62U.js";
3
- import "./close-issue-BJGX9_z7.js";
4
- import { n as resetToTodo } from "./lifecycle-CR6tZfl1.js";
3
+ import "./close-issue-Djajb6Sv.js";
4
+ import { n as resetToTodo } from "./lifecycle-SmrqysDf.js";
5
5
  import "./compact-beads-BrBt37Xm.js";
6
6
  export { resetToTodo };
@@ -9,7 +9,7 @@ import { w as listSessionNames, x as killSession, y as init_tmux } from "./tmux-
9
9
  import { u as init_infra } from "./infra-SH1L_MHI.js";
10
10
  import { i as init_activity_logger, n as emitActivityEntrySync, r as emitActivityTtsSync } from "./activity-logger-DR4VJx-J.js";
11
11
  import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population-5MWfsQI_.js";
12
- import { a as init_review_status, m as setReviewStatusSync } from "./review-status-iJwfEoNX.js";
12
+ import { a as init_review_status, m as setReviewStatusSync } from "./review-status-B_XXomV0.js";
13
13
  import { n as init_workspace_config } from "./workspace-config-xej6WNHY.js";
14
14
  import { n as restoreTrackedBeadsExport, t as init_beads_restore } from "./beads-restore-DU1wppIp.js";
15
15
  import { r as init_git_utils, t as cleanupStaleLocks } from "./git-utils-C5O8mm1X.js";
@@ -306,7 +306,7 @@ async function postMergeLifecycle(issueId, projectPath, sourceBranch, options) {
306
306
  console.warn(`[merge-agent] Beads compaction failed: ${err}`);
307
307
  }
308
308
  try {
309
- const { setAgentPaused, getAgentState } = await import("./agents-pp8FO7Uj.js");
309
+ const { setAgentPaused, getAgentState } = await import("./agents-By3u_fQ8.js");
310
310
  const { killSession, sessionExists } = await import("./tmux-Bv9NyDJW.js");
311
311
  const issueLower = issueId.toLowerCase();
312
312
  const reason = "awaiting close-out (verify on main)";
@@ -332,7 +332,7 @@ async function postMergeLifecycle(issueId, projectPath, sourceBranch, options) {
332
332
  console.warn(`[merge-agent] Could not pause or kill agent sessions: ${err}`);
333
333
  }
334
334
  try {
335
- const { killAllReviewerSessions } = await import("./review-agent-DjVadURa.js");
335
+ const { killAllReviewerSessions } = await import("./review-agent-hLbRRxZF.js");
336
336
  const { resolveProjectFromIssueSync } = await import("./projects-DbssjAtz.js");
337
337
  const projectKey = resolveProjectFromIssueSync(issueId)?.projectKey;
338
338
  if (projectKey) {
@@ -347,7 +347,7 @@ async function postMergeLifecycle(issueId, projectPath, sourceBranch, options) {
347
347
  }
348
348
  await killPostMergeRoleSessions(issueId);
349
349
  try {
350
- const { createResetMarker } = await import("./cli-DBWG12XK.js");
350
+ const { createResetMarker } = await import("./cli-MTB9IOoR.js");
351
351
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
352
352
  const marker = await createResetMarker({
353
353
  projectId: basename(projectPath),
@@ -391,7 +391,7 @@ async function postMergeLifecycle(issueId, projectPath, sourceBranch, options) {
391
391
  async function transitionIssueToVerifyingOnMain(issueId, projectPath) {
392
392
  const [effectModule, issueLifecycleModule, githubModule, linearModule, rallyModule, errorsModule] = await Promise.all([
393
393
  import("effect"),
394
- import("./issue-lifecycle-fVqvCdKM.js"),
394
+ import("./issue-lifecycle-Bc1l3U9f.js"),
395
395
  import("./github-client-CbqzETjP.js"),
396
396
  import("./linear-client-DMrmeuKs.js"),
397
397
  import("./rally-client-BvL4iRfu.js"),
@@ -806,4 +806,4 @@ var init_merge_agent = __esmMin((() => {
806
806
  //#endregion
807
807
  export { isSyncMainMainPreferredPath as a, resetPostMergeState as c, isAutoCommitExcludedPath as i, syncMainIntoWorkspace as l, autoCommitWorkspaceChangesBeforeSync as n, notifyTldrDaemon as o, init_merge_agent as r, postMergeLifecycle as s, AUTO_COMMIT_EXCLUDED_PATHS as t };
808
808
 
809
- //# sourceMappingURL=merge-agent-LM4avOtA.js.map
809
+ //# sourceMappingURL=merge-agent-B9hIZ6Z0.js.map