@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.
- package/dist/{agent-state-KVbJEG5f.js → agent-state-RLhS7ckO.js} +1 -1
- package/dist/{agents-pp8FO7Uj.js → agents-By3u_fQ8.js} +1 -1
- package/dist/{agents-CQHK0CSA.js → agents-CgVr77Qq.js} +12 -12
- package/dist/{agents-CQHK0CSA.js.map → agents-CgVr77Qq.js.map} +1 -1
- package/dist/{backlog-auto-trigger-CyuoS0nl.js → backlog-auto-trigger-B_-1tk4e.js} +5 -5
- package/dist/{backlog-auto-trigger-CyuoS0nl.js.map → backlog-auto-trigger-B_-1tk4e.js.map} +1 -1
- package/dist/cli/index.js +45 -45
- package/dist/{cli-Cewlu3yU.js → cli-DGeSW85B.js} +2 -2
- package/dist/{cli-Cewlu3yU.js.map → cli-DGeSW85B.js.map} +1 -1
- package/dist/cli-MTB9IOoR.js +3 -0
- package/dist/{close-issue-BJGX9_z7.js → close-issue-Djajb6Sv.js} +2 -2
- package/dist/{close-issue-BJGX9_z7.js.map → close-issue-Djajb6Sv.js.map} +1 -1
- package/dist/{concurrency-Ca-fC7tA.js → concurrency-4rzjHAQA.js} +1 -1
- package/dist/{conversation-compaction-B_6s9EvM.js → conversation-compaction-BQvZh09I.js} +4 -4
- package/dist/{conversation-compaction-B_6s9EvM.js.map → conversation-compaction-BQvZh09I.js.map} +1 -1
- package/dist/dashboard/{advancing-selfheal-CMlGznKv.js → advancing-selfheal-BezNfM3P.js} +3 -3
- package/dist/dashboard/{advancing-selfheal-CMlGznKv.js.map → advancing-selfheal-BezNfM3P.js.map} +1 -1
- package/dist/dashboard/{agent-state-xk_G8t90.js → agent-state-BUANcaA7.js} +1 -1
- package/dist/dashboard/{agent-state-service-C1iUF9Ft.js → agent-state-service-DmFpIMbP.js} +1 -1
- package/dist/dashboard/{agent-state-service-5ge9xxhx.js → agent-state-service-tXUdp6UF.js} +2 -2
- package/dist/dashboard/{agent-state-service-5ge9xxhx.js.map → agent-state-service-tXUdp6UF.js.map} +1 -1
- package/dist/dashboard/{agents-BIggLvi_.js → agents-C-vqmKDi.js} +1 -1
- package/dist/dashboard/{agents-DHvsjsuP.js → agents-C7V4odQ6.js} +11 -11
- package/dist/dashboard/{agents-DHvsjsuP.js.map → agents-C7V4odQ6.js.map} +1 -1
- package/dist/dashboard/{backlog-auto-trigger-COm_R96V.js → backlog-auto-trigger-Cb8PR-5w.js} +2 -2
- package/dist/dashboard/{backlog-auto-trigger-COm_R96V.js.map → backlog-auto-trigger-Cb8PR-5w.js.map} +1 -1
- package/dist/dashboard/{cli-CvK9xuSS.js → cli-BgzbB6h3.js} +2 -2
- package/dist/dashboard/{cli-CvK9xuSS.js.map → cli-BgzbB6h3.js.map} +1 -1
- package/dist/dashboard/cli-DCqy_wFa.js +3 -0
- package/dist/dashboard/{close-issue-BnpErnD1.js → close-issue-BWf3pxn4.js} +2 -2
- package/dist/dashboard/{close-issue-BnpErnD1.js.map → close-issue-BWf3pxn4.js.map} +1 -1
- package/dist/dashboard/{closed-issue-reaper-DRqK5k39.js → closed-issue-reaper-D7XPq5pY.js} +4 -4
- package/dist/dashboard/{closed-issue-reaper-DRqK5k39.js.map → closed-issue-reaper-D7XPq5pY.js.map} +1 -1
- package/dist/dashboard/{closed-issue-reaper-BLCQwTpF.js → closed-issue-reaper-VSTSTROK.js} +1 -1
- package/dist/dashboard/{conflict-gate-JdFuhKuF.js → conflict-gate-DwOslTij.js} +1 -1
- package/dist/dashboard/{conflict-gate-BhKvrPxn.js → conflict-gate-FFEvTDVA.js} +3 -3
- package/dist/dashboard/{conflict-gate-BhKvrPxn.js.map → conflict-gate-FFEvTDVA.js.map} +1 -1
- package/dist/dashboard/{conversation-compaction-C5o_eKEm.js → conversation-compaction-CCqN4hWk.js} +4 -4
- package/dist/dashboard/{conversation-compaction-C5o_eKEm.js.map → conversation-compaction-CCqN4hWk.js.map} +1 -1
- package/dist/dashboard/{conversation-compaction-Ba5aZdrb.js → conversation-compaction-CL5Ti4j4.js} +1 -1
- package/dist/dashboard/{deacon-j3qSZ7--.js → deacon-CGHl90eC.js} +107 -50
- package/dist/dashboard/{deacon-j3qSZ7--.js.map → deacon-CGHl90eC.js.map} +1 -1
- package/dist/dashboard/{deacon-Cv2RMfHs.js → deacon-DMPh40Im.js} +2 -2
- package/dist/dashboard/deacon-swarm-CVTiNL0N.js +2 -0
- package/dist/dashboard/{deacon-swarm-DadWNi5J.js → deacon-swarm-aMMJTq6t.js} +4 -4
- package/dist/dashboard/{deacon-swarm-DadWNi5J.js.map → deacon-swarm-aMMJTq6t.js.map} +1 -1
- package/dist/dashboard/deacon.js +4 -4
- package/dist/dashboard/{feedback-target-oE4-Esxl.js → feedback-target-dJjFfITP.js} +4 -4
- package/dist/dashboard/{feedback-target-oE4-Esxl.js.map → feedback-target-dJjFfITP.js.map} +1 -1
- package/dist/dashboard/{feedback-target-C4DaDSZ8.js → feedback-target-nQSM6ygL.js} +1 -1
- package/dist/dashboard/{flywheel-ClMjGW_u.js → flywheel-BLoVNtJV.js} +6 -6
- package/dist/dashboard/{flywheel-ClMjGW_u.js.map → flywheel-BLoVNtJV.js.map} +1 -1
- package/dist/dashboard/{flywheel-DefHRzY4.js → flywheel-Cqf8vu7N.js} +6 -6
- package/dist/dashboard/{flywheel-DefHRzY4.js.map → flywheel-Cqf8vu7N.js.map} +1 -1
- package/dist/dashboard/{flywheel-BqDdGvrQ.js → flywheel-PJsbrXNY.js} +1 -1
- package/dist/dashboard/{flywheel-merge-order-CuDcqTRJ.js → flywheel-merge-order-B7BH8mZ3.js} +2 -2
- package/dist/dashboard/{flywheel-merge-order-CuDcqTRJ.js.map → flywheel-merge-order-B7BH8mZ3.js.map} +1 -1
- package/dist/dashboard/{flywheel-merge-order-B6YDSElh.js → flywheel-merge-order-CCwF60b-.js} +1 -1
- package/dist/dashboard/{harness-resolve-DKeSVsJL.js → harness-resolve-B3f9G1Kp.js} +2 -2
- package/dist/dashboard/{harness-resolve-DKeSVsJL.js.map → harness-resolve-B3f9G1Kp.js.map} +1 -1
- package/dist/dashboard/{inspect-agent-BKKc0XnB.js → inspect-agent-CKF5-SJr.js} +3 -3
- package/dist/dashboard/{inspect-agent-BKKc0XnB.js.map → inspect-agent-CKF5-SJr.js.map} +1 -1
- package/dist/dashboard/inspect-agent-CqpEWGWy.js +2 -0
- package/dist/dashboard/{issue-lifecycle-DnhQgddB.js → issue-lifecycle-5LbOcATP.js} +7 -7
- package/dist/dashboard/{issue-lifecycle-DnhQgddB.js.map → issue-lifecycle-5LbOcATP.js.map} +1 -1
- package/dist/dashboard/{issue-lifecycle-nY4esZn8.js → issue-lifecycle-CjYqQ669.js} +1 -1
- package/dist/dashboard/{issue-service-singleton-Bnqv1uaa.js → issue-service-singleton-B8iu_TKV.js} +1 -1
- package/dist/dashboard/{issue-service-singleton-_AquSBTl.js → issue-service-singleton-CDGt__oQ.js} +2 -2
- package/dist/dashboard/{issue-service-singleton-_AquSBTl.js.map → issue-service-singleton-CDGt__oQ.js.map} +1 -1
- package/dist/dashboard/{lifecycle-CGKm7doE.js → lifecycle-CEg4sHZH.js} +4 -4
- package/dist/dashboard/{lifecycle-CGKm7doE.js.map → lifecycle-CEg4sHZH.js.map} +1 -1
- package/dist/dashboard/{merge-agent-Dh8Y9PDO.js → merge-agent-7nBiCytp.js} +1 -1
- package/dist/dashboard/{merge-agent-BcgAYStl.js → merge-agent-C81xPIGd.js} +6 -6
- package/dist/dashboard/{merge-agent-BcgAYStl.js.map → merge-agent-C81xPIGd.js.map} +1 -1
- package/dist/dashboard/merge-ops-DE_6CnmZ.js +2 -0
- package/dist/dashboard/{merge-train-DmxlYbEo.js → merge-train-D3qzRccL.js} +2 -2
- package/dist/dashboard/{merge-train-DmxlYbEo.js.map → merge-train-D3qzRccL.js.map} +1 -1
- package/dist/dashboard/{merge-train-deps-DBHsOWt9.js → merge-train-deps-Be5ElC_P.js} +2 -2
- package/dist/dashboard/{merge-train-deps-DBHsOWt9.js.map → merge-train-deps-Be5ElC_P.js.map} +1 -1
- package/dist/dashboard/{orphan-proposed-reconciler-Db8tUhce.js → orphan-proposed-reconciler-Boq_XaRe.js} +3 -3
- package/dist/dashboard/{orphan-proposed-reconciler-Db8tUhce.js.map → orphan-proposed-reconciler-Boq_XaRe.js.map} +1 -1
- package/dist/dashboard/{orphan-proposed-reconciler-mXV--tcB.js → orphan-proposed-reconciler-C0sPnDq_.js} +1 -1
- package/dist/dashboard/{reconstruct-cache-_tDZ2D72.js → reconstruct-cache-C2pCltOq.js} +3 -3
- package/dist/dashboard/{reconstruct-cache-_tDZ2D72.js.map → reconstruct-cache-C2pCltOq.js.map} +1 -1
- package/dist/dashboard/{remote-completion-Bklh6loJ.js → remote-completion-BmxD5UMQ.js} +3 -3
- package/dist/dashboard/{remote-completion-Bklh6loJ.js.map → remote-completion-BmxD5UMQ.js.map} +1 -1
- package/dist/dashboard/resume-C-nxu9Y4.js +3 -0
- package/dist/dashboard/{review-agent-phzqNqIs.js → review-agent-D6P6d3pz.js} +26 -17
- package/dist/dashboard/review-agent-D6P6d3pz.js.map +1 -0
- package/dist/dashboard/review-agent-DTINEffB.js +3 -0
- package/dist/dashboard/{review-context-CCq56O_Y.js → review-context-Dyo0tsBa.js} +2 -2
- package/dist/dashboard/{review-context-CCq56O_Y.js.map → review-context-Dyo0tsBa.js.map} +1 -1
- package/dist/dashboard/{review-status-BQjqQXZG.js → review-status-B5ZASOo4.js} +18 -5
- package/dist/dashboard/review-status-B5ZASOo4.js.map +1 -0
- package/dist/dashboard/{review-status-bBkqUj5i.js → review-status-h7BXIA4z.js} +1 -1
- package/dist/dashboard/{review-verdict-feedback-wqnikhMK.js → review-verdict-feedback-B70VbfRL.js} +4 -4
- package/dist/dashboard/{review-verdict-feedback-wqnikhMK.js.map → review-verdict-feedback-B70VbfRL.js.map} +1 -1
- package/dist/dashboard/{review-verdict-feedback-cZh9Wi9G.js → review-verdict-feedback-CorgH49f.js} +1 -1
- package/dist/dashboard/{sequence-io-B2GmilSI.js → sequence-io-6YP8fVpH.js} +2 -2
- package/dist/dashboard/{sequence-io-B2GmilSI.js.map → sequence-io-6YP8fVpH.js.map} +1 -1
- package/dist/dashboard/{sequencer-agent-D8pW2aU_.js → sequencer-agent-ja-nkEc1.js} +5 -5
- package/dist/dashboard/{sequencer-agent-D8pW2aU_.js.map → sequencer-agent-ja-nkEc1.js.map} +1 -1
- package/dist/dashboard/server.js +66 -55
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/{service-CILd-uOt.js → service-HKDrIy0h.js} +24 -24
- package/dist/dashboard/{service-CILd-uOt.js.map → service-HKDrIy0h.js.map} +1 -1
- package/dist/dashboard/{smart-compaction-Bgp_gwcA.js → smart-compaction-L0LSnF0_.js} +1 -1
- package/dist/dashboard/{smart-compaction-CrP90OFE.js → smart-compaction-uke1npUz.js} +2 -2
- package/dist/dashboard/{smart-compaction-CrP90OFE.js.map → smart-compaction-uke1npUz.js.map} +1 -1
- package/dist/dashboard/{spawn-planning-session-D15KbPOy.js → spawn-planning-session-CSMWco8B.js} +1 -1
- package/dist/dashboard/{spawn-planning-session-BmJWHSCu.js → spawn-planning-session-CXc0NkwV.js} +3 -3
- package/dist/dashboard/{spawn-planning-session-BmJWHSCu.js.map → spawn-planning-session-CXc0NkwV.js.map} +1 -1
- package/dist/dashboard/{specialist-context-CwKkcXL9.js → specialist-context-BGCJ24LH.js} +3 -3
- package/dist/dashboard/{specialist-context-CwKkcXL9.js.map → specialist-context-BGCJ24LH.js.map} +1 -1
- package/dist/dashboard/{specialist-logs-CvDxquV_.js → specialist-logs--Uz-r8ia.js} +2 -2
- package/dist/dashboard/{specialist-logs-CvDxquV_.js.map → specialist-logs--Uz-r8ia.js.map} +1 -1
- package/dist/dashboard/{specialists-BCjcG4uE.js → specialists-Ca9XSBCS.js} +1 -1
- package/dist/dashboard/{specialists-D07ybnam.js → specialists-DEfrAbWs.js} +36 -36
- package/dist/dashboard/{specialists-D07ybnam.js.map → specialists-DEfrAbWs.js.map} +1 -1
- package/dist/dashboard/{specialists-F2uMO4QS.js → specialists-DeZx9xom.js} +1 -1
- package/dist/dashboard/{specialists-BYi0k8CZ.js → specialists-nZ0mRwpZ.js} +12 -12
- package/dist/dashboard/{specialists-BYi0k8CZ.js.map → specialists-nZ0mRwpZ.js.map} +1 -1
- package/dist/dashboard/{summary-fork-DedqguZb.js → summary-fork-2a1L2DIU.js} +2 -2
- package/dist/dashboard/{summary-fork-EjvOkEPl.js → summary-fork-Xn0QUNmb.js} +3 -3
- package/dist/dashboard/{summary-fork-EjvOkEPl.js.map → summary-fork-Xn0QUNmb.js.map} +1 -1
- package/dist/dashboard/{teardown-workspace-5LCVbjfq.js → teardown-workspace-DhA6oAIK.js} +2 -2
- package/dist/dashboard/{teardown-workspace-5LCVbjfq.js.map → teardown-workspace-DhA6oAIK.js.map} +1 -1
- package/dist/dashboard/{test-agent-queue-qfsq6uaC.js → test-agent-queue-B_ukPyIK.js} +3 -3
- package/dist/dashboard/{test-agent-queue-qfsq6uaC.js.map → test-agent-queue-B_ukPyIK.js.map} +1 -1
- package/dist/dashboard/{uat-train-CtNGgXxj.js → uat-train-BLBAbJ8Y.js} +10 -10
- package/dist/dashboard/{uat-train-CtNGgXxj.js.map → uat-train-BLBAbJ8Y.js.map} +1 -1
- package/dist/dashboard/{uat-train-C3hWXtip.js → uat-train-DPfGR9_I.js} +1 -1
- package/dist/dashboard/{verification-runner-DuZRHjPU.js → verification-runner-KTGTNugM.js} +1 -1
- package/dist/dashboard/{verification-runner-BPAhPWR7.js → verification-runner-R2-4XgMO.js} +4 -4
- package/dist/dashboard/{verification-runner-BPAhPWR7.js.map → verification-runner-R2-4XgMO.js.map} +1 -1
- package/dist/dashboard/{workflows-H-COJ84X.js → workflows-CSKX5MhC.js} +7 -7
- package/dist/dashboard/{workflows-H-COJ84X.js.map → workflows-CSKX5MhC.js.map} +1 -1
- package/dist/dashboard/workflows-DVwXauef.js +2 -0
- package/dist/dashboard/{workspaces-CRU9_vRn.js → workspaces-DXLDgXo2.js} +32 -32
- package/dist/dashboard/{workspaces-CRU9_vRn.js.map → workspaces-DXLDgXo2.js.map} +1 -1
- package/dist/docs-index.sqlite +0 -0
- package/dist/{feedback-target-DTGAhFkM.js → feedback-target-BsKN4Tr_.js} +4 -4
- package/dist/{feedback-target-DTGAhFkM.js.map → feedback-target-BsKN4Tr_.js.map} +1 -1
- package/dist/{feedback-target-DutF088V.js → feedback-target-DM1WzOKy.js} +1 -1
- package/dist/{harness-resolve-Bz1prk6B.js → harness-resolve-B-YDNwNW.js} +2 -2
- package/dist/{harness-resolve-Bz1prk6B.js.map → harness-resolve-B-YDNwNW.js.map} +1 -1
- package/dist/{issue-lifecycle-fVqvCdKM.js → issue-lifecycle-Bc1l3U9f.js} +7 -7
- package/dist/{issue-lifecycle-fVqvCdKM.js.map → issue-lifecycle-Bc1l3U9f.js.map} +1 -1
- package/dist/{issue-service-singleton-CZm8p6Rj.js → issue-service-singleton-D-8Q6tdT.js} +1 -1
- package/dist/{issue-service-singleton-Cr73JAaR.js → issue-service-singleton-D1433I7n.js} +2 -2
- package/dist/{issue-service-singleton-Cr73JAaR.js.map → issue-service-singleton-D1433I7n.js.map} +1 -1
- package/dist/{lifecycle-CR6tZfl1.js → lifecycle-SmrqysDf.js} +7 -7
- package/dist/{lifecycle-CR6tZfl1.js.map → lifecycle-SmrqysDf.js.map} +1 -1
- package/dist/{lifecycle-D_EWiUjk.js → lifecycle-mRMyiIXs.js} +2 -2
- package/dist/{merge-agent-LM4avOtA.js → merge-agent-B9hIZ6Z0.js} +6 -6
- package/dist/{merge-agent-LM4avOtA.js.map → merge-agent-B9hIZ6Z0.js.map} +1 -1
- package/dist/{merge-agent-Bj046HE1.js → merge-agent-DUj22cXL.js} +1 -1
- package/dist/{merge-fulfillment-DrnC1Kmg.js → merge-fulfillment-__P4WE-T.js} +3 -3
- package/dist/{merge-fulfillment-DrnC1Kmg.js.map → merge-fulfillment-__P4WE-T.js.map} +1 -1
- package/dist/{reconstruct-cache-NPqoAUg-.js → reconstruct-cache-9SWp82SQ.js} +3 -3
- package/dist/{reconstruct-cache-NPqoAUg-.js.map → reconstruct-cache-9SWp82SQ.js.map} +1 -1
- package/dist/{records-BIkN1LQ4.js → records-CTmvuRzz.js} +14 -1
- package/dist/{records-BIkN1LQ4.js.map → records-CTmvuRzz.js.map} +1 -1
- package/dist/records-backfill-BQcmTmwF.js +2 -0
- package/dist/{records-backfill-HM0Pln6N.js → records-backfill-BrNsv_zT.js} +2 -2
- package/dist/{records-backfill-HM0Pln6N.js.map → records-backfill-BrNsv_zT.js.map} +1 -1
- package/dist/resume-Bn4kDk9x.js +3 -0
- package/dist/{review-agent-DFosQzCG.js → review-agent-PhqOhpx3.js} +24 -16
- package/dist/{review-agent-DFosQzCG.js.map → review-agent-PhqOhpx3.js.map} +1 -1
- package/dist/review-agent-hLbRRxZF.js +3 -0
- package/dist/{review-status-iJwfEoNX.js → review-status-B_XXomV0.js} +6 -6
- package/dist/{review-status-iJwfEoNX.js.map → review-status-B_XXomV0.js.map} +1 -1
- package/dist/{review-status-BbNVlXh1.js → review-status-Bo-EFVKh.js} +1 -1
- package/dist/{review-verdict-feedback-BGPw3z1X.js → review-verdict-feedback-CXHkoiKZ.js} +1 -1
- package/dist/{review-verdict-feedback-CCZ05atV.js → review-verdict-feedback-DGV13LDb.js} +4 -4
- package/dist/{review-verdict-feedback-CCZ05atV.js.map → review-verdict-feedback-DGV13LDb.js.map} +1 -1
- package/dist/{sequence-io-CcxZNHcD.js → sequence-io-Cg4NHAco.js} +1 -1
- package/dist/{sequence-io-Cx1usxG3.js → sequence-io-CyxvNHfA.js} +2 -2
- package/dist/{sequence-io-Cx1usxG3.js.map → sequence-io-CyxvNHfA.js.map} +1 -1
- package/dist/{smart-compaction-ByUEgQkF.js → smart-compaction-ByKXTQNy.js} +2 -2
- package/dist/{smart-compaction-ByUEgQkF.js.map → smart-compaction-ByKXTQNy.js.map} +1 -1
- package/dist/{smart-compaction-DfLe_CtH.js → smart-compaction-U6e_uB1E.js} +1 -1
- package/dist/{specialist-context-McuGkaeR.js → specialist-context-BUTadO-U.js} +3 -3
- package/dist/{specialist-context-McuGkaeR.js.map → specialist-context-BUTadO-U.js.map} +1 -1
- package/dist/{specialist-logs-CUUJ4eiB.js → specialist-logs-pEMCTtGZ.js} +2 -2
- package/dist/{specialist-logs-CUUJ4eiB.js.map → specialist-logs-pEMCTtGZ.js.map} +1 -1
- package/dist/{specialists-BSrylD1S.js → specialists-BGFnrQ8n.js} +1 -1
- package/dist/{specialists-B0elgInc.js → specialists-DeTkkp8b.js} +12 -12
- package/dist/{specialists-B0elgInc.js.map → specialists-DeTkkp8b.js.map} +1 -1
- package/dist/{summary-fork-DskMRnyb.js → summary-fork-CgzThE2-.js} +2 -2
- package/dist/{summary-fork-CPUTKcAT.js → summary-fork-Dx1RMuvU.js} +3 -3
- package/dist/{summary-fork-CPUTKcAT.js.map → summary-fork-Dx1RMuvU.js.map} +1 -1
- package/dist/{sync-BiNVQHBf.js → sync-Bsww9tuj.js} +2 -2
- package/dist/{sync-BiNVQHBf.js.map → sync-Bsww9tuj.js.map} +1 -1
- package/dist/sync-CylE_SjB.js +2 -0
- package/dist/{verdict-restore-DQiV7_fe.js → verdict-restore-DGpX0ZOJ.js} +5 -5
- package/dist/{verdict-restore-DQiV7_fe.js.map → verdict-restore-DGpX0ZOJ.js.map} +1 -1
- package/dist/{webhook-handlers-DHBSEDEm.js → webhook-handlers-BjsfIL7u.js} +3 -3
- package/dist/{webhook-handlers-DHBSEDEm.js.map → webhook-handlers-BjsfIL7u.js.map} +1 -1
- package/dist/{workspace-migrate-duUsWNpd.js → workspace-migrate-BBQ8nAnP.js} +2 -2
- package/dist/{workspace-migrate-duUsWNpd.js.map → workspace-migrate-BBQ8nAnP.js.map} +1 -1
- package/dist/{workspace-reap-DLCIoJmn.js → workspace-reap-12O9354k.js} +2 -2
- package/dist/{workspace-reap-DLCIoJmn.js.map → workspace-reap-12O9354k.js.map} +1 -1
- package/package.json +1 -1
- package/scripts/file-size-baseline.txt +1 -1
- package/dist/cli-DBWG12XK.js +0 -3
- package/dist/dashboard/cli-CJDWXE_Y.js +0 -3
- package/dist/dashboard/deacon-swarm-D1iAUX-P.js +0 -2
- package/dist/dashboard/inspect-agent-vm88mLYr.js +0 -2
- package/dist/dashboard/merge-ops-QdBiQ8XB.js +0 -2
- package/dist/dashboard/resume-DnIsmIgC.js +0 -3
- package/dist/dashboard/review-agent-DgySDb-G.js +0 -3
- package/dist/dashboard/review-agent-phzqNqIs.js.map +0 -1
- package/dist/dashboard/review-status-BQjqQXZG.js.map +0 -1
- package/dist/dashboard/workflows-Cz8OtiB4.js +0 -2
- package/dist/records-backfill-DEgtRyKL.js +0 -2
- package/dist/resume-DGymuXZM.js +0 -3
- package/dist/review-agent-DjVadURa.js +0 -3
- package/dist/sync-4jqukkxz.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deacon-swarm-DadWNi5J.js","names":["execAsync","listDurableSlotAssignments","execAsync","existsSync","execAsync","defaultDeps","loadYamlConfig","existsSync","join","existsSync","listTmuxSessionNames","existsSync","listDurableSlotAssignments"],"sources":["../../src/lib/agents/slot-merge.ts","../../src/lib/cloister/deacon-workspaces.ts","../../src/lib/cloister/deacon-swarm-orphan-gc.ts","../../src/lib/cloister/deacon-swarm-completion.ts","../../src/lib/cloister/deacon-swarm-finalization.ts","../../src/lib/cloister/deacon-swarm-gc.ts","../../src/lib/cloister/deacon-swarm-record.ts","../../src/lib/cloister/swarm-tiered-hooks.ts","../../src/lib/cloister/recovery-trip.ts","../../src/lib/cloister/redrive-gate.ts","../../src/lib/cloister/swarm-failed-slot.ts","../../src/lib/cloister/deacon-swarm.ts"],"sourcesContent":["import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { defaultRunWorkspace } from './spawn-prep.js';\nimport type { VBriefItem } from '../vbrief/types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface SlotMergeIssue {\n issueId: string;\n featureWorkspace?: string;\n}\n\nexport interface SlotMergeEvidence {\n verifyCommands: string[];\n expectedOutputs: string[];\n commandOutputs: Array<{ command: string; stdout: string; stderr: string }>;\n mergeOutput?: { stdout: string; stderr: string };\n}\n\nexport interface SlotMergeResult {\n verified: boolean;\n merged: boolean;\n conflicts: boolean;\n evidence: SlotMergeEvidence;\n failure?: string;\n}\n\nexport interface SlotMergeDeps {\n run: (command: string, cwd: string) => Promise<{ stdout: string; stderr: string }>;\n}\n\nexport interface SlotMergeOptions {\n deps?: Partial<SlotMergeDeps>;\n}\n\nexport async function verifyAndMergeSlot(\n issue: string | SlotMergeIssue,\n slotIndex: number,\n item: VBriefItem,\n options: SlotMergeOptions = {},\n): Promise<SlotMergeResult> {\n const issueId = typeof issue === 'string' ? issue : issue.issueId;\n const featureWorkspace = typeof issue === 'string'\n ? defaultRunWorkspace(issue)\n : issue.featureWorkspace ?? defaultRunWorkspace(issue.issueId);\n const slotWorkspace = `${featureWorkspace}-slot-${slotIndex}`;\n const slotBranch = `feature/${issueId.toLowerCase()}-slot-${slotIndex}`;\n const deps: SlotMergeDeps = {\n run: async (command, cwd) => execAsync(command, { cwd }),\n ...options.deps,\n };\n const verifyCommands = item.metadata?.verify_commands ?? [];\n const expectedOutputs = item.metadata?.expected_outputs ?? [];\n const evidence: SlotMergeEvidence = {\n verifyCommands,\n expectedOutputs,\n commandOutputs: [],\n };\n\n if (!Number.isInteger(slotIndex) || slotIndex < 1) {\n return { verified: false, merged: false, conflicts: false, evidence, failure: `Invalid slot index: ${slotIndex}` };\n }\n if (verifyCommands.length === 0) {\n return { verified: false, merged: false, conflicts: false, evidence, failure: `Item ${item.id} has no verify_commands` };\n }\n if (expectedOutputs.length === 0) {\n return { verified: false, merged: false, conflicts: false, evidence, failure: `Item ${item.id} has no expected_outputs` };\n }\n\n for (const command of verifyCommands) {\n try {\n const output = await deps.run(command, slotWorkspace);\n evidence.commandOutputs.push({ command, stdout: output.stdout, stderr: output.stderr });\n } catch (error) {\n const failed = commandFailure(error);\n evidence.commandOutputs.push({ command, stdout: failed.stdout, stderr: failed.stderr });\n return {\n verified: false,\n merged: false,\n conflicts: false,\n evidence,\n failure: `Verify command failed for ${item.id}: ${command}`,\n };\n }\n }\n\n try {\n const mergeOutput = await deps.run(`git merge --no-ff ${JSON.stringify(slotBranch)}`, featureWorkspace);\n evidence.mergeOutput = mergeOutput;\n return { verified: true, merged: true, conflicts: false, evidence };\n } catch (error) {\n const failed = commandFailure(error);\n evidence.mergeOutput = { stdout: failed.stdout, stderr: failed.stderr };\n await deps.run('git merge --abort', featureWorkspace).catch(() => {});\n return {\n verified: true,\n merged: false,\n conflicts: true,\n evidence,\n failure: `Slot branch ${slotBranch} did not merge cleanly`,\n };\n }\n}\n\nfunction commandFailure(error: unknown): { stdout: string; stderr: string } {\n const partial = error as { stdout?: unknown; stderr?: unknown; message?: unknown };\n return {\n stdout: typeof partial.stdout === 'string' ? partial.stdout : '',\n stderr: typeof partial.stderr === 'string'\n ? partial.stderr\n : typeof partial.message === 'string'\n ? partial.message\n : String(error),\n };\n}\n","import { existsSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { listProjectsSync } from '../projects.js';\n\nexport interface FeatureWorkspace {\n issueId: string;\n workspacePath: string;\n projectPath: string;\n}\n\nexport interface ListFeatureWorkspacesOptions {\n includeSlotWorkspaces?: boolean;\n}\n\nexport function listFeatureWorkspaces(options: ListFeatureWorkspacesOptions = {}): FeatureWorkspace[] {\n const includeSlotWorkspaces = options.includeSlotWorkspaces ?? true;\n const projects = listProjectsSync();\n const workspaces: FeatureWorkspace[] = [];\n\n for (const { config: projectConfig } of projects) {\n const workspacesRoot = join(projectConfig.path, 'workspaces');\n if (!existsSync(workspacesRoot)) continue;\n\n let entries: string[];\n try {\n entries = readdirSync(workspacesRoot, { withFileTypes: true })\n .filter(e => e.isDirectory() && e.name.startsWith('feature-'))\n .filter(e => includeSlotWorkspaces || !/-slot-\\d+$/.test(e.name))\n .map(e => e.name);\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n workspaces.push({\n issueId: entry.replace(/^feature-/, '').toUpperCase(),\n workspacePath: join(workspacesRoot, entry),\n projectPath: projectConfig.path,\n });\n }\n }\n\n return workspaces;\n}\n","import { listSlotAssignments as listDurableSlotAssignments, type SlotReconcileResult } from '../agents/slot-reconcile.js';\nimport type { CoordinateSwarmSlotsDeps } from './deacon-swarm.js';\n\ntype OrphanGcDeps = Pick<CoordinateSwarmSlotsDeps, 'runGitCommand' | 'listSessionNames' | 'listSlotAssignments'>;\n\n/**\n * Reconcile GC for truly-orphaned slots (PAN-2214, completes PAN-2213(c)).\n *\n * An orphan is a slot index with an on-disk worktree or a local slot branch but\n * no slotAssignments entry and no live agent tmux session. Zero-commit-ahead\n * orphans are removed; orphans with unmerged commits are only reported so the\n * operator can push them via `pan swarm reset` — never deleted.\n */\nexport async function gcOrphanedSlots(\n issueId: string,\n workspacePath: string,\n reconciled: SlotReconcileResult,\n deps: OrphanGcDeps,\n): Promise<string[]> {\n const actions: string[] = [];\n const issueLower = issueId.toLowerCase();\n\n const worktreeSlotIndexes = await listSlotWorktreeIndexes(workspacePath, deps.runGitCommand);\n const branchesBySlot = new Map(reconciled.branches.map(branch => [branch.slotIndex, branch.branch]));\n const candidateSlotIndexes = [...new Set([...worktreeSlotIndexes, ...branchesBySlot.keys()])].sort((a, b) => a - b);\n if (candidateSlotIndexes.length === 0) return actions;\n\n const ownedSlotIndexes = new Set([\n ...(deps.listSlotAssignments ?? listDurableSlotAssignments)(issueId, workspacePath).map(assignment => assignment.slotIndex),\n ...reconciled.merged.map(slot => slot.slotIndex),\n ...reconciled.inFlight.map(slot => slot.slotIndex),\n ]);\n const sessionNames = new Set(await deps.listSessionNames());\n\n for (const slotIndex of candidateSlotIndexes) {\n if (ownedSlotIndexes.has(slotIndex)) continue;\n if (sessionNames.has(`agent-${issueLower}-slot-${slotIndex}`)) continue;\n\n const branch = branchesBySlot.get(slotIndex);\n const aheadCount = branch ? await countCommitsAhead(workspacePath, branch, deps.runGitCommand) : 0;\n if (aheadCount === null || aheadCount > 0) {\n actions.push(\n `[swarm] orphan slot ${slotIndex} for ${issueId} preserved: ${branch} has `\n + `${aheadCount ?? 'an unknown number of'} unmerged commit(s) — run \\`pan swarm reset ${issueId}\\` `\n + 'to push it to origin before cleanup',\n );\n continue;\n }\n\n if (worktreeSlotIndexes.has(slotIndex)) {\n await deps.runGitCommand(`git worktree remove --force ${JSON.stringify(`${workspacePath}-slot-${slotIndex}`)}`, workspacePath);\n }\n if (branch) {\n await deps.runGitCommand(`git branch -D ${JSON.stringify(branch)}`, workspacePath);\n }\n actions.push(`[swarm] gc-orphan slot ${slotIndex} for ${issueId}`);\n }\n\n return actions;\n}\n\nasync function listSlotWorktreeIndexes(\n workspacePath: string,\n runGitCommand: CoordinateSwarmSlotsDeps['runGitCommand'],\n): Promise<Set<number>> {\n const indexes = new Set<number>();\n try {\n const result = await runGitCommand('git worktree list --porcelain', workspacePath) as { stdout?: unknown };\n const pattern = new RegExp(`^worktree ${escapeRegExp(workspacePath)}-slot-(\\\\d+)$`);\n for (const line of String(result?.stdout ?? '').split('\\n')) {\n const match = pattern.exec(line.trim());\n if (match) indexes.add(Number(match[1]));\n }\n } catch {\n // Worktree enumeration failed — fall back to branch-derived candidates only.\n }\n return indexes;\n}\n\nasync function countCommitsAhead(\n workspacePath: string,\n branch: string,\n runGitCommand: CoordinateSwarmSlotsDeps['runGitCommand'],\n): Promise<number | null> {\n try {\n const result = await runGitCommand(`git rev-list --count HEAD..${JSON.stringify(branch)}`, workspacePath) as { stdout?: unknown };\n const count = Number(String(result?.stdout ?? '').trim());\n return Number.isFinite(count) ? count : null;\n } catch {\n return null;\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { messageAgent } from '../agents/messaging.js';\nimport type { ReconciledSlotItem } from '../agents/slot-reconcile.js';\nimport { isStatePlaneOnlyStatus } from '../state-plane.js';\nimport { loadCloisterConfigSync, type SwarmInferCompletionMode } from './config.js';\nimport type { ClassifiedSwarmSlot, ClassifyInFlightSlotsOptions, CoordinateSwarmSlotsDeps } from './deacon-swarm.js';\n\nconst execAsync = promisify(exec);\nconst slotCompletionObservations = new Map<string, SlotCompletionObservation>();\n\ninterface SlotCompletionObservation {\n signature: string;\n nudged: boolean;\n consecutiveDoneCount: number;\n}\n\nexport interface DoneWithoutSignalObservation {\n commitTime: number | null;\n outputDigest: string;\n progressKey: string;\n stalledForMs: number;\n}\n\nexport async function classifyDoneWithoutSignal(\n slot: ReconciledSlotItem,\n deps: Partial<Pick<CoordinateSwarmSlotsDeps, 'getSlotBranchAheadCount' | 'isSlotWorktreeClean' | 'sendCompletionNudge'>>,\n options: ClassifyInFlightSlotsOptions,\n observation: DoneWithoutSignalObservation,\n): Promise<ClassifiedSwarmSlot | null> {\n const mode = options.inferCompletion ?? 'off';\n if (mode === 'off' || !slot.agentId || !slot.branch || !options.workspacePath || !options.issueId) {\n slotCompletionObservations.delete(observation.progressKey);\n return null;\n }\n\n const aheadCount = await (deps.getSlotBranchAheadCount ?? defaultGetSlotBranchAheadCount)(\n options.workspacePath,\n options.issueId,\n slot.branch,\n ).catch(() => 0);\n const clean = await (deps.isSlotWorktreeClean ?? defaultIsSlotWorktreeClean)(\n `${options.workspacePath}-slot-${slot.slotIndex}`,\n ).catch(() => false);\n if (aheadCount < 1 || !clean) {\n slotCompletionObservations.delete(observation.progressKey);\n return null;\n }\n\n const signature = `${observation.commitTime ?? 'none'}:${observation.outputDigest}:${aheadCount}:clean`;\n const previous = slotCompletionObservations.get(observation.progressKey);\n const current: SlotCompletionObservation = {\n signature,\n nudged: previous?.signature === signature ? previous.nudged : false,\n consecutiveDoneCount: previous?.signature === signature ? previous.consecutiveDoneCount + 1 : 1,\n };\n const actions: string[] = [];\n const normalizedIssueId = options.issueId.toUpperCase();\n\n if (!current.nudged) {\n await (deps.sendCompletionNudge ?? defaultSendCompletionNudge)(slot.agentId, normalizedIssueId);\n current.nudged = true;\n actions.push(`[swarm] nudged slot ${slot.slotIndex} (item ${slot.itemId}) for ${normalizedIssueId}: run pan done ${normalizedIssueId}`);\n }\n\n slotCompletionObservations.set(observation.progressKey, current);\n if (mode === 'auto' && current.consecutiveDoneCount >= 2) {\n return { ...slot, lifecycle: 'ready-to-merge', exitStatus: 0, signal: 'inferred', actions };\n }\n\n return {\n ...slot,\n lifecycle: 'awaiting-completion-signal',\n reason: 'no-progress-timeout',\n stalledForMs: observation.stalledForMs,\n signal: 'completion-nudge',\n actions,\n };\n}\n\nexport async function classifyDurableReadySlot(\n slot: ReconciledSlotItem,\n deps: Partial<Pick<CoordinateSwarmSlotsDeps, 'getSlotBranchAheadCount' | 'isSlotWorktreeClean'>>,\n options: ClassifyInFlightSlotsOptions,\n): Promise<ClassifiedSwarmSlot | null> {\n if (!slot.branch || !options.workspacePath || !options.issueId) return null;\n\n const aheadCount = await (deps.getSlotBranchAheadCount ?? defaultGetSlotBranchAheadCount)(\n options.workspacePath,\n options.issueId,\n slot.branch,\n ).catch(() => 0);\n if (aheadCount < 1) return null;\n\n const clean = await (deps.isSlotWorktreeClean ?? defaultIsSlotWorktreeClean)(\n `${options.workspacePath}-slot-${slot.slotIndex}`,\n ).catch(() => false);\n if (!clean) return null;\n\n return { ...slot, lifecycle: 'ready-to-merge', exitStatus: 0, signal: 'inferred' };\n}\n\nexport function resetSwarmCompletionInferenceForTests(): void {\n slotCompletionObservations.clear();\n}\n\nexport function clearSwarmCompletionObservation(progressKey: string): void {\n slotCompletionObservations.delete(progressKey);\n}\n\nexport function swarmInferCompletionMode(): SwarmInferCompletionMode {\n const raw = process.env.PAN_SWARM_INFER_COMPLETION ?? loadCloisterConfigSync().swarm?.infer_completion;\n // PAN-2372 WI-5 / FR-8: default to 'auto' (nudge once, then converge after two stable\n // observations). Explicit 'nudge' / 'off' in config.yaml or PAN_SWARM_INFER_COMPLETION\n // still parse and keep their exact prior semantics.\n return raw === 'off' || raw === 'nudge' || raw === 'auto' ? raw : 'auto';\n}\n\nexport async function defaultGetSlotBranchAheadCount(\n workspacePath: string,\n issueId: string,\n branch: string,\n): Promise<number> {\n const baseBranch = `feature/${issueId.toLowerCase()}`;\n const { stdout } = await execAsync(\n `git rev-list --count ${JSON.stringify(baseBranch)}..${JSON.stringify(branch)}`,\n { cwd: workspacePath },\n );\n const count = Number(stdout.trim());\n return Number.isFinite(count) && count > 0 ? count : 0;\n}\n\nexport async function defaultIsSlotWorktreeClean(slotWorkspacePath: string): Promise<boolean> {\n const { stdout } = await execAsync('git status --porcelain', { cwd: slotWorkspacePath });\n // PAN-2372 WI-6 / FR-9: treat state-plane-only dirt (.pan/continue.json, .pan/records/...,\n // the workspace record door) as clean. The swarm writes durable state to those paths on the\n // permanent plane, so their presence must not block a slot from being inferred complete.\n // isStatePlaneOnlyStatus already returns true for empty porcelain (vacuous every()), so one\n // shared classifier covers both cases — no local path list here. See docs/STATE-PLANE-COMMIT-POLICY.md.\n return isStatePlaneOnlyStatus(stdout);\n}\n\nexport async function defaultSendCompletionNudge(agentId: string, issueId: string): Promise<void> {\n await messageAgent(\n agentId,\n `You appear to have committed clean slot work but have not signaled completion. If the slot is complete, run exactly:\\n\\npan done ${issueId}`,\n 'deacon:swarm-completion-inference',\n );\n}\n","import { Effect } from 'effect';\nimport { setReviewStatusSync, getReviewStatusSync } from '../review-status.js';\nimport { applyStatusOverrides } from '../vbrief/io.js';\nimport type { VBriefDocument } from '../vbrief/types.js';\n\nexport interface RequestIssueReviewResult {\n success: boolean;\n message: string;\n error?: string;\n gated?: boolean;\n}\n\nexport async function defaultRequestIssueReview(\n issueId: string,\n workspacePath: string,\n): Promise<RequestIssueReviewResult> {\n setReviewStatusSync(issueId, {\n reviewStatus: 'pending',\n testStatus: 'pending',\n mergeStatus: 'pending',\n readyForMerge: false,\n verificationStatus: 'pending',\n verificationCycleCount: 0,\n autoRequeueCount: 0,\n reviewRequestedAt: new Date().toISOString(),\n });\n\n const { spawnReviewRoleForIssue } = await import('./review-agent.js');\n return Effect.runPromise(spawnReviewRoleForIssue({\n issueId,\n workspace: workspacePath,\n branch: `feature/${issueId.toLowerCase()}`,\n }));\n}\n\nexport async function finalizeSwarmIssueIfComplete(\n issueId: string,\n workspacePath: string,\n baseDoc: VBriefDocument,\n deps: {\n readStatusOverrides?: (workspacePath: string, issueId: string) => Record<string, string> | undefined;\n getFinalizedAt?: (issueId: string, workspacePath: string) => string | undefined;\n setFinalizedAt?: (issueId: string, workspacePath: string, finalizedAt: string) => void;\n requestIssueReview: (issueId: string, workspacePath: string) => Promise<RequestIssueReviewResult>;\n },\n): Promise<string[]> {\n const overrides = deps.readStatusOverrides?.(workspacePath, issueId);\n const doc = overrides && Object.keys(overrides).length > 0\n ? applyStatusOverrides(baseDoc, overrides)\n : baseDoc;\n\n if (!doc.plan.items.every(item => item.status === 'completed')) return [];\n if (deps.getFinalizedAt?.(issueId, workspacePath)) return [];\n const currentStatus = getReviewStatusSync(issueId);\n if (currentStatus?.mergeStatus === 'merged') return [];\n if (currentStatus?.reviewRequestedAt || currentStatus?.reviewStatus === 'reviewing' || currentStatus?.reviewStatus === 'passed') {\n return [];\n }\n\n const result = await deps.requestIssueReview(issueId, workspacePath);\n if (result.success) {\n deps.setFinalizedAt?.(issueId, workspacePath, new Date().toISOString());\n return [`[swarm] finalized ${issueId}: issue-level review requested`];\n }\n return [`[swarm] finalization deferred ${issueId}: ${result.error || result.message}`];\n}\n","import { existsSync } from 'node:fs';\nimport { Effect } from 'effect';\nimport type { ReconciledSlotItem } from '../agents/slot-reconcile.js';\nimport { getAgentStateSync } from '../agents/agent-state.js';\nimport { stopAgent } from '../agents/termination.js';\nimport type { CoordinateSwarmSlotsDeps } from './deacon-swarm.js';\n\nconst MERGED_LIVE_SLOT_IDLE_MS = 30 * 60 * 1000;\n\nexport async function gcMergedSlots(\n issueId: string,\n workspacePath: string,\n slots: ReconciledSlotItem[],\n deps: Pick<CoordinateSwarmSlotsDeps, 'runGitCommand' | 'clearSlotAssignment' | 'listSessionNames'> & {\n slotWorktreeExists?: (path: string) => boolean;\n getAgentLastActivity?: (agentId: string) => string | undefined;\n stopSlotAgent?: (agentId: string) => Promise<void>;\n },\n): Promise<string[]> {\n const actions: string[] = [];\n // A freshly dispatched slot branch points at the feature branch HEAD, so\n // `--merged HEAD` classifies it as merged before the agent's first commit.\n // Without a liveness guard, gc destroys the worktree/branch/assignment under\n // the live agent and the item redispatches at the next index.\n const sessionNames = new Set(await deps.listSessionNames());\n const worktreeExists = deps.slotWorktreeExists ?? existsSync;\n\n for (const slot of slots) {\n if (slot.status !== 'merged') continue;\n\n const agentId = slot.agentId ?? `agent-${issueId.toLowerCase()}-slot-${slot.slotIndex}`;\n if (sessionNames.has(agentId)) {\n const lastActivity = (deps.getAgentLastActivity ?? (id => getAgentStateSync(id)?.lastActivity))(agentId);\n const idleFor = lastActivity ? Date.now() - Date.parse(lastActivity) : 0;\n if (!Number.isFinite(idleFor) || idleFor < MERGED_LIVE_SLOT_IDLE_MS) {\n actions.push(`[swarm] gc skipped slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: agent session alive`);\n continue;\n }\n await (deps.stopSlotAgent ?? (id => Effect.runPromise(stopAgent(id))))(agentId);\n actions.push(`[swarm] gc reaped idle merged agent ${agentId}`);\n }\n\n const slotWorkspace = `${workspacePath}-slot-${slot.slotIndex}`;\n const slotBranch = slot.branch ?? `feature/${issueId.toLowerCase()}-slot-${slot.slotIndex}`;\n if (worktreeExists(slotWorkspace)) {\n try {\n await deps.runGitCommand(`git worktree remove --force ${JSON.stringify(slotWorkspace)}`, workspacePath);\n } catch (error) {\n actions.push(`[swarm] gc deferred slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: worktree remove failed: ${error instanceof Error ? error.message : String(error)}`);\n continue;\n }\n }\n try {\n await deps.runGitCommand(`git branch -D ${JSON.stringify(slotBranch)}`, workspacePath);\n } catch (error) {\n actions.push(`[swarm] gc deferred slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: branch delete failed: ${error instanceof Error ? error.message : String(error)}`);\n continue;\n }\n deps.clearSlotAssignment(workspacePath, issueId, slot.slotIndex, slot.itemId);\n actions.push(`[swarm] gc slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}`);\n }\n\n return actions;\n}\n","import {\n readIssueRecordForWorkspaceSync,\n writeIssueRecordForWorkspaceSync,\n type PanIssueRecord,\n type PanIssueSwarmSlotCompletion,\n} from '../pan-dir/record.js';\n\nexport function createMinimalIssueRecord(issueId: string): PanIssueRecord {\n const now = new Date().toISOString();\n return {\n issueId,\n schemaVersion: 2,\n created: now,\n updated: now,\n feedback: [],\n pipeline: {\n issueId,\n reviewStatus: 'pending',\n testStatus: 'pending',\n mergeStatus: 'pending',\n readyForMerge: false,\n updatedAt: now,\n },\n closeOut: {\n usage: {\n byStage: {},\n totals: {},\n },\n merges: [],\n ranOn: '',\n },\n };\n}\n\nexport function writeSwarmFinalizedAt(workspacePath: string, issueId: string, finalizedAt: string): void {\n const normalizedIssueId = issueId.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId)\n ?? createMinimalIssueRecord(normalizedIssueId);\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...(record.swarm ?? {}),\n finalizedAt,\n },\n });\n}\n\n/**\n * PAN-2372 WI-3 / FR-4: persist a durable per-slot completion marker keyed by\n * `String(slotIndex)`. Read-modify-write preserves every other record field\n * (statusOverrides, slotAssignments, etc.) — see the byte-identical\n * preservation test in deacon-swarm-slot-completion.test.ts.\n */\nexport function writeSwarmSlotCompletion(\n workspacePath: string,\n issueId: string,\n completion: PanIssueSwarmSlotCompletion,\n): void {\n const normalizedIssueId = issueId.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId)\n ?? createMinimalIssueRecord(normalizedIssueId);\n const swarm = record.swarm ?? {};\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...swarm,\n slotCompletions: {\n ...(swarm.slotCompletions ?? {}),\n [String(completion.slotIndex)]: completion,\n },\n },\n });\n}\n\n/**\n * PAN-2372 WI-3 / FR-6: clear a slot's completion marker once the coordinator\n * (WI-4) has consumed it (merge/requeue). No-op when no marker exists for the\n * slot, so callers can clear unconditionally on the terminal transition.\n */\nexport function clearSwarmSlotCompletion(workspacePath: string, issueId: string, slotIndex: number): void {\n const normalizedIssueId = issueId.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId);\n const existing = record?.swarm?.slotCompletions;\n if (!existing || !(String(slotIndex) in existing)) return;\n const next: Record<string, PanIssueSwarmSlotCompletion> = { ...existing };\n delete next[String(slotIndex)];\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...record!.swarm,\n slotCompletions: next,\n },\n });\n}\n\n/**\n * PAN-2372 WI-3 / FR-4, FR-5: write the durable slot-completion marker and read\n * it straight back to confirm it persisted. Returns true only when the keyed\n * marker exists on disk with a matching agentId. The slot `pan done` caller MUST\n * refuse to mark the slot done when this returns false — that is the whole point\n * of the issue: a slot used to finish without durably recording completion, so\n * the coordinator could not observe it. Keeping the write+verify here (not inline\n * in the CLI command) keeps the god-file done.ts from growing and co-locates the\n * swarm-record mechanics with the other slot-completion door functions.\n */\nexport function persistAndVerifySwarmSlotCompletion(\n workspacePath: string,\n issueId: string,\n completion: PanIssueSwarmSlotCompletion,\n): boolean {\n writeSwarmSlotCompletion(workspacePath, issueId, completion);\n const reread = readIssueRecordForWorkspaceSync(workspacePath, issueId.toUpperCase());\n const persisted = reread?.swarm?.slotCompletions?.[String(completion.slotIndex)];\n return Boolean(persisted && persisted.agentId === completion.agentId);\n}\n","/**\n * PAN-2385 — tiered-execution commit hooks for the swarm dispatch path.\n *\n * The tier-feed and tier-supervisor libraries shipped with PAN-1791/2222 but\n * had no production caller: commits landed and neither the standing crew nor\n * the subscribe-policy supervisor ever heard about them (found live during\n * the first Standing Crew run, PAN-2383). This module is the ignition.\n *\n * Fired from mergeReadySlots after a slot's bead commits merge into the\n * feature workspace:\n * 1. broadcastCommit — every live slot agent hears the rendered diff\n * (ingestion-only; everyone-hears-everything per docs/TIERED-EXECUTION.md).\n * 2. shouldSupervise(item, subscribe) → deliverCommitForReview — the\n * standing supervisor reviews per its subscribe policy. This is\n * independent of supervisor.owns_inspection, which only routes\n * `pan inspect`.\n *\n * Both hooks are best-effort: the commit has already landed, so a delivery\n * failure logs loudly and never blocks the merge loop.\n */\n\nimport { Effect } from 'effect';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { sessionExists } from '../tmux.js';\nimport { loadConfigSync as loadYamlConfig } from '../config-yaml.js';\nimport { resolveTieredExecutionEnabled, type ValidatedTieredExecutionConfig } from '../agents/tier-table.js';\nimport { resolveTier } from '../agents/resolve-tier.js';\nimport { broadcastCommit } from '../agents/tier-feed.js';\nimport {\n deliverCommitForReview,\n loadPrdDraft,\n shouldSupervise,\n spawnTierSupervisor,\n supervisorAgentId,\n} from '../agents/tier-supervisor.js';\nimport { listSlotAssignments } from '../agents/slot-reconcile.js';\nimport type { VBriefDocument, VBriefItem } from '../vbrief/types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface FireTieredCommitHooksOptions {\n issueId: string;\n /** Feature workspace the slot branch just merged into (its HEAD is the commit). */\n workspacePath: string;\n /** The bead the merged commits implement. */\n item: VBriefItem;\n /** The merged plan view — plan.metadata carries the per-issue tiered override. */\n doc: VBriefDocument;\n}\n\nexport interface FireTieredCommitHooksDeps {\n loadConfig: typeof loadYamlConfig;\n getHeadSha: (workspacePath: string) => Promise<string>;\n listAssignments: typeof listSlotAssignments;\n isSessionAlive: (sessionName: string) => Promise<boolean>;\n broadcast: typeof broadcastCommit;\n ensureSupervisor: typeof spawnTierSupervisor;\n deliverReview: typeof deliverCommitForReview;\n loadPrd: typeof loadPrdDraft;\n}\n\nconst defaultDeps: FireTieredCommitHooksDeps = {\n loadConfig: loadYamlConfig,\n getHeadSha: async (workspacePath) =>\n (await execAsync('git rev-parse HEAD', { cwd: workspacePath })).stdout.trim(),\n listAssignments: listSlotAssignments,\n isSessionAlive: (sessionName) => Effect.runPromise(sessionExists(sessionName)),\n broadcast: broadcastCommit,\n ensureSupervisor: spawnTierSupervisor,\n deliverReview: deliverCommitForReview,\n loadPrd: loadPrdDraft,\n};\n\n/** Resolve the tier name a bead belongs to, for the feed header. Falls back to\n * the slot label when the tier table cannot resolve the item (fail-open here is\n * correct: the feed is informational and the commit has already landed). */\nfunction tierNameForItem(\n item: VBriefItem | undefined,\n tiered: ValidatedTieredExecutionConfig,\n slotIndex: number,\n): string {\n if (item) {\n try {\n return resolveTier(item, tiered).tierName;\n } catch {\n // fall through to the slot label\n }\n }\n return `slot-${slotIndex}`;\n}\n\n/**\n * Fire the commit feed + supervisor review for a bead whose commits just\n * merged into the feature workspace. Returns deacon action-log lines.\n */\nexport async function fireTieredCommitHooks(\n options: FireTieredCommitHooksOptions,\n deps: FireTieredCommitHooksDeps = defaultDeps,\n): Promise<string[]> {\n const actions: string[] = [];\n const { issueId, workspacePath, item, doc } = options;\n\n let tiered: ValidatedTieredExecutionConfig | undefined;\n try {\n tiered = deps.loadConfig().config.tieredExecution;\n } catch (err) {\n actions.push(`[tiered] skipped commit hooks for ${issueId}: config load failed (${err instanceof Error ? err.message : String(err)})`);\n return actions;\n }\n if (!tiered || !resolveTieredExecutionEnabled(tiered, doc.plan.metadata)) return actions;\n\n let sha: string;\n try {\n sha = await deps.getHeadSha(workspacePath);\n } catch (err) {\n actions.push(`[tiered] commit hooks for ${issueId} item ${item.id} could not resolve HEAD: ${err instanceof Error ? err.message : String(err)}`);\n return actions;\n }\n\n // ── 1. Broadcast to every live standing slot agent ────────────────────────\n try {\n const itemsById = new Map(doc.plan.items.map((planItem) => [planItem.id, planItem]));\n const assignments = deps.listAssignments(issueId, workspacePath);\n const listeners: Array<{ tierName: string; agentId: string }> = [];\n for (const assignment of assignments) {\n if (!assignment.agentId) continue;\n if (!(await deps.isSessionAlive(assignment.agentId))) continue;\n listeners.push({\n tierName: tierNameForItem(itemsById.get(assignment.itemId), tiered, assignment.slotIndex),\n agentId: assignment.agentId,\n });\n }\n if (listeners.length > 0) {\n const deliveries = await deps.broadcast({\n workspace: workspacePath,\n issueId,\n sha,\n beadTitle: item.title,\n beadId: item.id,\n tiers: listeners,\n feedConfig: tiered.feed,\n });\n const delivered = deliveries.filter((delivery) => delivery.result.ok).length;\n actions.push(`[tiered] broadcast commit ${sha.slice(0, 10)} (item ${item.id}) for ${issueId} to ${delivered}/${listeners.length} standing agents`);\n }\n } catch (err) {\n actions.push(`[tiered] feed broadcast FAILED for ${issueId} item ${item.id}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n // ── 2. Supervisor review per subscribe policy ─────────────────────────────\n try {\n const supervisor = tiered.supervisor;\n if (supervisor && shouldSupervise(item, supervisor.subscribe)) {\n const agentId = supervisorAgentId(issueId);\n if (!(await deps.isSessionAlive(agentId))) {\n await deps.ensureSupervisor(issueId, supervisor, { workspace: workspacePath });\n actions.push(`[tiered] spawned standing supervisor ${agentId} for ${issueId}`);\n }\n const prdMarkdown = await deps.loadPrd(workspacePath, issueId).catch(() => undefined);\n await deps.deliverReview({\n supervisorAgentId: agentId,\n workspacePath,\n issueId,\n item,\n sha,\n beadId: item.id,\n prdMarkdown,\n });\n actions.push(`[tiered] supervisor review dispatched for ${issueId} item ${item.id} (subscribe=${supervisor.subscribe})`);\n }\n } catch (err) {\n actions.push(`[tiered] supervisor review FAILED for ${issueId} item ${item.id}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n return actions;\n}\n","import { readIssueRecordForWorkspaceSync, writeIssueRecordForWorkspaceSync, type PanIssueRecoveryTrip } from '../pan-dir/record.js';\nimport { createMinimalIssueRecord } from './deacon-swarm-record.js';\n\nexport function recordRecoveryFailure(\n workspacePath: string,\n issue: string,\n recoveryPath: string,\n obligationGeneration: string,\n threshold = 25,\n now = new Date(),\n): { trip: PanIssueRecoveryTrip; emitNeedsYou: boolean } {\n const normalized = issue.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalized) ?? createMinimalIssueRecord(normalized);\n const trips = [...(record.recoveryTrips ?? [])];\n const index = trips.findIndex(trip => trip.issue === normalized && trip.recoveryPath === recoveryPath && trip.obligationGeneration === obligationGeneration);\n const prior = index >= 0 ? trips[index] : undefined;\n if (prior?.open) return { trip: prior, emitNeedsYou: false };\n const tripCount = (prior?.tripCount ?? 0) + 1;\n const emitNeedsYou = tripCount >= threshold && !prior?.open;\n const trip: PanIssueRecoveryTrip = {\n issue: normalized, recoveryPath, obligationGeneration, tripCount,\n open: prior?.open === true || emitNeedsYou,\n ...(prior?.needsYouEmittedAt ? { needsYouEmittedAt: prior.needsYouEmittedAt } : emitNeedsYou ? { needsYouEmittedAt: now.toISOString() } : {}),\n };\n if (index >= 0) trips[index] = trip; else trips.push(trip);\n writeIssueRecordForWorkspaceSync(workspacePath, normalized, { ...record, recoveryTrips: trips });\n return { trip, emitNeedsYou };\n}\n\nexport function acknowledgeRecoveryTrip(workspacePath: string, issue: string, recoveryPath: string, obligationGeneration: string): void {\n const normalized = issue.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalized);\n if (!record) return;\n writeIssueRecordForWorkspaceSync(workspacePath, normalized, {\n ...record,\n recoveryTrips: (record.recoveryTrips ?? []).filter(trip => !(trip.issue === normalized && trip.recoveryPath === recoveryPath && trip.obligationGeneration === obligationGeneration)),\n });\n}\n","/**\n * PAN-2543 shared autonomous re-drive gate.\n *\n * Recovery entry points classify agent gates, apply the intent policy, and\n * consult the cached memory verdict through this one function before acting.\n * Callers still reserve their role-specific concurrency slot after admission.\n */\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport {\n decideResumeGate,\n getAgentResumeGateBlockReason,\n type AgentState,\n type ResumeGateContext,\n type ResumeGateDecision,\n} from '../agents/agent-state.js';\nimport { getCachedMemoryVerdict } from './memory-verdict-cache.js';\n\nexport const REDRIVE_ENTRY_POINTS = ['dead-session-rework', 'swarm-slot-requeue'] as const;\n\nexport type RedriveGateDecision =\n | { decision: 'proceed'; gateDecision: Extract<ResumeGateDecision, { decision: 'proceed' }> }\n | { decision: 'defer'; reason: string; needsYou?: true };\n\nexport function decideAutonomousRedrive(\n state: Pick<AgentState, 'paused' | 'pausedReason' | 'yieldedByScheduler' | 'troubled' | 'troubledAt' | 'stoppedByUser' | 'consecutiveFailures'>,\n context: ResumeGateContext = {},\n): RedriveGateDecision {\n const gateDecision = decideResumeGate(getAgentResumeGateBlockReason(state), 'autonomous', context);\n if (gateDecision.decision !== 'proceed') {\n return {\n decision: 'defer',\n reason: gateDecision.reason,\n ...(gateDecision.decision === 'block' && gateDecision.needsYou ? { needsYou: true } : {}),\n };\n }\n\n const memoryVerdict = getCachedMemoryVerdict();\n if (memoryVerdict && memoryVerdict.band !== 'ok') {\n return { decision: 'defer', reason: `memory pressure is ${memoryVerdict.band}` };\n }\n return { decision: 'proceed', gateDecision };\n}\n\nexport function decideAgentAutonomousRedrive(\n state: Pick<AgentState, 'paused' | 'pausedReason' | 'yieldedByScheduler' | 'troubled' | 'troubledAt' | 'stoppedByUser' | 'consecutiveFailures'>,\n agentDir: string,\n owesRework: boolean,\n): RedriveGateDecision {\n const hasCompletedHandoff = existsSync(join(agentDir, 'completed'))\n || existsSync(join(agentDir, 'completed.processed'));\n return decideAutonomousRedrive(state, { hasCompletedHandoff, owesRework });\n}\n","import { existsSync } from 'node:fs';\nimport type { ReconciledSlotItem, SlotReconcileResult } from '../agents/slot-reconcile.js';\nimport {\n readIssueRecordForWorkspaceSync,\n writeIssueRecordForWorkspaceSync,\n type PanIssueRecord,\n type PanIssueSwarmSupersededAttempt,\n} from '../pan-dir/record.js';\nimport { createMinimalIssueRecord, clearSwarmSlotCompletion } from './deacon-swarm-record.js';\nimport type { PersistedTaskOperation } from '../vbrief/dag.js';\nimport type { VBriefDocument } from '../vbrief/types.js';\nimport { recordRecoveryFailure } from './recovery-trip.js';\nimport { getAgentStateSync } from '../agents/agent-state.js';\nimport { decideAutonomousRedrive } from './redrive-gate.js';\n\n/** Patrol GC never removes forensic attempts; configured issue close-out owns teardown. */\nexport const SWARM_SUPERSEDED_RETENTION = 'issue-close-out' as const;\n\nexport interface FailedSlotArchiveDeps {\n runGitCommand: (command: string, cwd: string) => Promise<unknown>;\n clearSlotAssignment: (workspacePath: string, issueId: string, slotIndex: number, itemId?: string) => void;\n}\ninterface ClassifiedSlot extends ReconciledSlotItem { lifecycle: string; reason?: string }\n\nexport function nextSwarmSlotIndex(record: PanIssueRecord | undefined, reconciled: SlotReconcileResult): number {\n return Math.max(0,\n ...reconciled.branches.map(value => value.slotIndex),\n ...reconciled.agents.map(value => value.slotIndex),\n ...reconciled.inFlight.map(value => value.slotIndex),\n ...(record?.swarm?.slotAssignments ?? []).map(value => value.slotIndex),\n ...(record?.swarm?.supersededAttempts ?? []).map(value => value.slotIndex),\n ) + 1;\n}\n\nexport async function archiveFailedSwarmSlot(\n issueId: string,\n workspacePath: string,\n slot: ReconciledSlotItem & { reason?: string },\n deps: FailedSlotArchiveDeps,\n now = new Date(),\n): Promise<PanIssueSwarmSupersededAttempt> {\n const normalized = issueId.toUpperCase();\n const suffix = now.toISOString().replace(/[-:.TZ]/g, '');\n const archivedStem = `slot-${slot.slotIndex}-failed-${suffix}`;\n const oldWorktree = `${workspacePath}-slot-${slot.slotIndex}`;\n const archivedWorktree = `${workspacePath}-${archivedStem}`;\n const oldBranch = slot.branch ?? `feature/${issueId.toLowerCase()}-slot-${slot.slotIndex}`;\n const archivedBranch = `feature/${issueId.toLowerCase()}-${archivedStem}`;\n\n if (existsSync(oldWorktree)) {\n await deps.runGitCommand(`git worktree move ${JSON.stringify(oldWorktree)} ${JSON.stringify(archivedWorktree)}`, workspacePath);\n }\n await deps.runGitCommand(`git branch -m ${JSON.stringify(oldBranch)} ${JSON.stringify(archivedBranch)}`, workspacePath);\n\n const attempt: PanIssueSwarmSupersededAttempt = {\n slotIndex: slot.slotIndex,\n itemId: slot.itemId,\n agentId: slot.agentId,\n branch: oldBranch,\n archivedBranch,\n ...(existsSync(archivedWorktree) ? { archivedWorktree } : {}),\n reason: slot.reason ?? 'failed swarm slot',\n supersededAt: now.toISOString(),\n };\n const existing = readIssueRecordForWorkspaceSync(workspacePath, normalized) ?? createMinimalIssueRecord(normalized);\n writeIssueRecordForWorkspaceSync(workspacePath, normalized, {\n ...existing,\n swarm: {\n ...(existing.swarm ?? {}),\n supersededAttempts: [...(existing.swarm?.supersededAttempts ?? []), attempt],\n },\n });\n // PAN-2372 WI-4 / FR-6: this slot is being superseded/requeued — clear its\n // durable completion marker so a fresh attempt on the same slotIndex is not\n // falsely observed as already-completed by classifyInFlightSlots.\n clearSwarmSlotCompletion(workspacePath, normalized, slot.slotIndex);\n deps.clearSlotAssignment(workspacePath, normalized, slot.slotIndex, slot.itemId);\n return attempt;\n}\n\nexport async function requeueFailedSwarmSlots(\n issueId: string,\n workspacePath: string,\n classified: ClassifiedSlot[],\n doc: VBriefDocument,\n reconciled: SlotReconcileResult,\n deps: FailedSlotArchiveDeps & { applyTaskOperationToPlanFile: (path: string, operation: PersistedTaskOperation, workspace?: string) => Promise<unknown> },\n blockedSlotIndexes: Set<number> = new Set(),\n): Promise<{ doc: VBriefDocument; actions: string[] }> {\n let nextDoc = doc;\n const actions: string[] = [];\n for (const slot of classified.filter(candidate => candidate.lifecycle === 'failed')) {\n if (blockedSlotIndexes.has(slot.slotIndex)) {\n actions.push(`[swarm] skipped requeue slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: failed-merge block — awaiting operator recovery`);\n continue;\n }\n const admission = decideAutonomousRedrive(slot.agentId ? getAgentStateSync(slot.agentId) ?? {} : {}, { owesRework: true });\n if (admission.decision === 'defer') { actions.push(`[swarm] deferred failed slot ${slot.slotIndex}: ${admission.reason}`); continue; }\n const attempt = await archiveFailedSwarmSlot(issueId, workspacePath, slot, deps);\n await deps.applyTaskOperationToPlanFile(`${workspacePath}/.pan/spec.vbrief.json`, {\n type: 'unblock', itemId: slot.itemId, writerId: 'deacon-swarm', reason: `Redispatch after ${slot.reason ?? 'slot failure'}`,\n }, workspacePath);\n reconciled.inFlight = reconciled.inFlight.filter(candidate => candidate.itemId !== slot.itemId);\n reconciled.superseded = [...(reconciled.superseded ?? []), attempt];\n nextDoc = { ...nextDoc, plan: { ...nextDoc.plan, items: nextDoc.plan.items.map(item => item.id === slot.itemId ? { ...item, status: 'pending' as const } : item) } };\n actions.push(`[swarm] archived failed slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}`);\n const failure = recordRecoveryFailure(workspacePath, issueId, 'swarm-slot-requeue', slot.itemId);\n if (failure.emitNeedsYou) actions.push(`[swarm] needs-you ${issueId}: slot item ${slot.itemId} failed ${failure.trip.tripCount} times`);\n }\n return { doc: nextDoc, actions };\n}\n\nexport function applySupersededSlotHighWater(\n occupied: Set<number>,\n reconciled: SlotReconcileResult,\n configuredMax: number,\n): number {\n const highWater = Math.max(0, ...(reconciled.superseded ?? []).map(attempt => attempt.slotIndex));\n if (highWater > 0) for (let index = 1; index <= highWater; index++) occupied.add(index);\n return Math.max(configuredMax, highWater + 1);\n}\n","import { exec } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { promisify } from 'node:util';\nimport { Effect } from 'effect';\nimport { join } from 'path';\nimport { getAgentRuntimeSnapshot } from '../agent-runtime.js';\nimport type { AgentRuntimeSnapshot } from '@overdeck/contracts';\nimport { spawnRun } from '../agents/spawn.js';\nimport type { SpawnRunOptions } from '../agents/spawn-prep.js';\nimport { verifyAndMergeSlot, type SlotMergeResult } from '../agents/slot-merge.js';\nimport {\n listSlotAssignments as listDurableSlotAssignments,\n reconcileSlotState,\n type ReconciledSlotItem,\n type SlotReconcileResult,\n} from '../agents/slot-reconcile.js';\nimport {\n readIssueRecordForWorkspaceSync,\n writeIssueRecordForWorkspaceSync,\n getIssueRecordPathForWorkspace,\n type PanIssueRecord,\n type PanIssueSwarmFailedMergeBlock,\n type PanIssueSwarmSlotCompletion,\n} from '../pan-dir/record.js';\nimport { findSpecByIssue } from '../pan-dir/specs.js';\nimport { capturePane, isPaneDead, listPaneValues, listSessionNames as listTmuxSessionNames } from '../tmux.js';\nimport {\n applyTaskOperationToPlanFile,\n blockingParentCount,\n createActiveSlice,\n getDispatchableItems,\n type PersistedTaskOperation,\n} from '../vbrief/dag.js';\nimport { applyStatusOverrides } from '../vbrief/io.js';\nimport { analyzeSwarmReadiness, type SwarmReadinessVerdict } from '../vbrief/swarm-readiness.js';\nimport type { VBriefDocument, VBriefItem } from '../vbrief/types.js';\nimport { getReviewStatusSync, type ReviewStatus } from '../review-status.js';\nimport { isDeaconGloballyPausedSync } from '../overdeck/control-settings.js';\nimport type { SwarmInferCompletionMode } from './config.js';\nimport {\n countRunningSwarmSlotsForIssue,\n getConcurrencyLimits,\n releaseSwarmSlot,\n tryReserveSwarmSlot,\n type ConcurrencyLimits,\n} from './concurrency.js';\nimport { listFeatureWorkspaces, type FeatureWorkspace } from './deacon-workspaces.js';\nimport { gcOrphanedSlots } from './deacon-swarm-orphan-gc.js';\nimport {\n classifyDoneWithoutSignal,\n classifyDurableReadySlot,\n clearSwarmCompletionObservation,\n defaultGetSlotBranchAheadCount,\n defaultIsSlotWorktreeClean,\n defaultSendCompletionNudge,\n resetSwarmCompletionInferenceForTests,\n swarmInferCompletionMode,\n} from './deacon-swarm-completion.js';\nimport {\n defaultRequestIssueReview,\n finalizeSwarmIssueIfComplete,\n type RequestIssueReviewResult,\n} from './deacon-swarm-finalization.js';\nimport { gcMergedSlots } from './deacon-swarm-gc.js';\nimport { createMinimalIssueRecord, writeSwarmFinalizedAt, clearSwarmSlotCompletion } from './deacon-swarm-record.js';\nimport { fireTieredCommitHooks } from './swarm-tiered-hooks.js';\nimport { applySupersededSlotHighWater, archiveFailedSwarmSlot, requeueFailedSwarmSlots } from './swarm-failed-slot.js';\n\nexport { gcOrphanedSlots } from './deacon-swarm-orphan-gc.js';\nexport { gcMergedSlots } from './deacon-swarm-gc.js';\n\nconst execAsync = promisify(exec);\nconst SLOT_MERGE_REFIRE_COOLDOWN_MS = 5_000;\nconst SWARM_ADVANCE_FAILURE_THRESHOLD = 3;\nconst SWARM_ADVANCE_FAILURE_COOLDOWN_MS = 60_000;\nconst DEFAULT_SWARM_STALL_THRESHOLD_MS = 30 * 60 * 1000;\n\nconst recentSlotMergeFires = new Map<string, number>();\nconst issueAdvanceFailures = new Map<string, { count: number; cooldownUntil: number }>();\nconst failedMergeBlocks = new Map<string, FailedMergeBlock>();\nconst slotProgressObservations = new Map<string, SlotProgressObservation>();\nexport type SwarmRecoveryAction = 'retry' | 'drop' | 'handoff';\n\nexport interface FailedMergeBlock {\n issueId: string;\n itemId: string;\n slotIndex: number;\n branch?: string;\n note: string;\n}\n\nexport interface CoordinateSwarmSlotsOptions {\n issueId?: string;\n}\n\nexport interface CoordinateSwarmSlotsDeps {\n listFeatureWorkspaces: () => FeatureWorkspace[];\n reconcileSlotState: (\n issueId: string,\n workspace: string,\n doc: VBriefDocument,\n ) => Promise<SlotReconcileResult>;\n listSessionNames: () => Promise<readonly string[]>;\n isPaneDead: (sessionName: string) => Promise<boolean>;\n getPaneExitStatus: (sessionName: string) => Promise<number | null>;\n getAgentRuntimeState: (agentId: string) => Promise<Pick<AgentRuntimeSnapshot, 'resolution'> | null>;\n getPaneOutputDigest: (sessionName: string) => Promise<string>;\n getBranchTipCommitTime: (workspacePath: string, branch: string) => Promise<number | null>;\n getSlotBranchAheadCount: (workspacePath: string, issueId: string, branch: string) => Promise<number>;\n isSlotWorktreeClean: (slotWorkspacePath: string) => Promise<boolean>;\n sendCompletionNudge: (agentId: string, issueId: string) => Promise<void>;\n slotWorktreeExists: (slotWorkspacePath: string) => boolean;\n verifyAndMergeSlot: (\n issue: { issueId: string; featureWorkspace: string },\n slotIndex: number,\n item: VBriefItem,\n ) => Promise<SlotMergeResult>;\n applyTaskOperationToPlanFile: (\n planPath: string,\n operation: PersistedTaskOperation,\n workspacePath?: string,\n ) => Promise<unknown>;\n /** PAN-2385: fire the tiered commit feed + supervisor review after a slot merges. */\n fireTieredCommitHooks: (\n options: { issueId: string; workspacePath: string; item: VBriefItem; doc: VBriefDocument },\n ) => Promise<string[]>;\n recordSlotAssignment: (workspacePath: string, issueId: string, assignment: SlotAssignment) => void;\n clearSlotAssignment: (workspacePath: string, issueId: string, slotIndex: number, itemId?: string) => void;\n runGitCommand: (command: string, cwd: string) => Promise<unknown>;\n registeredSlotCapacityAvailable: (issueId: string, selectedCount: number) => boolean;\n tryReserveSwarmSlot: () => boolean;\n releaseSwarmSlot: () => void;\n spawnRun: (issueId: string, role: 'work', options: SpawnRunOptions) => Promise<unknown>;\n /** Per-issue hold: deaconIgnored (operator) suppresses all swarm coordination (PAN-2214);\n * system-set `stuck` is logged but no longer halts coordination (PAN-2469). */\n getIssueHold?: (issueId: string) => Pick<ReviewStatus, 'stuck' | 'deaconIgnored' | 'stuckReason'> | null;\n /** Per-issue record statusOverrides — the durable item done-ness the merged plan view applies. */\n readStatusOverrides?: (workspacePath: string, issueId: string) => Record<string, string> | undefined;\n /**\n * PAN-2372 WI-4 / FR-6: durable per-slot completion marker (written by slot\n * `pan done`). When present for a slot, it beats every other classification —\n * even a vanished session or missing agent — because it is the durable record\n * that the slot finished; the runtime plane is rebuildable and may be absent.\n */\n readSlotCompletion?: (workspacePath: string, issueId: string, slotIndex: number) => PanIssueSwarmSlotCompletion | undefined;\n getFinalizedAt: (issueId: string, workspacePath: string) => string | undefined;\n setFinalizedAt: (issueId: string, workspacePath: string, finalizedAt: string) => void;\n /**\n * Re-evaluated immediately before EVERY slot spawn: global freeze + per-issue hold.\n * The cycle-start checks alone let an in-flight wave keep dispatching after a freeze\n * activates mid-patrol (PAN-2214 slot-20 regression).\n */\n shouldDispatch?: (issueId: string) => boolean;\n /**\n * Inclusive upper bound for slot index allocation — the swarm reserve.\n * Unbounded allocation climbed slot-5..slot-20 under an inconsistent\n * registry (PAN-2214).\n */\n getMaxSlotIndex?: () => number;\n /** Durable slot assignments from the issue record; they survive registry resets (PAN-2214). */\n listSlotAssignments?: (issueId: string, workspacePath: string) => Array<{ slotIndex: number }>;\n /** Request issue-level review once every swarm item has been assembled into the feature branch. */\n requestIssueReview: (issueId: string, workspacePath: string) => Promise<RequestIssueReviewResult>;\n}\n\nconst defaultDeps: CoordinateSwarmSlotsDeps = {\n listFeatureWorkspaces: () => listFeatureWorkspaces({ includeSlotWorkspaces: false }),\n reconcileSlotState,\n listSessionNames: () => Effect.runPromise(listTmuxSessionNames()),\n isPaneDead: (sessionName) => Effect.runPromise(isPaneDead(sessionName)),\n getPaneExitStatus: async (sessionName) => {\n const values = await Effect.runPromise(listPaneValues(sessionName, '#{pane_dead_status}'));\n const raw = values[0]?.trim();\n if (!raw) return null;\n const status = Number(raw);\n return Number.isFinite(status) ? status : null;\n },\n getAgentRuntimeState: (agentId) => Effect.runPromise(getAgentRuntimeSnapshot(agentId)),\n getPaneOutputDigest: async (sessionName) => Effect.runPromise(capturePane(sessionName, 200)),\n getBranchTipCommitTime: async (workspacePath, branch) => {\n try {\n const { stdout } = await execAsync(`git log -1 --format=%ct ${JSON.stringify(branch)}`, { cwd: workspacePath });\n const seconds = Number(stdout.trim());\n return Number.isFinite(seconds) ? seconds * 1000 : null;\n } catch {\n return null;\n }\n },\n getSlotBranchAheadCount: defaultGetSlotBranchAheadCount,\n isSlotWorktreeClean: defaultIsSlotWorktreeClean,\n sendCompletionNudge: defaultSendCompletionNudge,\n slotWorktreeExists: existsSync,\n verifyAndMergeSlot,\n applyTaskOperationToPlanFile: (planPath, operation, workspacePath) =>\n Effect.runPromise(applyTaskOperationToPlanFile(planPath, operation, workspacePath)),\n fireTieredCommitHooks,\n recordSlotAssignment,\n clearSlotAssignment,\n runGitCommand: (command, cwd) => execAsync(command, { cwd }),\n registeredSlotCapacityAvailable: (issueId, selectedCount) => registeredSlotCapacityAvailable(issueId, selectedCount),\n tryReserveSwarmSlot,\n releaseSwarmSlot,\n spawnRun,\n getIssueHold: defaultGetIssueHold,\n shouldDispatch: defaultShouldDispatch,\n getMaxSlotIndex: defaultGetMaxSlotIndex,\n listSlotAssignments: listDurableSlotAssignments,\n readStatusOverrides: defaultReadStatusOverrides,\n readSlotCompletion: defaultReadSlotCompletion,\n getFinalizedAt: getSwarmFinalizedAt,\n setFinalizedAt: recordSwarmFinalizedAt,\n requestIssueReview: defaultRequestIssueReview,\n};\n\nfunction defaultGetMaxSlotIndex(): number {\n return Math.max(1, getConcurrencyLimits().reservedSwarmSlots);\n}\n\nfunction defaultGetIssueHold(issueId: string): Pick<ReviewStatus, 'stuck' | 'deaconIgnored' | 'stuckReason'> | null {\n try {\n return getReviewStatusSync(issueId);\n } catch {\n return null;\n }\n}\n\nfunction defaultReadStatusOverrides(workspacePath: string, issueId: string): Record<string, string> | undefined {\n // PAN-2372 WI-4 / FR-7: distinguish an absent record (silent undefined — a\n // brand-new issue that simply has no overrides yet) from an UNREADABLE record\n // (the file exists but won't parse). readIssueRecordForWorkspaceSync returns\n // null for both, so the existsSync check is what separates them. A corrupt\n // record is preserved as a .corrupt-<ts> sidecar by the atomic writer (WI-1);\n // warn so a broken sidecar never silently masks a slot's done-ness.\n const normalized = issueId.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalized);\n if (record === null && existsSync(getIssueRecordPathForWorkspace(workspacePath, normalized))) {\n console.warn(`[swarm] record unreadable for ${normalized} — treating as no overrides; see .corrupt sidecar`);\n return undefined;\n }\n return record?.statusOverrides;\n}\n\n/**\n * PAN-2372 WI-4 / FR-6: read a slot's durable completion marker from the record\n * door. Returns undefined when no record or no marker exists. Used by\n * classifyInFlightSlots to recognize a slot whose `pan done` durably recorded\n * completion even when the runtime plane (agent state, tmux session) is gone.\n */\nfunction defaultReadSlotCompletion(\n workspacePath: string,\n issueId: string,\n slotIndex: number,\n): PanIssueSwarmSlotCompletion | undefined {\n try {\n return readIssueRecordForWorkspaceSync(workspacePath, issueId.toUpperCase())?.swarm?.slotCompletions?.[String(slotIndex)];\n } catch {\n return undefined;\n }\n}\n\nfunction defaultShouldDispatch(issueId: string): boolean {\n if (isDeaconGloballyPausedSync()) return false;\n const hold = defaultGetIssueHold(issueId);\n return !(hold?.stuck || hold?.deaconIgnored);\n}\n\nexport type SwarmSlotLifecycle = 'running' | 'ready-to-merge' | 'failed' | 'stalled' | 'awaiting-completion-signal' | 'failed-merge-blocked';\n\nexport interface ClassifyInFlightSlotsOptions {\n workspacePath?: string;\n issueId?: string;\n inferCompletion?: SwarmInferCompletionMode;\n stallThresholdMs?: number;\n now?: number;\n}\n\nexport interface ClassifiedSwarmSlot extends ReconciledSlotItem {\n lifecycle: SwarmSlotLifecycle;\n exitStatus?: number | null;\n reason?: 'missing-agent' | 'vanished-session' | 'pane-exit-nonzero' | 'pane-exit-unknown' | 'no-progress-timeout';\n stalledForMs?: number;\n signal?: 'inferred' | 'completion-nudge' | 'durable-completion';\n actions?: string[];\n}\n\ninterface SlotProgressObservation {\n commitTime: number | null;\n outputDigest: string;\n lastProgressAt: number;\n}\n\ninterface SlotAssignment {\n slotIndex: number;\n itemId: string;\n agentId?: string;\n branch?: string;\n}\n\ntype SlotAssignments = NonNullable<NonNullable<PanIssueRecord['swarm']>['slotAssignments']>;\n\nexport async function coordinateSwarmSlots(\n opts: CoordinateSwarmSlotsOptions = {},\n deps: CoordinateSwarmSlotsDeps = defaultDeps,\n): Promise<string[]> {\n const actions: string[] = [];\n const filterIssueId = opts.issueId?.toUpperCase();\n\n for (const workspace of deps.listFeatureWorkspaces()) {\n const issueId = workspace.issueId.toUpperCase();\n if (filterIssueId && issueId !== filterIssueId) continue;\n const hold = (deps.getIssueHold ?? defaultGetIssueHold)(issueId);\n if (hold?.deaconIgnored) {\n actions.push(`[swarm] skipped ${issueId}: deacon-ignored — operator hold`);\n continue;\n }\n // PAN-2469: `stuck` is a SYSTEM-set failure marker (delivery/verification\n // trouble), not an operator hold — skipping coordination on it froze the\n // whole swarm forever: PAN-2388's slots sat ready-to-merge for hours while\n // the coordinator skipped the issue because the verification-gate deadlock\n // (PAN-2461) had marked it stuck. Coordination (merge/gc/endgame) continues\n // through system-stuck; only operator deacon-ignore fully halts it.\n if (hold?.stuck) {\n actions.push(`[swarm] ${issueId} is system-stuck (${hold.stuckReason ?? 'unknown'}) — coordinating anyway (stuck no longer halts assembly, PAN-2469)`);\n }\n if (isSwarmAdvanceCoolingDown(issueId)) {\n actions.push(`[swarm] deferred ${issueId}: advance backoff active`);\n continue;\n }\n const failedMergeBlocks = getFailedMergeBlocks(issueId, workspace.workspacePath);\n const blockedSlotIndexes = new Set(failedMergeBlocks.map(block => block.slotIndex));\n const blockedItemIds = new Set(failedMergeBlocks.map(block => block.itemId));\n if (failedMergeBlocks.length > 0) {\n const slots = failedMergeBlocks\n .map(block => `slot ${block.slotIndex} (item ${block.itemId})`)\n .join(', ');\n actions.push(`[swarm] blocked slots for ${issueId}: ${slots} — other slots continue; run \\`pan swarm recover ${issueId} <slot>\\``);\n }\n\n try {\n const spec = await Effect.runPromise(findSpecByIssue(workspace.projectPath, issueId));\n if (!spec) continue;\n const planStatus = spec.document.plan.status;\n if (planStatus === 'completed' || planStatus === 'cancelled') continue;\n\n // Coordinate against the merged plan view; slot done-ness lives in statusOverrides.\n const overrides = (deps.readStatusOverrides ?? defaultReadStatusOverrides)(workspace.workspacePath, issueId);\n const doc = overrides && Object.keys(overrides).length > 0\n ? applyStatusOverrides(spec.document, overrides)\n : spec.document;\n\n const readiness = analyzeSwarmReadiness(doc);\n const slotEligibleCount = readiness.items.filter(item => item.slotEligible).length;\n // Eligibility gates dispatch only; active swarms still need merge/gc/endgame passes.\n const swarmInProgress = Object.entries(overrides ?? {})\n .some(([key, value]) => !key.includes('.') && value === 'completed');\n const dispatchEligible = readiness.swarmEligible && (slotEligibleCount >= 2 || swarmInProgress);\n if (dispatchEligible) {\n actions.push(`[swarm] considered ${issueId}: swarm eligible`);\n }\n\n const reconciled = await deps.reconcileSlotState(issueId, workspace.workspacePath, doc);\n if (!dispatchEligible) {\n const hasSlotState = reconciled.merged.length > 0 || reconciled.inFlight.length > 0\n || reconciled.branches.length > 0 || reconciled.agents.length > 0;\n if (!hasSlotState) {\n actions.push(...await finalizeSwarmIssueIfComplete(issueId, workspace.workspacePath, doc, deps));\n continue;\n }\n actions.push(`[swarm] considered ${issueId}: endgame (merge/cleanup only)`);\n }\n const classified = await classifyInFlightSlots(reconciled.inFlight, deps, {\n workspacePath: workspace.workspacePath,\n issueId,\n inferCompletion: swarmInferCompletionMode(),\n });\n for (const slot of classified) {\n actions.push(`[swarm] ${issueId} slot ${slot.slotIndex} ${slot.lifecycle}${slot.signal ? ` signal: ${slot.signal}` : ''}`);\n if (slot.actions) actions.push(...slot.actions);\n }\n const requeue = await requeueFailedSwarmSlots(issueId, workspace.workspacePath, classified, doc, reconciled, deps, blockedSlotIndexes);\n actions.push(...requeue.actions);\n actions.push(...recordStalledSlotRecovery(issueId, classified, workspace.workspacePath)); // stalled slots remain operator-recoverable\n actions.push(...await mergeReadySlots(issueId, workspace.workspacePath, doc, classified, deps, blockedSlotIndexes));\n actions.push(...await gcMergedSlots(issueId, workspace.workspacePath, reconciled.merged, deps));\n actions.push(...await gcOrphanedSlots(issueId, workspace.workspacePath, reconciled, deps));\n actions.push(...await finalizeSwarmIssueIfComplete(issueId, workspace.workspacePath, spec.document, deps));\n if (dispatchEligible) {\n actions.push(...await dispatchNextWave(issueId, workspace.workspacePath, requeue.doc, reconciled, analyzeSwarmReadiness(requeue.doc), deps, blockedSlotIndexes, blockedItemIds));\n }\n recordSwarmAdvanceSuccess(issueId);\n } catch (err) {\n recordSwarmAdvanceFailure(issueId);\n console.warn(`[deacon] Error coordinating swarm ${issueId}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return actions;\n}\n\nexport async function classifyInFlightSlots(\n slots: ReconciledSlotItem[],\n deps: Pick<CoordinateSwarmSlotsDeps, 'listSessionNames' | 'isPaneDead' | 'getPaneExitStatus'>\n & Partial<Pick<\n CoordinateSwarmSlotsDeps,\n 'getAgentRuntimeState'\n | 'getPaneOutputDigest'\n | 'getBranchTipCommitTime'\n | 'getSlotBranchAheadCount'\n | 'isSlotWorktreeClean'\n | 'sendCompletionNudge'\n | 'readSlotCompletion'\n >> = defaultDeps,\n options: ClassifyInFlightSlotsOptions = {},\n): Promise<ClassifiedSwarmSlot[]> {\n const sessionNames = new Set(await deps.listSessionNames());\n const classified: ClassifiedSwarmSlot[] = [];\n const now = options.now ?? Date.now();\n const stallThresholdMs = options.stallThresholdMs ?? swarmStallThresholdMs();\n\n for (const slot of slots) {\n // PAN-2372 WI-4 / FR-6: a durable completion marker (written by slot\n // `pan done`) is the STRONGEST completion signal — it is the durable record\n // that the slot finished, so it beats a vanished session, a missing agent,\n // and the rebuildable runtime plane. Check it before everything else. The\n // itemId guard (AC2) ignores a stale marker left for a slot now bound to a\n // different item (e.g. after a re-plan rotated slot→item).\n if (options.workspacePath && options.issueId) {\n const completion = await (deps.readSlotCompletion ?? defaultReadSlotCompletion)(\n options.workspacePath,\n options.issueId,\n slot.slotIndex,\n );\n if (completion && (!completion.itemId || completion.itemId === slot.itemId)) {\n classified.push({ ...slot, lifecycle: 'ready-to-merge', exitStatus: 0, signal: 'durable-completion' });\n continue;\n }\n }\n\n const durableReady = await classifyDurableReadySlot(slot, deps, options);\n if (!slot.agentId) {\n if (durableReady) {\n classified.push(durableReady);\n continue;\n }\n classified.push({ ...slot, lifecycle: 'failed', reason: 'missing-agent' });\n continue;\n }\n\n const runtimeState = deps.getAgentRuntimeState ? await deps.getAgentRuntimeState(slot.agentId) : null;\n if (runtimeState?.resolution === 'done' || runtimeState?.resolution === 'completed') {\n classified.push({ ...slot, lifecycle: 'ready-to-merge', exitStatus: 0 });\n continue;\n }\n\n if (!sessionNames.has(slot.agentId)) {\n if (durableReady) {\n classified.push(durableReady);\n continue;\n }\n classified.push({ ...slot, lifecycle: 'failed', reason: 'vanished-session' });\n continue;\n }\n\n const dead = await deps.isPaneDead(slot.agentId);\n if (!dead) {\n const outputDigest = deps.getPaneOutputDigest\n ? await deps.getPaneOutputDigest(slot.agentId).catch(() => '')\n : '';\n const commitTime = slot.branch && options.workspacePath && deps.getBranchTipCommitTime\n ? await deps.getBranchTipCommitTime(options.workspacePath, slot.branch).catch(() => null)\n : null;\n const progressKey = slotProgressKey(slot);\n const previous = slotProgressObservations.get(progressKey);\n if (\n !previous\n || previous.commitTime !== commitTime\n || previous.outputDigest !== outputDigest\n ) {\n slotProgressObservations.set(progressKey, { commitTime, outputDigest, lastProgressAt: now });\n clearSwarmCompletionObservation(progressKey);\n classified.push({ ...slot, lifecycle: 'running' });\n continue;\n }\n\n const stalledForMs = now - previous.lastProgressAt;\n if (stalledForMs > stallThresholdMs) {\n const inferred = await classifyDoneWithoutSignal(slot, deps, options, {\n commitTime,\n outputDigest,\n progressKey,\n stalledForMs,\n });\n if (inferred) {\n classified.push(inferred);\n continue;\n }\n\n classified.push({\n ...slot,\n lifecycle: 'stalled',\n reason: 'no-progress-timeout',\n stalledForMs,\n });\n continue;\n }\n\n classified.push({ ...slot, lifecycle: 'running' });\n continue;\n }\n\n const exitStatus = await deps.getPaneExitStatus(slot.agentId);\n if (exitStatus === 0) {\n classified.push({ ...slot, lifecycle: 'ready-to-merge', exitStatus });\n continue;\n }\n\n classified.push({\n ...slot,\n lifecycle: 'failed',\n exitStatus,\n reason: exitStatus === null ? 'pane-exit-unknown' : 'pane-exit-nonzero',\n });\n }\n\n return classified;\n}\n\nfunction slotProgressKey(slot: ReconciledSlotItem): string {\n return slot.agentId ?? slot.branch ?? `${slot.itemId}:${slot.slotIndex}`;\n}\n\nfunction swarmStallThresholdMs(): number {\n const raw = process.env.PAN_SWARM_STALL_THRESHOLD_MS;\n if (!raw) return DEFAULT_SWARM_STALL_THRESHOLD_MS;\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_SWARM_STALL_THRESHOLD_MS;\n}\n\nexport async function mergeReadySlots(\n issueId: string,\n workspacePath: string,\n doc: VBriefDocument,\n slots: ClassifiedSwarmSlot[],\n deps: Pick<CoordinateSwarmSlotsDeps, 'verifyAndMergeSlot' | 'applyTaskOperationToPlanFile' | 'fireTieredCommitHooks'> = defaultDeps,\n blockedSlotIndexes: Set<number> = new Set(),\n): Promise<string[]> {\n const actions: string[] = [];\n const itemsById = new Map(doc.plan.items.map(item => [item.id, item]));\n const planPath = join(workspacePath, '.pan', 'spec.vbrief.json');\n\n for (const slot of slots) {\n if (slot.lifecycle !== 'ready-to-merge') continue;\n\n if (blockedSlotIndexes.has(slot.slotIndex)) {\n actions.push(`[swarm] skipped merge slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: failed-merge block — awaiting \\`pan swarm recover\\``);\n continue;\n }\n\n const item = itemsById.get(slot.itemId);\n if (!item) {\n // PAN-2469: this skip was silent — a slot whose itemId drifted from the\n // current spec (e.g. after a re-plan) sat ready-to-merge forever with no\n // trace. Say so every pass.\n actions.push(`[swarm] cannot merge slot ${slot.slotIndex} for ${issueId}: itemId \"${slot.itemId}\" not in the current plan (spec drift?) — needs operator attention`);\n continue;\n }\n\n const branchKey = slot.branch ?? `feature/${issueId.toLowerCase()}-slot-${slot.slotIndex}`;\n if (isSlotMergeCoolingDown(branchKey)) {\n actions.push(`[swarm] skipped merge slot ${slot.slotIndex} (item ${item.id}) for ${issueId}: refire cooldown`);\n continue;\n }\n\n recordSlotMergeFire(branchKey);\n const result = await deps.verifyAndMergeSlot({ issueId, featureWorkspace: workspacePath }, slot.slotIndex, item);\n if (result.merged) {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'done',\n itemId: item.id,\n writerId: 'deacon-swarm',\n }, workspacePath);\n // PAN-2372 WI-4 / FR-6: the durable marker has done its job — the slot is\n // merged. Clear it so the same slotIndex can be re-dispatched later without\n // a stale \"completed\" marker falsely surfacing as ready-to-merge.\n clearSwarmSlotCompletion(workspacePath, issueId, slot.slotIndex);\n actions.push(`[swarm] merged slot ${slot.slotIndex} (item ${item.id}) for ${issueId}`);\n // PAN-2385: commits just landed — fire the tiered feed + supervisor review (best-effort).\n try {\n actions.push(...await deps.fireTieredCommitHooks({ issueId, workspacePath, item, doc }));\n } catch (err) {\n actions.push(`[tiered] commit hooks threw for ${issueId} item ${item.id}: ${err instanceof Error ? err.message : String(err)}`);\n }\n continue;\n }\n\n if (result.conflicts) {\n recordFailedMergeBlock({\n issueId,\n itemId: item.id,\n slotIndex: slot.slotIndex,\n branch: slot.branch,\n note: `Slot branch ${slot.branch ?? slot.slotIndex} did not merge cleanly`,\n }, workspacePath);\n actions.push(`[swarm] failed-merge slot ${slot.slotIndex} (item ${item.id}) for ${issueId}`);\n continue;\n }\n\n // Verification failure (merged result fails typecheck/tests) previously\n // fell through with no action at all — the slot silently re-verified on\n // every pass with nobody told why. Surface the failure so the operator\n // or recovery machinery can act on it.\n actions.push(`[swarm] verify-failed slot ${slot.slotIndex} (item ${item.id}) for ${issueId}: ${result.failure ?? 'verification failed'}`);\n }\n\n return actions;\n}\n\nexport function resetSwarmLoopSafetyForTests(): void {\n recentSlotMergeFires.clear();\n issueAdvanceFailures.clear();\n failedMergeBlocks.clear();\n slotProgressObservations.clear();\n resetSwarmCompletionInferenceForTests();\n}\n\nexport function recordSwarmAdvanceFailure(issueId: string, now = Date.now()): void {\n const normalized = issueId.toUpperCase();\n const previous = issueAdvanceFailures.get(normalized);\n const count = (previous?.count ?? 0) + 1;\n issueAdvanceFailures.set(normalized, {\n count,\n cooldownUntil: count >= SWARM_ADVANCE_FAILURE_THRESHOLD\n ? now + SWARM_ADVANCE_FAILURE_COOLDOWN_MS\n : previous?.cooldownUntil ?? 0,\n });\n}\n\nexport function recordSwarmAdvanceSuccess(issueId: string): void {\n issueAdvanceFailures.delete(issueId.toUpperCase());\n}\n\nexport function isSwarmAdvanceCoolingDown(issueId: string, now = Date.now()): boolean {\n const record = issueAdvanceFailures.get(issueId.toUpperCase());\n return record !== undefined && record.cooldownUntil > now;\n}\n\nexport function getFailedMergeBlock(\n issueId: string,\n slotIndex: number,\n workspacePath?: string,\n): FailedMergeBlock | undefined {\n const normalized = issueId.toUpperCase();\n if (workspacePath) {\n const swarm = readIssueRecordForWorkspaceSync(workspacePath, normalized)?.swarm;\n const keyed = swarm?.failedMergeBlocks?.[String(slotIndex)];\n if (keyed) return { ...keyed, issueId: keyed.issueId.toUpperCase() };\n const legacy = swarm?.failedMergeBlock;\n if (legacy && legacy.slotIndex === slotIndex) {\n return { ...legacy, issueId: legacy.issueId.toUpperCase() };\n }\n }\n return failedMergeBlocks.get(`${normalized}:${slotIndex}`);\n}\n\nexport function getFailedMergeBlocks(issueId: string, workspacePath?: string): FailedMergeBlock[] {\n const normalized = issueId.toUpperCase();\n const bySlot = new Map<number, FailedMergeBlock>();\n\n if (workspacePath) {\n const swarm = readIssueRecordForWorkspaceSync(workspacePath, normalized)?.swarm;\n if (swarm?.failedMergeBlock) {\n const legacy = swarm.failedMergeBlock;\n bySlot.set(legacy.slotIndex, { ...legacy, issueId: legacy.issueId.toUpperCase() });\n }\n if (swarm?.failedMergeBlocks) {\n for (const [key, block] of Object.entries(swarm.failedMergeBlocks)) {\n bySlot.set(Number(key), { ...block, issueId: block.issueId.toUpperCase() });\n }\n }\n }\n\n for (const [key, block] of failedMergeBlocks.entries()) {\n if (key.startsWith(`${normalized}:`) && !bySlot.has(block.slotIndex)) {\n bySlot.set(block.slotIndex, { ...block });\n }\n }\n\n return [...bySlot.values()].sort((a, b) => a.slotIndex - b.slotIndex);\n}\n\nexport function getSwarmFinalizedAt(issueId: string, workspacePath?: string): string | undefined {\n return workspacePath ? readIssueRecordForWorkspaceSync(workspacePath, issueId.toUpperCase())?.swarm?.finalizedAt : undefined;\n}\n\nexport function recordSwarmFinalizedAt(issueId: string, workspacePath: string, finalizedAt: string): void {\n writeSwarmFinalizedAt(workspacePath, issueId.toUpperCase(), finalizedAt);\n}\n\nexport function recordFailedMergeBlock(block: FailedMergeBlock, workspacePath?: string): void {\n const normalizedBlock = { ...block, issueId: block.issueId.toUpperCase() };\n failedMergeBlocks.set(`${normalizedBlock.issueId}:${normalizedBlock.slotIndex}`, normalizedBlock);\n if (workspacePath) {\n writeSwarmFailedMergeBlock(workspacePath, normalizedBlock.issueId, normalizedBlock.slotIndex, normalizedBlock);\n }\n}\n\nexport function clearFailedMergeBlock(issueId: string, slotIndex: number, workspacePath?: string): void {\n const normalizedIssueId = issueId.toUpperCase();\n failedMergeBlocks.delete(`${normalizedIssueId}:${slotIndex}`);\n if (workspacePath) {\n writeSwarmFailedMergeBlock(workspacePath, normalizedIssueId, slotIndex, undefined);\n }\n}\n\nexport async function recoverFailedMergeSlot(\n issueId: string,\n workspacePath: string,\n slotIndex: number,\n doc: VBriefDocument,\n action: SwarmRecoveryAction,\n deps: Pick<\n CoordinateSwarmSlotsDeps,\n 'applyTaskOperationToPlanFile'\n | 'clearSlotAssignment'\n | 'recordSlotAssignment'\n | 'registeredSlotCapacityAvailable'\n | 'tryReserveSwarmSlot'\n | 'releaseSwarmSlot'\n | 'spawnRun'\n | 'shouldDispatch'\n | 'getMaxSlotIndex'\n | 'listSlotAssignments'\n | 'runGitCommand'\n > = defaultDeps,\n): Promise<string[]> {\n const normalizedIssueId = issueId.toUpperCase();\n const block = getFailedMergeBlock(normalizedIssueId, slotIndex, workspacePath);\n if (!block) {\n const otherBlocks = getFailedMergeBlocks(normalizedIssueId, workspacePath);\n if (otherBlocks.length === 0) {\n return [`[swarm] no failed-merge slot for ${normalizedIssueId}`];\n }\n const lines = otherBlocks\n .map(b => ` slot ${b.slotIndex} (item ${b.itemId}): ${b.note}`)\n .join('\\n');\n return [\n `[swarm] no failed-merge block for ${normalizedIssueId} slot ${slotIndex}. Currently blocked slots:\\n${lines}`,\n ];\n }\n\n const planPath = join(workspacePath, '.pan', 'spec.vbrief.json');\n if (action === 'handoff') {\n block.note = `Operator handoff required for slot ${block.slotIndex} (item ${block.itemId})`;\n recordFailedMergeBlock(block, workspacePath);\n return [`[swarm] handoff paused ${normalizedIssueId} slot ${block.slotIndex} (item ${block.itemId})`];\n }\n\n if (action === 'drop') {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'done',\n itemId: block.itemId,\n writerId: 'deacon-swarm',\n reason: 'Dropped failed swarm slot after operator recovery',\n }, workspacePath);\n clearFailedMergeBlock(normalizedIssueId, block.slotIndex, workspacePath);\n deps.clearSlotAssignment(workspacePath, normalizedIssueId, block.slotIndex, block.itemId);\n return [`[swarm] dropped failed-merge slot ${block.slotIndex} (item ${block.itemId}) for ${normalizedIssueId}`];\n }\n\n // retry: archive the conflicted attempt so it cannot re-assert, then unblock\n // and dispatch a fresh attempt.\n await archiveFailedSwarmSlot(\n normalizedIssueId,\n workspacePath,\n {\n itemId: block.itemId,\n slotIndex: block.slotIndex,\n status: 'in_flight',\n branch: block.branch,\n agentId: block.branch ? `agent-${normalizedIssueId.toLowerCase()}-slot-${block.slotIndex}` : undefined,\n },\n { runGitCommand: deps.runGitCommand, clearSlotAssignment: deps.clearSlotAssignment },\n );\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'unblock',\n itemId: block.itemId,\n writerId: 'deacon-swarm',\n reason: 'Retrying failed swarm slot after merge conflict',\n }, workspacePath);\n clearFailedMergeBlock(normalizedIssueId, block.slotIndex, workspacePath);\n const remainingBlocks = getFailedMergeBlocks(normalizedIssueId, workspacePath);\n const blockedSlotIndexes = new Set(remainingBlocks.map(b => b.slotIndex));\n const blockedItemIds = new Set(remainingBlocks.map(b => b.itemId));\n const retryDoc = {\n ...doc,\n plan: {\n ...doc.plan,\n items: doc.plan.items.map(item =>\n item.id === block.itemId ? { ...item, status: 'pending' as const } : item\n ),\n },\n };\n return [\n `[swarm] retrying failed-merge slot ${block.slotIndex} (item ${block.itemId}) for ${normalizedIssueId}`,\n ...await dispatchNextWave(normalizedIssueId, workspacePath, retryDoc, {\n issueId: normalizedIssueId,\n merged: [],\n inFlight: [],\n pending: [],\n branches: [],\n agents: [],\n }, analyzeSwarmReadiness(retryDoc), deps, blockedSlotIndexes, blockedItemIds),\n ];\n}\n\nexport function recordStalledSlotRecovery(issueId: string, slots: ClassifiedSwarmSlot[], workspacePath?: string): string[] {\n const actions: string[] = [];\n const normalizedIssueId = issueId.toUpperCase();\n\n for (const slot of slots.filter(s => s.lifecycle === 'stalled')) {\n if (getFailedMergeBlock(normalizedIssueId, slot.slotIndex, workspacePath)) continue;\n\n recordFailedMergeBlock({\n issueId: normalizedIssueId,\n itemId: slot.itemId,\n slotIndex: slot.slotIndex,\n branch: slot.branch,\n note: `Slot ${slot.slotIndex} stalled with no branch commit or pane output progress`,\n }, workspacePath);\n actions.push(`[swarm] stalled slot ${slot.slotIndex} (item ${slot.itemId}) for ${normalizedIssueId}: recovery required`);\n }\n\n return actions;\n}\n\nfunction writeSwarmFailedMergeBlock(\n workspacePath: string,\n issueId: string,\n slotIndex: number,\n block: FailedMergeBlock | undefined,\n): void {\n const normalizedIssueId = issueId.toUpperCase();\n const existing = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId);\n const record = existing ?? createMinimalIssueRecord(normalizedIssueId);\n const existingSwarm = record.swarm ?? {};\n const existingBlocks = existingSwarm.failedMergeBlocks ?? {};\n\n // PAN-2364: fold a legacy singular block into the per-slot map and clear the\n // singular field on first write to the new keyed storage.\n const foldedBlocks: Record<string, PanIssueSwarmFailedMergeBlock> = { ...existingBlocks };\n if (existingSwarm.failedMergeBlock) {\n foldedBlocks[String(existingSwarm.failedMergeBlock.slotIndex)] = existingSwarm.failedMergeBlock;\n }\n\n const nextBlocks = { ...foldedBlocks };\n if (block) {\n nextBlocks[String(slotIndex)] = block;\n } else {\n delete nextBlocks[String(slotIndex)];\n }\n\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...existingSwarm,\n failedMergeBlocks: nextBlocks,\n failedMergeBlock: undefined,\n },\n });\n}\n\nfunction recordSlotMergeFire(branchKey: string, now = Date.now()): void {\n recentSlotMergeFires.set(branchKey, now + SLOT_MERGE_REFIRE_COOLDOWN_MS);\n}\n\nfunction isSlotMergeCoolingDown(branchKey: string, now = Date.now()): boolean {\n const until = recentSlotMergeFires.get(branchKey);\n if (until === undefined) return false;\n if (until > now) return true;\n recentSlotMergeFires.delete(branchKey);\n return false;\n}\n\nexport async function dispatchNextWave(\n issueId: string,\n workspacePath: string,\n doc: VBriefDocument,\n reconciled: SlotReconcileResult,\n readiness: SwarmReadinessVerdict,\n deps: Pick<\n CoordinateSwarmSlotsDeps,\n 'registeredSlotCapacityAvailable'\n | 'tryReserveSwarmSlot'\n | 'releaseSwarmSlot'\n | 'applyTaskOperationToPlanFile'\n | 'recordSlotAssignment'\n | 'clearSlotAssignment'\n | 'spawnRun'\n | 'shouldDispatch'\n | 'getMaxSlotIndex'\n | 'listSlotAssignments'\n > & Partial<Pick<CoordinateSwarmSlotsDeps, 'listSessionNames' | 'slotWorktreeExists'>> = defaultDeps,\n blockedSlotIndexes: Set<number> = new Set(),\n blockedItemIds: Set<string> = new Set(),\n): Promise<string[]> {\n const actions: string[] = [];\n const mergedItemIds = new Set(reconciled.merged.map(slot => slot.itemId));\n const slotEligibleIds = new Set(readiness.items.filter(item => item.slotEligible).map(item => item.id));\n const configuredMaxSlotIndex = Math.max(1, Math.floor((deps.getMaxSlotIndex ?? defaultGetMaxSlotIndex)()));\n const occupiedSlotIndexes = new Set([\n ...blockedSlotIndexes, // PAN-2364: blocked slots count as occupied so other slots cannot collide with them\n ...reconciled.inFlight.map(slot => slot.slotIndex),\n // Local branches hold their index until GC; archived indexes are added below.\n ...reconciled.branches.map(branch => branch.slotIndex),\n ...reconciled.agents.map(agent => agent.slotIndex),\n ...(deps.listSlotAssignments ?? listDurableSlotAssignments)(issueId, workspacePath).map(assignment => assignment.slotIndex),\n ...(reconciled.superseded ?? []).map(attempt => attempt.slotIndex),\n ]);\n const maxSlotIndex = applySupersededSlotHighWater(occupiedSlotIndexes, reconciled, configuredMaxSlotIndex);\n // Orphaned on-disk worktrees still occupy their index (PAN-2213).\n if (deps.slotWorktreeExists) {\n for (let index = 1; index <= maxSlotIndex; index++) {\n if (!occupiedSlotIndexes.has(index) && deps.slotWorktreeExists(`${workspacePath}-slot-${index}`)) {\n occupiedSlotIndexes.add(index);\n }\n }\n }\n const sessionNames = deps.listSessionNames ? await deps.listSessionNames() : [];\n const inFlightItemIds = new Set(reconciled.inFlight.map(slot => slot.itemId));\n const selectedItemIds: string[] = [];\n const planPath = join(workspacePath, '.pan', 'spec.vbrief.json');\n\n for (const item of getDispatchableItems(doc, mergedItemIds)) {\n if (blockedItemIds.has(item.id)) continue;\n if (!slotEligibleIds.has(item.id)) continue;\n if (inFlightItemIds.has(item.id)) continue;\n\n const overlapItemId = firstOverlappingItemId(item.id, [...inFlightItemIds, ...selectedItemIds], readiness);\n if (overlapItemId) {\n actions.push(`[swarm] deferred ${item.id} for ${issueId}: files_scope overlaps ${overlapItemId}`);\n continue;\n }\n\n if (!deps.registeredSlotCapacityAvailable(issueId, selectedItemIds.length)) {\n actions.push(`[swarm] deferred ${item.id} for ${issueId}: registered slot cap reached`);\n continue;\n }\n\n let slotIndex: number | null = null;\n for (;;) {\n const candidate = allocateSlotIndex(occupiedSlotIndexes, maxSlotIndex);\n if (candidate === null) break;\n const conflict = slotIndexConflictReason(issueId, workspacePath, candidate, sessionNames, reconciled, deps);\n if (!conflict) {\n slotIndex = candidate;\n break;\n }\n // An index-level conflict the registry missed (live session, unmerged\n // branch, orphaned worktree) means the index is occupied — advance to\n // the next free index instead of refusing the item (PAN-2213).\n occupiedSlotIndexes.add(candidate);\n actions.push(`[swarm] slot ${candidate} occupied for ${issueId}: ${conflict} — advancing`);\n }\n if (slotIndex === null) {\n const occupying = [...occupiedSlotIndexes].filter(index => index >= 1 && index <= maxSlotIndex).sort((a, b) => a - b);\n actions.push(\n `[swarm] deferred ${item.id} for ${issueId}: all slot indexes 1..${maxSlotIndex} are occupied (slots ${occupying.join(', ')})`\n + ` — run \\`pan swarm reset ${issueId}\\` if these slots are orphans`,\n );\n break;\n }\n\n if (!deps.tryReserveSwarmSlot()) {\n actions.push(`[swarm] deferred ${item.id} for ${issueId}: swarm dispatch budget exhausted`);\n continue;\n }\n\n try {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'claim',\n itemId: item.id,\n writerId: 'deacon-swarm',\n }, workspacePath);\n deps.recordSlotAssignment(workspacePath, issueId, {\n slotIndex,\n itemId: item.id,\n agentId: `agent-${issueId.toLowerCase()}-slot-${slotIndex}`,\n branch: `feature/${issueId.toLowerCase()}-slot-${slotIndex}`,\n });\n // Freeze/hold can activate mid-wave; the cycle-start gate has already passed\n // by then, so re-check before every spawn (PAN-2214 slot-20 regression).\n if (!(deps.shouldDispatch ?? defaultShouldDispatch)(issueId)) {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'unblock',\n itemId: item.id,\n writerId: 'deacon-swarm',\n reason: 'dispatch halted: freeze/hold active',\n }, workspacePath).catch(() => undefined);\n deps.clearSlotAssignment(workspacePath, issueId, slotIndex, item.id);\n deps.releaseSwarmSlot();\n actions.push(`[swarm] dispatch-halted ${item.id}: freeze/hold active`);\n continue;\n }\n await deps.spawnRun(issueId, 'work', {\n workspace: workspacePath,\n slotIndex,\n slotItemId: item.id,\n prompt: promptForDispatchItem(issueId, doc, item),\n });\n occupiedSlotIndexes.add(slotIndex);\n selectedItemIds.push(item.id);\n actions.push(`[swarm] dispatched ${dispatchPhaseForItem(doc, item)} slot ${slotIndex} (item ${item.id}) for ${issueId}`);\n } catch (error) {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'unblock',\n itemId: item.id,\n writerId: 'deacon-swarm',\n reason: `slot dispatch failed: ${error instanceof Error ? error.message : String(error)}`,\n }, workspacePath).catch(() => undefined);\n deps.clearSlotAssignment(workspacePath, issueId, slotIndex, item.id);\n deps.releaseSwarmSlot();\n actions.push(`[swarm] failed-dispatch ${item.id} for ${issueId}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n return actions;\n}\n\nfunction recordSlotAssignment(workspacePath: string, issueId: string, assignment: SlotAssignment): void {\n writeSwarmSlotAssignments(workspacePath, issueId, (existing) => [\n ...existing.filter(slot => slot.slotIndex !== assignment.slotIndex && slot.itemId !== assignment.itemId),\n {\n ...assignment,\n assignedAt: new Date().toISOString(),\n },\n ]);\n}\n\n/** Drop every recorded slot assignment for the issue — used by `pan swarm reset` (PAN-2214). */\nexport function clearAllSlotAssignments(workspacePath: string, issueId: string): void {\n writeSwarmSlotAssignments(workspacePath, issueId, () => []);\n}\n\nfunction clearSlotAssignment(workspacePath: string, issueId: string, slotIndex: number, itemId?: string): void {\n writeSwarmSlotAssignments(workspacePath, issueId, (existing) =>\n existing.filter(slot => slot.slotIndex !== slotIndex && (itemId === undefined || slot.itemId !== itemId))\n );\n}\n\nfunction writeSwarmSlotAssignments(\n workspacePath: string,\n issueId: string,\n update: (existing: SlotAssignments) => SlotAssignments,\n): void {\n const normalizedIssueId = issueId.toUpperCase();\n const existing = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId);\n const record = existing ?? createMinimalIssueRecord(normalizedIssueId);\n const existingAssignments: SlotAssignments = record.swarm?.slotAssignments ?? [];\n const slotAssignments = update(existingAssignments)\n .filter(assignment => Number.isInteger(assignment.slotIndex) && assignment.slotIndex > 0 && assignment.itemId.trim().length > 0)\n .sort((a, b) => a.slotIndex - b.slotIndex);\n\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...(record.swarm ?? {}),\n slotAssignments,\n },\n });\n}\n\nfunction slotIndexConflictReason(\n issueId: string,\n workspacePath: string,\n slotIndex: number,\n sessionNames: readonly string[],\n reconciled: SlotReconcileResult,\n deps: Partial<Pick<CoordinateSwarmSlotsDeps, 'slotWorktreeExists'>>,\n): string | undefined {\n const issueLower = issueId.toLowerCase();\n const agentId = `agent-${issueLower}-slot-${slotIndex}`;\n const branch = `feature/${issueLower}-slot-${slotIndex}`;\n if (sessionNames.includes(agentId)) {\n return `live ${agentId} session already exists`;\n }\n\n const unmergedBranch = reconciled.branches.find(slotBranch =>\n slotBranch.slotIndex === slotIndex && slotBranch.branch === branch && !slotBranch.merged\n );\n if (unmergedBranch) {\n return `unmerged ${branch} branch already exists`;\n }\n\n const slotWorkspacePath = `${workspacePath}-slot-${slotIndex}`;\n if (deps.slotWorktreeExists?.(slotWorkspacePath)) {\n return `slot worktree already exists at ${slotWorkspacePath}`;\n }\n\n return undefined;\n}\n\nfunction dispatchPhaseForItem(doc: VBriefDocument, item: VBriefItem): 'implementation' | 'synthesis' {\n return itemRequiresSynthesis(doc, item) && !synthesisContextForItem(item) ? 'synthesis' : 'implementation';\n}\n\nfunction promptForDispatchItem(issueId: string, doc: VBriefDocument, item: VBriefItem): string | undefined {\n if (!itemRequiresSynthesis(doc, item)) return undefined;\n\n const synthesisContext = synthesisContextForItem(item);\n if (synthesisContext) {\n return createActiveSlice(doc, {\n issueId,\n itemId: item.id,\n currentItemIds: [item.id],\n synthesisOutputs: { [item.id]: { contextUpdate: synthesisContext } },\n }).prompt;\n }\n\n const parentIds = doc.plan.edges\n .filter(edge => edge.type === 'blocks' && edge.to === item.id)\n .map(edge => edge.from);\n\n return [\n `SYNTHESIS PHASE for ${item.id}`,\n '',\n 'Do not implement this item yet. Summarize the blocking parent outputs into a concise context update for the implementation slot.',\n `Blocking parents: ${parentIds.join(', ') || '(none)'}`,\n '',\n 'Persist the synthesis context on the vBRIEF item metadata as synthesisContext, commit it, then stop.',\n ].join('\\n');\n}\n\nfunction itemRequiresSynthesis(doc: VBriefDocument, item: VBriefItem): boolean {\n return item.metadata?.requiresSynthesis === true || blockingParentCount(doc, item.id) > 1;\n}\n\nfunction synthesisContextForItem(item: VBriefItem): string | undefined {\n const raw = item.metadata?.synthesisContext;\n return typeof raw === 'string' && raw.trim().length > 0 ? raw : undefined;\n}\n\n/**\n * Lowest free slot index within the bound, derived purely from the occupied\n * set. Returns null — never an index above the bound — when indexes 1..bound\n * are all occupied (PAN-2214: unbounded allocation climbed slot-5..slot-20).\n */\nexport function allocateSlotIndex(occupiedSlotIndexes: ReadonlySet<number>, bound: number): number | null {\n const maxIndex = Math.max(1, Math.floor(bound));\n for (let slotIndex = 1; slotIndex <= maxIndex; slotIndex++) {\n if (!occupiedSlotIndexes.has(slotIndex)) return slotIndex;\n }\n return null;\n}\n\nfunction firstOverlappingItemId(\n itemId: string,\n activeItemIds: string[],\n readiness: SwarmReadinessVerdict,\n): string | undefined {\n for (const activeItemId of activeItemIds) {\n if ((readiness.overlapMatrix[itemId]?.[activeItemId]?.length ?? 0) > 0) return activeItemId;\n }\n return undefined;\n}\n\n/**\n * Whether the issue may register another slot. Counts only tmux-ALIVE slot\n * sessions (stale agents-table rows blocked all dispatch at zero live slots\n * after a reset), capped by the same swarm reserve tryReserveSwarmSlot\n * enforces — never maxWorkAgents (PAN-2214).\n */\nexport function registeredSlotCapacityAvailable(\n issueId: string,\n selectedCount: number,\n liveSlotCount: number = countRunningSwarmSlotsForIssue(issueId),\n limits: Pick<ConcurrencyLimits, 'reservedSwarmSlots'> = getConcurrencyLimits(),\n): boolean {\n return liveSlotCount + selectedCount < limits.reservedSwarmSlots;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"deacon-swarm-aMMJTq6t.js","names":["execAsync","listDurableSlotAssignments","execAsync","existsSync","execAsync","defaultDeps","loadYamlConfig","existsSync","join","existsSync","listTmuxSessionNames","existsSync","listDurableSlotAssignments"],"sources":["../../src/lib/agents/slot-merge.ts","../../src/lib/cloister/deacon-workspaces.ts","../../src/lib/cloister/deacon-swarm-orphan-gc.ts","../../src/lib/cloister/deacon-swarm-completion.ts","../../src/lib/cloister/deacon-swarm-finalization.ts","../../src/lib/cloister/deacon-swarm-gc.ts","../../src/lib/cloister/deacon-swarm-record.ts","../../src/lib/cloister/swarm-tiered-hooks.ts","../../src/lib/cloister/recovery-trip.ts","../../src/lib/cloister/redrive-gate.ts","../../src/lib/cloister/swarm-failed-slot.ts","../../src/lib/cloister/deacon-swarm.ts"],"sourcesContent":["import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { defaultRunWorkspace } from './spawn-prep.js';\nimport type { VBriefItem } from '../vbrief/types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface SlotMergeIssue {\n issueId: string;\n featureWorkspace?: string;\n}\n\nexport interface SlotMergeEvidence {\n verifyCommands: string[];\n expectedOutputs: string[];\n commandOutputs: Array<{ command: string; stdout: string; stderr: string }>;\n mergeOutput?: { stdout: string; stderr: string };\n}\n\nexport interface SlotMergeResult {\n verified: boolean;\n merged: boolean;\n conflicts: boolean;\n evidence: SlotMergeEvidence;\n failure?: string;\n}\n\nexport interface SlotMergeDeps {\n run: (command: string, cwd: string) => Promise<{ stdout: string; stderr: string }>;\n}\n\nexport interface SlotMergeOptions {\n deps?: Partial<SlotMergeDeps>;\n}\n\nexport async function verifyAndMergeSlot(\n issue: string | SlotMergeIssue,\n slotIndex: number,\n item: VBriefItem,\n options: SlotMergeOptions = {},\n): Promise<SlotMergeResult> {\n const issueId = typeof issue === 'string' ? issue : issue.issueId;\n const featureWorkspace = typeof issue === 'string'\n ? defaultRunWorkspace(issue)\n : issue.featureWorkspace ?? defaultRunWorkspace(issue.issueId);\n const slotWorkspace = `${featureWorkspace}-slot-${slotIndex}`;\n const slotBranch = `feature/${issueId.toLowerCase()}-slot-${slotIndex}`;\n const deps: SlotMergeDeps = {\n run: async (command, cwd) => execAsync(command, { cwd }),\n ...options.deps,\n };\n const verifyCommands = item.metadata?.verify_commands ?? [];\n const expectedOutputs = item.metadata?.expected_outputs ?? [];\n const evidence: SlotMergeEvidence = {\n verifyCommands,\n expectedOutputs,\n commandOutputs: [],\n };\n\n if (!Number.isInteger(slotIndex) || slotIndex < 1) {\n return { verified: false, merged: false, conflicts: false, evidence, failure: `Invalid slot index: ${slotIndex}` };\n }\n if (verifyCommands.length === 0) {\n return { verified: false, merged: false, conflicts: false, evidence, failure: `Item ${item.id} has no verify_commands` };\n }\n if (expectedOutputs.length === 0) {\n return { verified: false, merged: false, conflicts: false, evidence, failure: `Item ${item.id} has no expected_outputs` };\n }\n\n for (const command of verifyCommands) {\n try {\n const output = await deps.run(command, slotWorkspace);\n evidence.commandOutputs.push({ command, stdout: output.stdout, stderr: output.stderr });\n } catch (error) {\n const failed = commandFailure(error);\n evidence.commandOutputs.push({ command, stdout: failed.stdout, stderr: failed.stderr });\n return {\n verified: false,\n merged: false,\n conflicts: false,\n evidence,\n failure: `Verify command failed for ${item.id}: ${command}`,\n };\n }\n }\n\n try {\n const mergeOutput = await deps.run(`git merge --no-ff ${JSON.stringify(slotBranch)}`, featureWorkspace);\n evidence.mergeOutput = mergeOutput;\n return { verified: true, merged: true, conflicts: false, evidence };\n } catch (error) {\n const failed = commandFailure(error);\n evidence.mergeOutput = { stdout: failed.stdout, stderr: failed.stderr };\n await deps.run('git merge --abort', featureWorkspace).catch(() => {});\n return {\n verified: true,\n merged: false,\n conflicts: true,\n evidence,\n failure: `Slot branch ${slotBranch} did not merge cleanly`,\n };\n }\n}\n\nfunction commandFailure(error: unknown): { stdout: string; stderr: string } {\n const partial = error as { stdout?: unknown; stderr?: unknown; message?: unknown };\n return {\n stdout: typeof partial.stdout === 'string' ? partial.stdout : '',\n stderr: typeof partial.stderr === 'string'\n ? partial.stderr\n : typeof partial.message === 'string'\n ? partial.message\n : String(error),\n };\n}\n","import { existsSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { listProjectsSync } from '../projects.js';\n\nexport interface FeatureWorkspace {\n issueId: string;\n workspacePath: string;\n projectPath: string;\n}\n\nexport interface ListFeatureWorkspacesOptions {\n includeSlotWorkspaces?: boolean;\n}\n\nexport function listFeatureWorkspaces(options: ListFeatureWorkspacesOptions = {}): FeatureWorkspace[] {\n const includeSlotWorkspaces = options.includeSlotWorkspaces ?? true;\n const projects = listProjectsSync();\n const workspaces: FeatureWorkspace[] = [];\n\n for (const { config: projectConfig } of projects) {\n const workspacesRoot = join(projectConfig.path, 'workspaces');\n if (!existsSync(workspacesRoot)) continue;\n\n let entries: string[];\n try {\n entries = readdirSync(workspacesRoot, { withFileTypes: true })\n .filter(e => e.isDirectory() && e.name.startsWith('feature-'))\n .filter(e => includeSlotWorkspaces || !/-slot-\\d+$/.test(e.name))\n .map(e => e.name);\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n workspaces.push({\n issueId: entry.replace(/^feature-/, '').toUpperCase(),\n workspacePath: join(workspacesRoot, entry),\n projectPath: projectConfig.path,\n });\n }\n }\n\n return workspaces;\n}\n","import { listSlotAssignments as listDurableSlotAssignments, type SlotReconcileResult } from '../agents/slot-reconcile.js';\nimport type { CoordinateSwarmSlotsDeps } from './deacon-swarm.js';\n\ntype OrphanGcDeps = Pick<CoordinateSwarmSlotsDeps, 'runGitCommand' | 'listSessionNames' | 'listSlotAssignments'>;\n\n/**\n * Reconcile GC for truly-orphaned slots (PAN-2214, completes PAN-2213(c)).\n *\n * An orphan is a slot index with an on-disk worktree or a local slot branch but\n * no slotAssignments entry and no live agent tmux session. Zero-commit-ahead\n * orphans are removed; orphans with unmerged commits are only reported so the\n * operator can push them via `pan swarm reset` — never deleted.\n */\nexport async function gcOrphanedSlots(\n issueId: string,\n workspacePath: string,\n reconciled: SlotReconcileResult,\n deps: OrphanGcDeps,\n): Promise<string[]> {\n const actions: string[] = [];\n const issueLower = issueId.toLowerCase();\n\n const worktreeSlotIndexes = await listSlotWorktreeIndexes(workspacePath, deps.runGitCommand);\n const branchesBySlot = new Map(reconciled.branches.map(branch => [branch.slotIndex, branch.branch]));\n const candidateSlotIndexes = [...new Set([...worktreeSlotIndexes, ...branchesBySlot.keys()])].sort((a, b) => a - b);\n if (candidateSlotIndexes.length === 0) return actions;\n\n const ownedSlotIndexes = new Set([\n ...(deps.listSlotAssignments ?? listDurableSlotAssignments)(issueId, workspacePath).map(assignment => assignment.slotIndex),\n ...reconciled.merged.map(slot => slot.slotIndex),\n ...reconciled.inFlight.map(slot => slot.slotIndex),\n ]);\n const sessionNames = new Set(await deps.listSessionNames());\n\n for (const slotIndex of candidateSlotIndexes) {\n if (ownedSlotIndexes.has(slotIndex)) continue;\n if (sessionNames.has(`agent-${issueLower}-slot-${slotIndex}`)) continue;\n\n const branch = branchesBySlot.get(slotIndex);\n const aheadCount = branch ? await countCommitsAhead(workspacePath, branch, deps.runGitCommand) : 0;\n if (aheadCount === null || aheadCount > 0) {\n actions.push(\n `[swarm] orphan slot ${slotIndex} for ${issueId} preserved: ${branch} has `\n + `${aheadCount ?? 'an unknown number of'} unmerged commit(s) — run \\`pan swarm reset ${issueId}\\` `\n + 'to push it to origin before cleanup',\n );\n continue;\n }\n\n if (worktreeSlotIndexes.has(slotIndex)) {\n await deps.runGitCommand(`git worktree remove --force ${JSON.stringify(`${workspacePath}-slot-${slotIndex}`)}`, workspacePath);\n }\n if (branch) {\n await deps.runGitCommand(`git branch -D ${JSON.stringify(branch)}`, workspacePath);\n }\n actions.push(`[swarm] gc-orphan slot ${slotIndex} for ${issueId}`);\n }\n\n return actions;\n}\n\nasync function listSlotWorktreeIndexes(\n workspacePath: string,\n runGitCommand: CoordinateSwarmSlotsDeps['runGitCommand'],\n): Promise<Set<number>> {\n const indexes = new Set<number>();\n try {\n const result = await runGitCommand('git worktree list --porcelain', workspacePath) as { stdout?: unknown };\n const pattern = new RegExp(`^worktree ${escapeRegExp(workspacePath)}-slot-(\\\\d+)$`);\n for (const line of String(result?.stdout ?? '').split('\\n')) {\n const match = pattern.exec(line.trim());\n if (match) indexes.add(Number(match[1]));\n }\n } catch {\n // Worktree enumeration failed — fall back to branch-derived candidates only.\n }\n return indexes;\n}\n\nasync function countCommitsAhead(\n workspacePath: string,\n branch: string,\n runGitCommand: CoordinateSwarmSlotsDeps['runGitCommand'],\n): Promise<number | null> {\n try {\n const result = await runGitCommand(`git rev-list --count HEAD..${JSON.stringify(branch)}`, workspacePath) as { stdout?: unknown };\n const count = Number(String(result?.stdout ?? '').trim());\n return Number.isFinite(count) ? count : null;\n } catch {\n return null;\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { messageAgent } from '../agents/messaging.js';\nimport type { ReconciledSlotItem } from '../agents/slot-reconcile.js';\nimport { isStatePlaneOnlyStatus } from '../state-plane.js';\nimport { loadCloisterConfigSync, type SwarmInferCompletionMode } from './config.js';\nimport type { ClassifiedSwarmSlot, ClassifyInFlightSlotsOptions, CoordinateSwarmSlotsDeps } from './deacon-swarm.js';\n\nconst execAsync = promisify(exec);\nconst slotCompletionObservations = new Map<string, SlotCompletionObservation>();\n\ninterface SlotCompletionObservation {\n signature: string;\n nudged: boolean;\n consecutiveDoneCount: number;\n}\n\nexport interface DoneWithoutSignalObservation {\n commitTime: number | null;\n outputDigest: string;\n progressKey: string;\n stalledForMs: number;\n}\n\nexport async function classifyDoneWithoutSignal(\n slot: ReconciledSlotItem,\n deps: Partial<Pick<CoordinateSwarmSlotsDeps, 'getSlotBranchAheadCount' | 'isSlotWorktreeClean' | 'sendCompletionNudge'>>,\n options: ClassifyInFlightSlotsOptions,\n observation: DoneWithoutSignalObservation,\n): Promise<ClassifiedSwarmSlot | null> {\n const mode = options.inferCompletion ?? 'off';\n if (mode === 'off' || !slot.agentId || !slot.branch || !options.workspacePath || !options.issueId) {\n slotCompletionObservations.delete(observation.progressKey);\n return null;\n }\n\n const aheadCount = await (deps.getSlotBranchAheadCount ?? defaultGetSlotBranchAheadCount)(\n options.workspacePath,\n options.issueId,\n slot.branch,\n ).catch(() => 0);\n const clean = await (deps.isSlotWorktreeClean ?? defaultIsSlotWorktreeClean)(\n `${options.workspacePath}-slot-${slot.slotIndex}`,\n ).catch(() => false);\n if (aheadCount < 1 || !clean) {\n slotCompletionObservations.delete(observation.progressKey);\n return null;\n }\n\n const signature = `${observation.commitTime ?? 'none'}:${observation.outputDigest}:${aheadCount}:clean`;\n const previous = slotCompletionObservations.get(observation.progressKey);\n const current: SlotCompletionObservation = {\n signature,\n nudged: previous?.signature === signature ? previous.nudged : false,\n consecutiveDoneCount: previous?.signature === signature ? previous.consecutiveDoneCount + 1 : 1,\n };\n const actions: string[] = [];\n const normalizedIssueId = options.issueId.toUpperCase();\n\n if (!current.nudged) {\n await (deps.sendCompletionNudge ?? defaultSendCompletionNudge)(slot.agentId, normalizedIssueId);\n current.nudged = true;\n actions.push(`[swarm] nudged slot ${slot.slotIndex} (item ${slot.itemId}) for ${normalizedIssueId}: run pan done ${normalizedIssueId}`);\n }\n\n slotCompletionObservations.set(observation.progressKey, current);\n if (mode === 'auto' && current.consecutiveDoneCount >= 2) {\n return { ...slot, lifecycle: 'ready-to-merge', exitStatus: 0, signal: 'inferred', actions };\n }\n\n return {\n ...slot,\n lifecycle: 'awaiting-completion-signal',\n reason: 'no-progress-timeout',\n stalledForMs: observation.stalledForMs,\n signal: 'completion-nudge',\n actions,\n };\n}\n\nexport async function classifyDurableReadySlot(\n slot: ReconciledSlotItem,\n deps: Partial<Pick<CoordinateSwarmSlotsDeps, 'getSlotBranchAheadCount' | 'isSlotWorktreeClean'>>,\n options: ClassifyInFlightSlotsOptions,\n): Promise<ClassifiedSwarmSlot | null> {\n if (!slot.branch || !options.workspacePath || !options.issueId) return null;\n\n const aheadCount = await (deps.getSlotBranchAheadCount ?? defaultGetSlotBranchAheadCount)(\n options.workspacePath,\n options.issueId,\n slot.branch,\n ).catch(() => 0);\n if (aheadCount < 1) return null;\n\n const clean = await (deps.isSlotWorktreeClean ?? defaultIsSlotWorktreeClean)(\n `${options.workspacePath}-slot-${slot.slotIndex}`,\n ).catch(() => false);\n if (!clean) return null;\n\n return { ...slot, lifecycle: 'ready-to-merge', exitStatus: 0, signal: 'inferred' };\n}\n\nexport function resetSwarmCompletionInferenceForTests(): void {\n slotCompletionObservations.clear();\n}\n\nexport function clearSwarmCompletionObservation(progressKey: string): void {\n slotCompletionObservations.delete(progressKey);\n}\n\nexport function swarmInferCompletionMode(): SwarmInferCompletionMode {\n const raw = process.env.PAN_SWARM_INFER_COMPLETION ?? loadCloisterConfigSync().swarm?.infer_completion;\n // PAN-2372 WI-5 / FR-8: default to 'auto' (nudge once, then converge after two stable\n // observations). Explicit 'nudge' / 'off' in config.yaml or PAN_SWARM_INFER_COMPLETION\n // still parse and keep their exact prior semantics.\n return raw === 'off' || raw === 'nudge' || raw === 'auto' ? raw : 'auto';\n}\n\nexport async function defaultGetSlotBranchAheadCount(\n workspacePath: string,\n issueId: string,\n branch: string,\n): Promise<number> {\n const baseBranch = `feature/${issueId.toLowerCase()}`;\n const { stdout } = await execAsync(\n `git rev-list --count ${JSON.stringify(baseBranch)}..${JSON.stringify(branch)}`,\n { cwd: workspacePath },\n );\n const count = Number(stdout.trim());\n return Number.isFinite(count) && count > 0 ? count : 0;\n}\n\nexport async function defaultIsSlotWorktreeClean(slotWorkspacePath: string): Promise<boolean> {\n const { stdout } = await execAsync('git status --porcelain', { cwd: slotWorkspacePath });\n // PAN-2372 WI-6 / FR-9: treat state-plane-only dirt (.pan/continue.json, .pan/records/...,\n // the workspace record door) as clean. The swarm writes durable state to those paths on the\n // permanent plane, so their presence must not block a slot from being inferred complete.\n // isStatePlaneOnlyStatus already returns true for empty porcelain (vacuous every()), so one\n // shared classifier covers both cases — no local path list here. See docs/STATE-PLANE-COMMIT-POLICY.md.\n return isStatePlaneOnlyStatus(stdout);\n}\n\nexport async function defaultSendCompletionNudge(agentId: string, issueId: string): Promise<void> {\n await messageAgent(\n agentId,\n `You appear to have committed clean slot work but have not signaled completion. If the slot is complete, run exactly:\\n\\npan done ${issueId}`,\n 'deacon:swarm-completion-inference',\n );\n}\n","import { Effect } from 'effect';\nimport { setReviewStatusSync, getReviewStatusSync } from '../review-status.js';\nimport { applyStatusOverrides } from '../vbrief/io.js';\nimport type { VBriefDocument } from '../vbrief/types.js';\n\nexport interface RequestIssueReviewResult {\n success: boolean;\n message: string;\n error?: string;\n gated?: boolean;\n}\n\nexport async function defaultRequestIssueReview(\n issueId: string,\n workspacePath: string,\n): Promise<RequestIssueReviewResult> {\n setReviewStatusSync(issueId, {\n reviewStatus: 'pending',\n testStatus: 'pending',\n mergeStatus: 'pending',\n readyForMerge: false,\n verificationStatus: 'pending',\n verificationCycleCount: 0,\n autoRequeueCount: 0,\n reviewRequestedAt: new Date().toISOString(),\n });\n\n const { spawnReviewRoleForIssue } = await import('./review-agent.js');\n return Effect.runPromise(spawnReviewRoleForIssue({\n issueId,\n workspace: workspacePath,\n branch: `feature/${issueId.toLowerCase()}`,\n }));\n}\n\nexport async function finalizeSwarmIssueIfComplete(\n issueId: string,\n workspacePath: string,\n baseDoc: VBriefDocument,\n deps: {\n readStatusOverrides?: (workspacePath: string, issueId: string) => Record<string, string> | undefined;\n getFinalizedAt?: (issueId: string, workspacePath: string) => string | undefined;\n setFinalizedAt?: (issueId: string, workspacePath: string, finalizedAt: string) => void;\n requestIssueReview: (issueId: string, workspacePath: string) => Promise<RequestIssueReviewResult>;\n },\n): Promise<string[]> {\n const overrides = deps.readStatusOverrides?.(workspacePath, issueId);\n const doc = overrides && Object.keys(overrides).length > 0\n ? applyStatusOverrides(baseDoc, overrides)\n : baseDoc;\n\n if (!doc.plan.items.every(item => item.status === 'completed')) return [];\n if (deps.getFinalizedAt?.(issueId, workspacePath)) return [];\n const currentStatus = getReviewStatusSync(issueId);\n if (currentStatus?.mergeStatus === 'merged') return [];\n if (currentStatus?.reviewRequestedAt || currentStatus?.reviewStatus === 'reviewing' || currentStatus?.reviewStatus === 'passed') {\n return [];\n }\n\n const result = await deps.requestIssueReview(issueId, workspacePath);\n if (result.success) {\n deps.setFinalizedAt?.(issueId, workspacePath, new Date().toISOString());\n return [`[swarm] finalized ${issueId}: issue-level review requested`];\n }\n return [`[swarm] finalization deferred ${issueId}: ${result.error || result.message}`];\n}\n","import { existsSync } from 'node:fs';\nimport { Effect } from 'effect';\nimport type { ReconciledSlotItem } from '../agents/slot-reconcile.js';\nimport { getAgentStateSync } from '../agents/agent-state.js';\nimport { stopAgent } from '../agents/termination.js';\nimport type { CoordinateSwarmSlotsDeps } from './deacon-swarm.js';\n\nconst MERGED_LIVE_SLOT_IDLE_MS = 30 * 60 * 1000;\n\nexport async function gcMergedSlots(\n issueId: string,\n workspacePath: string,\n slots: ReconciledSlotItem[],\n deps: Pick<CoordinateSwarmSlotsDeps, 'runGitCommand' | 'clearSlotAssignment' | 'listSessionNames'> & {\n slotWorktreeExists?: (path: string) => boolean;\n getAgentLastActivity?: (agentId: string) => string | undefined;\n stopSlotAgent?: (agentId: string) => Promise<void>;\n },\n): Promise<string[]> {\n const actions: string[] = [];\n // A freshly dispatched slot branch points at the feature branch HEAD, so\n // `--merged HEAD` classifies it as merged before the agent's first commit.\n // Without a liveness guard, gc destroys the worktree/branch/assignment under\n // the live agent and the item redispatches at the next index.\n const sessionNames = new Set(await deps.listSessionNames());\n const worktreeExists = deps.slotWorktreeExists ?? existsSync;\n\n for (const slot of slots) {\n if (slot.status !== 'merged') continue;\n\n const agentId = slot.agentId ?? `agent-${issueId.toLowerCase()}-slot-${slot.slotIndex}`;\n if (sessionNames.has(agentId)) {\n const lastActivity = (deps.getAgentLastActivity ?? (id => getAgentStateSync(id)?.lastActivity))(agentId);\n const idleFor = lastActivity ? Date.now() - Date.parse(lastActivity) : 0;\n if (!Number.isFinite(idleFor) || idleFor < MERGED_LIVE_SLOT_IDLE_MS) {\n actions.push(`[swarm] gc skipped slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: agent session alive`);\n continue;\n }\n await (deps.stopSlotAgent ?? (id => Effect.runPromise(stopAgent(id))))(agentId);\n actions.push(`[swarm] gc reaped idle merged agent ${agentId}`);\n }\n\n const slotWorkspace = `${workspacePath}-slot-${slot.slotIndex}`;\n const slotBranch = slot.branch ?? `feature/${issueId.toLowerCase()}-slot-${slot.slotIndex}`;\n if (worktreeExists(slotWorkspace)) {\n try {\n await deps.runGitCommand(`git worktree remove --force ${JSON.stringify(slotWorkspace)}`, workspacePath);\n } catch (error) {\n actions.push(`[swarm] gc deferred slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: worktree remove failed: ${error instanceof Error ? error.message : String(error)}`);\n continue;\n }\n }\n try {\n await deps.runGitCommand(`git branch -D ${JSON.stringify(slotBranch)}`, workspacePath);\n } catch (error) {\n actions.push(`[swarm] gc deferred slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: branch delete failed: ${error instanceof Error ? error.message : String(error)}`);\n continue;\n }\n deps.clearSlotAssignment(workspacePath, issueId, slot.slotIndex, slot.itemId);\n actions.push(`[swarm] gc slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}`);\n }\n\n return actions;\n}\n","import {\n readIssueRecordForWorkspaceSync,\n writeIssueRecordForWorkspaceSync,\n type PanIssueRecord,\n type PanIssueSwarmSlotCompletion,\n} from '../pan-dir/record.js';\n\nexport function createMinimalIssueRecord(issueId: string): PanIssueRecord {\n const now = new Date().toISOString();\n return {\n issueId,\n schemaVersion: 2,\n created: now,\n updated: now,\n feedback: [],\n pipeline: {\n issueId,\n reviewStatus: 'pending',\n testStatus: 'pending',\n mergeStatus: 'pending',\n readyForMerge: false,\n updatedAt: now,\n },\n closeOut: {\n usage: {\n byStage: {},\n totals: {},\n },\n merges: [],\n ranOn: '',\n },\n };\n}\n\nexport function writeSwarmFinalizedAt(workspacePath: string, issueId: string, finalizedAt: string): void {\n const normalizedIssueId = issueId.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId)\n ?? createMinimalIssueRecord(normalizedIssueId);\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...(record.swarm ?? {}),\n finalizedAt,\n },\n });\n}\n\n/**\n * PAN-2372 WI-3 / FR-4: persist a durable per-slot completion marker keyed by\n * `String(slotIndex)`. Read-modify-write preserves every other record field\n * (statusOverrides, slotAssignments, etc.) — see the byte-identical\n * preservation test in deacon-swarm-slot-completion.test.ts.\n */\nexport function writeSwarmSlotCompletion(\n workspacePath: string,\n issueId: string,\n completion: PanIssueSwarmSlotCompletion,\n): void {\n const normalizedIssueId = issueId.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId)\n ?? createMinimalIssueRecord(normalizedIssueId);\n const swarm = record.swarm ?? {};\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...swarm,\n slotCompletions: {\n ...(swarm.slotCompletions ?? {}),\n [String(completion.slotIndex)]: completion,\n },\n },\n });\n}\n\n/**\n * PAN-2372 WI-3 / FR-6: clear a slot's completion marker once the coordinator\n * (WI-4) has consumed it (merge/requeue). No-op when no marker exists for the\n * slot, so callers can clear unconditionally on the terminal transition.\n */\nexport function clearSwarmSlotCompletion(workspacePath: string, issueId: string, slotIndex: number): void {\n const normalizedIssueId = issueId.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId);\n const existing = record?.swarm?.slotCompletions;\n if (!existing || !(String(slotIndex) in existing)) return;\n const next: Record<string, PanIssueSwarmSlotCompletion> = { ...existing };\n delete next[String(slotIndex)];\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...record!.swarm,\n slotCompletions: next,\n },\n });\n}\n\n/**\n * PAN-2372 WI-3 / FR-4, FR-5: write the durable slot-completion marker and read\n * it straight back to confirm it persisted. Returns true only when the keyed\n * marker exists on disk with a matching agentId. The slot `pan done` caller MUST\n * refuse to mark the slot done when this returns false — that is the whole point\n * of the issue: a slot used to finish without durably recording completion, so\n * the coordinator could not observe it. Keeping the write+verify here (not inline\n * in the CLI command) keeps the god-file done.ts from growing and co-locates the\n * swarm-record mechanics with the other slot-completion door functions.\n */\nexport function persistAndVerifySwarmSlotCompletion(\n workspacePath: string,\n issueId: string,\n completion: PanIssueSwarmSlotCompletion,\n): boolean {\n writeSwarmSlotCompletion(workspacePath, issueId, completion);\n const reread = readIssueRecordForWorkspaceSync(workspacePath, issueId.toUpperCase());\n const persisted = reread?.swarm?.slotCompletions?.[String(completion.slotIndex)];\n return Boolean(persisted && persisted.agentId === completion.agentId);\n}\n","/**\n * PAN-2385 — tiered-execution commit hooks for the swarm dispatch path.\n *\n * The tier-feed and tier-supervisor libraries shipped with PAN-1791/2222 but\n * had no production caller: commits landed and neither the standing crew nor\n * the subscribe-policy supervisor ever heard about them (found live during\n * the first Standing Crew run, PAN-2383). This module is the ignition.\n *\n * Fired from mergeReadySlots after a slot's bead commits merge into the\n * feature workspace:\n * 1. broadcastCommit — every live slot agent hears the rendered diff\n * (ingestion-only; everyone-hears-everything per docs/TIERED-EXECUTION.md).\n * 2. shouldSupervise(item, subscribe) → deliverCommitForReview — the\n * standing supervisor reviews per its subscribe policy. This is\n * independent of supervisor.owns_inspection, which only routes\n * `pan inspect`.\n *\n * Both hooks are best-effort: the commit has already landed, so a delivery\n * failure logs loudly and never blocks the merge loop.\n */\n\nimport { Effect } from 'effect';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { sessionExists } from '../tmux.js';\nimport { loadConfigSync as loadYamlConfig } from '../config-yaml.js';\nimport { resolveTieredExecutionEnabled, type ValidatedTieredExecutionConfig } from '../agents/tier-table.js';\nimport { resolveTier } from '../agents/resolve-tier.js';\nimport { broadcastCommit } from '../agents/tier-feed.js';\nimport {\n deliverCommitForReview,\n loadPrdDraft,\n shouldSupervise,\n spawnTierSupervisor,\n supervisorAgentId,\n} from '../agents/tier-supervisor.js';\nimport { listSlotAssignments } from '../agents/slot-reconcile.js';\nimport type { VBriefDocument, VBriefItem } from '../vbrief/types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface FireTieredCommitHooksOptions {\n issueId: string;\n /** Feature workspace the slot branch just merged into (its HEAD is the commit). */\n workspacePath: string;\n /** The bead the merged commits implement. */\n item: VBriefItem;\n /** The merged plan view — plan.metadata carries the per-issue tiered override. */\n doc: VBriefDocument;\n}\n\nexport interface FireTieredCommitHooksDeps {\n loadConfig: typeof loadYamlConfig;\n getHeadSha: (workspacePath: string) => Promise<string>;\n listAssignments: typeof listSlotAssignments;\n isSessionAlive: (sessionName: string) => Promise<boolean>;\n broadcast: typeof broadcastCommit;\n ensureSupervisor: typeof spawnTierSupervisor;\n deliverReview: typeof deliverCommitForReview;\n loadPrd: typeof loadPrdDraft;\n}\n\nconst defaultDeps: FireTieredCommitHooksDeps = {\n loadConfig: loadYamlConfig,\n getHeadSha: async (workspacePath) =>\n (await execAsync('git rev-parse HEAD', { cwd: workspacePath })).stdout.trim(),\n listAssignments: listSlotAssignments,\n isSessionAlive: (sessionName) => Effect.runPromise(sessionExists(sessionName)),\n broadcast: broadcastCommit,\n ensureSupervisor: spawnTierSupervisor,\n deliverReview: deliverCommitForReview,\n loadPrd: loadPrdDraft,\n};\n\n/** Resolve the tier name a bead belongs to, for the feed header. Falls back to\n * the slot label when the tier table cannot resolve the item (fail-open here is\n * correct: the feed is informational and the commit has already landed). */\nfunction tierNameForItem(\n item: VBriefItem | undefined,\n tiered: ValidatedTieredExecutionConfig,\n slotIndex: number,\n): string {\n if (item) {\n try {\n return resolveTier(item, tiered).tierName;\n } catch {\n // fall through to the slot label\n }\n }\n return `slot-${slotIndex}`;\n}\n\n/**\n * Fire the commit feed + supervisor review for a bead whose commits just\n * merged into the feature workspace. Returns deacon action-log lines.\n */\nexport async function fireTieredCommitHooks(\n options: FireTieredCommitHooksOptions,\n deps: FireTieredCommitHooksDeps = defaultDeps,\n): Promise<string[]> {\n const actions: string[] = [];\n const { issueId, workspacePath, item, doc } = options;\n\n let tiered: ValidatedTieredExecutionConfig | undefined;\n try {\n tiered = deps.loadConfig().config.tieredExecution;\n } catch (err) {\n actions.push(`[tiered] skipped commit hooks for ${issueId}: config load failed (${err instanceof Error ? err.message : String(err)})`);\n return actions;\n }\n if (!tiered || !resolveTieredExecutionEnabled(tiered, doc.plan.metadata)) return actions;\n\n let sha: string;\n try {\n sha = await deps.getHeadSha(workspacePath);\n } catch (err) {\n actions.push(`[tiered] commit hooks for ${issueId} item ${item.id} could not resolve HEAD: ${err instanceof Error ? err.message : String(err)}`);\n return actions;\n }\n\n // ── 1. Broadcast to every live standing slot agent ────────────────────────\n try {\n const itemsById = new Map(doc.plan.items.map((planItem) => [planItem.id, planItem]));\n const assignments = deps.listAssignments(issueId, workspacePath);\n const listeners: Array<{ tierName: string; agentId: string }> = [];\n for (const assignment of assignments) {\n if (!assignment.agentId) continue;\n if (!(await deps.isSessionAlive(assignment.agentId))) continue;\n listeners.push({\n tierName: tierNameForItem(itemsById.get(assignment.itemId), tiered, assignment.slotIndex),\n agentId: assignment.agentId,\n });\n }\n if (listeners.length > 0) {\n const deliveries = await deps.broadcast({\n workspace: workspacePath,\n issueId,\n sha,\n beadTitle: item.title,\n beadId: item.id,\n tiers: listeners,\n feedConfig: tiered.feed,\n });\n const delivered = deliveries.filter((delivery) => delivery.result.ok).length;\n actions.push(`[tiered] broadcast commit ${sha.slice(0, 10)} (item ${item.id}) for ${issueId} to ${delivered}/${listeners.length} standing agents`);\n }\n } catch (err) {\n actions.push(`[tiered] feed broadcast FAILED for ${issueId} item ${item.id}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n // ── 2. Supervisor review per subscribe policy ─────────────────────────────\n try {\n const supervisor = tiered.supervisor;\n if (supervisor && shouldSupervise(item, supervisor.subscribe)) {\n const agentId = supervisorAgentId(issueId);\n if (!(await deps.isSessionAlive(agentId))) {\n await deps.ensureSupervisor(issueId, supervisor, { workspace: workspacePath });\n actions.push(`[tiered] spawned standing supervisor ${agentId} for ${issueId}`);\n }\n const prdMarkdown = await deps.loadPrd(workspacePath, issueId).catch(() => undefined);\n await deps.deliverReview({\n supervisorAgentId: agentId,\n workspacePath,\n issueId,\n item,\n sha,\n beadId: item.id,\n prdMarkdown,\n });\n actions.push(`[tiered] supervisor review dispatched for ${issueId} item ${item.id} (subscribe=${supervisor.subscribe})`);\n }\n } catch (err) {\n actions.push(`[tiered] supervisor review FAILED for ${issueId} item ${item.id}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n return actions;\n}\n","import { readIssueRecordForWorkspaceSync, writeIssueRecordForWorkspaceSync, type PanIssueRecoveryTrip } from '../pan-dir/record.js';\nimport { createMinimalIssueRecord } from './deacon-swarm-record.js';\n\nexport function recordRecoveryFailure(\n workspacePath: string,\n issue: string,\n recoveryPath: string,\n obligationGeneration: string,\n threshold = 25,\n now = new Date(),\n): { trip: PanIssueRecoveryTrip; emitNeedsYou: boolean } {\n const normalized = issue.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalized) ?? createMinimalIssueRecord(normalized);\n const trips = [...(record.recoveryTrips ?? [])];\n const index = trips.findIndex(trip => trip.issue === normalized && trip.recoveryPath === recoveryPath && trip.obligationGeneration === obligationGeneration);\n const prior = index >= 0 ? trips[index] : undefined;\n if (prior?.open) return { trip: prior, emitNeedsYou: false };\n const tripCount = (prior?.tripCount ?? 0) + 1;\n const emitNeedsYou = tripCount >= threshold && !prior?.open;\n const trip: PanIssueRecoveryTrip = {\n issue: normalized, recoveryPath, obligationGeneration, tripCount,\n open: prior?.open === true || emitNeedsYou,\n ...(prior?.needsYouEmittedAt ? { needsYouEmittedAt: prior.needsYouEmittedAt } : emitNeedsYou ? { needsYouEmittedAt: now.toISOString() } : {}),\n };\n if (index >= 0) trips[index] = trip; else trips.push(trip);\n writeIssueRecordForWorkspaceSync(workspacePath, normalized, { ...record, recoveryTrips: trips });\n return { trip, emitNeedsYou };\n}\n\nexport function acknowledgeRecoveryTrip(workspacePath: string, issue: string, recoveryPath: string, obligationGeneration: string): void {\n const normalized = issue.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalized);\n if (!record) return;\n writeIssueRecordForWorkspaceSync(workspacePath, normalized, {\n ...record,\n recoveryTrips: (record.recoveryTrips ?? []).filter(trip => !(trip.issue === normalized && trip.recoveryPath === recoveryPath && trip.obligationGeneration === obligationGeneration)),\n });\n}\n","/**\n * PAN-2543 shared autonomous re-drive gate.\n *\n * Recovery entry points classify agent gates, apply the intent policy, and\n * consult the cached memory verdict through this one function before acting.\n * Callers still reserve their role-specific concurrency slot after admission.\n */\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport {\n decideResumeGate,\n getAgentResumeGateBlockReason,\n type AgentState,\n type ResumeGateContext,\n type ResumeGateDecision,\n} from '../agents/agent-state.js';\nimport { getCachedMemoryVerdict } from './memory-verdict-cache.js';\n\nexport const REDRIVE_ENTRY_POINTS = ['dead-session-rework', 'swarm-slot-requeue'] as const;\n\nexport type RedriveGateDecision =\n | { decision: 'proceed'; gateDecision: Extract<ResumeGateDecision, { decision: 'proceed' }> }\n | { decision: 'defer'; reason: string; needsYou?: true };\n\nexport function decideAutonomousRedrive(\n state: Pick<AgentState, 'paused' | 'pausedReason' | 'yieldedByScheduler' | 'troubled' | 'troubledAt' | 'stoppedByUser' | 'consecutiveFailures'>,\n context: ResumeGateContext = {},\n): RedriveGateDecision {\n const gateDecision = decideResumeGate(getAgentResumeGateBlockReason(state), 'autonomous', context);\n if (gateDecision.decision !== 'proceed') {\n return {\n decision: 'defer',\n reason: gateDecision.reason,\n ...(gateDecision.decision === 'block' && gateDecision.needsYou ? { needsYou: true } : {}),\n };\n }\n\n const memoryVerdict = getCachedMemoryVerdict();\n if (memoryVerdict && memoryVerdict.band !== 'ok') {\n return { decision: 'defer', reason: `memory pressure is ${memoryVerdict.band}` };\n }\n return { decision: 'proceed', gateDecision };\n}\n\nexport function decideAgentAutonomousRedrive(\n state: Pick<AgentState, 'paused' | 'pausedReason' | 'yieldedByScheduler' | 'troubled' | 'troubledAt' | 'stoppedByUser' | 'consecutiveFailures'>,\n agentDir: string,\n owesRework: boolean,\n): RedriveGateDecision {\n const hasCompletedHandoff = existsSync(join(agentDir, 'completed'))\n || existsSync(join(agentDir, 'completed.processed'));\n return decideAutonomousRedrive(state, { hasCompletedHandoff, owesRework });\n}\n","import { existsSync } from 'node:fs';\nimport type { ReconciledSlotItem, SlotReconcileResult } from '../agents/slot-reconcile.js';\nimport {\n readIssueRecordForWorkspaceSync,\n writeIssueRecordForWorkspaceSync,\n type PanIssueRecord,\n type PanIssueSwarmSupersededAttempt,\n} from '../pan-dir/record.js';\nimport { createMinimalIssueRecord, clearSwarmSlotCompletion } from './deacon-swarm-record.js';\nimport type { PersistedTaskOperation } from '../vbrief/dag.js';\nimport type { VBriefDocument } from '../vbrief/types.js';\nimport { recordRecoveryFailure } from './recovery-trip.js';\nimport { getAgentStateSync } from '../agents/agent-state.js';\nimport { decideAutonomousRedrive } from './redrive-gate.js';\n\n/** Patrol GC never removes forensic attempts; configured issue close-out owns teardown. */\nexport const SWARM_SUPERSEDED_RETENTION = 'issue-close-out' as const;\n\nexport interface FailedSlotArchiveDeps {\n runGitCommand: (command: string, cwd: string) => Promise<unknown>;\n clearSlotAssignment: (workspacePath: string, issueId: string, slotIndex: number, itemId?: string) => void;\n}\ninterface ClassifiedSlot extends ReconciledSlotItem { lifecycle: string; reason?: string }\n\nexport function nextSwarmSlotIndex(record: PanIssueRecord | undefined, reconciled: SlotReconcileResult): number {\n return Math.max(0,\n ...reconciled.branches.map(value => value.slotIndex),\n ...reconciled.agents.map(value => value.slotIndex),\n ...reconciled.inFlight.map(value => value.slotIndex),\n ...(record?.swarm?.slotAssignments ?? []).map(value => value.slotIndex),\n ...(record?.swarm?.supersededAttempts ?? []).map(value => value.slotIndex),\n ) + 1;\n}\n\nexport async function archiveFailedSwarmSlot(\n issueId: string,\n workspacePath: string,\n slot: ReconciledSlotItem & { reason?: string },\n deps: FailedSlotArchiveDeps,\n now = new Date(),\n): Promise<PanIssueSwarmSupersededAttempt> {\n const normalized = issueId.toUpperCase();\n const suffix = now.toISOString().replace(/[-:.TZ]/g, '');\n const archivedStem = `slot-${slot.slotIndex}-failed-${suffix}`;\n const oldWorktree = `${workspacePath}-slot-${slot.slotIndex}`;\n const archivedWorktree = `${workspacePath}-${archivedStem}`;\n const oldBranch = slot.branch ?? `feature/${issueId.toLowerCase()}-slot-${slot.slotIndex}`;\n const archivedBranch = `feature/${issueId.toLowerCase()}-${archivedStem}`;\n\n if (existsSync(oldWorktree)) {\n await deps.runGitCommand(`git worktree move ${JSON.stringify(oldWorktree)} ${JSON.stringify(archivedWorktree)}`, workspacePath);\n }\n await deps.runGitCommand(`git branch -m ${JSON.stringify(oldBranch)} ${JSON.stringify(archivedBranch)}`, workspacePath);\n\n const attempt: PanIssueSwarmSupersededAttempt = {\n slotIndex: slot.slotIndex,\n itemId: slot.itemId,\n agentId: slot.agentId,\n branch: oldBranch,\n archivedBranch,\n ...(existsSync(archivedWorktree) ? { archivedWorktree } : {}),\n reason: slot.reason ?? 'failed swarm slot',\n supersededAt: now.toISOString(),\n };\n const existing = readIssueRecordForWorkspaceSync(workspacePath, normalized) ?? createMinimalIssueRecord(normalized);\n writeIssueRecordForWorkspaceSync(workspacePath, normalized, {\n ...existing,\n swarm: {\n ...(existing.swarm ?? {}),\n supersededAttempts: [...(existing.swarm?.supersededAttempts ?? []), attempt],\n },\n });\n // PAN-2372 WI-4 / FR-6: this slot is being superseded/requeued — clear its\n // durable completion marker so a fresh attempt on the same slotIndex is not\n // falsely observed as already-completed by classifyInFlightSlots.\n clearSwarmSlotCompletion(workspacePath, normalized, slot.slotIndex);\n deps.clearSlotAssignment(workspacePath, normalized, slot.slotIndex, slot.itemId);\n return attempt;\n}\n\nexport async function requeueFailedSwarmSlots(\n issueId: string,\n workspacePath: string,\n classified: ClassifiedSlot[],\n doc: VBriefDocument,\n reconciled: SlotReconcileResult,\n deps: FailedSlotArchiveDeps & { applyTaskOperationToPlanFile: (path: string, operation: PersistedTaskOperation, workspace?: string) => Promise<unknown> },\n blockedSlotIndexes: Set<number> = new Set(),\n): Promise<{ doc: VBriefDocument; actions: string[] }> {\n let nextDoc = doc;\n const actions: string[] = [];\n for (const slot of classified.filter(candidate => candidate.lifecycle === 'failed')) {\n if (blockedSlotIndexes.has(slot.slotIndex)) {\n actions.push(`[swarm] skipped requeue slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: failed-merge block — awaiting operator recovery`);\n continue;\n }\n const admission = decideAutonomousRedrive(slot.agentId ? getAgentStateSync(slot.agentId) ?? {} : {}, { owesRework: true });\n if (admission.decision === 'defer') { actions.push(`[swarm] deferred failed slot ${slot.slotIndex}: ${admission.reason}`); continue; }\n const attempt = await archiveFailedSwarmSlot(issueId, workspacePath, slot, deps);\n await deps.applyTaskOperationToPlanFile(`${workspacePath}/.pan/spec.vbrief.json`, {\n type: 'unblock', itemId: slot.itemId, writerId: 'deacon-swarm', reason: `Redispatch after ${slot.reason ?? 'slot failure'}`,\n }, workspacePath);\n reconciled.inFlight = reconciled.inFlight.filter(candidate => candidate.itemId !== slot.itemId);\n reconciled.superseded = [...(reconciled.superseded ?? []), attempt];\n nextDoc = { ...nextDoc, plan: { ...nextDoc.plan, items: nextDoc.plan.items.map(item => item.id === slot.itemId ? { ...item, status: 'pending' as const } : item) } };\n actions.push(`[swarm] archived failed slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}`);\n const failure = recordRecoveryFailure(workspacePath, issueId, 'swarm-slot-requeue', slot.itemId);\n if (failure.emitNeedsYou) actions.push(`[swarm] needs-you ${issueId}: slot item ${slot.itemId} failed ${failure.trip.tripCount} times`);\n }\n return { doc: nextDoc, actions };\n}\n\nexport function applySupersededSlotHighWater(\n occupied: Set<number>,\n reconciled: SlotReconcileResult,\n configuredMax: number,\n): number {\n const highWater = Math.max(0, ...(reconciled.superseded ?? []).map(attempt => attempt.slotIndex));\n if (highWater > 0) for (let index = 1; index <= highWater; index++) occupied.add(index);\n return Math.max(configuredMax, highWater + 1);\n}\n","import { exec } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { promisify } from 'node:util';\nimport { Effect } from 'effect';\nimport { join } from 'path';\nimport { getAgentRuntimeSnapshot } from '../agent-runtime.js';\nimport type { AgentRuntimeSnapshot } from '@overdeck/contracts';\nimport { spawnRun } from '../agents/spawn.js';\nimport type { SpawnRunOptions } from '../agents/spawn-prep.js';\nimport { verifyAndMergeSlot, type SlotMergeResult } from '../agents/slot-merge.js';\nimport {\n listSlotAssignments as listDurableSlotAssignments,\n reconcileSlotState,\n type ReconciledSlotItem,\n type SlotReconcileResult,\n} from '../agents/slot-reconcile.js';\nimport {\n readIssueRecordForWorkspaceSync,\n writeIssueRecordForWorkspaceSync,\n getIssueRecordPathForWorkspace,\n type PanIssueRecord,\n type PanIssueSwarmFailedMergeBlock,\n type PanIssueSwarmSlotCompletion,\n} from '../pan-dir/record.js';\nimport { findSpecByIssue } from '../pan-dir/specs.js';\nimport { capturePane, isPaneDead, listPaneValues, listSessionNames as listTmuxSessionNames } from '../tmux.js';\nimport {\n applyTaskOperationToPlanFile,\n blockingParentCount,\n createActiveSlice,\n getDispatchableItems,\n type PersistedTaskOperation,\n} from '../vbrief/dag.js';\nimport { applyStatusOverrides } from '../vbrief/io.js';\nimport { analyzeSwarmReadiness, type SwarmReadinessVerdict } from '../vbrief/swarm-readiness.js';\nimport type { VBriefDocument, VBriefItem } from '../vbrief/types.js';\nimport { getReviewStatusSync, type ReviewStatus } from '../review-status.js';\nimport { isDeaconGloballyPausedSync } from '../overdeck/control-settings.js';\nimport type { SwarmInferCompletionMode } from './config.js';\nimport {\n countRunningSwarmSlotsForIssue,\n getConcurrencyLimits,\n releaseSwarmSlot,\n tryReserveSwarmSlot,\n type ConcurrencyLimits,\n} from './concurrency.js';\nimport { listFeatureWorkspaces, type FeatureWorkspace } from './deacon-workspaces.js';\nimport { gcOrphanedSlots } from './deacon-swarm-orphan-gc.js';\nimport {\n classifyDoneWithoutSignal,\n classifyDurableReadySlot,\n clearSwarmCompletionObservation,\n defaultGetSlotBranchAheadCount,\n defaultIsSlotWorktreeClean,\n defaultSendCompletionNudge,\n resetSwarmCompletionInferenceForTests,\n swarmInferCompletionMode,\n} from './deacon-swarm-completion.js';\nimport {\n defaultRequestIssueReview,\n finalizeSwarmIssueIfComplete,\n type RequestIssueReviewResult,\n} from './deacon-swarm-finalization.js';\nimport { gcMergedSlots } from './deacon-swarm-gc.js';\nimport { createMinimalIssueRecord, writeSwarmFinalizedAt, clearSwarmSlotCompletion } from './deacon-swarm-record.js';\nimport { fireTieredCommitHooks } from './swarm-tiered-hooks.js';\nimport { applySupersededSlotHighWater, archiveFailedSwarmSlot, requeueFailedSwarmSlots } from './swarm-failed-slot.js';\n\nexport { gcOrphanedSlots } from './deacon-swarm-orphan-gc.js';\nexport { gcMergedSlots } from './deacon-swarm-gc.js';\n\nconst execAsync = promisify(exec);\nconst SLOT_MERGE_REFIRE_COOLDOWN_MS = 5_000;\nconst SWARM_ADVANCE_FAILURE_THRESHOLD = 3;\nconst SWARM_ADVANCE_FAILURE_COOLDOWN_MS = 60_000;\nconst DEFAULT_SWARM_STALL_THRESHOLD_MS = 30 * 60 * 1000;\n\nconst recentSlotMergeFires = new Map<string, number>();\nconst issueAdvanceFailures = new Map<string, { count: number; cooldownUntil: number }>();\nconst failedMergeBlocks = new Map<string, FailedMergeBlock>();\nconst slotProgressObservations = new Map<string, SlotProgressObservation>();\nexport type SwarmRecoveryAction = 'retry' | 'drop' | 'handoff';\n\nexport interface FailedMergeBlock {\n issueId: string;\n itemId: string;\n slotIndex: number;\n branch?: string;\n note: string;\n}\n\nexport interface CoordinateSwarmSlotsOptions {\n issueId?: string;\n}\n\nexport interface CoordinateSwarmSlotsDeps {\n listFeatureWorkspaces: () => FeatureWorkspace[];\n reconcileSlotState: (\n issueId: string,\n workspace: string,\n doc: VBriefDocument,\n ) => Promise<SlotReconcileResult>;\n listSessionNames: () => Promise<readonly string[]>;\n isPaneDead: (sessionName: string) => Promise<boolean>;\n getPaneExitStatus: (sessionName: string) => Promise<number | null>;\n getAgentRuntimeState: (agentId: string) => Promise<Pick<AgentRuntimeSnapshot, 'resolution'> | null>;\n getPaneOutputDigest: (sessionName: string) => Promise<string>;\n getBranchTipCommitTime: (workspacePath: string, branch: string) => Promise<number | null>;\n getSlotBranchAheadCount: (workspacePath: string, issueId: string, branch: string) => Promise<number>;\n isSlotWorktreeClean: (slotWorkspacePath: string) => Promise<boolean>;\n sendCompletionNudge: (agentId: string, issueId: string) => Promise<void>;\n slotWorktreeExists: (slotWorkspacePath: string) => boolean;\n verifyAndMergeSlot: (\n issue: { issueId: string; featureWorkspace: string },\n slotIndex: number,\n item: VBriefItem,\n ) => Promise<SlotMergeResult>;\n applyTaskOperationToPlanFile: (\n planPath: string,\n operation: PersistedTaskOperation,\n workspacePath?: string,\n ) => Promise<unknown>;\n /** PAN-2385: fire the tiered commit feed + supervisor review after a slot merges. */\n fireTieredCommitHooks: (\n options: { issueId: string; workspacePath: string; item: VBriefItem; doc: VBriefDocument },\n ) => Promise<string[]>;\n recordSlotAssignment: (workspacePath: string, issueId: string, assignment: SlotAssignment) => void;\n clearSlotAssignment: (workspacePath: string, issueId: string, slotIndex: number, itemId?: string) => void;\n runGitCommand: (command: string, cwd: string) => Promise<unknown>;\n registeredSlotCapacityAvailable: (issueId: string, selectedCount: number) => boolean;\n tryReserveSwarmSlot: () => boolean;\n releaseSwarmSlot: () => void;\n spawnRun: (issueId: string, role: 'work', options: SpawnRunOptions) => Promise<unknown>;\n /** Per-issue hold: deaconIgnored (operator) suppresses all swarm coordination (PAN-2214);\n * system-set `stuck` is logged but no longer halts coordination (PAN-2469). */\n getIssueHold?: (issueId: string) => Pick<ReviewStatus, 'stuck' | 'deaconIgnored' | 'stuckReason'> | null;\n /** Per-issue record statusOverrides — the durable item done-ness the merged plan view applies. */\n readStatusOverrides?: (workspacePath: string, issueId: string) => Record<string, string> | undefined;\n /**\n * PAN-2372 WI-4 / FR-6: durable per-slot completion marker (written by slot\n * `pan done`). When present for a slot, it beats every other classification —\n * even a vanished session or missing agent — because it is the durable record\n * that the slot finished; the runtime plane is rebuildable and may be absent.\n */\n readSlotCompletion?: (workspacePath: string, issueId: string, slotIndex: number) => PanIssueSwarmSlotCompletion | undefined;\n getFinalizedAt: (issueId: string, workspacePath: string) => string | undefined;\n setFinalizedAt: (issueId: string, workspacePath: string, finalizedAt: string) => void;\n /**\n * Re-evaluated immediately before EVERY slot spawn: global freeze + per-issue hold.\n * The cycle-start checks alone let an in-flight wave keep dispatching after a freeze\n * activates mid-patrol (PAN-2214 slot-20 regression).\n */\n shouldDispatch?: (issueId: string) => boolean;\n /**\n * Inclusive upper bound for slot index allocation — the swarm reserve.\n * Unbounded allocation climbed slot-5..slot-20 under an inconsistent\n * registry (PAN-2214).\n */\n getMaxSlotIndex?: () => number;\n /** Durable slot assignments from the issue record; they survive registry resets (PAN-2214). */\n listSlotAssignments?: (issueId: string, workspacePath: string) => Array<{ slotIndex: number }>;\n /** Request issue-level review once every swarm item has been assembled into the feature branch. */\n requestIssueReview: (issueId: string, workspacePath: string) => Promise<RequestIssueReviewResult>;\n}\n\nconst defaultDeps: CoordinateSwarmSlotsDeps = {\n listFeatureWorkspaces: () => listFeatureWorkspaces({ includeSlotWorkspaces: false }),\n reconcileSlotState,\n listSessionNames: () => Effect.runPromise(listTmuxSessionNames()),\n isPaneDead: (sessionName) => Effect.runPromise(isPaneDead(sessionName)),\n getPaneExitStatus: async (sessionName) => {\n const values = await Effect.runPromise(listPaneValues(sessionName, '#{pane_dead_status}'));\n const raw = values[0]?.trim();\n if (!raw) return null;\n const status = Number(raw);\n return Number.isFinite(status) ? status : null;\n },\n getAgentRuntimeState: (agentId) => Effect.runPromise(getAgentRuntimeSnapshot(agentId)),\n getPaneOutputDigest: async (sessionName) => Effect.runPromise(capturePane(sessionName, 200)),\n getBranchTipCommitTime: async (workspacePath, branch) => {\n try {\n const { stdout } = await execAsync(`git log -1 --format=%ct ${JSON.stringify(branch)}`, { cwd: workspacePath });\n const seconds = Number(stdout.trim());\n return Number.isFinite(seconds) ? seconds * 1000 : null;\n } catch {\n return null;\n }\n },\n getSlotBranchAheadCount: defaultGetSlotBranchAheadCount,\n isSlotWorktreeClean: defaultIsSlotWorktreeClean,\n sendCompletionNudge: defaultSendCompletionNudge,\n slotWorktreeExists: existsSync,\n verifyAndMergeSlot,\n applyTaskOperationToPlanFile: (planPath, operation, workspacePath) =>\n Effect.runPromise(applyTaskOperationToPlanFile(planPath, operation, workspacePath)),\n fireTieredCommitHooks,\n recordSlotAssignment,\n clearSlotAssignment,\n runGitCommand: (command, cwd) => execAsync(command, { cwd }),\n registeredSlotCapacityAvailable: (issueId, selectedCount) => registeredSlotCapacityAvailable(issueId, selectedCount),\n tryReserveSwarmSlot,\n releaseSwarmSlot,\n spawnRun,\n getIssueHold: defaultGetIssueHold,\n shouldDispatch: defaultShouldDispatch,\n getMaxSlotIndex: defaultGetMaxSlotIndex,\n listSlotAssignments: listDurableSlotAssignments,\n readStatusOverrides: defaultReadStatusOverrides,\n readSlotCompletion: defaultReadSlotCompletion,\n getFinalizedAt: getSwarmFinalizedAt,\n setFinalizedAt: recordSwarmFinalizedAt,\n requestIssueReview: defaultRequestIssueReview,\n};\n\nfunction defaultGetMaxSlotIndex(): number {\n return Math.max(1, getConcurrencyLimits().reservedSwarmSlots);\n}\n\nfunction defaultGetIssueHold(issueId: string): Pick<ReviewStatus, 'stuck' | 'deaconIgnored' | 'stuckReason'> | null {\n try {\n return getReviewStatusSync(issueId);\n } catch {\n return null;\n }\n}\n\nfunction defaultReadStatusOverrides(workspacePath: string, issueId: string): Record<string, string> | undefined {\n // PAN-2372 WI-4 / FR-7: distinguish an absent record (silent undefined — a\n // brand-new issue that simply has no overrides yet) from an UNREADABLE record\n // (the file exists but won't parse). readIssueRecordForWorkspaceSync returns\n // null for both, so the existsSync check is what separates them. A corrupt\n // record is preserved as a .corrupt-<ts> sidecar by the atomic writer (WI-1);\n // warn so a broken sidecar never silently masks a slot's done-ness.\n const normalized = issueId.toUpperCase();\n const record = readIssueRecordForWorkspaceSync(workspacePath, normalized);\n if (record === null && existsSync(getIssueRecordPathForWorkspace(workspacePath, normalized))) {\n console.warn(`[swarm] record unreadable for ${normalized} — treating as no overrides; see .corrupt sidecar`);\n return undefined;\n }\n return record?.statusOverrides;\n}\n\n/**\n * PAN-2372 WI-4 / FR-6: read a slot's durable completion marker from the record\n * door. Returns undefined when no record or no marker exists. Used by\n * classifyInFlightSlots to recognize a slot whose `pan done` durably recorded\n * completion even when the runtime plane (agent state, tmux session) is gone.\n */\nfunction defaultReadSlotCompletion(\n workspacePath: string,\n issueId: string,\n slotIndex: number,\n): PanIssueSwarmSlotCompletion | undefined {\n try {\n return readIssueRecordForWorkspaceSync(workspacePath, issueId.toUpperCase())?.swarm?.slotCompletions?.[String(slotIndex)];\n } catch {\n return undefined;\n }\n}\n\nfunction defaultShouldDispatch(issueId: string): boolean {\n if (isDeaconGloballyPausedSync()) return false;\n const hold = defaultGetIssueHold(issueId);\n return !(hold?.stuck || hold?.deaconIgnored);\n}\n\nexport type SwarmSlotLifecycle = 'running' | 'ready-to-merge' | 'failed' | 'stalled' | 'awaiting-completion-signal' | 'failed-merge-blocked';\n\nexport interface ClassifyInFlightSlotsOptions {\n workspacePath?: string;\n issueId?: string;\n inferCompletion?: SwarmInferCompletionMode;\n stallThresholdMs?: number;\n now?: number;\n}\n\nexport interface ClassifiedSwarmSlot extends ReconciledSlotItem {\n lifecycle: SwarmSlotLifecycle;\n exitStatus?: number | null;\n reason?: 'missing-agent' | 'vanished-session' | 'pane-exit-nonzero' | 'pane-exit-unknown' | 'no-progress-timeout';\n stalledForMs?: number;\n signal?: 'inferred' | 'completion-nudge' | 'durable-completion';\n actions?: string[];\n}\n\ninterface SlotProgressObservation {\n commitTime: number | null;\n outputDigest: string;\n lastProgressAt: number;\n}\n\ninterface SlotAssignment {\n slotIndex: number;\n itemId: string;\n agentId?: string;\n branch?: string;\n}\n\ntype SlotAssignments = NonNullable<NonNullable<PanIssueRecord['swarm']>['slotAssignments']>;\n\nexport async function coordinateSwarmSlots(\n opts: CoordinateSwarmSlotsOptions = {},\n deps: CoordinateSwarmSlotsDeps = defaultDeps,\n): Promise<string[]> {\n const actions: string[] = [];\n const filterIssueId = opts.issueId?.toUpperCase();\n\n for (const workspace of deps.listFeatureWorkspaces()) {\n const issueId = workspace.issueId.toUpperCase();\n if (filterIssueId && issueId !== filterIssueId) continue;\n const hold = (deps.getIssueHold ?? defaultGetIssueHold)(issueId);\n if (hold?.deaconIgnored) {\n actions.push(`[swarm] skipped ${issueId}: deacon-ignored — operator hold`);\n continue;\n }\n // PAN-2469: `stuck` is a SYSTEM-set failure marker (delivery/verification\n // trouble), not an operator hold — skipping coordination on it froze the\n // whole swarm forever: PAN-2388's slots sat ready-to-merge for hours while\n // the coordinator skipped the issue because the verification-gate deadlock\n // (PAN-2461) had marked it stuck. Coordination (merge/gc/endgame) continues\n // through system-stuck; only operator deacon-ignore fully halts it.\n if (hold?.stuck) {\n actions.push(`[swarm] ${issueId} is system-stuck (${hold.stuckReason ?? 'unknown'}) — coordinating anyway (stuck no longer halts assembly, PAN-2469)`);\n }\n if (isSwarmAdvanceCoolingDown(issueId)) {\n actions.push(`[swarm] deferred ${issueId}: advance backoff active`);\n continue;\n }\n const failedMergeBlocks = getFailedMergeBlocks(issueId, workspace.workspacePath);\n const blockedSlotIndexes = new Set(failedMergeBlocks.map(block => block.slotIndex));\n const blockedItemIds = new Set(failedMergeBlocks.map(block => block.itemId));\n if (failedMergeBlocks.length > 0) {\n const slots = failedMergeBlocks\n .map(block => `slot ${block.slotIndex} (item ${block.itemId})`)\n .join(', ');\n actions.push(`[swarm] blocked slots for ${issueId}: ${slots} — other slots continue; run \\`pan swarm recover ${issueId} <slot>\\``);\n }\n\n try {\n const spec = await Effect.runPromise(findSpecByIssue(workspace.projectPath, issueId));\n if (!spec) continue;\n const planStatus = spec.document.plan.status;\n if (planStatus === 'completed' || planStatus === 'cancelled') continue;\n\n // Coordinate against the merged plan view; slot done-ness lives in statusOverrides.\n const overrides = (deps.readStatusOverrides ?? defaultReadStatusOverrides)(workspace.workspacePath, issueId);\n const doc = overrides && Object.keys(overrides).length > 0\n ? applyStatusOverrides(spec.document, overrides)\n : spec.document;\n\n const readiness = analyzeSwarmReadiness(doc);\n const slotEligibleCount = readiness.items.filter(item => item.slotEligible).length;\n // Eligibility gates dispatch only; active swarms still need merge/gc/endgame passes.\n const swarmInProgress = Object.entries(overrides ?? {})\n .some(([key, value]) => !key.includes('.') && value === 'completed');\n const dispatchEligible = readiness.swarmEligible && (slotEligibleCount >= 2 || swarmInProgress);\n if (dispatchEligible) {\n actions.push(`[swarm] considered ${issueId}: swarm eligible`);\n }\n\n const reconciled = await deps.reconcileSlotState(issueId, workspace.workspacePath, doc);\n if (!dispatchEligible) {\n const hasSlotState = reconciled.merged.length > 0 || reconciled.inFlight.length > 0\n || reconciled.branches.length > 0 || reconciled.agents.length > 0;\n if (!hasSlotState) {\n actions.push(...await finalizeSwarmIssueIfComplete(issueId, workspace.workspacePath, doc, deps));\n continue;\n }\n actions.push(`[swarm] considered ${issueId}: endgame (merge/cleanup only)`);\n }\n const classified = await classifyInFlightSlots(reconciled.inFlight, deps, {\n workspacePath: workspace.workspacePath,\n issueId,\n inferCompletion: swarmInferCompletionMode(),\n });\n for (const slot of classified) {\n actions.push(`[swarm] ${issueId} slot ${slot.slotIndex} ${slot.lifecycle}${slot.signal ? ` signal: ${slot.signal}` : ''}`);\n if (slot.actions) actions.push(...slot.actions);\n }\n const requeue = await requeueFailedSwarmSlots(issueId, workspace.workspacePath, classified, doc, reconciled, deps, blockedSlotIndexes);\n actions.push(...requeue.actions);\n actions.push(...recordStalledSlotRecovery(issueId, classified, workspace.workspacePath)); // stalled slots remain operator-recoverable\n actions.push(...await mergeReadySlots(issueId, workspace.workspacePath, doc, classified, deps, blockedSlotIndexes));\n actions.push(...await gcMergedSlots(issueId, workspace.workspacePath, reconciled.merged, deps));\n actions.push(...await gcOrphanedSlots(issueId, workspace.workspacePath, reconciled, deps));\n actions.push(...await finalizeSwarmIssueIfComplete(issueId, workspace.workspacePath, spec.document, deps));\n if (dispatchEligible) {\n actions.push(...await dispatchNextWave(issueId, workspace.workspacePath, requeue.doc, reconciled, analyzeSwarmReadiness(requeue.doc), deps, blockedSlotIndexes, blockedItemIds));\n }\n recordSwarmAdvanceSuccess(issueId);\n } catch (err) {\n recordSwarmAdvanceFailure(issueId);\n console.warn(`[deacon] Error coordinating swarm ${issueId}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return actions;\n}\n\nexport async function classifyInFlightSlots(\n slots: ReconciledSlotItem[],\n deps: Pick<CoordinateSwarmSlotsDeps, 'listSessionNames' | 'isPaneDead' | 'getPaneExitStatus'>\n & Partial<Pick<\n CoordinateSwarmSlotsDeps,\n 'getAgentRuntimeState'\n | 'getPaneOutputDigest'\n | 'getBranchTipCommitTime'\n | 'getSlotBranchAheadCount'\n | 'isSlotWorktreeClean'\n | 'sendCompletionNudge'\n | 'readSlotCompletion'\n >> = defaultDeps,\n options: ClassifyInFlightSlotsOptions = {},\n): Promise<ClassifiedSwarmSlot[]> {\n const sessionNames = new Set(await deps.listSessionNames());\n const classified: ClassifiedSwarmSlot[] = [];\n const now = options.now ?? Date.now();\n const stallThresholdMs = options.stallThresholdMs ?? swarmStallThresholdMs();\n\n for (const slot of slots) {\n // PAN-2372 WI-4 / FR-6: a durable completion marker (written by slot\n // `pan done`) is the STRONGEST completion signal — it is the durable record\n // that the slot finished, so it beats a vanished session, a missing agent,\n // and the rebuildable runtime plane. Check it before everything else. The\n // itemId guard (AC2) ignores a stale marker left for a slot now bound to a\n // different item (e.g. after a re-plan rotated slot→item).\n if (options.workspacePath && options.issueId) {\n const completion = await (deps.readSlotCompletion ?? defaultReadSlotCompletion)(\n options.workspacePath,\n options.issueId,\n slot.slotIndex,\n );\n if (completion && (!completion.itemId || completion.itemId === slot.itemId)) {\n classified.push({ ...slot, lifecycle: 'ready-to-merge', exitStatus: 0, signal: 'durable-completion' });\n continue;\n }\n }\n\n const durableReady = await classifyDurableReadySlot(slot, deps, options);\n if (!slot.agentId) {\n if (durableReady) {\n classified.push(durableReady);\n continue;\n }\n classified.push({ ...slot, lifecycle: 'failed', reason: 'missing-agent' });\n continue;\n }\n\n const runtimeState = deps.getAgentRuntimeState ? await deps.getAgentRuntimeState(slot.agentId) : null;\n if (runtimeState?.resolution === 'done' || runtimeState?.resolution === 'completed') {\n classified.push({ ...slot, lifecycle: 'ready-to-merge', exitStatus: 0 });\n continue;\n }\n\n if (!sessionNames.has(slot.agentId)) {\n if (durableReady) {\n classified.push(durableReady);\n continue;\n }\n classified.push({ ...slot, lifecycle: 'failed', reason: 'vanished-session' });\n continue;\n }\n\n const dead = await deps.isPaneDead(slot.agentId);\n if (!dead) {\n const outputDigest = deps.getPaneOutputDigest\n ? await deps.getPaneOutputDigest(slot.agentId).catch(() => '')\n : '';\n const commitTime = slot.branch && options.workspacePath && deps.getBranchTipCommitTime\n ? await deps.getBranchTipCommitTime(options.workspacePath, slot.branch).catch(() => null)\n : null;\n const progressKey = slotProgressKey(slot);\n const previous = slotProgressObservations.get(progressKey);\n if (\n !previous\n || previous.commitTime !== commitTime\n || previous.outputDigest !== outputDigest\n ) {\n slotProgressObservations.set(progressKey, { commitTime, outputDigest, lastProgressAt: now });\n clearSwarmCompletionObservation(progressKey);\n classified.push({ ...slot, lifecycle: 'running' });\n continue;\n }\n\n const stalledForMs = now - previous.lastProgressAt;\n if (stalledForMs > stallThresholdMs) {\n const inferred = await classifyDoneWithoutSignal(slot, deps, options, {\n commitTime,\n outputDigest,\n progressKey,\n stalledForMs,\n });\n if (inferred) {\n classified.push(inferred);\n continue;\n }\n\n classified.push({\n ...slot,\n lifecycle: 'stalled',\n reason: 'no-progress-timeout',\n stalledForMs,\n });\n continue;\n }\n\n classified.push({ ...slot, lifecycle: 'running' });\n continue;\n }\n\n const exitStatus = await deps.getPaneExitStatus(slot.agentId);\n if (exitStatus === 0) {\n classified.push({ ...slot, lifecycle: 'ready-to-merge', exitStatus });\n continue;\n }\n\n classified.push({\n ...slot,\n lifecycle: 'failed',\n exitStatus,\n reason: exitStatus === null ? 'pane-exit-unknown' : 'pane-exit-nonzero',\n });\n }\n\n return classified;\n}\n\nfunction slotProgressKey(slot: ReconciledSlotItem): string {\n return slot.agentId ?? slot.branch ?? `${slot.itemId}:${slot.slotIndex}`;\n}\n\nfunction swarmStallThresholdMs(): number {\n const raw = process.env.PAN_SWARM_STALL_THRESHOLD_MS;\n if (!raw) return DEFAULT_SWARM_STALL_THRESHOLD_MS;\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_SWARM_STALL_THRESHOLD_MS;\n}\n\nexport async function mergeReadySlots(\n issueId: string,\n workspacePath: string,\n doc: VBriefDocument,\n slots: ClassifiedSwarmSlot[],\n deps: Pick<CoordinateSwarmSlotsDeps, 'verifyAndMergeSlot' | 'applyTaskOperationToPlanFile' | 'fireTieredCommitHooks'> = defaultDeps,\n blockedSlotIndexes: Set<number> = new Set(),\n): Promise<string[]> {\n const actions: string[] = [];\n const itemsById = new Map(doc.plan.items.map(item => [item.id, item]));\n const planPath = join(workspacePath, '.pan', 'spec.vbrief.json');\n\n for (const slot of slots) {\n if (slot.lifecycle !== 'ready-to-merge') continue;\n\n if (blockedSlotIndexes.has(slot.slotIndex)) {\n actions.push(`[swarm] skipped merge slot ${slot.slotIndex} (item ${slot.itemId}) for ${issueId}: failed-merge block — awaiting \\`pan swarm recover\\``);\n continue;\n }\n\n const item = itemsById.get(slot.itemId);\n if (!item) {\n // PAN-2469: this skip was silent — a slot whose itemId drifted from the\n // current spec (e.g. after a re-plan) sat ready-to-merge forever with no\n // trace. Say so every pass.\n actions.push(`[swarm] cannot merge slot ${slot.slotIndex} for ${issueId}: itemId \"${slot.itemId}\" not in the current plan (spec drift?) — needs operator attention`);\n continue;\n }\n\n const branchKey = slot.branch ?? `feature/${issueId.toLowerCase()}-slot-${slot.slotIndex}`;\n if (isSlotMergeCoolingDown(branchKey)) {\n actions.push(`[swarm] skipped merge slot ${slot.slotIndex} (item ${item.id}) for ${issueId}: refire cooldown`);\n continue;\n }\n\n recordSlotMergeFire(branchKey);\n const result = await deps.verifyAndMergeSlot({ issueId, featureWorkspace: workspacePath }, slot.slotIndex, item);\n if (result.merged) {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'done',\n itemId: item.id,\n writerId: 'deacon-swarm',\n }, workspacePath);\n // PAN-2372 WI-4 / FR-6: the durable marker has done its job — the slot is\n // merged. Clear it so the same slotIndex can be re-dispatched later without\n // a stale \"completed\" marker falsely surfacing as ready-to-merge.\n clearSwarmSlotCompletion(workspacePath, issueId, slot.slotIndex);\n actions.push(`[swarm] merged slot ${slot.slotIndex} (item ${item.id}) for ${issueId}`);\n // PAN-2385: commits just landed — fire the tiered feed + supervisor review (best-effort).\n try {\n actions.push(...await deps.fireTieredCommitHooks({ issueId, workspacePath, item, doc }));\n } catch (err) {\n actions.push(`[tiered] commit hooks threw for ${issueId} item ${item.id}: ${err instanceof Error ? err.message : String(err)}`);\n }\n continue;\n }\n\n if (result.conflicts) {\n recordFailedMergeBlock({\n issueId,\n itemId: item.id,\n slotIndex: slot.slotIndex,\n branch: slot.branch,\n note: `Slot branch ${slot.branch ?? slot.slotIndex} did not merge cleanly`,\n }, workspacePath);\n actions.push(`[swarm] failed-merge slot ${slot.slotIndex} (item ${item.id}) for ${issueId}`);\n continue;\n }\n\n // Verification failure (merged result fails typecheck/tests) previously\n // fell through with no action at all — the slot silently re-verified on\n // every pass with nobody told why. Surface the failure so the operator\n // or recovery machinery can act on it.\n actions.push(`[swarm] verify-failed slot ${slot.slotIndex} (item ${item.id}) for ${issueId}: ${result.failure ?? 'verification failed'}`);\n }\n\n return actions;\n}\n\nexport function resetSwarmLoopSafetyForTests(): void {\n recentSlotMergeFires.clear();\n issueAdvanceFailures.clear();\n failedMergeBlocks.clear();\n slotProgressObservations.clear();\n resetSwarmCompletionInferenceForTests();\n}\n\nexport function recordSwarmAdvanceFailure(issueId: string, now = Date.now()): void {\n const normalized = issueId.toUpperCase();\n const previous = issueAdvanceFailures.get(normalized);\n const count = (previous?.count ?? 0) + 1;\n issueAdvanceFailures.set(normalized, {\n count,\n cooldownUntil: count >= SWARM_ADVANCE_FAILURE_THRESHOLD\n ? now + SWARM_ADVANCE_FAILURE_COOLDOWN_MS\n : previous?.cooldownUntil ?? 0,\n });\n}\n\nexport function recordSwarmAdvanceSuccess(issueId: string): void {\n issueAdvanceFailures.delete(issueId.toUpperCase());\n}\n\nexport function isSwarmAdvanceCoolingDown(issueId: string, now = Date.now()): boolean {\n const record = issueAdvanceFailures.get(issueId.toUpperCase());\n return record !== undefined && record.cooldownUntil > now;\n}\n\nexport function getFailedMergeBlock(\n issueId: string,\n slotIndex: number,\n workspacePath?: string,\n): FailedMergeBlock | undefined {\n const normalized = issueId.toUpperCase();\n if (workspacePath) {\n const swarm = readIssueRecordForWorkspaceSync(workspacePath, normalized)?.swarm;\n const keyed = swarm?.failedMergeBlocks?.[String(slotIndex)];\n if (keyed) return { ...keyed, issueId: keyed.issueId.toUpperCase() };\n const legacy = swarm?.failedMergeBlock;\n if (legacy && legacy.slotIndex === slotIndex) {\n return { ...legacy, issueId: legacy.issueId.toUpperCase() };\n }\n }\n return failedMergeBlocks.get(`${normalized}:${slotIndex}`);\n}\n\nexport function getFailedMergeBlocks(issueId: string, workspacePath?: string): FailedMergeBlock[] {\n const normalized = issueId.toUpperCase();\n const bySlot = new Map<number, FailedMergeBlock>();\n\n if (workspacePath) {\n const swarm = readIssueRecordForWorkspaceSync(workspacePath, normalized)?.swarm;\n if (swarm?.failedMergeBlock) {\n const legacy = swarm.failedMergeBlock;\n bySlot.set(legacy.slotIndex, { ...legacy, issueId: legacy.issueId.toUpperCase() });\n }\n if (swarm?.failedMergeBlocks) {\n for (const [key, block] of Object.entries(swarm.failedMergeBlocks)) {\n bySlot.set(Number(key), { ...block, issueId: block.issueId.toUpperCase() });\n }\n }\n }\n\n for (const [key, block] of failedMergeBlocks.entries()) {\n if (key.startsWith(`${normalized}:`) && !bySlot.has(block.slotIndex)) {\n bySlot.set(block.slotIndex, { ...block });\n }\n }\n\n return [...bySlot.values()].sort((a, b) => a.slotIndex - b.slotIndex);\n}\n\nexport function getSwarmFinalizedAt(issueId: string, workspacePath?: string): string | undefined {\n return workspacePath ? readIssueRecordForWorkspaceSync(workspacePath, issueId.toUpperCase())?.swarm?.finalizedAt : undefined;\n}\n\nexport function recordSwarmFinalizedAt(issueId: string, workspacePath: string, finalizedAt: string): void {\n writeSwarmFinalizedAt(workspacePath, issueId.toUpperCase(), finalizedAt);\n}\n\nexport function recordFailedMergeBlock(block: FailedMergeBlock, workspacePath?: string): void {\n const normalizedBlock = { ...block, issueId: block.issueId.toUpperCase() };\n failedMergeBlocks.set(`${normalizedBlock.issueId}:${normalizedBlock.slotIndex}`, normalizedBlock);\n if (workspacePath) {\n writeSwarmFailedMergeBlock(workspacePath, normalizedBlock.issueId, normalizedBlock.slotIndex, normalizedBlock);\n }\n}\n\nexport function clearFailedMergeBlock(issueId: string, slotIndex: number, workspacePath?: string): void {\n const normalizedIssueId = issueId.toUpperCase();\n failedMergeBlocks.delete(`${normalizedIssueId}:${slotIndex}`);\n if (workspacePath) {\n writeSwarmFailedMergeBlock(workspacePath, normalizedIssueId, slotIndex, undefined);\n }\n}\n\nexport async function recoverFailedMergeSlot(\n issueId: string,\n workspacePath: string,\n slotIndex: number,\n doc: VBriefDocument,\n action: SwarmRecoveryAction,\n deps: Pick<\n CoordinateSwarmSlotsDeps,\n 'applyTaskOperationToPlanFile'\n | 'clearSlotAssignment'\n | 'recordSlotAssignment'\n | 'registeredSlotCapacityAvailable'\n | 'tryReserveSwarmSlot'\n | 'releaseSwarmSlot'\n | 'spawnRun'\n | 'shouldDispatch'\n | 'getMaxSlotIndex'\n | 'listSlotAssignments'\n | 'runGitCommand'\n > = defaultDeps,\n): Promise<string[]> {\n const normalizedIssueId = issueId.toUpperCase();\n const block = getFailedMergeBlock(normalizedIssueId, slotIndex, workspacePath);\n if (!block) {\n const otherBlocks = getFailedMergeBlocks(normalizedIssueId, workspacePath);\n if (otherBlocks.length === 0) {\n return [`[swarm] no failed-merge slot for ${normalizedIssueId}`];\n }\n const lines = otherBlocks\n .map(b => ` slot ${b.slotIndex} (item ${b.itemId}): ${b.note}`)\n .join('\\n');\n return [\n `[swarm] no failed-merge block for ${normalizedIssueId} slot ${slotIndex}. Currently blocked slots:\\n${lines}`,\n ];\n }\n\n const planPath = join(workspacePath, '.pan', 'spec.vbrief.json');\n if (action === 'handoff') {\n block.note = `Operator handoff required for slot ${block.slotIndex} (item ${block.itemId})`;\n recordFailedMergeBlock(block, workspacePath);\n return [`[swarm] handoff paused ${normalizedIssueId} slot ${block.slotIndex} (item ${block.itemId})`];\n }\n\n if (action === 'drop') {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'done',\n itemId: block.itemId,\n writerId: 'deacon-swarm',\n reason: 'Dropped failed swarm slot after operator recovery',\n }, workspacePath);\n clearFailedMergeBlock(normalizedIssueId, block.slotIndex, workspacePath);\n deps.clearSlotAssignment(workspacePath, normalizedIssueId, block.slotIndex, block.itemId);\n return [`[swarm] dropped failed-merge slot ${block.slotIndex} (item ${block.itemId}) for ${normalizedIssueId}`];\n }\n\n // retry: archive the conflicted attempt so it cannot re-assert, then unblock\n // and dispatch a fresh attempt.\n await archiveFailedSwarmSlot(\n normalizedIssueId,\n workspacePath,\n {\n itemId: block.itemId,\n slotIndex: block.slotIndex,\n status: 'in_flight',\n branch: block.branch,\n agentId: block.branch ? `agent-${normalizedIssueId.toLowerCase()}-slot-${block.slotIndex}` : undefined,\n },\n { runGitCommand: deps.runGitCommand, clearSlotAssignment: deps.clearSlotAssignment },\n );\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'unblock',\n itemId: block.itemId,\n writerId: 'deacon-swarm',\n reason: 'Retrying failed swarm slot after merge conflict',\n }, workspacePath);\n clearFailedMergeBlock(normalizedIssueId, block.slotIndex, workspacePath);\n const remainingBlocks = getFailedMergeBlocks(normalizedIssueId, workspacePath);\n const blockedSlotIndexes = new Set(remainingBlocks.map(b => b.slotIndex));\n const blockedItemIds = new Set(remainingBlocks.map(b => b.itemId));\n const retryDoc = {\n ...doc,\n plan: {\n ...doc.plan,\n items: doc.plan.items.map(item =>\n item.id === block.itemId ? { ...item, status: 'pending' as const } : item\n ),\n },\n };\n return [\n `[swarm] retrying failed-merge slot ${block.slotIndex} (item ${block.itemId}) for ${normalizedIssueId}`,\n ...await dispatchNextWave(normalizedIssueId, workspacePath, retryDoc, {\n issueId: normalizedIssueId,\n merged: [],\n inFlight: [],\n pending: [],\n branches: [],\n agents: [],\n }, analyzeSwarmReadiness(retryDoc), deps, blockedSlotIndexes, blockedItemIds),\n ];\n}\n\nexport function recordStalledSlotRecovery(issueId: string, slots: ClassifiedSwarmSlot[], workspacePath?: string): string[] {\n const actions: string[] = [];\n const normalizedIssueId = issueId.toUpperCase();\n\n for (const slot of slots.filter(s => s.lifecycle === 'stalled')) {\n if (getFailedMergeBlock(normalizedIssueId, slot.slotIndex, workspacePath)) continue;\n\n recordFailedMergeBlock({\n issueId: normalizedIssueId,\n itemId: slot.itemId,\n slotIndex: slot.slotIndex,\n branch: slot.branch,\n note: `Slot ${slot.slotIndex} stalled with no branch commit or pane output progress`,\n }, workspacePath);\n actions.push(`[swarm] stalled slot ${slot.slotIndex} (item ${slot.itemId}) for ${normalizedIssueId}: recovery required`);\n }\n\n return actions;\n}\n\nfunction writeSwarmFailedMergeBlock(\n workspacePath: string,\n issueId: string,\n slotIndex: number,\n block: FailedMergeBlock | undefined,\n): void {\n const normalizedIssueId = issueId.toUpperCase();\n const existing = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId);\n const record = existing ?? createMinimalIssueRecord(normalizedIssueId);\n const existingSwarm = record.swarm ?? {};\n const existingBlocks = existingSwarm.failedMergeBlocks ?? {};\n\n // PAN-2364: fold a legacy singular block into the per-slot map and clear the\n // singular field on first write to the new keyed storage.\n const foldedBlocks: Record<string, PanIssueSwarmFailedMergeBlock> = { ...existingBlocks };\n if (existingSwarm.failedMergeBlock) {\n foldedBlocks[String(existingSwarm.failedMergeBlock.slotIndex)] = existingSwarm.failedMergeBlock;\n }\n\n const nextBlocks = { ...foldedBlocks };\n if (block) {\n nextBlocks[String(slotIndex)] = block;\n } else {\n delete nextBlocks[String(slotIndex)];\n }\n\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...existingSwarm,\n failedMergeBlocks: nextBlocks,\n failedMergeBlock: undefined,\n },\n });\n}\n\nfunction recordSlotMergeFire(branchKey: string, now = Date.now()): void {\n recentSlotMergeFires.set(branchKey, now + SLOT_MERGE_REFIRE_COOLDOWN_MS);\n}\n\nfunction isSlotMergeCoolingDown(branchKey: string, now = Date.now()): boolean {\n const until = recentSlotMergeFires.get(branchKey);\n if (until === undefined) return false;\n if (until > now) return true;\n recentSlotMergeFires.delete(branchKey);\n return false;\n}\n\nexport async function dispatchNextWave(\n issueId: string,\n workspacePath: string,\n doc: VBriefDocument,\n reconciled: SlotReconcileResult,\n readiness: SwarmReadinessVerdict,\n deps: Pick<\n CoordinateSwarmSlotsDeps,\n 'registeredSlotCapacityAvailable'\n | 'tryReserveSwarmSlot'\n | 'releaseSwarmSlot'\n | 'applyTaskOperationToPlanFile'\n | 'recordSlotAssignment'\n | 'clearSlotAssignment'\n | 'spawnRun'\n | 'shouldDispatch'\n | 'getMaxSlotIndex'\n | 'listSlotAssignments'\n > & Partial<Pick<CoordinateSwarmSlotsDeps, 'listSessionNames' | 'slotWorktreeExists'>> = defaultDeps,\n blockedSlotIndexes: Set<number> = new Set(),\n blockedItemIds: Set<string> = new Set(),\n): Promise<string[]> {\n const actions: string[] = [];\n const mergedItemIds = new Set(reconciled.merged.map(slot => slot.itemId));\n const slotEligibleIds = new Set(readiness.items.filter(item => item.slotEligible).map(item => item.id));\n const configuredMaxSlotIndex = Math.max(1, Math.floor((deps.getMaxSlotIndex ?? defaultGetMaxSlotIndex)()));\n const occupiedSlotIndexes = new Set([\n ...blockedSlotIndexes, // PAN-2364: blocked slots count as occupied so other slots cannot collide with them\n ...reconciled.inFlight.map(slot => slot.slotIndex),\n // Local branches hold their index until GC; archived indexes are added below.\n ...reconciled.branches.map(branch => branch.slotIndex),\n ...reconciled.agents.map(agent => agent.slotIndex),\n ...(deps.listSlotAssignments ?? listDurableSlotAssignments)(issueId, workspacePath).map(assignment => assignment.slotIndex),\n ...(reconciled.superseded ?? []).map(attempt => attempt.slotIndex),\n ]);\n const maxSlotIndex = applySupersededSlotHighWater(occupiedSlotIndexes, reconciled, configuredMaxSlotIndex);\n // Orphaned on-disk worktrees still occupy their index (PAN-2213).\n if (deps.slotWorktreeExists) {\n for (let index = 1; index <= maxSlotIndex; index++) {\n if (!occupiedSlotIndexes.has(index) && deps.slotWorktreeExists(`${workspacePath}-slot-${index}`)) {\n occupiedSlotIndexes.add(index);\n }\n }\n }\n const sessionNames = deps.listSessionNames ? await deps.listSessionNames() : [];\n const inFlightItemIds = new Set(reconciled.inFlight.map(slot => slot.itemId));\n const selectedItemIds: string[] = [];\n const planPath = join(workspacePath, '.pan', 'spec.vbrief.json');\n\n for (const item of getDispatchableItems(doc, mergedItemIds)) {\n if (blockedItemIds.has(item.id)) continue;\n if (!slotEligibleIds.has(item.id)) continue;\n if (inFlightItemIds.has(item.id)) continue;\n\n const overlapItemId = firstOverlappingItemId(item.id, [...inFlightItemIds, ...selectedItemIds], readiness);\n if (overlapItemId) {\n actions.push(`[swarm] deferred ${item.id} for ${issueId}: files_scope overlaps ${overlapItemId}`);\n continue;\n }\n\n if (!deps.registeredSlotCapacityAvailable(issueId, selectedItemIds.length)) {\n actions.push(`[swarm] deferred ${item.id} for ${issueId}: registered slot cap reached`);\n continue;\n }\n\n let slotIndex: number | null = null;\n for (;;) {\n const candidate = allocateSlotIndex(occupiedSlotIndexes, maxSlotIndex);\n if (candidate === null) break;\n const conflict = slotIndexConflictReason(issueId, workspacePath, candidate, sessionNames, reconciled, deps);\n if (!conflict) {\n slotIndex = candidate;\n break;\n }\n // An index-level conflict the registry missed (live session, unmerged\n // branch, orphaned worktree) means the index is occupied — advance to\n // the next free index instead of refusing the item (PAN-2213).\n occupiedSlotIndexes.add(candidate);\n actions.push(`[swarm] slot ${candidate} occupied for ${issueId}: ${conflict} — advancing`);\n }\n if (slotIndex === null) {\n const occupying = [...occupiedSlotIndexes].filter(index => index >= 1 && index <= maxSlotIndex).sort((a, b) => a - b);\n actions.push(\n `[swarm] deferred ${item.id} for ${issueId}: all slot indexes 1..${maxSlotIndex} are occupied (slots ${occupying.join(', ')})`\n + ` — run \\`pan swarm reset ${issueId}\\` if these slots are orphans`,\n );\n break;\n }\n\n if (!deps.tryReserveSwarmSlot()) {\n actions.push(`[swarm] deferred ${item.id} for ${issueId}: swarm dispatch budget exhausted`);\n continue;\n }\n\n try {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'claim',\n itemId: item.id,\n writerId: 'deacon-swarm',\n }, workspacePath);\n deps.recordSlotAssignment(workspacePath, issueId, {\n slotIndex,\n itemId: item.id,\n agentId: `agent-${issueId.toLowerCase()}-slot-${slotIndex}`,\n branch: `feature/${issueId.toLowerCase()}-slot-${slotIndex}`,\n });\n // Freeze/hold can activate mid-wave; the cycle-start gate has already passed\n // by then, so re-check before every spawn (PAN-2214 slot-20 regression).\n if (!(deps.shouldDispatch ?? defaultShouldDispatch)(issueId)) {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'unblock',\n itemId: item.id,\n writerId: 'deacon-swarm',\n reason: 'dispatch halted: freeze/hold active',\n }, workspacePath).catch(() => undefined);\n deps.clearSlotAssignment(workspacePath, issueId, slotIndex, item.id);\n deps.releaseSwarmSlot();\n actions.push(`[swarm] dispatch-halted ${item.id}: freeze/hold active`);\n continue;\n }\n await deps.spawnRun(issueId, 'work', {\n workspace: workspacePath,\n slotIndex,\n slotItemId: item.id,\n prompt: promptForDispatchItem(issueId, doc, item),\n });\n occupiedSlotIndexes.add(slotIndex);\n selectedItemIds.push(item.id);\n actions.push(`[swarm] dispatched ${dispatchPhaseForItem(doc, item)} slot ${slotIndex} (item ${item.id}) for ${issueId}`);\n } catch (error) {\n await deps.applyTaskOperationToPlanFile(planPath, {\n type: 'unblock',\n itemId: item.id,\n writerId: 'deacon-swarm',\n reason: `slot dispatch failed: ${error instanceof Error ? error.message : String(error)}`,\n }, workspacePath).catch(() => undefined);\n deps.clearSlotAssignment(workspacePath, issueId, slotIndex, item.id);\n deps.releaseSwarmSlot();\n actions.push(`[swarm] failed-dispatch ${item.id} for ${issueId}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n return actions;\n}\n\nfunction recordSlotAssignment(workspacePath: string, issueId: string, assignment: SlotAssignment): void {\n writeSwarmSlotAssignments(workspacePath, issueId, (existing) => [\n ...existing.filter(slot => slot.slotIndex !== assignment.slotIndex && slot.itemId !== assignment.itemId),\n {\n ...assignment,\n assignedAt: new Date().toISOString(),\n },\n ]);\n}\n\n/** Drop every recorded slot assignment for the issue — used by `pan swarm reset` (PAN-2214). */\nexport function clearAllSlotAssignments(workspacePath: string, issueId: string): void {\n writeSwarmSlotAssignments(workspacePath, issueId, () => []);\n}\n\nfunction clearSlotAssignment(workspacePath: string, issueId: string, slotIndex: number, itemId?: string): void {\n writeSwarmSlotAssignments(workspacePath, issueId, (existing) =>\n existing.filter(slot => slot.slotIndex !== slotIndex && (itemId === undefined || slot.itemId !== itemId))\n );\n}\n\nfunction writeSwarmSlotAssignments(\n workspacePath: string,\n issueId: string,\n update: (existing: SlotAssignments) => SlotAssignments,\n): void {\n const normalizedIssueId = issueId.toUpperCase();\n const existing = readIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId);\n const record = existing ?? createMinimalIssueRecord(normalizedIssueId);\n const existingAssignments: SlotAssignments = record.swarm?.slotAssignments ?? [];\n const slotAssignments = update(existingAssignments)\n .filter(assignment => Number.isInteger(assignment.slotIndex) && assignment.slotIndex > 0 && assignment.itemId.trim().length > 0)\n .sort((a, b) => a.slotIndex - b.slotIndex);\n\n writeIssueRecordForWorkspaceSync(workspacePath, normalizedIssueId, {\n ...record,\n swarm: {\n ...(record.swarm ?? {}),\n slotAssignments,\n },\n });\n}\n\nfunction slotIndexConflictReason(\n issueId: string,\n workspacePath: string,\n slotIndex: number,\n sessionNames: readonly string[],\n reconciled: SlotReconcileResult,\n deps: Partial<Pick<CoordinateSwarmSlotsDeps, 'slotWorktreeExists'>>,\n): string | undefined {\n const issueLower = issueId.toLowerCase();\n const agentId = `agent-${issueLower}-slot-${slotIndex}`;\n const branch = `feature/${issueLower}-slot-${slotIndex}`;\n if (sessionNames.includes(agentId)) {\n return `live ${agentId} session already exists`;\n }\n\n const unmergedBranch = reconciled.branches.find(slotBranch =>\n slotBranch.slotIndex === slotIndex && slotBranch.branch === branch && !slotBranch.merged\n );\n if (unmergedBranch) {\n return `unmerged ${branch} branch already exists`;\n }\n\n const slotWorkspacePath = `${workspacePath}-slot-${slotIndex}`;\n if (deps.slotWorktreeExists?.(slotWorkspacePath)) {\n return `slot worktree already exists at ${slotWorkspacePath}`;\n }\n\n return undefined;\n}\n\nfunction dispatchPhaseForItem(doc: VBriefDocument, item: VBriefItem): 'implementation' | 'synthesis' {\n return itemRequiresSynthesis(doc, item) && !synthesisContextForItem(item) ? 'synthesis' : 'implementation';\n}\n\nfunction promptForDispatchItem(issueId: string, doc: VBriefDocument, item: VBriefItem): string | undefined {\n if (!itemRequiresSynthesis(doc, item)) return undefined;\n\n const synthesisContext = synthesisContextForItem(item);\n if (synthesisContext) {\n return createActiveSlice(doc, {\n issueId,\n itemId: item.id,\n currentItemIds: [item.id],\n synthesisOutputs: { [item.id]: { contextUpdate: synthesisContext } },\n }).prompt;\n }\n\n const parentIds = doc.plan.edges\n .filter(edge => edge.type === 'blocks' && edge.to === item.id)\n .map(edge => edge.from);\n\n return [\n `SYNTHESIS PHASE for ${item.id}`,\n '',\n 'Do not implement this item yet. Summarize the blocking parent outputs into a concise context update for the implementation slot.',\n `Blocking parents: ${parentIds.join(', ') || '(none)'}`,\n '',\n 'Persist the synthesis context on the vBRIEF item metadata as synthesisContext, commit it, then stop.',\n ].join('\\n');\n}\n\nfunction itemRequiresSynthesis(doc: VBriefDocument, item: VBriefItem): boolean {\n return item.metadata?.requiresSynthesis === true || blockingParentCount(doc, item.id) > 1;\n}\n\nfunction synthesisContextForItem(item: VBriefItem): string | undefined {\n const raw = item.metadata?.synthesisContext;\n return typeof raw === 'string' && raw.trim().length > 0 ? raw : undefined;\n}\n\n/**\n * Lowest free slot index within the bound, derived purely from the occupied\n * set. Returns null — never an index above the bound — when indexes 1..bound\n * are all occupied (PAN-2214: unbounded allocation climbed slot-5..slot-20).\n */\nexport function allocateSlotIndex(occupiedSlotIndexes: ReadonlySet<number>, bound: number): number | null {\n const maxIndex = Math.max(1, Math.floor(bound));\n for (let slotIndex = 1; slotIndex <= maxIndex; slotIndex++) {\n if (!occupiedSlotIndexes.has(slotIndex)) return slotIndex;\n }\n return null;\n}\n\nfunction firstOverlappingItemId(\n itemId: string,\n activeItemIds: string[],\n readiness: SwarmReadinessVerdict,\n): string | undefined {\n for (const activeItemId of activeItemIds) {\n if ((readiness.overlapMatrix[itemId]?.[activeItemId]?.length ?? 0) > 0) return activeItemId;\n }\n return undefined;\n}\n\n/**\n * Whether the issue may register another slot. Counts only tmux-ALIVE slot\n * sessions (stale agents-table rows blocked all dispatch at zero live slots\n * after a reset), capped by the same swarm reserve tryReserveSwarmSlot\n * enforces — never maxWorkAgents (PAN-2214).\n */\nexport function registeredSlotCapacityAvailable(\n issueId: string,\n selectedCount: number,\n liveSlotCount: number = countRunningSwarmSlotsForIssue(issueId),\n limits: Pick<ConcurrencyLimits, 'reservedSwarmSlots'> = getConcurrencyLimits(),\n): boolean {\n return liveSlotCount + selectedCount < limits.reservedSwarmSlots;\n}\n"],"mappings":"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"}
|