@overdeck/desktop 0.45.13 → 0.45.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/package.json +1 -1
  2. package/server/{acceptance-criteria-CfujPRrz.js → acceptance-criteria-DHZk2ceV.js} +2 -2
  3. package/server/{advancing-selfheal-Bn5QiLtn.js → advancing-selfheal-CSuZ31bB.js} +5 -5
  4. package/server/{agent-gc-Cl9Nm0Zu.js → agent-gc-D_DxfBHR.js} +3 -3
  5. package/server/{agent-state-C6Rm6FPR.js → agent-state-EP2QFV9n.js} +1 -1
  6. package/server/{agent-state-service-JhFzYCP_.js → agent-state-service-BZkvgQf4.js} +5 -5
  7. package/server/{agent-state-service-U8feBf8t.js → agent-state-service-C_2ZAQRP.js} +1 -1
  8. package/server/{agents-DqQa4Dq_.js → agents-CsOzAmRg.js} +117 -74
  9. package/server/{agents-CxbuBjID.js → agents-DCvyTXNU.js} +1 -1
  10. package/server/{archive-planning-DmpT1_14.js → archive-planning-CTILQRnV.js} +1 -1
  11. package/server/{archive-planning-CPitEZo4.js → archive-planning-DkivCk1A.js} +4 -4
  12. package/server/{artifact-index-jobs-sMnNtPhy.js → artifact-index-jobs-CmsvQ1ey.js} +2 -2
  13. package/server/auto-commit-QAfsu3Sb.js +3 -0
  14. package/server/{backlog-auto-trigger-Cf9C8fwD.js → backlog-auto-trigger-ueRaT8Dy.js} +2 -2
  15. package/server/{bd-process-lock-D1aJxeYv.js → bd-process-lock-D3S4T4o-.js} +32 -11
  16. package/server/{beads-DRoj6-e1.js → beads-BGGxrkZ5.js} +96 -196
  17. package/server/{beads-CivpXztb.js → beads-CYsLiyIM.js} +1 -1
  18. package/server/{beads-query-tOsAYP5h.js → beads-query-B1DlJVp9.js} +24 -99
  19. package/server/beads-restore-CyygSmmn.js +23 -0
  20. package/server/{behavior-D3d2mVyD.js → behavior-Cpj03N4v.js} +3 -3
  21. package/server/{briefing-freshness-BL3Q6p7R.js → briefing-freshness-Kh5V8RTh.js} +4 -4
  22. package/server/{checkpoint-manager-j5URlFY7.js → checkpoint-manager-CAFos8e1.js} +1 -1
  23. package/server/{checkpoint-manager-DCxjQvP_.js → checkpoint-manager-fu9oVsR-.js} +2 -2
  24. package/server/checkpoint-worker.js +1 -1
  25. package/server/{checkpoints-BoX1H2Hf.js → checkpoints-1BqOlS4q.js} +2 -2
  26. package/server/{checkpoints-Bu_M_Q9W.js → checkpoints-DvhGi8P_.js} +1 -1
  27. package/server/{claude-hooks-provision-D-jGXmu1.js → claude-hooks-provision-s_wdpeVj.js} +2 -2
  28. package/server/{claude-permissions-DxIjkOVl.js → claude-permissions-CaWqysff.js} +2 -2
  29. package/server/{claude-settings-overlay-5b9X2S0C.js → claude-settings-overlay-BbA4FbVI.js} +1 -1
  30. package/server/{claude-settings-overlay-BPDS6GfE.js → claude-settings-overlay-CcTf0xzG.js} +2 -2
  31. package/server/{cli-s7bPWy-E.js → cli-BwCvCUBK.js} +9 -9
  32. package/server/cli-ClIQwgMI.js +3 -0
  33. package/server/{cliproxy-BituqWtR.js → cliproxy-BsoNNDAj.js} +2 -2
  34. package/server/{cliproxy-D3sHB0sI.js → cliproxy-C2xC-3vH.js} +1 -1
  35. package/server/{close-issue-CrBE7voz.js → close-issue-BleIwP3f.js} +5 -5
  36. package/server/{closed-issue-reaper-BRQBc7Xa.js → closed-issue-reaper-BwUUvjEW.js} +1 -1
  37. package/server/{closed-issue-reaper-DX9mYUji.js → closed-issue-reaper-mC5pujeb.js} +102 -30
  38. package/server/{codex-Bi1ITSOo.js → codex-B7DTpwEw.js} +1 -1
  39. package/server/{codex-CO0HrK3j.js → codex-DW60_5j2.js} +5 -5
  40. package/server/{compact-beads-CrA8-k10.js → compact-beads-CK_hHEnB.js} +1 -1
  41. package/server/{compact-beads-DUkCUFxA.js → compact-beads-DKL54y6j.js} +15 -8
  42. package/server/{config-B4_d7z7z.js → config-BRNQJXhA.js} +1 -1
  43. package/server/{config-DsCxzjXK.js → config-ZNnMpIlh.js} +2 -2
  44. package/server/{config-yaml-C_djSurJ.js → config-yaml-Dcz-8uit.js} +29 -3
  45. package/server/{conflict-gate-CpOn9KC-.js → conflict-gate-DGT8jCLp.js} +1 -1
  46. package/server/{conflict-gate-D47Kl78u.js → conflict-gate-DTje2Ll7.js} +3 -3
  47. package/server/{context-layers-BNhUBTkf.js → context-layers-BdUCQ-cl.js} +3 -3
  48. package/server/{context-layers-CHl3Nroz.js → context-layers-ByOWUjUg.js} +2 -2
  49. package/server/{control-settings-KyYNXZLv.js → control-settings-DwkAeooY.js} +4 -4
  50. package/server/{conversation-compaction-D3aS5PnS.js → conversation-compaction-OTYgd6eg.js} +8 -8
  51. package/server/{conversation-compaction-D4Wed1BJ.js → conversation-compaction-WYQZUVDm.js} +1 -1
  52. package/server/{conversation-service-CFZIjs-M.js → conversation-service-BR1OgvxO.js} +5 -5
  53. package/server/{conversation-service-DcDB5usR.js → conversation-service-C_kNZPLx.js} +1 -1
  54. package/server/{conversations-BSOU5qnu.js → conversations-DG2M8WnT.js} +4 -4
  55. package/server/{conversations-BbDPrz89.js → conversations-izHvSoAR.js} +1 -1
  56. package/server/{cost-BE_ulOrw.js → cost-B2mj17iG.js} +3 -3
  57. package/server/{cost-CaiG63FG.js → cost-DQ2ajr_m.js} +2 -2
  58. package/server/{cost-sync-D6AX8jv-.js → cost-sync-gTayEuWP.js} +3 -3
  59. package/server/{dag-BQFtXOuJ.js → dag-CqTehWpY.js} +3 -3
  60. package/server/{dangerous-git-ops-04Ba-Qu3.js → dangerous-git-ops-DDWQlPC3.js} +1 -1
  61. package/server/dashboard-db-worker.js +6 -6
  62. package/server/{deacon-Bz-6Wjmn.js → deacon-BqW9HMew.js} +3 -3
  63. package/server/{deacon-2EvA9Ci3.js → deacon-DrKDBeJL.js} +161 -1594
  64. package/server/{deacon-nudge-log-B-naf89q.js → deacon-nudge-log-D1wEK6zF.js} +1 -1
  65. package/server/deacon-swarm-BY5hKNaU.js +2 -0
  66. package/server/{deacon-swarm-DYYOzHRH.js → deacon-swarm-CO_A7xyd.js} +12 -105
  67. package/server/deacon.js +7 -7
  68. package/server/{devcontainer-renderer-Dx0C7VWJ.js → devcontainer-renderer-BQolp_qZ.js} +3 -3
  69. package/server/{dist-ya66D9ze.js → dist-Bc32rWJB.js} +1 -1
  70. package/server/dist-DGTwcZhI.js +3 -0
  71. package/server/{docker-D2TbXDO6.js → docker-s-esqZ__.js} +67 -28
  72. package/server/{ensure-devcontainer-BTiMfFp5.js → ensure-devcontainer-DA4-jF6R.js} +4 -4
  73. package/server/{ensure-devcontainer-BIShzs3M.js → ensure-devcontainer-pUVaT0h3.js} +1 -1
  74. package/server/{esm-shims-DiV9jHa_.js → esm-shims-CJHy8CZY.js} +1 -1
  75. package/server/{event-store-C02Gprug.js → event-store-CcJAhKCl.js} +1 -1
  76. package/server/{event-store-C71x6h0i.js → event-store-DRte2Rwt.js} +3 -3
  77. package/server/{events-BFDuPV6n.js → events-Bej1w_k8.js} +3 -3
  78. package/server/{events-D2gP2-Yv.js → events-CtsLScn8.js} +1 -1
  79. package/server/export-Dx_qJ3h8.js +87 -0
  80. package/server/{factory-ByfbrCab.js → factory-FN727tWr.js} +4 -4
  81. package/server/{feature-registry-population-CSH66UO8.js → feature-registry-population-ie-yBcQC.js} +4 -4
  82. package/server/{feature-registry-storage-DW7dUefc.js → feature-registry-storage-CkZTFSsn.js} +2 -2
  83. package/server/{features-x_aLR7U9.js → features-Dtm9ABuz.js} +2 -2
  84. package/server/{feedback-target-BFo9fScH.js → feedback-target-BYtpyt1i.js} +6 -6
  85. package/server/{feedback-target-C4VMPTZu.js → feedback-target-DVJQDiE4.js} +1 -1
  86. package/server/{feedback-writer-DCyd75yJ.js → feedback-writer-DOUhyIW2.js} +1 -1
  87. package/server/{feedback-writer-B9ZqnnX3.js → feedback-writer-fdE1BzeL.js} +4 -4
  88. package/server/{flywheel-DB48X7Nn.js → flywheel-Bi82iiNl.js} +1 -1
  89. package/server/{flywheel-D9NKvWqb.js → flywheel-Bv3wv2S6.js} +23 -15
  90. package/server/{flywheel-DwQCoZQG.js → flywheel-CUErLAyN.js} +13 -13
  91. package/server/{flywheel-merge-order-DrjmFXg4.js → flywheel-merge-order-BaEN3iyN.js} +7 -7
  92. package/server/{flywheel-merge-order-f1bi5XIf.js → flywheel-merge-order-DXjeBnJ1.js} +1 -1
  93. package/server/{forge-C-SoKy8U.js → forge-ButEdJ31.js} +2 -2
  94. package/server/forge-XlDgPQWs.js +2 -0
  95. package/server/{from-fu7ZumnY.js → from-CbtTxftl.js} +1 -1
  96. package/server/{fts-db-CL-YzSRG.js → fts-db-CBgBLZcL.js} +2 -2
  97. package/server/{fts-operations-Bylu5NjM.js → fts-operations-CI9Xuo_1.js} +2 -2
  98. package/server/{git-utils-Ym380hJZ.js → git-utils-BCLRWQ-y.js} +1 -1
  99. package/server/{git-utils-C8koBs8j.js → git-utils-ClfpP47N.js} +2 -2
  100. package/server/{github-app-DIr70YLg.js → github-app-DRD2woO0.js} +1 -1
  101. package/server/{github-app-DhycHVLF.js → github-app-DscZ0_B6.js} +2 -2
  102. package/server/{github-client-7gkcXcBS.js → github-client-DpiZnxGH.js} +2 -2
  103. package/server/{github-client-Ji9lUTNF.js → github-client-iFRw8f7e.js} +1 -1
  104. package/server/{github-pr-lookup-rt7T9FwA.js → github-pr-lookup-D-EBexxC.js} +2 -2
  105. package/server/{harness-resolve-CvGXUnAF.js → harness-resolve-iMjyNUJ2.js} +3 -3
  106. package/server/{health-events-DDfkoO5a.js → health-events-B_WsQyYm.js} +1 -1
  107. package/server/{health-events-D4E1DLN-.js → health-events-CRdxDFN2.js} +2 -2
  108. package/server/{hooks-DvdnCVv6.js → hooks-C1ScyVxP.js} +1 -1
  109. package/server/{hooks-D_6pAbuJ.js → hooks-C9b7Vqpw.js} +2 -2
  110. package/server/hume-K1pi8jC4.js +3 -0
  111. package/server/{hume-DkVOs1Qi.js → hume-TQ5pvOZ_.js} +2 -2
  112. package/server/{idle-stack-reaper-cDRXDpgE.js → idle-stack-reaper-B1kG7B_X.js} +2 -2
  113. package/server/{idle-stack-reaper-DNbV9-fj.js → idle-stack-reaper-iFVOAoJy.js} +1 -1
  114. package/server/{infra-Clew3DpF.js → infra-bpq1MHKU.js} +3 -3
  115. package/server/{injection-QCIHOpk6.js → injection-BLWfwTVZ.js} +1 -1
  116. package/server/{injection-ql0Nddcn.js → injection-DJqWld1v.js} +7 -7
  117. package/server/inspect-agent-477VxQim.js +2 -0
  118. package/server/{inspect-agent-DY18KEx4.js → inspect-agent-DytCsltn.js} +9 -9
  119. package/server/{internal-token-C90jBp-y.js → internal-token-CCaWaTwE.js} +1 -1
  120. package/server/{internal-token-BeXjPLKy.js → internal-token-CjlhdufS.js} +2 -2
  121. package/server/{io-CbAFXQge.js → io-BiQ2Cs3k.js} +2 -2
  122. package/server/{issue-closed-BYC2TCk-.js → issue-closed-FApNiOOs.js} +4 -4
  123. package/server/{issue-lifecycle-CLHbj8RS.js → issue-lifecycle-BkFWNjlD.js} +1 -1
  124. package/server/{issue-lifecycle-BoJa6qIt.js → issue-lifecycle-C-K53ASY.js} +21 -21
  125. package/server/{issue-service-singleton-BS9NENuR.js → issue-service-singleton-CuHGpJJP.js} +8 -8
  126. package/server/{issue-service-singleton-3g_CCY-1.js → issue-service-singleton-bG1WdSdQ.js} +1 -1
  127. package/server/{issues-BPcqPqfV.js → issues-CwQMphDH.js} +2 -2
  128. package/server/jsonl-parser-dNIjHgym.js +245 -0
  129. package/server/{label-cleanup-CwiCSZrb.js → label-cleanup-DYvAZknd.js} +3 -3
  130. package/server/{layers-OHHLphl0.js → layers-CD6FysRU.js} +2 -2
  131. package/server/{lifecycle-B8IdvUbt.js → lifecycle-C_73gi-C.js} +7 -7
  132. package/server/{lifecycle-io-BMCH1Bxg.js → lifecycle-io-C_Wu0_i-.js} +1 -1
  133. package/server/{lifecycle-io-C73m5e6R.js → lifecycle-io-CeYxP3cE.js} +4 -4
  134. package/server/{linear-client-BMxgycoy.js → linear-client-4qoKnuQu.js} +1 -1
  135. package/server/{linear-client-CgQlM4aT.js → linear-client-EtVyblVz.js} +2 -2
  136. package/server/memory-fts-worker.js +1 -1
  137. package/server/{merge-B7Oi-g6k.js → merge-7rqkTUm2.js} +3 -3
  138. package/server/{merge-agent-Bwm34MZ5.js → merge-agent-36wfYm2u.js} +1 -1
  139. package/server/{merge-agent-DNFFsiEm.js → merge-agent-4Zhlgvqp.js} +28 -28
  140. package/server/{merge-batch-BpYXUaqJ.js → merge-batch-itfnwdsT.js} +1 -1
  141. package/server/{merge-blockers-DIOZmqdK.js → merge-blockers-Bto_Oe_o.js} +2 -2
  142. package/server/{merge-BRkVaIx-.js → merge-brm721Es.js} +1 -1
  143. package/server/merge-ops-PzqsW69V.js +2 -0
  144. package/server/{merge-rebase-C8WH39MB.js → merge-rebase-Czfqfe4q.js} +2 -2
  145. package/server/{merge-set-CsEE2CyQ.js → merge-set-BIkGQL9j.js} +3 -3
  146. package/server/{merge-set-DOsBTBQc.js → merge-set-G1RHcu3D.js} +1 -1
  147. package/server/{merge-sync-C2B322Ot.js → merge-sync-B43Dybea.js} +2 -2
  148. package/server/{merge-sync-CcLM2vwW.js → merge-sync-DIrmlZUr.js} +1 -1
  149. package/server/{merge-train-BIm7-7cy.js → merge-train-DGqVuNZV.js} +3 -3
  150. package/server/{merge-train-deps-DG1oQ2DT.js → merge-train-deps-q15XLnAS.js} +4 -4
  151. package/server/{merge-verification-BAbjxEd5.js → merge-verification-Cqfxx6bE.js} +4 -4
  152. package/server/{multipart-parser-jKtKAXtl.js → multipart-parser-CiPxxfUH.js} +2 -2
  153. package/server/node_modules/.package-lock.json +1 -1
  154. package/server/{orphan-proposed-reconciler-zHrwJ3xr.js → orphan-proposed-reconciler-BWWHn4Lr.js} +15 -39
  155. package/server/{orphan-proposed-reconciler-BqVGaOIj.js → orphan-proposed-reconciler-DAD9FJtQ.js} +1 -1
  156. package/server/package-lock.json +2 -2
  157. package/server/package.json +1 -1
  158. package/server/{pan-dir-BlNrLzW7.js → pan-dir-Bj7Hy8iu.js} +3 -3
  159. package/server/{paths-CiVeo4N_.js → paths-C9DkhIOT.js} +2 -2
  160. package/server/{pickup-KLRUhThD.js → pickup-CKRuGDsB.js} +1 -1
  161. package/server/{pipeline-notifier-nkWCe042.js → pipeline-notifier-BkKbQ8ji.js} +1 -1
  162. package/server/{pipeline-notifier-DBF6dHxH.js → pipeline-notifier-CAurUste.js} +2 -2
  163. package/server/project-pipelines-BRWaGmI4.js +162 -0
  164. package/server/projects-KJ94e50I.js +3 -0
  165. package/server/{prompts-CXbQvevY.js → prompts-DfI5qbTW.js} +2 -2
  166. package/server/{providers-CUdAb5Qu.js → providers-CWDXoaMA.js} +7 -7
  167. package/server/providers-D-5txBRc.js +3 -0
  168. package/server/public/assets/{chunk-BO2N2NFS-C-6y8VFI.js → chunk-BO2N2NFS-ClukPsZQ.js} +4 -4
  169. package/server/public/assets/{diagram-OG6HWLK6-NACO1xW5.js → diagram-OG6HWLK6-Avtvq2qI.js} +1 -1
  170. package/server/public/assets/{dist-DQD-ZjQY.js → dist-BEHQuasD.js} +3 -3
  171. package/server/public/assets/{dist-D1FjqGgm.js → dist-BvmY-qb1.js} +1 -1
  172. package/server/public/assets/{ganttDiagram-6RSMTGT7-CEMAKgmE.js → ganttDiagram-6RSMTGT7-7KhCd0fH.js} +1 -1
  173. package/server/public/assets/{highlighted-body-OFNGDK62-D5lC7FW8.js → highlighted-body-OFNGDK62-iQoBMTf0.js} +1 -1
  174. package/server/public/assets/index-DUFDmvmH.css +1 -0
  175. package/server/public/assets/{index-BDqWyuZQ.js → index-DnTZ2QeN.js} +132 -132
  176. package/server/public/assets/{linear-DDHAMRPB.js → linear-CiJHW9g5.js} +1 -1
  177. package/server/public/assets/mermaid-GHXKKRXX-DZJOwgBG.js +1 -0
  178. package/server/public/assets/{pieDiagram-4H26LBE5-DwBdeKBb.js → pieDiagram-4H26LBE5-BOhmvUhW.js} +1 -1
  179. package/server/public/assets/{prod-DAZt0c4G.js → prod-DmLBBqat.js} +4 -4
  180. package/server/public/assets/{quadrantDiagram-W4KKPZXB-CNDLp-_m.js → quadrantDiagram-W4KKPZXB-Cjku660G.js} +1 -1
  181. package/server/public/assets/{sankeyDiagram-5OEKKPKP-oIUL_uO1.js → sankeyDiagram-5OEKKPKP-D52w5oPh.js} +1 -1
  182. package/server/public/assets/{xychartDiagram-2RQKCTM6-B-IM6Cck.js → xychartDiagram-2RQKCTM6-BTO07_Iv.js} +1 -1
  183. package/server/public/index.html +2 -2
  184. package/server/{pull-requests-kTRl7cWC.js → pull-requests-Bmre-Xlz.js} +3 -3
  185. package/server/{pull-requests-DZ-V7_LB.js → pull-requests-CKZPWhjD.js} +1 -1
  186. package/server/{rally-xCTZ-UcI.js → rally-BBd9tQ__.js} +3 -3
  187. package/server/rally-Dc2Wnxw2.js +3 -0
  188. package/server/{rally-api-jOk4vit_.js → rally-api-DDc85HIz.js} +1 -1
  189. package/server/{rally-api-DpZo3WwF.js → rally-api-DxZFObI_.js} +2 -2
  190. package/server/{rally-client-BQjm3aaq.js → rally-client-BADHn0m_.js} +1 -1
  191. package/server/{rally-client-CoWZeVEj.js → rally-client-DvvLiAQP.js} +4 -4
  192. package/server/{reap-terminal-sessions-CAmURC2h.js → reap-terminal-sessions-D6JDJsqF.js} +1 -1
  193. package/server/{reap-terminal-sessions-BwJb2DLJ.js → reap-terminal-sessions-D_xvy-Mk.js} +1 -1
  194. package/server/{rebuild-stack-BZ7j27xY.js → rebuild-stack-D19i080j.js} +6 -6
  195. package/server/{rebuild-stack-r-cxcr26.js → rebuild-stack-GOsWqXi3.js} +1 -1
  196. package/server/{reconstruct-cache-13EkMg_i.js → reconstruct-cache-lQrG4xGg.js} +6 -6
  197. package/server/record-pyB6VA32.js +3 -0
  198. package/server/recovery-trip-Dfh1tNHn.js +98 -0
  199. package/server/{release-engine-YLTnEO_K.js → release-engine-DxcMWRuK.js} +5 -5
  200. package/server/{release-set-DwvT_Opu.js → release-set-BYsgX7o6.js} +3 -3
  201. package/server/{remote-9u9WL0NJ.js → remote-8W2Yhygw.js} +3 -3
  202. package/server/{remote-B062S1Kc.js → remote-DmeL21dF.js} +3 -3
  203. package/server/{remote-agents-BBTg-vLT.js → remote-agents-BfQBE6MN.js} +5 -5
  204. package/server/{remote-agents-B4eWgwNd.js → remote-agents-DlvbzO7m.js} +1 -1
  205. package/server/{remote-completion-B0rmBnbL.js → remote-completion-BgkiSQmx.js} +12 -12
  206. package/server/resolver-dTpSSzaH.js +158 -0
  207. package/server/resume-DhcIqsTm.js +3 -0
  208. package/server/{review-agent-tfR5RDzG.js → review-agent-D025Wt7w.js} +22 -22
  209. package/server/{review-agent-Bf9XjLnl.js → review-agent-Rub0OpZc.js} +1 -1
  210. package/server/{review-artifacts-D0_IE6DQ.js → review-artifacts-CX951jTU.js} +6 -6
  211. package/server/{review-context-CXO5ml5D.js → review-context-DGGGR_w5.js} +7 -7
  212. package/server/{review-monitor-DfFUSx0J.js → review-monitor-0_qqMcnS.js} +2 -2
  213. package/server/{review-status-BcfwcAcO.js → review-status-4qqLkRMu.js} +17 -17
  214. package/server/{review-status-B0Axo-Ma.js → review-status-Br6lAFGO.js} +1 -1
  215. package/server/{review-status-enrichment-Cp5kFTGl.js → review-status-enrichment-Cr8m3uVL.js} +3 -3
  216. package/server/{review-status-sync-Bc0c_u12.js → review-status-sync-D3KUhsdA.js} +1 -1
  217. package/server/{review-status-sync-CEFty1pW.js → review-status-sync-OC-l1lNt.js} +2 -2
  218. package/server/{review-verdict-feedback-BOKRLLDf.js → review-verdict-feedback-DrWMuRaj.js} +6 -6
  219. package/server/{review-verdict-feedback-BnGtT0vN.js → review-verdict-feedback-YOzmsq9G.js} +1 -1
  220. package/server/{rollup-C22QDVxh.js → rollup-CnxbwaLH.js} +8 -8
  221. package/server/{rollup-BVqFuiS9.js → rollup-DmazRY0j.js} +1 -1
  222. package/server/{scanner-BLCnuXqY.js → scanner-DE1MqAaF.js} +7 -7
  223. package/server/{sequence-io-BozlUb6f.js → sequence-io-C0uoqfGx.js} +4 -4
  224. package/server/{sequencer-agent-BEDEHfd2.js → sequencer-agent-i-b2u4SJ.js} +10 -6
  225. package/server/server.js +1020 -293
  226. package/server/{service-C8jKYZ0w.js → service-D0_gh2tl.js} +1668 -1408
  227. package/server/{session-fork-BDGksK4e.js → session-fork-DZ12vipL.js} +2 -2
  228. package/server/{settings-CSLhh6qR.js → settings-ByqjPtFO.js} +2 -2
  229. package/server/{settings-DrRQCren.js → settings-DCC4BAqj.js} +3 -3
  230. package/server/settings-yydgaqhv.js +2 -0
  231. package/server/{shadow-engineering-BMcBN-Of.js → shadow-engineering-BhnmtW5m.js} +2 -2
  232. package/server/{shadow-state-CHqWHD3T.js → shadow-state-ByXZehsy.js} +1 -1
  233. package/server/{shadow-state-B4ayC7nx.js → shadow-state-CKm8xWX9.js} +2 -2
  234. package/server/{ship-log-CDVmOlZP.js → ship-log-DE_0Cv_i.js} +1 -1
  235. package/server/{smart-compaction-C-F5sP9P.js → smart-compaction-D5Zen3AA.js} +7 -7
  236. package/server/{smart-compaction-V9DBrGcr.js → smart-compaction-h4_ca6Uk.js} +1 -1
  237. package/server/{spawn-planning-session-Bz4_JES2.js → spawn-planning-session-Bgi7Ub02.js} +1 -1
  238. package/server/{spawn-planning-session-dSpOU0lP.js → spawn-planning-session-Dueit4WX.js} +15 -15
  239. package/server/{specialist-completion-Coz3eTSr.js → specialist-completion-BZ8M-WZ0.js} +1 -1
  240. package/server/{specialist-context-fmb03vXQ.js → specialist-context-BMq83C58.js} +5 -5
  241. package/server/{specialist-handoff-logger-B9HK_lRu.js → specialist-handoff-logger-BxX1YefH.js} +2 -2
  242. package/server/{specialist-logs-B24R2B9Y.js → specialist-logs-BWZYcJ6P.js} +3 -3
  243. package/server/{specialists-Chvvwf5z.js → specialists-8ZAguXef.js} +1 -1
  244. package/server/{specialists-CL7E8yUg.js → specialists-BudKrjOu.js} +76 -76
  245. package/server/{specialists-BGNZ0_ZW.js → specialists-DrPrC9Y9.js} +20 -256
  246. package/server/{specialists-B6f5-5nG.js → specialists-ZkW4Mb7U.js} +1 -1
  247. package/server/specs-DwoAEGrW.js +3 -0
  248. package/server/{src-DGAEtABV.js → src-DHn4Rd2F.js} +13 -2
  249. package/server/{src-D-VXCC9C.js → src-DNUUqkec.js} +6 -6
  250. package/server/{src-BVxZuHMg.js → src-Dv6L03vW.js} +3 -3
  251. package/server/{stack-health-BKbTTOT2.js → stack-health-Dclm7_tu.js} +1 -1
  252. package/server/{stack-health-C-le5erA.js → stack-health-DxsTx7II.js} +2 -2
  253. package/server/{state-home-CoyWsECg.js → state-home-CRowbXqU.js} +6 -6
  254. package/server/stuck-remediation-CFWUP8_I.js +1491 -0
  255. package/server/stuck-remediation-CLHd-lrF.js +2 -0
  256. package/server/{summary-fork-BF_0vxrq.js → summary-fork-CKc01Our.js} +2 -2
  257. package/server/{summary-fork-BlE30Q-I.js → summary-fork-CtCwBJ2Z.js} +8 -8
  258. package/server/{supervisor-BSeML_p0.js → supervisor-BA5D72Qa.js} +2 -2
  259. package/server/supervisor-DHjumXlL.js +2 -0
  260. package/server/{swarm-readiness-CQ4sjrXc.js → swarm-readiness-CL5sM9B1.js} +3 -3
  261. package/server/{system-prerequisites-DnmLYOnU.js → system-prerequisites-DmFSXIE5.js} +1 -1
  262. package/server/{teardown-workspace-CpcjDrZ4.js → teardown-workspace-DWmFJzTw.js} +37 -68
  263. package/server/{test-agent-queue-Bq298zZl.js → test-agent-queue-DjsQoV5X.js} +6 -6
  264. package/server/{test-verdict-CCDd25uN.js → test-verdict-BSqsQp3G.js} +1 -1
  265. package/server/{test-verdict-Bm4uv_AA.js → test-verdict-D1AmZ2c0.js} +1 -1
  266. package/server/{tldr-daemon-CaSUXd9r.js → tldr-daemon-C-MGomL8.js} +2 -2
  267. package/server/{tldr-daemon-Rn1Zue0P.js → tldr-daemon-DD9rI5gA.js} +1 -1
  268. package/server/{tmux-BVc-NeKM.js → tmux-C_d-lSIq.js} +2 -2
  269. package/server/{tmux-CbcrkUx5.js → tmux-x291Gjjb.js} +1 -1
  270. package/server/{token-D2OC_9ms.js → token-DfBf1bsd.js} +1 -1
  271. package/server/{tracker-config-C1Y_2CIo.js → tracker-config-CNODpd11.js} +2 -2
  272. package/server/{tracker-config-EsBoOWEy.js → tracker-config-DItsdelv.js} +1 -1
  273. package/server/{tracker-utils-DSb9cfrF.js → tracker-utils-B9ZoVA9b.js} +1 -1
  274. package/server/{tracker-utils-lph9C3Pw.js → tracker-utils-Ch2_5GGf.js} +2 -2
  275. package/server/{traefik-connect-5EP1WS_Z.js → traefik-connect-BF4x_LUQ.js} +1 -1
  276. package/server/{tunnel-DDe-ATFF.js → tunnel-YD80_IHr.js} +1 -1
  277. package/server/{tunnel-BFBCeo97.js → tunnel-r_5nHAI6.js} +3 -3
  278. package/server/{types-B5u3NxMl.js → types-33JEP4LZ.js} +1 -1
  279. package/server/{uat-train-8T24rPzc.js → uat-train-DDI00aqD.js} +1 -1
  280. package/server/{uat-train-DtKHHy1U.js → uat-train-DjkFWXge.js} +25 -25
  281. package/server/{validation-lyudzPvD.js → validation-DUTiJnyz.js} +4 -4
  282. package/server/{validation-COOXwNXU.js → validation-ict8hnXk.js} +1 -1
  283. package/server/{verification-runner-Dd1FX8Qk.js → verification-runner-ATaLbpr5.js} +1 -1
  284. package/server/{verification-runner-DO0nYTJx.js → verification-runner-inLgeQux.js} +12 -12
  285. package/server/{vtt-parser-C57tEF7-.js → vtt-parser-QnRfcjiU.js} +1 -1
  286. package/server/{work-agent-prompt-B2F3ZwKm.js → work-agent-prompt-fZljjA1_.js} +12 -12
  287. package/server/{workflows-Clz_AFwR.js → workflows-oBnJ7Tm0.js} +14 -14
  288. package/server/workflows-tU7KKxQi.js +2 -0
  289. package/server/{workspace-D0rCFemz.js → workspace-B2WOW9Hw.js} +1 -1
  290. package/server/{workspace-CY_2-Ddv.js → workspace-CNuW2j41.js} +3 -3
  291. package/server/{workspace-config-DA8U97k9.js → workspace-config-CBgMGhWs.js} +1 -1
  292. package/server/{workspace-manager-D6NgGkiF.js → workspace-manager-CB-R07R3.js} +12 -12
  293. package/server/{workspace-manager-BIfpzqdU.js → workspace-manager-DjUAJCSs.js} +1 -1
  294. package/server/{workspace-metadata-C8yn8kAH.js → workspace-metadata-9Nn5kgRl.js} +2 -2
  295. package/server/{workspace-metadata-DfgR40YU.js → workspace-metadata-Fd58uUQG.js} +1 -1
  296. package/server/{workspaces-DOeHyKmA.js → workspaces-BjWXntty.js} +94 -120
  297. package/server/writer-CQMGzEkw.js +3 -0
  298. package/server/writer-fe1-8iGc.js +251 -0
  299. package/sync-sources/hooks/record-cost-event.js +2 -1
  300. package/sync-sources/hooks/record-cost-event.js.map +1 -1
  301. package/server/auto-commit-wZ9X7Isd.js +0 -3
  302. package/server/bd-mutex-BItGvLQ8.js +0 -35
  303. package/server/beads-restore-CMbDSB5R.js +0 -60
  304. package/server/cli-CqgiSAU8.js +0 -3
  305. package/server/deacon-swarm-B8pgK2a7.js +0 -2
  306. package/server/dist-BYSj075e.js +0 -3
  307. package/server/forge-CUCYK7h_.js +0 -2
  308. package/server/hume-x9voULey.js +0 -3
  309. package/server/inspect-agent-D8UBDgfR.js +0 -2
  310. package/server/merge-ops-B7m-hBEZ.js +0 -2
  311. package/server/projects-BqRMlDOv.js +0 -3
  312. package/server/providers-gZ0cUgQM.js +0 -3
  313. package/server/public/assets/index-CZiADHcL.css +0 -1
  314. package/server/public/assets/mermaid-GHXKKRXX-DRM2ANcR.js +0 -1
  315. package/server/rally-CRteqXe0.js +0 -3
  316. package/server/record-CJsjvRO4.js +0 -3
  317. package/server/resume-R7xkSmLW.js +0 -3
  318. package/server/settings-CSaXtkoA.js +0 -2
  319. package/server/specs-oaaYaA5c.js +0 -3
  320. package/server/supervisor-03Tj_Wra.js +0 -2
  321. package/server/workflows-B4fIN8VP.js +0 -2
@@ -1,695 +1,53 @@
1
1
  import { i as __require, t as __commonJSMin } from "./rolldown-runtime-DNCzzKnI.js";
2
- import { $n as extractPrefixSync, Dn as getProjectSync, Gn as resolveProjectFromIssueSync, Hr as init_paths, Kr as sessionFilePath, Ln as listProjectsSync, Mt as readIssueRecordForWorkspaceSync, Nn as init_projects, Nt as readIssueRecordSync, Ot as init_record, Rr as encodeClaudeProjectDir, St as ensureIssueRecordSync, Vr as getOverdeckHome, an as queueBeadsAutoCommit, br as AGENTS_DIR, cn as getMainDivergence, dn as isStatePlanePath, er as init_issue_id, f as loadConfigSync, gr as TmuxError, kr as OVERDECK_HOME, ln as init_state_plane, lr as FsError, rn as init_auto_commit, s as init_load, sn as STATE_PLANE_PATHS, wn as getIssuePrefix, yr as init_errors, zt as writeIssueRecordSync } from "./config-yaml-C_djSurJ.js";
2
+ import { Ar as OVERDECK_HOME, Bt as writeIssueRecordSync, Ct as ensureIssueRecordSync, Kn as resolveProjectFromIssueSync, Nt as readIssueRecordForWorkspaceSync, On as getProjectSync, Pn as init_projects, Pt as readIssueRecordSync, Rn as listProjectsSync, Tn as getIssuePrefix, Zr as sessionFilePath, br as init_errors, cn as STATE_PLANE_PATHS, f as loadConfigSync, fn as isStatePlanePath, in as init_auto_commit, kt as init_record, ln as getMainDivergence, on as queueBeadsAutoCommit, qr as init_paths, s as init_load, un as init_state_plane, xr as AGENTS_DIR } from "./config-yaml-Dcz-8uit.js";
3
3
  import { a as init_activity_logger, n as emitActivityEntrySync, r as emitActivityTtsSync } from "./activity-logger-pcbf-e30.js";
4
- import { C as isPaneDead, D as listPaneValuesSync, E as listPaneValues, F as sendKeysAsync, L as sessionExists, O as listSessionNames, P as sendKeys, R as sessionExistsSync, T as killSessionSync, i as capturePane, k as listSessions, w as killSession, x as init_tmux } from "./tmux-BVc-NeKM.js";
5
- import { a as init_event_store, i as initEventStore } from "./event-store-C71x6h0i.js";
6
- import { n as CLAUDE_CODE_BEHAVIOR } from "./src-DGAEtABV.js";
7
- import { C as init_record_lock, S as needsReviewDispatch, c as init_review_status, h as reviewGatesPassedSync, s as getReviewStatusSync, u as loadReviewStatuses, w as withIssueRecordLock, x as init_review_dispatch_decision, y as setReviewStatusSync } from "./review-status-BcfwcAcO.js";
8
- import { d as init_agents, g as isTerminalIssueStage, h as getIssueStageSync, p as listAllAgentsSync } from "./briefing-freshness-BL3Q6p7R.js";
9
- import { An as getAgentDir, B as createOhmypiRuntimeSync, Bn as markAgentRunningState, D as init_context_overflow, Dn as clearAgentTroubledSync, Dt as captureTranscriptUserRecordSnapshot, E as resumeAgent, Fn as init_agent_state, G as init_termination, Hn as markAgentTroubled, Jn as saveAgentStateSync, K as stopAgent, Kn as resetAgentFailureCount, Mn as getAgentState, On as clearYieldForResumeSync, Ot as init_transcript_landing, Pn as getAgentStateSync, Q as listRunningAgentsSync, U as spawnAgent, Un as recordAgentFailure, V as init_ohmypi, X as listAgentStates, Xn as setAgentPausedSync, Y as init_queries, Z as listRunningAgents, Zn as setAgentYieldedSync, _r as init_runtime_state, _t as init_config, at as init_concurrency, cn as determineModel, ct as resetPatrolDispatchBudget, dt as workResumeSlotsAvailable, en as init_pi_fifo, er as init_persistent_logger, et as countRunningAgents, gn as buildDefaultResumeContinueMessage, gr as getAgentRuntimeStateSync, hr as getAgentRuntimeState, ht as DEFAULT_CLOISTER_CONFIG, it as getConcurrencyLimits, j as messageAgent, k as isContextOverflowTail, lt as tryReserveAdvancingSlot, mt as setCachedMemoryVerdict, nr as logDeaconEventSync, nt as describeRunningAgents, ot as releaseAdvancingSlot, pt as init_memory_verdict_cache, qn as saveAgentState, t as init_agents$1, tr as logAgentLifecycleSync, vr as saveAgentRuntimeState, vt as loadCloisterConfig, wt as deliverInitialPromptWithRetry, yt as loadCloisterConfigSync } from "./agents-DqQa4Dq_.js";
10
- import { t as init_behavior } from "./behavior-D3d2mVyD.js";
11
- import { a as init_tracker_config, t as getGitHubConfig } from "./tracker-config-C1Y_2CIo.js";
12
- import { i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils-lph9C3Pw.js";
4
+ import { C as isPaneDead, E as listPaneValues, F as sendKeysAsync, L as sessionExists, O as listSessionNames, P as sendKeys, R as sessionExistsSync, i as capturePane, k as listSessions, w as killSession, x as init_tmux } from "./tmux-C_d-lSIq.js";
5
+ import { a as init_event_store, i as initEventStore } from "./event-store-DRte2Rwt.js";
6
+ import { C as init_record_lock, S as needsReviewDispatch, c as init_review_status, h as reviewGatesPassedSync, s as getReviewStatusSync, u as loadReviewStatuses, w as withIssueRecordLock, x as init_review_dispatch_decision, y as setReviewStatusSync } from "./review-status-4qqLkRMu.js";
7
+ import { d as init_agents, g as isTerminalIssueStage, h as getIssueStageSync, p as listAllAgentsSync } from "./briefing-freshness-Kh5V8RTh.js";
8
+ import { An as getAgentDir, Bn as markAgentRunningState, D as init_context_overflow, Dn as clearAgentTroubledSync, Dt as captureTranscriptUserRecordSnapshot, E as resumeAgent, Fn as init_agent_state, G as init_termination, Jn as saveAgentStateSync, K as stopAgent, Kn as resetAgentFailureCount, Mn as getAgentState, On as clearYieldForResumeSync, Ot as init_transcript_landing, Pn as getAgentStateSync, Q as listRunningAgentsSync, Un as recordAgentFailure, X as listAgentStates, Xn as setAgentPausedSync, Y as init_queries, Z as listRunningAgents, Zn as setAgentYieldedSync, _r as init_runtime_state, _t as init_config, at as init_concurrency, ct as resetPatrolDispatchBudget, dt as workResumeSlotsAvailable, er as init_persistent_logger, et as countRunningAgents, gn as buildDefaultResumeContinueMessage, gr as getAgentRuntimeStateSync, hr as getAgentRuntimeState, it as getConcurrencyLimits, k as isContextOverflowTail, lt as tryReserveAdvancingSlot, mt as setCachedMemoryVerdict, nr as logDeaconEventSync, nt as describeRunningAgents, ot as releaseAdvancingSlot, pt as init_memory_verdict_cache, qn as saveAgentState, t as init_agents$1, tr as logAgentLifecycleSync, vr as saveAgentRuntimeState, vt as loadCloisterConfig, wt as deliverInitialPromptWithRetry, yt as loadCloisterConfigSync } from "./agents-CsOzAmRg.js";
9
+ import { i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils-Ch2_5GGf.js";
13
10
  import { n as mapGitHubStateToCanonical, t as init_state_mapping } from "./state-mapping-BvAgFK8n.js";
14
- import { c as init_review_status_sync, l as markWorkspaceStuck } from "./review-status-sync-CEFty1pW.js";
15
- import { f as init_config$1, m as loadConfigSync$1, p as loadConfig$1 } from "./config-DsCxzjXK.js";
16
- import { a as init_launcher_generator, n as init_state_home, t as findRecreatedLegacyStatePaths } from "./state-home-CoyWsECg.js";
17
- import { i as createCodexRuntimeSync, l as init_codex } from "./codex-CO0HrK3j.js";
18
- import { T as stampBootReconciliation, f as isFlywheelGloballyPaused, h as setBootReconciliationDecision, i as getFlywheelActiveRunId, l as isDeaconGloballyPaused, r as getBootReconciliationState, s as init_control_settings } from "./control-settings-KyYNXZLv.js";
19
- import { c as init_docker_stats, s as DockerStatsCollector } from "./stack-health-C-le5erA.js";
20
- import { a as queryBeadsForIssue, o as queryReadyBeadsByIssueLabels, r as init_beads_query, s as resolveBeadsQueryRoot } from "./beads-query-tOsAYP5h.js";
21
- import { n as __filename, r as init_esm_shims } from "./esm-shims-DiV9jHa_.js";
22
- import { O as init_specialists, R as parseReviewerSessionName, T as getTmuxSessionName, at as init_jsonl_parser, d as getAllProjectSpecialistStatuses, it as getSessionFilesSync, rt as getProjectDirsSync, st as parseClaudeSessionSync } from "./specialists-BGNZ0_ZW.js";
23
- import { t as recordDeaconNudge } from "./deacon-nudge-log-B-naf89q.js";
24
- import { n as init_review_monitor, t as REVIEW_SUB_ROLES } from "./review-monitor-DfFUSx0J.js";
25
- import { a as inferBranchFromWorkspace, i as findWorkspacePath, o as init_archive_planning } from "./archive-planning-CPitEZo4.js";
26
- import { n as init_issue_closed, r as isIssueClosed } from "./issue-closed-BYC2TCk-.js";
27
- import { n as shouldSkipDispatchAsMerged, t as init_merge_verification } from "./merge-verification-BAbjxEd5.js";
28
- import { n as init_review_verdict_feedback, t as deliverReviewVerdictFeedback } from "./review-verdict-feedback-BOKRLLDf.js";
29
- import { n as reconcileTraefikNetworks, t as init_traefik_connect } from "./traefik-connect-5EP1WS_Z.js";
30
- import { _ as recordRecoveryFailure, b as listFeatureWorkspaces, g as decideAgentAutonomousRedrive, r as coordinateSwarmSlots } from "./deacon-swarm-DYYOzHRH.js";
11
+ import { c as init_review_status_sync, l as markWorkspaceStuck } from "./review-status-sync-OC-l1lNt.js";
12
+ import { f as init_config$1, m as loadConfigSync$1, p as loadConfig$1 } from "./config-ZNnMpIlh.js";
13
+ import { n as init_state_home, t as findRecreatedLegacyStatePaths } from "./state-home-CRowbXqU.js";
14
+ import { T as stampBootReconciliation, h as setBootReconciliationDecision, l as isDeaconGloballyPaused, r as getBootReconciliationState, s as init_control_settings } from "./control-settings-DwkAeooY.js";
15
+ import { c as init_docker_stats, s as DockerStatsCollector } from "./stack-health-DxsTx7II.js";
16
+ import { a as queryBeadsForIssue, o as queryReadyBeadsByIssueLabels, r as init_beads_query, s as resolveBeadsQueryRoot } from "./beads-query-B1DlJVp9.js";
17
+ import { a as isAgentIdleForNudge, t as checkStuckAgentRemediation } from "./stuck-remediation-CFWUP8_I.js";
18
+ import { n as __filename, r as init_esm_shims } from "./esm-shims-CJHy8CZY.js";
19
+ import { t as recordDeaconNudge } from "./deacon-nudge-log-D1wEK6zF.js";
20
+ import { n as init_review_monitor, t as REVIEW_SUB_ROLES } from "./review-monitor-0_qqMcnS.js";
21
+ import { O as init_specialists, R as parseReviewerSessionName, T as getTmuxSessionName, d as getAllProjectSpecialistStatuses } from "./specialists-DrPrC9Y9.js";
22
+ import { a as inferBranchFromWorkspace, i as findWorkspacePath, o as init_archive_planning } from "./archive-planning-DkivCk1A.js";
23
+ import { n as init_issue_closed, r as isIssueClosed } from "./issue-closed-FApNiOOs.js";
24
+ import { n as shouldSkipDispatchAsMerged, t as init_merge_verification } from "./merge-verification-Cqfxx6bE.js";
25
+ import { n as init_review_verdict_feedback, t as deliverReviewVerdictFeedback } from "./review-verdict-feedback-DrWMuRaj.js";
26
+ import { n as reconcileTraefikNetworks, t as init_traefik_connect } from "./traefik-connect-BF4x_LUQ.js";
27
+ import { g as decideAgentAutonomousRedrive, r as coordinateSwarmSlots, y as listFeatureWorkspaces } from "./deacon-swarm-CO_A7xyd.js";
28
+ import { t as recordRecoveryFailure } from "./recovery-trip-Dfh1tNHn.js";
31
29
  import { n as isExplicitNoResumeRequest, t as init_no_resume_mode } from "./no-resume-mode-yrPEQ_pC.js";
32
- import { n as reconcileClosedIssueAgents } from "./closed-issue-reaper-DX9mYUji.js";
33
- import { a as RELEASED_LABEL, i as READY_LABEL, n as OBJECTION_LABEL, o as VETOED_LABEL, r as PARKED_LABEL, t as BLOCKS_MAIN_LABEL } from "./pickup-KLRUhThD.js";
34
- import { n as pruneTerminalStoppedAgents } from "./agent-gc-Cl9Nm0Zu.js";
35
- import { a as spawnWorkAgentThroughAgentsEndpoint, i as reconcileOrphanProposedSpecs, o as triggerRebuildAndStart } from "./orphan-proposed-reconciler-zHrwJ3xr.js";
36
- import { n as reconcileIdleWorkspaceStacks } from "./idle-stack-reaper-cDRXDpgE.js";
37
- import { i as readTestVerdictArtifact, n as decideUnsignaledTestAction, r as init_test_verdict } from "./test-verdict-Bm4uv_AA.js";
30
+ import { n as reconcileClosedIssueAgents } from "./closed-issue-reaper-mC5pujeb.js";
31
+ import { a as RELEASED_LABEL, i as READY_LABEL, n as OBJECTION_LABEL, o as VETOED_LABEL, r as PARKED_LABEL, t as BLOCKS_MAIN_LABEL } from "./pickup-CKRuGDsB.js";
32
+ import { n as pruneTerminalStoppedAgents } from "./agent-gc-D_DxfBHR.js";
33
+ import { a as spawnWorkAgentThroughAgentsEndpoint, i as reconcileOrphanProposedSpecs, o as triggerRebuildAndStart } from "./orphan-proposed-reconciler-BWWHn4Lr.js";
34
+ import { n as reconcileIdleWorkspaceStacks } from "./idle-stack-reaper-B1kG7B_X.js";
35
+ import { i as readTestVerdictArtifact, n as decideUnsignaledTestAction, r as init_test_verdict } from "./test-verdict-D1AmZ2c0.js";
38
36
  import { createRequire } from "node:module";
39
37
  import { join } from "node:path";
40
38
  import { Effect } from "effect";
41
- import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, unlinkSync, writeFileSync } from "fs";
39
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "fs";
42
40
  import { dirname as dirname$1, join as join$1 } from "path";
43
- import { cpus, homedir, loadavg } from "os";
41
+ import { cpus, loadavg } from "os";
44
42
  import { cpus as cpus$1, freemem as freemem$1, homedir as homedir$1, loadavg as loadavg$1, platform as platform$1, totalmem as totalmem$1 } from "node:os";
45
43
  import { closeSync as closeSync$1, existsSync as existsSync$1, openSync as openSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, unlinkSync as unlinkSync$1, writeFileSync as writeFileSync$1 } from "node:fs";
46
44
  import { access, readFile } from "node:fs/promises";
47
- import { readFile as readFile$1, readdir as readdir$1, stat as stat$2, writeFile as writeFile$1 } from "fs/promises";
45
+ import { readFile as readFile$1, readdir as readdir$1, writeFile as writeFile$1 } from "fs/promises";
48
46
  import { exec, execFile, spawn } from "node:child_process";
49
47
  import { promisify } from "node:util";
50
48
  import { exec as exec$1, execFile as execFile$1, spawn as spawn$1 } from "child_process";
51
49
  import { promisify as promisify$1 } from "util";
52
- import "node:crypto";
53
50
  import { layer } from "@effect/platform-node/NodeServices";
54
- //#region ../../lib/agent-input-detection.ts
55
- init_paths();
56
- init_activity_logger();
57
- init_issue_id();
58
- init_projects();
59
- init_state_plane();
60
- init_auto_commit();
61
- init_record();
62
- init_load();
63
- init_event_store();
64
- init_agents();
65
- init_tracker_utils();
66
- init_state_mapping();
67
- init_review_status_sync();
68
- init_record_lock();
69
- init_review_dispatch_decision();
70
- init_review_status();
71
- init_config$1();
72
- init_behavior();
73
- init_runtime_state();
74
- init_persistent_logger();
75
- init_agent_state();
76
- init_codex();
77
- init_pi_fifo();
78
- init_control_settings();
79
- init_docker_stats();
80
- init_launcher_generator();
81
- init_beads_query();
82
- init_transcript_landing();
83
- init_config();
84
- init_memory_verdict_cache();
85
- init_concurrency();
86
- init_queries();
87
- init_state_home();
88
- init_termination();
89
- init_ohmypi();
90
- init_context_overflow();
91
- init_agents$1();
92
- init_tmux();
93
- init_errors();
94
- const ANSI_PATTERN = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
95
- const MAX_PROMPT_CHARS = 2e3;
96
- const PANE_DETECTION_CACHE_TTL_MS = 1e4;
97
- const MAX_PANE_DETECTION_CACHE_ENTRIES = 256;
98
- const MAX_CONCURRENT_PANE_DETECTIONS = 4;
99
- const paneDetectionCache = /* @__PURE__ */ new Map();
100
- const paneDetectionInFlight = /* @__PURE__ */ new Map();
101
- const paneDetectionWaiters = [];
102
- let activePaneDetections = 0;
103
- function getPaneDetectionCacheKey(agentId, options) {
104
- return `${agentId}:${options.isPlanning === true ? "planning" : "agent"}:${options.lines ?? 90}`;
105
- }
106
- function sweepPaneDetectionCache(now = Date.now()) {
107
- for (const [key, entry] of paneDetectionCache) if (entry.expiresAt <= now) paneDetectionCache.delete(key);
108
- while (paneDetectionCache.size > MAX_PANE_DETECTION_CACHE_ENTRIES) {
109
- const oldestKey = paneDetectionCache.keys().next().value;
110
- if (!oldestKey) break;
111
- paneDetectionCache.delete(oldestKey);
112
- }
113
- }
114
- async function withPaneDetectionSlot(fn) {
115
- if (activePaneDetections >= MAX_CONCURRENT_PANE_DETECTIONS) await new Promise((resolve) => paneDetectionWaiters.push(resolve));
116
- activePaneDetections += 1;
117
- try {
118
- return await fn();
119
- } finally {
120
- activePaneDetections = Math.max(0, activePaneDetections - 1);
121
- paneDetectionWaiters.shift()?.();
122
- }
123
- }
124
- function cleanPaneLine(line) {
125
- return line.replace(ANSI_PATTERN, "").replace(/[\x00-\x1f\x7f]/g, "").replace(/\s+$/g, "");
126
- }
127
- function compactPrompt(prompt) {
128
- const compact = prompt.split("\n").map((line) => line.trim()).filter(Boolean).join("\n").trim();
129
- if (compact.length <= MAX_PROMPT_CHARS) return compact;
130
- return `${compact.slice(0, MAX_PROMPT_CHARS - 1)}…`;
131
- }
132
- function normalizeAwaitingInputPrompt(prompt) {
133
- return compactPrompt(prompt);
134
- }
135
- function snippetAround(lines, index, before = 8, after = 4) {
136
- const start = Math.max(0, index - before);
137
- const end = Math.min(lines.length, index + after + 1);
138
- return compactPrompt(lines.slice(start, end).join("\n"));
139
- }
140
- function lastIndexMatching(lines, predicate) {
141
- for (let i = lines.length - 1; i >= 0; i -= 1) if (predicate(lines[i], i)) return i;
142
- return -1;
143
- }
144
- function isRecentPromptIndex(lines, index) {
145
- if (index < 0) return false;
146
- return lines.length - index <= 25;
147
- }
148
- function isCurrentPromptIndex(lines, index, maxTrailingLines = 0) {
149
- if (index < 0) return false;
150
- return lines.length - index <= maxTrailingLines + 1;
151
- }
152
- function findPermissionMenuEndIndex(lines, menuStartIndex) {
153
- if (menuStartIndex < 0) return -1;
154
- const end = Math.min(lines.length, menuStartIndex + 8);
155
- for (let i = menuStartIndex; i < end; i += 1) if (/\s*3\.\s*No\b/i.test(lines[i])) return i;
156
- return menuStartIndex;
157
- }
158
- function looksLikeClaudePermissionMenu(text) {
159
- return /(?:^|\n)\s*❯?\s*1\.\s*Yes\b/i.test(text) && /(?:^|\n)\s*2\.\s*Yes,?\s*(?:and\s*)?(?:allow|don't ask|always)/i.test(text) && /(?:^|\n)\s*3\.\s*No\b/i.test(text);
160
- }
161
- function looksLikePermissionText(text) {
162
- return /permission|allow(?:\s+this)?|tool use|bash command|mcp tool|do you want to proceed|do you want to continue/i.test(text);
163
- }
164
- function looksLikeGenericConfirmation(line) {
165
- return /(?:\?|:)\s*(?:\[[Yy]\/[Nn]\]|\[[Nn]\/[Yy]\]|\([Yy]\/[Nn]\)|\([Nn]\/[Yy]\)|\[y\/N\]|\[Y\/n\])\s*$/i.test(line) || /\b(?:continue|proceed|confirm|approve|allow|run|execute|overwrite|delete|remove)\b.*(?:\[[Yy]\/[Nn]\]|\([Yy]\/[Nn]\)|\[y\/N\]|\[Y\/n\])/i.test(line);
166
- }
167
- function looksLikePiPermission(text) {
168
- return /(?:permission|approval|approve|allow).{0,80}(?:required|request|prompt|action|command)/i.test(text) || /(?:allow|approve|run|execute)\s+(?:this\s+)?(?:command|tool|action)/i.test(text);
169
- }
170
- function looksLikePlanningDone(text) {
171
- return /planning finalized\s*[—-]\s*click done/i.test(text) || /click Done in the dashboard/i.test(text) || /planning (?:is )?complete.{0,120}(?:click|press|select) Done/i.test(text);
172
- }
173
- /**
174
- * PAN-1520 (covers #1197) — Claude Code session-resume dialog. Fires when an
175
- * agent is resumed via `claude --resume <session>` and a prior session is
176
- * still considered active or interrupted. The dialog blocks tool execution
177
- * until acknowledged. Conservative patterns — we want false-negatives over
178
- * false-positives, so we only match strings that clearly indicate a resume
179
- * choice point.
180
- */
181
- function looksLikeSessionResumeDialog(text) {
182
- return /this session (?:is|was)\s+(?:still\s+)?(?:active|interrupted|running)/i.test(text) || /resume (?:the\s+)?previous session/i.test(text) || /(?:continue|resume) (?:this\s+)?session\??.{0,40}(?:\[[Yy]\/[Nn]\]|\([Yy]\/[Nn]\)|press\s+enter)/i.test(text) || /press enter to (?:continue|resume)/i.test(text);
183
- }
184
- /**
185
- * PAN-1834 — Codex/gpt-5.5 rate-limit / model-switch modal. The harness shows a
186
- * choice between keeping the current model and switching to an alternative.
187
- * To avoid matching prose that merely mentions rate limits, require BOTH option
188
- * lines to be present near the bottom of the pane.
189
- */
190
- function looksLikeRateLimitModelSwitchModal(text) {
191
- return /keep current model/i.test(text) && /switch to\s+\S+/i.test(text);
192
- }
193
- /**
194
- * PAN-1690 — Codex TUI approval prompt header. Codex asks for approval with a
195
- * distinctive "Would you like to …?" prompt box (command run, edits, network/
196
- * host grants) followed by a numbered Yes/…/No menu. Unlike Claude's menu,
197
- * Codex renders option descriptions and a footer hint *below* "3. No", so the
198
- * trailing-line heuristics the Claude path relies on never fire — we key on the
199
- * header instead. Verb list pulled from the codex binary; see PAN-1690.
200
- */
201
- function looksLikeCodexApprovalHeader(line) {
202
- return /Would you like to (?:run the following command|grant these permissions?|make the following edits|allow|apply)\b/i.test(line);
203
- }
204
- function detectAwaitingInputFromPaneSync(pane, options = {}) {
205
- const lines = pane.split("\n").map(cleanPaneLine).filter((line) => line.trim().length > 0);
206
- if (lines.length === 0) return null;
207
- const recentText = lines.slice(-45).join("\n");
208
- if (looksLikeClaudePermissionMenu(recentText) && looksLikePermissionText(recentText)) {
209
- const menuIndex = lastIndexMatching(lines, (line) => /❯?\s*1\.\s*Yes\b/i.test(line));
210
- const menuEndIndex = findPermissionMenuEndIndex(lines, menuIndex);
211
- if (isRecentPromptIndex(lines, menuIndex) && isCurrentPromptIndex(lines, menuEndIndex)) return {
212
- reason: "tool_permission",
213
- prompt: snippetAround(lines, menuIndex, 10, 3)
214
- };
215
- }
216
- const codexHeaderIndex = lastIndexMatching(lines, looksLikeCodexApprovalHeader);
217
- if (codexHeaderIndex >= 0 && isRecentPromptIndex(lines, codexHeaderIndex)) {
218
- const optionIndex = lastIndexMatching(lines, (line) => /^[^\w]*1\.\s*Yes\b/i.test(line));
219
- if (optionIndex > codexHeaderIndex && lines.length - optionIndex <= 12) return {
220
- reason: "tool_permission",
221
- prompt: snippetAround(lines, codexHeaderIndex, 1, 14)
222
- };
223
- }
224
- const piIndex = lastIndexMatching(lines, (line) => looksLikePiPermission(line) || looksLikeGenericConfirmation(line));
225
- if (isRecentPromptIndex(lines, piIndex) && isCurrentPromptIndex(lines, piIndex)) {
226
- const snippet = snippetAround(lines, piIndex, 6, 2);
227
- return {
228
- reason: looksLikeGenericConfirmation(lines[piIndex]) ? "confirmation" : "tool_permission",
229
- prompt: snippet
230
- };
231
- }
232
- if (options.isPlanning && looksLikePlanningDone(recentText)) {
233
- const doneIndex = lastIndexMatching(lines, (line) => /done|planning/i.test(line));
234
- return {
235
- reason: "planning_done",
236
- prompt: snippetAround(lines, doneIndex >= 0 ? doneIndex : lines.length - 1, 8, 2)
237
- };
238
- }
239
- if (looksLikeSessionResumeDialog(recentText)) {
240
- const resumeIndex = lastIndexMatching(lines, (line) => looksLikeSessionResumeDialog(line));
241
- return {
242
- reason: "session_resume",
243
- prompt: snippetAround(lines, resumeIndex >= 0 ? resumeIndex : lines.length - 1, 8, 2)
244
- };
245
- }
246
- if (looksLikeRateLimitModelSwitchModal(recentText)) {
247
- const rateLimitIndex = lastIndexMatching(lines, (line) => /keep current model|switch to\s+\S+/i.test(line));
248
- if (isRecentPromptIndex(lines, rateLimitIndex)) return {
249
- reason: "rate_limit",
250
- prompt: snippetAround(lines, rateLimitIndex >= 0 ? rateLimitIndex : lines.length - 1, 8, 2)
251
- };
252
- }
253
- return null;
254
- }
255
- async function detectAwaitingInputForAgentPromise(agentId, options = {}) {
256
- const cacheEnabled = options.cache !== false;
257
- const cacheKey = getPaneDetectionCacheKey(agentId, options);
258
- const now = Date.now();
259
- if (cacheEnabled) {
260
- sweepPaneDetectionCache(now);
261
- const cached = paneDetectionCache.get(cacheKey);
262
- if (cached && cached.expiresAt > now) {
263
- paneDetectionCache.delete(cacheKey);
264
- paneDetectionCache.set(cacheKey, cached);
265
- return cached.detection;
266
- }
267
- const inFlight = paneDetectionInFlight.get(cacheKey);
268
- if (inFlight) return inFlight;
269
- }
270
- const detectionPromise = withPaneDetectionSlot(async () => {
271
- const detection = detectAwaitingInputFromPaneSync(await Effect.runPromise(capturePane(agentId, options.lines ?? 90)), options);
272
- if (cacheEnabled) {
273
- paneDetectionCache.set(cacheKey, {
274
- expiresAt: Date.now() + PANE_DETECTION_CACHE_TTL_MS,
275
- detection
276
- });
277
- sweepPaneDetectionCache();
278
- }
279
- return detection;
280
- });
281
- if (!cacheEnabled) return detectionPromise;
282
- paneDetectionInFlight.set(cacheKey, detectionPromise);
283
- try {
284
- return await detectionPromise;
285
- } finally {
286
- paneDetectionInFlight.delete(cacheKey);
287
- }
288
- }
289
- /**
290
- * Effect-native variant of detectAwaitingInputForAgent. Fails with TmuxError if
291
- * the pane capture fails outside the in-cache fast path.
292
- */
293
- const detectAwaitingInputForAgent = (agentId, options = {}) => Effect.tryPromise({
294
- try: () => detectAwaitingInputForAgentPromise(agentId, options),
295
- catch: (cause) => new TmuxError({
296
- command: "capture-pane",
297
- message: `failed to detect awaiting input for ${agentId}`,
298
- cause
299
- })
300
- });
301
- /**
302
- * PAN-1690 — parse a Codex approval prompt (as captured by the codex-aware
303
- * branch of detectAwaitingInputFromPaneSync) into its header, detail, and
304
- * numbered options, so the dashboard can render the menu and answer it without
305
- * the terminal. Returns null when the text doesn't contain a usable menu
306
- * (fewer than two numbered options). Option lines tolerate a leading selection
307
- * cursor (❯ › > etc.); the footer hint and other non-numbered lines are
308
- * naturally excluded.
309
- */
310
- function parseCodexApprovalPrompt(text) {
311
- const lines = text.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
312
- if (lines.length === 0) return null;
313
- const headerIndex = lines.findIndex((l) => looksLikeCodexApprovalHeader(l));
314
- if (headerIndex < 0) return null;
315
- const optionRe = /^[^\w]*(\d+)\.\s*(.+?)\s*$/;
316
- const options = [];
317
- const detailLines = [];
318
- let firstOptionSeen = false;
319
- for (let i = headerIndex + 1; i < lines.length; i += 1) {
320
- const m = optionRe.exec(lines[i]);
321
- if (m) {
322
- firstOptionSeen = true;
323
- options.push({
324
- number: Number(m[1]),
325
- label: m[2].trim()
326
- });
327
- } else if (!firstOptionSeen) detailLines.push(lines[i]);
328
- }
329
- if (options.length < 2) return null;
330
- return {
331
- header: lines[headerIndex],
332
- detail: detailLines.join("\n"),
333
- options
334
- };
335
- }
336
- //#endregion
337
- //#region ../../lib/agent-enrichment.ts
338
- /**
339
- * Agent enrichment utilities (PAN-440 / PAN-1048)
340
- *
341
- * Shared functions for computing enrichment fields:
342
- * role, hasPendingQuestion, pendingQuestionCount, resolution, resolutionCount
343
- *
344
- * Used by both the legacy REST /api/agents endpoint and the new
345
- * AgentEnrichmentService background poller.
346
- *
347
- * PAN-1048: replaced the legacy `agentPhase` string with the role primitive —
348
- * the dashboard derives label/status from `role` + lifecycle state.
349
- */
350
- init_errors();
351
- init_tracker_config();
352
- const execAsync$8 = promisify$1(exec$1);
353
- function appendPaneDetectionKind(detection, kinds) {
354
- if (detection?.reason === "session_resume" && !kinds.includes("sessionResume")) kinds.push("sessionResume");
355
- if (detection?.reason === "rate_limit" && !kinds.includes("rateLimit")) kinds.push("rateLimit");
356
- }
357
- function isOwnActiveSpecialist(role) {
358
- return role === "review" || role === "test" || role === "ship";
359
- }
360
- function getClaudeProjectDir(workspacePath) {
361
- return join$1(homedir(), ".claude", "projects", encodeClaudeProjectDir(workspacePath));
362
- }
363
- async function getActiveSessionPath(projectDir) {
364
- if (!existsSync(projectDir)) return null;
365
- try {
366
- const jsonlFiles = (await readdir$1(projectDir)).filter((f) => f.endsWith(".jsonl"));
367
- if (jsonlFiles.length === 0) return null;
368
- const withMtime = (await Promise.all(jsonlFiles.map(async (f) => {
369
- try {
370
- return {
371
- name: f,
372
- path: join$1(projectDir, f),
373
- mtime: (await stat$2(join$1(projectDir, f))).mtime.getTime()
374
- };
375
- } catch {
376
- return null;
377
- }
378
- }))).filter((x) => x !== null);
379
- if (withMtime.length === 0) return null;
380
- withMtime.sort((a, b) => b.mtime - a.mtime);
381
- return withMtime[0].path;
382
- } catch {
383
- return null;
384
- }
385
- }
386
- function getProjectPathByPrefix(issuePrefix) {
387
- const resolved = resolveProjectFromIssueSync(`${issuePrefix}-1`);
388
- if (resolved) return resolved.projectPath;
389
- const config = getGitHubConfig();
390
- if (config) {
391
- for (const { owner, repo, prefix } of config.repos) if ((prefix || repo.toUpperCase().replace(/-CLI$/, "").replace(/-/g, "")).toUpperCase() === issuePrefix.toUpperCase()) {
392
- const possiblePaths = [
393
- join$1(homedir(), "Projects", repo),
394
- join$1(homedir(), "Projects", repo.replace(/-cli$/, "")),
395
- join$1(homedir(), "Projects", owner, repo)
396
- ];
397
- for (const path of possiblePaths) if (existsSync(path)) return path;
398
- }
399
- }
400
- return join$1(homedir(), "Projects");
401
- }
402
- async function getAgentWorkspacePromise(agentId) {
403
- const workspace = getAgentStateSync(agentId)?.workspace;
404
- if (workspace) return workspace;
405
- try {
406
- const { stdout: paneCwd } = await execAsync$8(`tmux display-message -t ${agentId} -p '#{pane_current_path}' 2>/dev/null`, { encoding: "utf-8" });
407
- const trimmed = paneCwd.trim();
408
- if (trimmed && existsSync(trimmed)) return trimmed;
409
- } catch {}
410
- const issueId = agentId.replace(/^(agent-|planning-)/, "").toUpperCase();
411
- const prefix = extractPrefixSync(issueId);
412
- if (!prefix) return null;
413
- try {
414
- const projectPath = getProjectPathByPrefix(prefix);
415
- const workspacePath = join$1(projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
416
- if (existsSync(workspacePath)) return workspacePath;
417
- return projectPath;
418
- } catch {
419
- return null;
420
- }
421
- }
422
- async function getAgentJsonlPathPromise(agentId) {
423
- const workspace = await Effect.runPromise(getAgentWorkspace(agentId));
424
- if (!workspace) return null;
425
- return await getActiveSessionPath(getClaudeProjectDir(workspace));
426
- }
427
- /**
428
- * Count outstanding AskUserQuestions across ALL of an agent's workspace JSONL
429
- * session files — not just the newest one. Claude Code rotates session files,
430
- * so an open AskUserQuestion can sit in a file that is not the most-recently-
431
- * modified. The complete-planning guard MUST be robust to that: scanning only
432
- * the active file let TIN-1 complete planning while the operator's question was
433
- * still open. Returns 0 only when no file has an unanswered AUQ.
434
- */
435
- async function countPendingAskUserQuestionsForAgentPromise(agentId) {
436
- const workspace = await Effect.runPromise(getAgentWorkspace(agentId));
437
- if (!workspace) return 0;
438
- const projectDir = getClaudeProjectDir(workspace);
439
- if (!existsSync(projectDir)) return 0;
440
- let files;
441
- try {
442
- files = (await readdir$1(projectDir)).filter((f) => f.endsWith(".jsonl"));
443
- } catch {
444
- return 0;
445
- }
446
- let total = 0;
447
- for (const f of files) try {
448
- const scan = await scanPendingInputsPromise(join$1(projectDir, f));
449
- total += scan.askUserQuestions.length;
450
- } catch {}
451
- return total;
452
- }
453
- /** Effect-native: count pending AskUserQuestions across all of an agent's JSONL files. */
454
- const countPendingAskUserQuestionsForAgent = (agentId) => Effect.promise(() => countPendingAskUserQuestionsForAgentPromise(agentId));
455
- /**
456
- * Read the last `maxBytes` from a file. Efficient for large JSONL files where
457
- * only recent entries (at the end) are relevant.
458
- */
459
- async function readFileTail(filePath, maxBytes) {
460
- try {
461
- const fileStat = await stat$2(filePath);
462
- const start = Math.max(0, fileStat.size - maxBytes);
463
- if (start === 0) return readFile$1(filePath, "utf-8");
464
- const { createReadStream } = await import("node:fs");
465
- return new Promise((resolve, reject) => {
466
- const stream = createReadStream(filePath, {
467
- start,
468
- encoding: "utf-8"
469
- });
470
- let data = "";
471
- stream.on("data", (chunk) => {
472
- data += chunk;
473
- });
474
- stream.on("end", () => resolve(data));
475
- stream.on("error", reject);
476
- });
477
- } catch {
478
- return "";
479
- }
480
- }
481
- const ASK_USER_QUESTION_HOOK_DENY_MARKER = "PAN-1520";
482
- function isAskUserQuestionHookDenyToolResult(item) {
483
- if (item.is_error !== true) return false;
484
- const content = item.content;
485
- if (typeof content === "string") return content.includes(ASK_USER_QUESTION_HOOK_DENY_MARKER);
486
- if (Array.isArray(content)) return content.some((part) => {
487
- if (typeof part === "string") return part.includes(ASK_USER_QUESTION_HOOK_DENY_MARKER);
488
- if (part && typeof part === "object" && "text" in part) {
489
- const text = part.text;
490
- return typeof text === "string" && text.includes(ASK_USER_QUESTION_HOOK_DENY_MARKER);
491
- }
492
- return false;
493
- });
494
- return false;
495
- }
496
- async function getPendingQuestionsPromise(jsonlPath) {
497
- return (await scanPendingInputsPromise(jsonlPath)).askUserQuestions;
498
- }
499
- /**
500
- * PAN-1520 — does this user-message entry carry operator text (i.e. an answer)
501
- * rather than just being a wrapper for a tool_result? When the hook denies an
502
- * AskUserQuestion the agent restates the question as plain text; the operator's
503
- * next user message — whether typed in the terminal, sent from the conversation
504
- * composer, or delivered by the answer-question route — is the actual answer.
505
- * The presence of that user-text turn after the deny is what resolves the AUQ.
506
- */
507
- function isUserTextEntry(entry) {
508
- if (!entry || typeof entry !== "object") return false;
509
- const e = entry;
510
- if (e.type !== "user") return false;
511
- const content = e.message?.content;
512
- if (typeof content === "string") return content.trim().length > 0;
513
- if (Array.isArray(content)) return content.some((item) => {
514
- if (!item || typeof item !== "object") return false;
515
- return item.type !== "tool_result";
516
- });
517
- return false;
518
- }
519
- async function scanPendingInputsPromise(jsonlPath) {
520
- if (!existsSync(jsonlPath)) return {
521
- askUserQuestions: [],
522
- enterPlanModeOpen: false,
523
- exitPlanModePending: false
524
- };
525
- try {
526
- const lines = (await readFileTail(jsonlPath, 512e3)).split("\n").filter((line) => line.trim());
527
- const askToolCalls = /* @__PURE__ */ new Map();
528
- const askAnswered = /* @__PURE__ */ new Set();
529
- const askDeniedAwaitingUser = /* @__PURE__ */ new Set();
530
- const exitPlanModeIds = /* @__PURE__ */ new Set();
531
- const exitPlanModeAnswered = /* @__PURE__ */ new Set();
532
- const enterPlanModeIds = /* @__PURE__ */ new Set();
533
- const exitPlanModeFiredAfterEnter = /* @__PURE__ */ new Set();
534
- for (const line of lines) try {
535
- const entry = JSON.parse(line);
536
- if (isUserTextEntry(entry)) {
537
- for (const id of askDeniedAwaitingUser) askAnswered.add(id);
538
- askDeniedAwaitingUser.clear();
539
- }
540
- const messageContent = entry.message?.content;
541
- if (!Array.isArray(messageContent)) continue;
542
- for (const item of messageContent) {
543
- if (item.type === "tool_use") {
544
- if (item.name === "AskUserQuestion" && typeof item.id === "string") askToolCalls.set(item.id, {
545
- toolId: item.id,
546
- timestamp: entry.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
547
- questions: item.input?.questions || []
548
- });
549
- else if (item.name === "ExitPlanMode" && typeof item.id === "string") {
550
- exitPlanModeIds.add(item.id);
551
- exitPlanModeFiredAfterEnter.add(item.id);
552
- } else if (item.name === "EnterPlanMode" && typeof item.id === "string") enterPlanModeIds.add(item.id);
553
- }
554
- if (item.type === "tool_result" && typeof item.tool_use_id === "string") {
555
- if (askToolCalls.has(item.tool_use_id)) if (isAskUserQuestionHookDenyToolResult(item)) askDeniedAwaitingUser.add(item.tool_use_id);
556
- else {
557
- askAnswered.add(item.tool_use_id);
558
- askDeniedAwaitingUser.delete(item.tool_use_id);
559
- }
560
- if (exitPlanModeIds.has(item.tool_use_id)) exitPlanModeAnswered.add(item.tool_use_id);
561
- }
562
- }
563
- } catch {}
564
- const askUserQuestions = Array.from(askToolCalls.entries()).filter(([id]) => !askAnswered.has(id)).map(([, question]) => question);
565
- const exitPlanModePending = Array.from(exitPlanModeIds).some((id) => !exitPlanModeAnswered.has(id));
566
- return {
567
- askUserQuestions,
568
- enterPlanModeOpen: enterPlanModeIds.size > 0 && exitPlanModeFiredAfterEnter.size === 0,
569
- exitPlanModePending
570
- };
571
- } catch {
572
- return {
573
- askUserQuestions: [],
574
- enterPlanModeOpen: false,
575
- exitPlanModePending: false
576
- };
577
- }
578
- }
579
- async function getAgentPendingQuestionsPromise(agentId) {
580
- const jsonlPath = await Effect.runPromise(getAgentJsonlPath(agentId));
581
- if (!jsonlPath) return [];
582
- return [...await Effect.runPromise(getPendingQuestions(jsonlPath))];
583
- }
584
- async function getAgentJsonlMtimePromise(agentId) {
585
- const jsonlPath = await Effect.runPromise(getAgentJsonlPath(agentId));
586
- if (!jsonlPath || !existsSync(jsonlPath)) return null;
587
- try {
588
- return (await stat$2(jsonlPath)).mtime.getTime();
589
- } catch {
590
- return null;
591
- }
592
- }
593
- async function computeAgentEnrichmentPromise(agentId, startedAt, hasActiveSpecialist, skipJsonlScan) {
594
- const isPlanning = agentId.startsWith("planning-");
595
- const stateRole = getAgentStateSync(agentId)?.role;
596
- const role = stateRole === "plan" || stateRole === "work" || stateRole === "review" || stateRole === "test" || stateRole === "ship" || stateRole === "flywheel" ? stateRole : isPlanning ? "plan" : void 0;
597
- const runtimeState = await Effect.runPromise(getAgentRuntimeState(agentId));
598
- let pendingQuestions = [];
599
- let enterPlanModeOpen = false;
600
- let exitPlanModePending = false;
601
- if (!skipJsonlScan) {
602
- const jsonlPath = await Effect.runPromise(getAgentJsonlPath(agentId));
603
- if (jsonlPath) {
604
- const scan = await scanPendingInputsPromise(jsonlPath);
605
- pendingQuestions = [...scan.askUserQuestions];
606
- enterPlanModeOpen = scan.enterPlanModeOpen;
607
- exitPlanModePending = scan.exitPlanModePending;
608
- }
609
- if (pendingQuestions.length > 0 && startedAt) {
610
- const agentStartTime = new Date(startedAt).getTime();
611
- pendingQuestions = pendingQuestions.filter((q) => {
612
- const qTime = new Date(q.timestamp).getTime();
613
- return !isNaN(qTime) && qTime >= agentStartTime;
614
- });
615
- }
616
- }
617
- const questionDetection = pendingQuestions.length > 0 ? {
618
- reason: "user_question",
619
- prompt: normalizeAwaitingInputPrompt(pendingQuestions[0]?.questions.map((q) => q.question).filter(Boolean).join("\n") || "Agent is waiting for a user answer")
620
- } : null;
621
- const runtimeDetection = runtimeState?.state === "waiting-on-human" ? {
622
- reason: runtimeState.waitingReason || "other",
623
- prompt: normalizeAwaitingInputPrompt(runtimeState.waitingNotification || "Agent is waiting for human input")
624
- } : null;
625
- const paneDetection = !questionDetection && !runtimeDetection ? await Effect.runPromise(detectAwaitingInputForAgent(agentId, { isPlanning })) : null;
626
- const fallbackDetection = runtimeState?.resolution === "needs_input" ? {
627
- reason: "other",
628
- prompt: normalizeAwaitingInputPrompt("Agent stopped because it needs human input or hit a blocker")
629
- } : null;
630
- const detection = questionDetection ?? runtimeDetection ?? paneDetection ?? fallbackDetection;
631
- const shouldSuppressPendingInput = hasActiveSpecialist === true && !isOwnActiveSpecialist(role);
632
- const hasPendingQuestion = !shouldSuppressPendingInput && detection !== null;
633
- const pendingInputKinds = [];
634
- let pendingAskUserQuestion;
635
- if (!shouldSuppressPendingInput) {
636
- if (pendingQuestions.length > 0) {
637
- pendingInputKinds.push("askUserQuestion");
638
- const first = pendingQuestions[0];
639
- pendingAskUserQuestion = {
640
- toolUseId: first.toolId,
641
- askedAt: first.timestamp,
642
- questions: first.questions.map((q) => ({
643
- question: q.question,
644
- header: q.header,
645
- multiSelect: q.multiSelect,
646
- options: q.options.map((o) => ({
647
- label: o.label,
648
- description: o.description
649
- }))
650
- }))
651
- };
652
- }
653
- if (exitPlanModePending) pendingInputKinds.push("exitPlanMode");
654
- if (enterPlanModeOpen && !exitPlanModePending) pendingInputKinds.push("enterPlanMode");
655
- appendPaneDetectionKind(detection, pendingInputKinds);
656
- }
657
- return {
658
- role,
659
- hasPendingQuestion,
660
- pendingQuestionCount: pendingQuestions.length,
661
- pendingQuestionPrompt: detection?.prompt,
662
- pendingQuestionReason: detection?.reason,
663
- pendingInputCount: pendingInputKinds.length,
664
- pendingInputKinds,
665
- pendingAskUserQuestion,
666
- resolution: runtimeState?.resolution || "working",
667
- resolutionCount: runtimeState?.resolutionCount || 0
668
- };
669
- }
670
- /**
671
- * Effect-native variant of computeAgentEnrichment. Fails with FsError if any
672
- * underlying filesystem read fails outside the swallowed branches.
673
- */
674
- const computeAgentEnrichment = (agentId, startedAt, hasActiveSpecialist, skipJsonlScan) => Effect.tryPromise({
675
- try: () => computeAgentEnrichmentPromise(agentId, startedAt, hasActiveSpecialist, skipJsonlScan),
676
- catch: (cause) => new FsError({
677
- path: getAgentDir(agentId),
678
- operation: "computeAgentEnrichment",
679
- cause
680
- })
681
- });
682
- /** Effect-native: resolve the workspace path for an agent (null on failure). */
683
- const getAgentWorkspace = (agentId) => Effect.promise(() => getAgentWorkspacePromise(agentId));
684
- /** Effect-native: resolve the active JSONL session path for an agent (null on failure). */
685
- const getAgentJsonlPath = (agentId) => Effect.promise(() => getAgentJsonlPathPromise(agentId));
686
- /** Effect-native: get the mtime of the agent's active JSONL session file. */
687
- const getAgentJsonlMtime = (agentId) => Effect.promise(() => getAgentJsonlMtimePromise(agentId));
688
- /** Effect-native: parse pending questions from a JSONL file. */
689
- const getPendingQuestions = (jsonlPath) => Effect.promise(() => getPendingQuestionsPromise(jsonlPath));
690
- /** Effect-native: get pending questions for an agent by id. */
691
- const getAgentPendingQuestions = (agentId) => Effect.promise(() => getAgentPendingQuestionsPromise(agentId));
692
- //#endregion
693
51
  //#region ../../../node_modules/.bun/undici@7.25.0/node_modules/undici/lib/core/symbols.js
694
52
  var require_symbols = /* @__PURE__ */ __commonJSMin(((exports, module) => {
695
53
  module.exports = {
@@ -22101,7 +21459,9 @@ var require_eventsource = /* @__PURE__ */ __commonJSMin(((exports, module) => {
22101
21459
  defaultReconnectionTime
22102
21460
  };
22103
21461
  }));
22104
- new ((/* @__PURE__ */ __commonJSMin(((exports, module) => {
21462
+ //#endregion
21463
+ //#region ../../../node_modules/.bun/undici@7.25.0/node_modules/undici/index.js
21464
+ var require_undici = /* @__PURE__ */ __commonJSMin(((exports, module) => {
22105
21465
  init_esm_shims();
22106
21466
  const Client = require_client();
22107
21467
  const Dispatcher = require_dispatcher();
@@ -22267,7 +21627,30 @@ new ((/* @__PURE__ */ __commonJSMin(((exports, module) => {
22267
21627
  globalThis.EventSource = module.exports.EventSource;
22268
21628
  }
22269
21629
  module.exports.install = install;
22270
- })))()).EnvHttpProxyAgent();
21630
+ }));
21631
+ //#endregion
21632
+ //#region ../../../node_modules/.bun/smee-client@5.0.0/node_modules/smee-client/index.js
21633
+ init_paths();
21634
+ init_errors();
21635
+ init_activity_logger();
21636
+ init_projects();
21637
+ init_tmux();
21638
+ init_agents();
21639
+ init_review_status_sync();
21640
+ init_review_dispatch_decision();
21641
+ init_review_status();
21642
+ init_runtime_state();
21643
+ init_persistent_logger();
21644
+ init_agent_state();
21645
+ init_transcript_landing();
21646
+ init_config();
21647
+ init_memory_verdict_cache();
21648
+ init_concurrency();
21649
+ init_queries();
21650
+ init_termination();
21651
+ init_context_overflow();
21652
+ init_agents$1();
21653
+ new (require_undici()).EnvHttpProxyAgent();
22271
21654
  //#endregion
22272
21655
  //#region ../../lib/smee.ts
22273
21656
  /**
@@ -22286,7 +21669,7 @@ new ((/* @__PURE__ */ __commonJSMin(((exports, module) => {
22286
21669
  * stopSmeeProcess();
22287
21670
  * isSmeeProcessRunning();
22288
21671
  */
22289
- init_errors();
21672
+ init_config$1();
22290
21673
  const SMEE_URL_PATH = join(homedir$1(), ".overdeck", "github-app", "smee-url");
22291
21674
  const SMEE_PID_PATH = join(homedir$1(), ".overdeck", "github-app", "smee.pid");
22292
21675
  const SMEE_LOG_PATH = join(homedir$1(), ".overdeck", "logs", "smee.log");
@@ -22451,10 +21834,9 @@ function startSmeeProcessSync() {
22451
21834
  }
22452
21835
  //#endregion
22453
21836
  //#region services/system-health-service.ts
22454
- init_agents$1();
22455
- init_projects();
22456
- init_tmux();
22457
- const execAsync$7 = promisify(exec);
21837
+ init_docker_stats();
21838
+ init_event_store();
21839
+ const execAsync$6 = promisify(exec);
22458
21840
  const DEFAULT_HEALTH_POLL_SECONDS = 15;
22459
21841
  const DEFAULT_RESOURCE_CONFIG = {
22460
21842
  memoryWarnGb: 4,
@@ -22586,7 +21968,7 @@ async function readProcMemoryDarwin() {
22586
21968
  let memAvailable = freemem$1();
22587
21969
  let memFree = freemem$1();
22588
21970
  try {
22589
- const { stdout } = await execAsync$7("vm_stat", {
21971
+ const { stdout } = await execAsync$6("vm_stat", {
22590
21972
  encoding: "utf-8",
22591
21973
  timeout: 5e3
22592
21974
  });
@@ -22606,7 +21988,7 @@ async function readProcMemoryDarwin() {
22606
21988
  let swapTotal = 0;
22607
21989
  let swapFree = 0;
22608
21990
  try {
22609
- const { stdout } = await execAsync$7("sysctl -n vm.swapusage", {
21991
+ const { stdout } = await execAsync$6("sysctl -n vm.swapusage", {
22610
21992
  encoding: "utf-8",
22611
21993
  timeout: 5e3
22612
21994
  });
@@ -22666,7 +22048,7 @@ async function readCpuPercent() {
22666
22048
  return Math.round((totalDelta - idleDelta) / totalDelta * 1e3) / 10;
22667
22049
  }
22668
22050
  async function readProcessTable() {
22669
- const { stdout } = await execAsync$7("ps -eo pid=,ppid=,rss=,args=", {
22051
+ const { stdout } = await execAsync$6("ps -eo pid=,ppid=,rss=,args=", {
22670
22052
  encoding: "utf-8",
22671
22053
  timeout: 1e4
22672
22054
  });
@@ -22943,6 +22325,7 @@ async function getSystemHealthSnapshot(snapshot) {
22943
22325
  }
22944
22326
  //#endregion
22945
22327
  //#region routes/resources/shared.ts
22328
+ init_load();
22946
22329
  init_docker_stats();
22947
22330
  function getCurrentDockerStats() {
22948
22331
  return [];
@@ -23111,378 +22494,6 @@ async function assessMemoryPressure() {
23111
22494
  return verdict;
23112
22495
  }
23113
22496
  //#endregion
23114
- //#region ../../lib/runtimes/claude-code.ts
23115
- /**
23116
- * Claude Code Runtime Implementation
23117
- *
23118
- * Implements AgentRuntime for Claude Code CLI.
23119
- *
23120
- * Session storage: ~/.claude/projects/<workspace-hash>/<session-id>.jsonl
23121
- * Session index: ~/.claude/projects/<workspace-hash>/sessions-index.json
23122
- */
23123
- init_agents$1();
23124
- init_tmux();
23125
- init_jsonl_parser();
23126
- init_errors();
23127
- const CLAUDE_PROJECTS_DIR = join$1(homedir(), ".claude", "projects");
23128
- /**
23129
- * Claude Code Runtime implementation
23130
- */
23131
- var ClaudeCodeRuntimeSync = class {
23132
- name = "claude-code";
23133
- getHarnessBehavior() {
23134
- return CLAUDE_CODE_BEHAVIOR;
23135
- }
23136
- /**
23137
- * Get the project directory for a workspace
23138
- *
23139
- * Claude Code hashes the workspace path to create project directories.
23140
- * We need to find the project directory that contains sessions for this workspace.
23141
- */
23142
- getProjectDirForWorkspace(workspace) {
23143
- if (!existsSync(CLAUDE_PROJECTS_DIR)) return null;
23144
- const projectDirs = getProjectDirsSync();
23145
- for (const projectDir of projectDirs) {
23146
- const indexPath = join$1(projectDir, "sessions-index.json");
23147
- if (existsSync(indexPath)) try {
23148
- if (readFileSync(indexPath, "utf-8").includes(workspace)) return projectDir;
23149
- } catch {}
23150
- }
23151
- return null;
23152
- }
23153
- /**
23154
- * Get the active session ID for an agent from the sessions index
23155
- */
23156
- getActiveSessionId(projectDir) {
23157
- const indexPath = join$1(projectDir, "sessions-index.json");
23158
- if (!existsSync(indexPath)) return null;
23159
- try {
23160
- const indexContent = readFileSync(indexPath, "utf-8");
23161
- const index = JSON.parse(indexContent);
23162
- if (index.sessions && Array.isArray(index.sessions)) {
23163
- const sessions = index.sessions;
23164
- if (sessions.length === 0) return null;
23165
- return sessions.sort((a, b) => {
23166
- return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
23167
- })[0].sessionId;
23168
- }
23169
- } catch {}
23170
- return null;
23171
- }
23172
- /**
23173
- * Get the most recent JSONL file for a project
23174
- */
23175
- getMostRecentJSONL(projectDir) {
23176
- const files = getSessionFilesSync(projectDir);
23177
- return files.length > 0 ? files[0] : null;
23178
- }
23179
- /**
23180
- * Get the session path for an agent
23181
- */
23182
- getSessionPath(agentId) {
23183
- const state = getAgentStateSync(agentId);
23184
- if (!state) return null;
23185
- const projectDir = this.getProjectDirForWorkspace(state.workspace);
23186
- if (!projectDir) return null;
23187
- const sessionId = this.getActiveSessionId(projectDir);
23188
- if (sessionId) {
23189
- const sessionPath = join$1(projectDir, `${sessionId}.jsonl`);
23190
- if (existsSync(sessionPath)) return sessionPath;
23191
- }
23192
- return this.getMostRecentJSONL(projectDir);
23193
- }
23194
- /**
23195
- * Get last activity timestamp for an agent
23196
- *
23197
- * Uses passive detection via JSONL file modification time.
23198
- */
23199
- getLastActivity(agentId) {
23200
- const sessionPath = this.getSessionPath(agentId);
23201
- if (!sessionPath || !existsSync(sessionPath)) return null;
23202
- try {
23203
- return statSync(sessionPath).mtime;
23204
- } catch {
23205
- return null;
23206
- }
23207
- }
23208
- /**
23209
- * Read active heartbeat file if it exists
23210
- */
23211
- getActiveHeartbeat(agentId) {
23212
- const heartbeatPath = join$1(homedir(), ".overdeck", "heartbeats", `${agentId}.json`);
23213
- if (!existsSync(heartbeatPath)) return null;
23214
- try {
23215
- const content = readFileSync(heartbeatPath, "utf-8");
23216
- const data = JSON.parse(content);
23217
- const timestamp = new Date(data.timestamp);
23218
- if ((/* @__PURE__ */ new Date()).getTime() - timestamp.getTime() > 300 * 1e3) return null;
23219
- return {
23220
- timestamp,
23221
- agentId: data.agent_id || agentId,
23222
- source: "active-heartbeat",
23223
- confidence: "high",
23224
- toolName: data.tool_name,
23225
- lastAction: data.last_action,
23226
- currentTask: data.current_task,
23227
- gitBranch: data.git_branch,
23228
- workspace: data.workspace,
23229
- pid: data.pid,
23230
- sessionId: data.session_id
23231
- };
23232
- } catch {
23233
- return null;
23234
- }
23235
- }
23236
- /**
23237
- * Get passive heartbeat from file timestamps
23238
- */
23239
- getPassiveHeartbeat(agentId) {
23240
- const lastActivity = this.getLastActivity(agentId);
23241
- if (!lastActivity) return null;
23242
- return {
23243
- timestamp: lastActivity,
23244
- agentId,
23245
- source: "jsonl",
23246
- confidence: "medium"
23247
- };
23248
- }
23249
- /**
23250
- * Get heartbeat for an agent
23251
- *
23252
- * Tries active heartbeat first (if hooks configured), falls back to passive.
23253
- */
23254
- getHeartbeat(agentId) {
23255
- const activeHeartbeat = this.getActiveHeartbeat(agentId);
23256
- if (activeHeartbeat) return activeHeartbeat;
23257
- return this.getPassiveHeartbeat(agentId);
23258
- }
23259
- /**
23260
- * Get token usage for an agent's current session
23261
- */
23262
- getTokenUsage(agentId) {
23263
- const sessionPath = this.getSessionPath(agentId);
23264
- if (!sessionPath) return null;
23265
- const sessionUsage = parseClaudeSessionSync(sessionPath);
23266
- if (!sessionUsage) return null;
23267
- return sessionUsage.usage;
23268
- }
23269
- /**
23270
- * Get cost breakdown for an agent's current session
23271
- */
23272
- getSessionCost(agentId) {
23273
- const sessionPath = this.getSessionPath(agentId);
23274
- if (!sessionPath) return null;
23275
- const sessionUsage = parseClaudeSessionSync(sessionPath);
23276
- if (!sessionUsage) return null;
23277
- const inputPrice = 3 / 1e6;
23278
- const outputPrice = 15 / 1e6;
23279
- const cacheReadPrice = .3 / 1e6;
23280
- const cacheWritePrice = 3.75 / 1e6;
23281
- const usage = sessionUsage.usage;
23282
- const inputCost = usage.inputTokens * inputPrice;
23283
- const outputCost = usage.outputTokens * outputPrice;
23284
- const cacheReadCost = (usage.cacheReadTokens || 0) * cacheReadPrice;
23285
- const cacheWriteCost = (usage.cacheWriteTokens || 0) * cacheWritePrice;
23286
- return {
23287
- inputCost,
23288
- outputCost,
23289
- cacheReadCost,
23290
- cacheWriteCost,
23291
- totalCost: inputCost + outputCost + cacheReadCost + cacheWriteCost,
23292
- currency: "USD"
23293
- };
23294
- }
23295
- /**
23296
- * Send a message to a running agent
23297
- */
23298
- async sendMessage(agentId, message) {
23299
- if (!sessionExistsSync(agentId)) throw new Error(`Agent ${agentId} is not running`);
23300
- await Effect.runPromise(sendKeys(agentId, message));
23301
- const mailDir = join$1(getAgentDir(agentId), "mail");
23302
- mkdirSync(mailDir, { recursive: true });
23303
- writeFileSync(join$1(mailDir, `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.md`), `# Message\n\n${message}\n`);
23304
- }
23305
- /**
23306
- * Kill an agent
23307
- */
23308
- killAgent(agentId) {
23309
- if (!sessionExistsSync(agentId)) throw new Error(`Agent ${agentId} is not running`);
23310
- killSessionSync(agentId);
23311
- saveAgentRuntimeState(agentId, {
23312
- state: "idle",
23313
- lastActivity: (/* @__PURE__ */ new Date()).toISOString()
23314
- });
23315
- const state = getAgentStateSync(agentId);
23316
- if (state) {
23317
- state.status = "stopped";
23318
- saveAgentStateSync(state);
23319
- }
23320
- }
23321
- /**
23322
- * Spawn a new agent
23323
- */
23324
- async spawnAgent(config) {
23325
- const state = await spawnAgent({
23326
- issueId: config.agentId.replace(/^agent-/, ""),
23327
- workspace: config.workspace,
23328
- harness: "claude-code",
23329
- model: determineModel({
23330
- model: config.model,
23331
- role: "work",
23332
- spawnKey: `work:${config.agentId.replace(/^agent-/, "")}`
23333
- }),
23334
- role: "work",
23335
- prompt: config.prompt
23336
- });
23337
- const projectDir = this.getProjectDirForWorkspace(config.workspace);
23338
- const sessionId = projectDir ? this.getActiveSessionId(projectDir) : void 0;
23339
- return {
23340
- id: state.id,
23341
- sessionId: sessionId || "unknown",
23342
- runtime: "claude-code",
23343
- model: state.model,
23344
- workspace: state.workspace,
23345
- startedAt: new Date(state.startedAt)
23346
- };
23347
- }
23348
- /**
23349
- * List all sessions for this runtime
23350
- */
23351
- listSessions(workspace) {
23352
- const sessions = [];
23353
- if (workspace) {
23354
- const projectDir = this.getProjectDirForWorkspace(workspace);
23355
- if (projectDir) {
23356
- const files = getSessionFilesSync(projectDir);
23357
- for (const file of files) {
23358
- const session = this.parseSessionFile(file, workspace);
23359
- if (session) sessions.push(session);
23360
- }
23361
- }
23362
- } else {
23363
- const projectDirs = getProjectDirsSync();
23364
- for (const projectDir of projectDirs) {
23365
- const files = getSessionFilesSync(projectDir);
23366
- for (const file of files) {
23367
- const session = this.parseSessionFile(file);
23368
- if (session) sessions.push(session);
23369
- }
23370
- }
23371
- }
23372
- return sessions;
23373
- }
23374
- /**
23375
- * Parse a session file into a Session object
23376
- */
23377
- parseSessionFile(file, workspace) {
23378
- const sessionUsage = parseClaudeSessionSync(file);
23379
- if (!sessionUsage) return null;
23380
- const stat = statSync(file);
23381
- return {
23382
- id: sessionUsage.sessionId,
23383
- agentId: "unknown",
23384
- workspace: workspace || "unknown",
23385
- model: sessionUsage.model,
23386
- startedAt: new Date(sessionUsage.startTime),
23387
- lastActivity: stat.mtime,
23388
- tokenUsage: sessionUsage.usage
23389
- };
23390
- }
23391
- /**
23392
- * Check if an agent is running
23393
- */
23394
- isRunning(agentId) {
23395
- return sessionExistsSync(agentId);
23396
- }
23397
- };
23398
- /**
23399
- * Create a Claude Code runtime instance
23400
- */
23401
- function createClaudeCodeRuntimeSync() {
23402
- return new ClaudeCodeRuntimeSync();
23403
- }
23404
- //#endregion
23405
- //#region ../../lib/cost-parsers/pi-parser.ts
23406
- init_errors();
23407
- //#endregion
23408
- //#region ../../lib/runtimes/pi.ts
23409
- init_behavior();
23410
- init_tmux();
23411
- init_errors();
23412
- init_paths();
23413
- promisify(exec);
23414
- //#endregion
23415
- //#region ../../lib/runtimes/index.ts
23416
- init_behavior();
23417
- init_agents$1();
23418
- /**
23419
- * Runtime registry implementation
23420
- *
23421
- * Manages multiple runtime adapters and provides lookup by agent ID.
23422
- */
23423
- var RuntimeRegistry = class {
23424
- runtimes = /* @__PURE__ */ new Map();
23425
- /**
23426
- * Register a runtime adapter
23427
- */
23428
- register(runtime) {
23429
- this.runtimes.set(runtime.name, runtime);
23430
- }
23431
- /**
23432
- * Get a runtime by name
23433
- */
23434
- get(name) {
23435
- return this.runtimes.get(name);
23436
- }
23437
- /**
23438
- * Get all registered runtimes
23439
- */
23440
- getAll() {
23441
- return Array.from(this.runtimes.values());
23442
- }
23443
- /**
23444
- * Get the runtime for a specific agent.
23445
- *
23446
- * Reads the agent's state file and dispatches by `state.harness`. When
23447
- * the harness field is missing or carries a legacy value (e.g. 'claude'
23448
- * from pre-PAN-636 wire format), we fall back to the claude-code runtime
23449
- * to preserve back-compat (PAN-636 ac2).
23450
- */
23451
- getRuntimeForAgent(agentId) {
23452
- const state = getAgentStateSync(agentId);
23453
- if (!state) return null;
23454
- const harness = state.harness;
23455
- if (harness === "ohmypi" || harness === "pi") return this.get("ohmypi") ?? null;
23456
- if (harness === "codex") return this.get("codex") ?? null;
23457
- return this.get("claude-code") ?? null;
23458
- }
23459
- };
23460
- /**
23461
- * Global runtime registry instance
23462
- */
23463
- let globalRegistry = null;
23464
- /**
23465
- * Get the global runtime registry
23466
- *
23467
- * Creates a new registry if one doesn't exist.
23468
- * Registers Claude Code runtime by default.
23469
- */
23470
- function getGlobalRegistry() {
23471
- if (!globalRegistry) {
23472
- globalRegistry = new RuntimeRegistry();
23473
- globalRegistry.register(createClaudeCodeRuntimeSync());
23474
- globalRegistry.register(createOhmypiRuntimeSync());
23475
- globalRegistry.register(createCodexRuntimeSync());
23476
- }
23477
- return globalRegistry;
23478
- }
23479
- /**
23480
- * Helper to get the runtime for an agent from the global registry
23481
- */
23482
- function getRuntimeForAgent(agentId) {
23483
- return getGlobalRegistry().getRuntimeForAgent(agentId);
23484
- }
23485
- //#endregion
23486
22497
  //#region ../../lib/cloister/deacon-inspect.ts
23487
22498
  init_review_status();
23488
22499
  init_tmux();
@@ -23526,7 +22537,7 @@ async function checkInspectAgentTimeouts(now = /* @__PURE__ */ new Date()) {
23526
22537
  console.warn(`[deacon] Failed to kill inspect session ${sessionName}: ${msg}`);
23527
22538
  });
23528
22539
  try {
23529
- const { messageAgent } = await import("./agents-CxbuBjID.js");
22540
+ const { messageAgent } = await import("./agents-DCvyTXNU.js");
23530
22541
  await messageAgent(`agent-${issueId.toLowerCase()}`, verdict, "deacon:inspect-watchdog");
23531
22542
  } catch (err) {
23532
22543
  const msg = err instanceof Error ? err.message : String(err);
@@ -23539,43 +22550,6 @@ async function checkInspectAgentTimeouts(now = /* @__PURE__ */ new Date()) {
23539
22550
  return actions;
23540
22551
  }
23541
22552
  //#endregion
23542
- //#region ../../lib/cloister/agent-idle.ts
23543
- init_agents$1();
23544
- init_tmux();
23545
- function getAgentEffectiveLastActivityMs(agentId) {
23546
- const candidates = [];
23547
- const runtimeState = getAgentRuntimeStateSync(agentId);
23548
- const runtimeMs = runtimeState?.lastActivity ? new Date(runtimeState.lastActivity).getTime() : NaN;
23549
- if (Number.isFinite(runtimeMs)) candidates.push(runtimeMs);
23550
- try {
23551
- const tmuxActivity = listPaneValuesSync(agentId, "#{window_activity}").map((value) => Number.parseInt(value.trim(), 10) * 1e3).filter(Number.isFinite);
23552
- candidates.push(...tmuxActivity);
23553
- } catch {}
23554
- try {
23555
- const heartbeat = getRuntimeForAgent(agentId)?.getHeartbeat(agentId);
23556
- if (heartbeat?.timestamp) {
23557
- const heartbeatMs = heartbeat.timestamp.getTime();
23558
- if (Number.isFinite(heartbeatMs)) candidates.push(heartbeatMs);
23559
- }
23560
- } catch {}
23561
- return candidates.length > 0 ? Math.max(...candidates) : null;
23562
- }
23563
- function isAgentIdleForNudge(agentId, staleActiveThresholdMs = 300 * 1e3, now = Date.now()) {
23564
- const runtimeState = getAgentRuntimeStateSync(agentId);
23565
- const effectiveLastActivityMs = getAgentEffectiveLastActivityMs(agentId);
23566
- if (!runtimeState) {
23567
- if (effectiveLastActivityMs === null) {
23568
- console.log(`[deacon] ${agentId}: no runtime.json — skipping (hook not yet fired)`);
23569
- return false;
23570
- }
23571
- return now - effectiveLastActivityMs > staleActiveThresholdMs;
23572
- }
23573
- if (runtimeState.state === "suspended" || runtimeState.state === "stopped") return false;
23574
- if (runtimeState.state === "waiting-on-human") return false;
23575
- if (runtimeState.state === "idle") return true;
23576
- return now - (effectiveLastActivityMs ?? new Date(runtimeState.lastActivity).getTime()) > staleActiveThresholdMs;
23577
- }
23578
- //#endregion
23579
22553
  //#region ../../lib/cloister/modal-detector.ts
23580
22554
  init_tmux();
23581
22555
  const KNOWN_AGENT_MODALS = [{
@@ -23584,9 +22558,15 @@ const KNOWN_AGENT_MODALS = [{
23584
22558
  keys: ["Down", "Enter"]
23585
22559
  }];
23586
22560
  /** Rollout JSONL is launch/turn attribution only until a captured switch proves otherwise. */
22561
+ const MODEL_SHAPED_TOKEN = /^(?:gpt|o\d|claude|kimi|glm|gemini|deepseek|qwen|minimax|grok)[\w.-]*$/i;
23587
22562
  function paneShowsModelSwitch(pane, launchModel) {
23588
- const match = pane.match(/(?:switched|switching)\s+(?:model\s+)?to\s+([\w.-]+)/i);
23589
- return Boolean(match?.[1] && match[1].toLowerCase() !== launchModel.toLowerCase());
22563
+ const modelPhrase = pane.match(/model\s+(?:switched|switching)\s+to\s+([\w.-]+)|(?:switched|switching)\s+model\s+to\s+([\w.-]+)/i);
22564
+ let target = modelPhrase?.[1] ?? modelPhrase?.[2];
22565
+ if (!target) {
22566
+ const generic = pane.match(/(?:switched|switching)\s+to\s+([\w.-]+)/i)?.[1];
22567
+ if (generic && MODEL_SHAPED_TOKEN.test(generic)) target = generic;
22568
+ }
22569
+ return Boolean(target && target.toLowerCase() !== launchModel.toLowerCase());
23590
22570
  }
23591
22571
  const defaultDeps = {
23592
22572
  capturePane: (agentId) => Effect.runPromise(capturePane(agentId, 100)),
@@ -23604,7 +22584,6 @@ async function handleKnownAgentModal(agentId, deps = defaultDeps, initialPane) {
23604
22584
  //#endregion
23605
22585
  //#region ../../lib/cloister/deacon-api-recovery.ts
23606
22586
  init_agents$1();
23607
- init_paths();
23608
22587
  init_review_status();
23609
22588
  init_tmux();
23610
22589
  /**
@@ -23701,7 +22680,7 @@ async function maybeProactivelyCompactContext(sessionName, now) {
23701
22680
  if (!agentState?.workspace || !sessionId || !agentState.model) return null;
23702
22681
  let usage = null;
23703
22682
  try {
23704
- const { computeContextUsage } = await import("./conversation-service-DcDB5usR.js");
22683
+ const { computeContextUsage } = await import("./conversation-service-C_kNZPLx.js");
23705
22684
  usage = await computeContextUsage(sessionFilePath(agentState.workspace, sessionId), agentState.model);
23706
22685
  } catch {
23707
22686
  return null;
@@ -23798,13 +22777,13 @@ async function checkApiErrorAgents() {
23798
22777
  const st = getAgentStateSync(sessionName);
23799
22778
  const sid = st?.sessionId ?? runtimeState?.claudeSessionId;
23800
22779
  if (st?.workspace && sid && st.model) {
23801
- const { computeContextUsage } = await import("./conversation-service-DcDB5usR.js");
22780
+ const { computeContextUsage } = await import("./conversation-service-C_kNZPLx.js");
23802
22781
  const usage = await computeContextUsage(sessionFilePath(st.workspace, sid), st.model);
23803
22782
  if (usage && usage.percentUsed < 85) recoveredPct = usage.percentUsed;
23804
22783
  }
23805
22784
  } catch {}
23806
22785
  if (recoveredPct !== null) {
23807
- const { clearWorkspaceStuck } = await import("./review-status-sync-Bc0c_u12.js");
22786
+ const { clearWorkspaceStuck } = await import("./review-status-sync-D3KUhsdA.js");
23808
22787
  clearWorkspaceStuck(issueId);
23809
22788
  stuckOverflowNativeRecoveryState.delete(sessionName);
23810
22789
  actions.push(`Context overflow recovery: cleared stuck flag for ${sessionName} (context back to ${Math.round(recoveredPct)}%)`);
@@ -23820,7 +22799,7 @@ async function checkApiErrorAgents() {
23820
22799
  rec.attempts += 1;
23821
22800
  rec.lastAttempt = now;
23822
22801
  stuckOverflowNativeRecoveryState.set(sessionName, rec);
23823
- const { resumeAgent } = await import("./agents-CxbuBjID.js");
22802
+ const { resumeAgent } = await import("./agents-DCvyTXNU.js");
23824
22803
  const recovered = await resumeAgent(sessionName, void 0, { compact: true });
23825
22804
  if (recovered.success) {
23826
22805
  stuckOverflowNativeRecoveryState.delete(sessionName);
@@ -23868,7 +22847,7 @@ async function checkApiErrorAgents() {
23868
22847
  }
23869
22848
  const compactAttempts = (ov?.compactAttempts ?? 0) + 1;
23870
22849
  if (issueId !== null) {
23871
- const { resumeAgent } = await import("./agents-CxbuBjID.js");
22850
+ const { resumeAgent } = await import("./agents-DCvyTXNU.js");
23872
22851
  const resumeResult = await resumeAgent(sessionName, void 0, { compact: true });
23873
22852
  contextOverflowRecoveryState.set(sessionName, {
23874
22853
  lastAttempt: now,
@@ -23943,8 +22922,8 @@ async function checkApiErrorAgents() {
23943
22922
  }
23944
22923
  //#endregion
23945
22924
  //#region ../../lib/cloister/preemption.ts
23946
- init_specialists();
23947
22925
  init_review_monitor();
22926
+ init_specialists();
23948
22927
  /**
23949
22928
  * PAN-2507: preemptive pipeline scheduler.
23950
22929
  *
@@ -24115,6 +23094,8 @@ async function resumeYieldedVictim(agentId) {
24115
23094
  init_archive_planning();
24116
23095
  init_issue_closed();
24117
23096
  init_merge_verification();
23097
+ init_state_mapping();
23098
+ init_tracker_utils();
24118
23099
  const execFileAsync$5 = promisify$1(execFile$1);
24119
23100
  const autoCloseOutCache = /* @__PURE__ */ new Map();
24120
23101
  const AUTO_CLOSE_OUT_CACHE_TTL_MS = 600 * 1e3;
@@ -24233,7 +23214,7 @@ function reviewConvoyLiveness(issueId) {
24233
23214
  */
24234
23215
  async function recoverUnhealthyTestStack(issueId, workspacePath) {
24235
23216
  const key = issueId.toUpperCase();
24236
- const { getWorkspaceStackHealth } = await import("./stack-health-BKbTTOT2.js");
23217
+ const { getWorkspaceStackHealth } = await import("./stack-health-Dclm7_tu.js");
24237
23218
  const health = await Effect.runPromise(getWorkspaceStackHealth(issueId, { workspacePath }));
24238
23219
  if (health.healthy) {
24239
23220
  testStackRebuildState.delete(key);
@@ -24265,7 +23246,7 @@ async function recoverUnhealthyTestStack(issueId, workspacePath) {
24265
23246
  record.attempts += 1;
24266
23247
  testStackRebuildState.set(key, record);
24267
23248
  console.log(`[deacon] Test stack for ${key} unhealthy (${health.reasons.join("; ")}) — rebuilding (attempt ${record.attempts}/${TEST_STACK_REBUILD_MAX_ATTEMPTS})`);
24268
- const { rebuildWorkspaceStack } = await import("./rebuild-stack-r-cxcr26.js");
23249
+ const { rebuildWorkspaceStack } = await import("./rebuild-stack-GOsWqXi3.js");
24269
23250
  const result = await Effect.runPromise(rebuildWorkspaceStack(issueId, { onProgress: (m) => console.log(`[deacon] ${key} stack rebuild: ${m}`) }));
24270
23251
  if (!result.success) {
24271
23252
  console.warn(`[deacon] Test stack rebuild failed for ${key}: ${result.error}`);
@@ -24393,7 +23374,7 @@ async function handleReviewCoordinatorDied(issueId, _sessionName, _reason) {
24393
23374
  return actions;
24394
23375
  }
24395
23376
  try {
24396
- const { spawnReviewRoleForIssue } = await import("./review-agent-Bf9XjLnl.js");
23377
+ const { spawnReviewRoleForIssue } = await import("./review-agent-Rub0OpZc.js");
24397
23378
  const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
24398
23379
  issueId,
24399
23380
  workspace,
@@ -24523,7 +23504,7 @@ async function reconcileReviewStatusOrphan(issueId, rawStatus) {
24523
23504
  const workspace = agentState?.workspace || (resolved ? findWorkspacePath(resolved.projectPath, issueLower) : null);
24524
23505
  if (workspace && resolved && !tryReserveAdvancingSlot() && !await tryYieldForAdvancingDispatch("review", issueId)) actions.push(`Deferred review re-dispatch for ${issueId} — advancing-role concurrency ceiling reached`);
24525
23506
  else if (workspace && resolved) try {
24526
- const { spawnReviewRoleForIssue } = await import("./review-agent-Bf9XjLnl.js");
23507
+ const { spawnReviewRoleForIssue } = await import("./review-agent-Rub0OpZc.js");
24527
23508
  const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
24528
23509
  issueId,
24529
23510
  workspace,
@@ -24548,8 +23529,8 @@ async function reconcileReviewStatusOrphan(issueId, rawStatus) {
24548
23529
  const workspace = agentState?.workspace || (resolved ? findWorkspacePath(resolved.projectPath, issueLower) : null);
24549
23530
  if (workspace && resolved) {
24550
23531
  const branch = `feature/${issueLower}`;
24551
- const { spawnRun } = await import("./agents-CxbuBjID.js");
24552
- const { buildTestRolePrompt } = await import("./test-agent-queue-Bq298zZl.js");
23532
+ const { spawnRun } = await import("./agents-DCvyTXNU.js");
23533
+ const { buildTestRolePrompt } = await import("./test-agent-queue-DjsQoV5X.js");
24553
23534
  const stackRecovery = await recoverUnhealthyTestStack(issueId, workspace);
24554
23535
  if (stackRecovery === "cooldown" || stackRecovery === "exhausted") {
24555
23536
  setReviewStatusSync(issueId, { testStatus: "dispatch_failed" });
@@ -24687,7 +23668,7 @@ async function recoverStalledReviewConvoys(getCanonicalState = getAutoCloseOutCa
24687
23668
  record.lastAttempt = now;
24688
23669
  record.attempts += 1;
24689
23670
  stalledReviewConvoyRecoveryState.set(key, record);
24690
- const { spawnReviewRoleForIssue } = await import("./review-agent-Bf9XjLnl.js");
23671
+ const { spawnReviewRoleForIssue } = await import("./review-agent-Rub0OpZc.js");
24691
23672
  try {
24692
23673
  const result = await Effect.runPromise(spawnReviewRoleForIssue({
24693
23674
  issueId,
@@ -24758,7 +23739,7 @@ async function checkMissingReviewStatuses() {
24758
23739
  continue;
24759
23740
  }
24760
23741
  try {
24761
- const { spawnReviewRoleForIssue } = await import("./review-agent-Bf9XjLnl.js");
23742
+ const { spawnReviewRoleForIssue } = await import("./review-agent-Rub0OpZc.js");
24762
23743
  await Effect.runPromise(spawnReviewRoleForIssue({
24763
23744
  issueId,
24764
23745
  workspace,
@@ -24809,7 +23790,7 @@ async function checkStuckReviewing() {
24809
23790
  const actions = [];
24810
23791
  const REVIEW_STUCK_THRESHOLD_MS = 1800 * 1e3;
24811
23792
  try {
24812
- const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-B0Axo-Ma.js");
23793
+ const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Br6lAFGO.js");
24813
23794
  const statuses = loadReviewStatuses();
24814
23795
  const now = Date.now();
24815
23796
  const activeReviewIssues = /* @__PURE__ */ new Set();
@@ -24825,7 +23806,7 @@ async function checkStuckReviewing() {
24825
23806
  if (rState?.state === "active" && rState.currentIssue) activeReviewIssues.add(rState.currentIssue.toUpperCase());
24826
23807
  }
24827
23808
  try {
24828
- const { listRunningAgents } = await import("./agents-CxbuBjID.js");
23809
+ const { listRunningAgents } = await import("./agents-DCvyTXNU.js");
24829
23810
  const agents = await Effect.runPromise(listRunningAgents());
24830
23811
  for (const agent of agents) {
24831
23812
  if (agent.status === "stopped" || agent.status === "error") continue;
@@ -24958,7 +23939,7 @@ async function checkCompletedButUnsignaledReviews() {
24958
23939
  }
24959
23940
  const nudge = `Your review synthesis is already written and saved. Your ONLY remaining task is to execute this Bash command immediately — do not analyze, do not summarize, do not ask questions, just run it:\n\n${`pan admin specialists done review ${issueId} --status ${verdict}${verdict === "blocked" || verdict === "failed" ? ` --notes "${topBlocker || "See synthesis.md"}"` : ""}`}\n\nRun this command NOW. Do not write any other response before executing it.`;
24960
23941
  try {
24961
- const { messageAgent } = await import("./agents-CxbuBjID.js");
23942
+ const { messageAgent } = await import("./agents-DCvyTXNU.js");
24962
23943
  await messageAgent(reviewSession, nudge);
24963
23944
  unsignaledReviewNudges.set(latestDir, now);
24964
23945
  actions.push(`Nudged ${reviewSession} to signal ${verdict} (synthesis written ${Math.round((now - latestMtime) / 6e4)}min ago)`);
@@ -25079,7 +24060,7 @@ async function respawnIdleReviewer(state, agentId) {
25079
24060
  return false;
25080
24061
  }
25081
24062
  try {
25082
- const { spawnReviewSubRoleForIssue } = await import("./review-agent-Bf9XjLnl.js");
24063
+ const { spawnReviewSubRoleForIssue } = await import("./review-agent-Rub0OpZc.js");
25083
24064
  const contextManifestPath = join$1(dirname$1(outputPath), "context.json");
25084
24065
  const result = await Effect.runPromise(spawnReviewSubRoleForIssue({
25085
24066
  issueId: state.issueId,
@@ -25117,7 +24098,7 @@ async function nudgeSynthesisForCompleteReviewerReports(states) {
25117
24098
  const status = getReviewStatusSync(state.issueId);
25118
24099
  if (!status || status.reviewStatus !== "reviewing") continue;
25119
24100
  const reviewDir = join$1(state.workspace, ".pan", "review", state.reviewRunId);
25120
- if (existsSync(join$1(reviewDir, "synthesis.md"))) continue;
24101
+ const synthesisAlreadyWritten = existsSync(join$1(reviewDir, "synthesis.md"));
25121
24102
  const startedMs = Date.parse(state.startedAt);
25122
24103
  const readyLines = [];
25123
24104
  const reports = [];
@@ -25156,7 +24137,7 @@ async function nudgeSynthesisForCompleteReviewerReports(states) {
25156
24137
  if (lastNudge && now - lastNudge < REVIEW_REPORTS_PRESENT_NUDGE_COOLDOWN_MS) continue;
25157
24138
  const sessionAlive = await Effect.runPromise(sessionExists(state.id)).catch(() => false);
25158
24139
  const paneDead = sessionAlive ? await Effect.runPromise(isPaneDead(state.id)).catch(() => true) : true;
25159
- if (lastNudge || !sessionAlive || paneDead) {
24140
+ if (synthesisAlreadyWritten || lastNudge || !sessionAlive || paneDead) {
25160
24141
  const synthesis = synthesizeReviewFromReports({
25161
24142
  issueId: state.issueId,
25162
24143
  reviewDir,
@@ -25208,7 +24189,7 @@ async function nudgeSynthesisForCompleteReviewerReports(states) {
25208
24189
  "Read the four reports, write synthesis.md, then signal review status exactly as roles/review.md instructs."
25209
24190
  ].join("\n");
25210
24191
  try {
25211
- const { messageAgent } = await import("./agents-CxbuBjID.js");
24192
+ const { messageAgent } = await import("./agents-DCvyTXNU.js");
25212
24193
  await messageAgent(state.id, message);
25213
24194
  reviewReportsPresentNudges.set(nudgeKey, now);
25214
24195
  const action = `Nudged ${state.id} to synthesize from ${REVIEW_SUB_ROLES.length} reviewer reports`;
@@ -25287,7 +24268,7 @@ async function monitorReviewConvoySignals() {
25287
24268
  if (!signal) continue;
25288
24269
  const message = signal === "ready" ? `REVIEWER_READY ${state.reviewSubRole} ${outputPath}` : signal === "timeout" ? `REVIEWER_TIMEOUT ${state.reviewSubRole} ${reason}` : `REVIEWER_FAILED ${state.reviewSubRole} ${reason}`;
25289
24270
  try {
25290
- const { messageAgent } = await import("./agents-CxbuBjID.js");
24271
+ const { messageAgent } = await import("./agents-DCvyTXNU.js");
25291
24272
  await messageAgent(state.reviewSynthesisAgentId, message);
25292
24273
  state.reviewMonitorSignaled = signal;
25293
24274
  saveAgentStateSync(state);
@@ -25295,7 +24276,7 @@ async function monitorReviewConvoySignals() {
25295
24276
  actions.push(action);
25296
24277
  logDeaconEventSync(`monitorReviewConvoySignals: ${action}`);
25297
24278
  if (signal === "ready") try {
25298
- const { notifyPipelineSync } = await import("./pipeline-notifier-nkWCe042.js");
24279
+ const { notifyPipelineSync } = await import("./pipeline-notifier-BkKbQ8ji.js");
25299
24280
  notifyPipelineSync({
25300
24281
  type: "reviewer_completed",
25301
24282
  issueId: state.issueId,
@@ -25303,7 +24284,7 @@ async function monitorReviewConvoySignals() {
25303
24284
  });
25304
24285
  } catch {}
25305
24286
  else if (signal === "timeout") try {
25306
- const { notifyPipelineSync } = await import("./pipeline-notifier-nkWCe042.js");
24287
+ const { notifyPipelineSync } = await import("./pipeline-notifier-BkKbQ8ji.js");
25307
24288
  notifyPipelineSync({
25308
24289
  type: "reviewer_timed_out",
25309
24290
  issueId: state.issueId,
@@ -25403,7 +24384,7 @@ const FORK_CACHE_CHECK_DELAY_MS = 180 * 1e3;
25403
24384
  async function checkStalledReviewDiscovery() {
25404
24385
  const actions = [];
25405
24386
  try {
25406
- const { listAgentStates } = await import("./agents-CxbuBjID.js");
24387
+ const { listAgentStates } = await import("./agents-DCvyTXNU.js");
25407
24388
  const states = listAgentStates();
25408
24389
  const now = Date.now();
25409
24390
  for (const state of states) {
@@ -25412,7 +24393,7 @@ async function checkStalledReviewDiscovery() {
25412
24393
  const aged = Number.isFinite(startedMs) && now - startedMs > 48e4;
25413
24394
  const dead = !await Effect.runPromise(sessionExists(state.id)).catch(() => false) || await Effect.runPromise(isPaneDead(state.id)).catch(() => true);
25414
24395
  if (!aged && !dead) continue;
25415
- const { handleReviewDiscoveryReady } = await import("./review-agent-Bf9XjLnl.js");
24396
+ const { handleReviewDiscoveryReady } = await import("./review-agent-Rub0OpZc.js");
25416
24397
  const result = await handleReviewDiscoveryReady(state.issueId, { source: dead ? "deacon-backstop (parent dead)" : "deacon-backstop (discovery timeout)" });
25417
24398
  actions.push(result.message);
25418
24399
  logDeaconEventSync(`checkStalledReviewDiscovery: ${result.message}`);
@@ -25435,8 +24416,8 @@ async function checkStalledReviewDiscovery() {
25435
24416
  async function checkStalledReviewParents() {
25436
24417
  const actions = [];
25437
24418
  try {
25438
- const { listAgentStates, markAgentStoppedState } = await import("./agents-CxbuBjID.js");
25439
- const { PARENT_REVIEW_TIMEOUT_MS } = await import("./review-agent-Bf9XjLnl.js");
24419
+ const { listAgentStates, markAgentStoppedState } = await import("./agents-DCvyTXNU.js");
24420
+ const { PARENT_REVIEW_TIMEOUT_MS } = await import("./review-agent-Rub0OpZc.js");
25440
24421
  const states = listAgentStates();
25441
24422
  const now = Date.now();
25442
24423
  for (const state of states) {
@@ -25485,8 +24466,8 @@ async function checkStalledReviewParents() {
25485
24466
  async function checkReviewForkCacheMisses() {
25486
24467
  const actions = [];
25487
24468
  try {
25488
- const { listAgentStates, saveAgentState } = await import("./agents-CxbuBjID.js");
25489
- const { readEventsSync } = await import("./events-D2gP2-Yv.js");
24469
+ const { listAgentStates, saveAgentState } = await import("./agents-DCvyTXNU.js");
24470
+ const { readEventsSync } = await import("./events-CtsLScn8.js");
25490
24471
  const { emitActivityEntrySync } = await import("./activity-logger-DvYvFhwZ.js");
25491
24472
  const states = listAgentStates();
25492
24473
  const now = Date.now();
@@ -25633,7 +24614,7 @@ async function reconcileStaleMergeStatus() {
25633
24614
  if (!project) continue;
25634
24615
  let specStatus;
25635
24616
  try {
25636
- const { findSpecByIssue } = await import("./specs-oaaYaA5c.js");
24617
+ const { findSpecByIssue } = await import("./specs-DwoAEGrW.js");
25637
24618
  const spec = await Effect.runPromise(findSpecByIssue(project.projectPath, issueId));
25638
24619
  specStatus = spec?.status;
25639
24620
  if (spec && (spec.status === "completed" || spec.status === "cancelled")) {
@@ -25648,7 +24629,7 @@ async function reconcileStaleMergeStatus() {
25648
24629
  if (branchTip.stdout.trim() === mainTip.stdout.trim()) console.log(`[deacon] ${issueId}: branch ${branch} points at main; not treating zero-commit branch as merged`);
25649
24630
  } catch {}
25650
24631
  if (!isMerged) {
25651
- const { resolveGitHubIssueSync: _resolveGitHubIssue } = await import("./tracker-utils-DSb9cfrF.js");
24632
+ const { resolveGitHubIssueSync: _resolveGitHubIssue } = await import("./tracker-utils-B9ZoVA9b.js");
25652
24633
  const ghResolved = _resolveGitHubIssue(issueId);
25653
24634
  if (ghResolved.isGitHub) try {
25654
24635
  const { stdout } = await execFileAsync$4("gh", [
@@ -25685,7 +24666,7 @@ async function reconcileStaleMergeStatus() {
25685
24666
  actions.push(msg);
25686
24667
  console.log(`[deacon] ${msg}`);
25687
24668
  try {
25688
- const { postMergeLifecycle } = await import("./merge-agent-Bwm34MZ5.js");
24669
+ const { postMergeLifecycle } = await import("./merge-agent-36wfYm2u.js");
25689
24670
  postMergeLifecycle(issueId, project.projectPath, branch, { skipDeploy: true }).catch((err) => console.warn(`[deacon] postMergeLifecycle (reconcile) failed for ${issueId}: ${err}`));
25690
24671
  } catch (err) {
25691
24672
  console.warn(`[deacon] Could not import postMergeLifecycle: ${err}`);
@@ -25710,7 +24691,7 @@ const falseMergedReset = /* @__PURE__ */ new Set();
25710
24691
  async function reconcileFalseMerged() {
25711
24692
  const actions = [];
25712
24693
  try {
25713
- const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-DIr70YLg.js");
24694
+ const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-DRD2woO0.js");
25714
24695
  if (!isGitHubAppConfigured()) return actions;
25715
24696
  const statuses = loadReviewStatuses();
25716
24697
  for (const [issueId, status] of Object.entries(statuses)) {
@@ -25755,7 +24736,7 @@ const CLOSED_PR_RECONCILE_COOLDOWN_MS = 600 * 1e3;
25755
24736
  async function reconcileClosedPrReadyForMerge() {
25756
24737
  const actions = [];
25757
24738
  try {
25758
- const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-DIr70YLg.js");
24739
+ const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-DRD2woO0.js");
25759
24740
  if (!isGitHubAppConfigured()) return actions;
25760
24741
  const statuses = loadReviewStatuses();
25761
24742
  const now = Date.now();
@@ -25827,7 +24808,7 @@ const STALE_MERGE_BLOCKER_COOLDOWN_MS = 120 * 1e3;
25827
24808
  async function reconcileStaleMergeBlockers() {
25828
24809
  const actions = [];
25829
24810
  try {
25830
- const { resolveConflictGate, buildRealConflictGateDeps } = await import("./conflict-gate-CpOn9KC-.js");
24811
+ const { resolveConflictGate, buildRealConflictGateDeps } = await import("./conflict-gate-DGT8jCLp.js");
25831
24812
  const statuses = loadReviewStatuses();
25832
24813
  const now = Date.now();
25833
24814
  const deps = buildRealConflictGateDeps();
@@ -25970,7 +24951,7 @@ async function checkFailedMergeRetry() {
25970
24951
  if (ciEntry.count === 5) {
25971
24952
  console.log(`[deacon] CI check failure for ${issueId} — retries exhausted, notifying work agent`);
25972
24953
  const ciNotes = status.mergeNotes || "CI checks are failing on the PR";
25973
- const { writeFeedbackFile } = await import("./feedback-writer-DCyd75yJ.js");
24954
+ const { writeFeedbackFile } = await import("./feedback-writer-DOUhyIW2.js");
25974
24955
  const ciFileResult = await Effect.runPromise(writeFeedbackFile({
25975
24956
  issueId,
25976
24957
  specialist: "merge-agent",
@@ -26002,7 +24983,7 @@ async function checkFailedMergeRetry() {
26002
24983
  ciRetryMap.set(issueId, ciEntry);
26003
24984
  console.log(`[deacon] CI check failure for ${issueId} — notifying agent to re-submit (attempt ${ciEntry.count}/5)`);
26004
24985
  const ciNotes = status.mergeNotes || "CI checks are failing on the PR";
26005
- const { writeFeedbackFile } = await import("./feedback-writer-DCyd75yJ.js");
24986
+ const { writeFeedbackFile } = await import("./feedback-writer-DOUhyIW2.js");
26006
24987
  const ciFileResult2 = await Effect.runPromise(writeFeedbackFile({
26007
24988
  issueId,
26008
24989
  specialist: "merge-agent",
@@ -26030,7 +25011,7 @@ async function checkFailedMergeRetry() {
26030
25011
  const lastNudge = timeoutNudgeCooldowns.get(issueIdForFb);
26031
25012
  if (!lastNudge || now - lastNudge >= TIMEOUT_NUDGE_COOLDOWN_MS) {
26032
25013
  const timeoutNotes = status.mergeNotes;
26033
- const { writeFeedbackFile } = await import("./feedback-writer-DCyd75yJ.js");
25014
+ const { writeFeedbackFile } = await import("./feedback-writer-DOUhyIW2.js");
26034
25015
  await Effect.runPromise(writeFeedbackFile({
26035
25016
  issueId: issueIdForFb,
26036
25017
  specialist: "merge-agent",
@@ -26135,7 +25116,7 @@ async function autoCloseOut(now = /* @__PURE__ */ new Date()) {
26135
25116
  } } : {}
26136
25117
  };
26137
25118
  try {
26138
- const { closeOut } = await import("./workflows-B4fIN8VP.js");
25119
+ const { closeOut } = await import("./workflows-tU7KKxQi.js");
26139
25120
  const result = await Effect.runPromise(closeOut(ctx));
26140
25121
  if (!result.success) {
26141
25122
  const failed = result.steps.find((step) => !step.success && !step.skipped);
@@ -26285,6 +25266,7 @@ function skippedBootReconciliationOutcomes(agents, reason) {
26285
25266
  }
26286
25267
  //#endregion
26287
25268
  //#region ../../lib/cloister/boot-reconciliation-predicates.ts
25269
+ init_control_settings();
26288
25270
  init_no_resume_mode();
26289
25271
  init_agent_state();
26290
25272
  init_review_status();
@@ -26438,6 +25420,7 @@ init_review_status();
26438
25420
  init_control_settings();
26439
25421
  init_agents$1();
26440
25422
  init_tmux();
25423
+ init_beads_query();
26441
25424
  const orphanFailureRecordedForAutoResume = /* @__PURE__ */ new Set();
26442
25425
  const appliedBootReconciliationDecisions = /* @__PURE__ */ new Set();
26443
25426
  const emptyBootReconciliationApplyResult = () => ({
@@ -26697,7 +25680,7 @@ async function nudgeStalledResumeWorkAgents() {
26697
25680
  const message = buildStalledResumePrompt(state);
26698
25681
  if (!message) continue;
26699
25682
  try {
26700
- const { messageAgent } = await import("./agents-CxbuBjID.js");
25683
+ const { messageAgent } = await import("./agents-DCvyTXNU.js");
26701
25684
  await messageAgent(agentId, message);
26702
25685
  recordCooldown(agentId, ".last-stalled-resume-nudge");
26703
25686
  const action = `Re-sent stalled resume prompt to ${agentId} (${state.issueId})`;
@@ -26812,10 +25795,10 @@ async function nudgeIdleWorkAgentsWithOpenBeads() {
26812
25795
  ``,
26813
25796
  `If you don't already have your full brief for ${state.issueId} in context (work-agent role instructions, the vBRIEF plan, recorded decisions & hazards), re-read it now — it is on disk at ${briefPath}, plus .pan/continue.json and .pan/spec.vbrief.json in your workspace. Startup kickoff delivery can silently fail on large briefs, so do not assume you received it.`,
26814
25797
  ``,
26815
- "Continue the per-bead workflow without asking — claim it (`bd update <bead-id> --claim`), implement, commit, close. Inspection is conditional on metadata.requiresInspection (default false; check the plan item before deciding to call `pan inspect`). Do NOT end your turn with a multi-paragraph summary; just advance to the next bead."
25798
+ "Continue the per-bead workflow without asking — claim it (`pan beads claim <bead-id>`), implement, commit, close through `pan beads close`. Inspection is conditional on metadata.requiresInspection (default false; check the plan item before deciding to call `pan inspect`). Do NOT end your turn with a multi-paragraph summary; just advance to the next bead."
26816
25799
  ].join("\n");
26817
25800
  try {
26818
- const { messageAgent } = await import("./agents-CxbuBjID.js");
25801
+ const { messageAgent } = await import("./agents-DCvyTXNU.js");
26819
25802
  await messageAgent(agentId, message);
26820
25803
  writeFileSync(join$1(getAgentDir(agentId), ".last-bead-nudge"), String(Date.now()), "utf-8");
26821
25804
  const action = `Nudged idle ${agentId} (${state.issueId}) — ${openBeads.length} open bead(s)`;
@@ -27137,6 +26120,7 @@ function createInFlightGuard() {
27137
26120
  }
27138
26121
  //#endregion
27139
26122
  //#region ../../lib/pipeline-state-paths.ts
26123
+ init_state_plane();
27140
26124
  const execFileAsync$3 = promisify$1(execFile$1);
27141
26125
  const STATE_PLANE_DIFF_EXCLUDES = STATE_PLANE_PATHS.map((path) => `:(exclude)${path.replace(/\/$/, "")}`);
27142
26126
  function isPipelineStatePath(relativePath) {
@@ -27246,6 +26230,9 @@ async function gitStdout(workspacePath, args) {
27246
26230
  }
27247
26231
  //#endregion
27248
26232
  //#region ../../lib/cloister/state-recreation-patrol.ts
26233
+ init_auto_commit();
26234
+ init_record();
26235
+ init_state_home();
27249
26236
  async function recreatedStateWarnings(projects) {
27250
26237
  const warnings = [];
27251
26238
  for (const { config } of projects) {
@@ -27257,6 +26244,7 @@ async function recreatedStateWarnings(projects) {
27257
26244
  }
27258
26245
  //#endregion
27259
26246
  //#region ../../lib/cloister/deacon-main-divergence.ts
26247
+ init_record_lock();
27260
26248
  init_projects();
27261
26249
  init_state_plane();
27262
26250
  async function recordMainDivergenceHealth(state, projects = listProjectsSync(), measure = getMainDivergence) {
@@ -27289,427 +26277,6 @@ async function recordMainDivergenceHealth(state, projects = listProjectsSync(),
27289
26277
  return warnings;
27290
26278
  }
27291
26279
  //#endregion
27292
- //#region ../../lib/cloister/agent-death.ts
27293
- /**
27294
- * Agent death diagnostics (PAN-2108).
27295
- *
27296
- * When an ohmypi/pi agent process dies, the launcher records its exit code +
27297
- * timestamp to `<agentDir>/exit-status` (see buildOhmypiCommand in
27298
- * launcher-generator.ts), and omp's stdout/stderr is captured to
27299
- * `<agentDir>/output.log`. This module turns those into a one-line death reason
27300
- * the deacon can log, replacing the opaque "session is dead" with an actual
27301
- * cause — the gap that made the flywheel orchestrator's silent death
27302
- * undiagnosable in RUN-30.
27303
- */
27304
- init_paths();
27305
- init_tmux();
27306
- function agentDir(agentId) {
27307
- return join$1(getOverdeckHome(), "agents", agentId);
27308
- }
27309
- /** Read the launcher-recorded exit code + UTC timestamp, or null if absent. */
27310
- function readAgentExitStatus(agentId) {
27311
- try {
27312
- const p = join$1(agentDir(agentId), "exit-status");
27313
- if (!existsSync(p)) return null;
27314
- const raw = readFileSync(p, "utf-8").trim();
27315
- if (!raw) return null;
27316
- const [code, at = ""] = raw.split(/\s+/);
27317
- return {
27318
- code: code ?? "?",
27319
- at
27320
- };
27321
- } catch {
27322
- return null;
27323
- }
27324
- }
27325
- /**
27326
- * Best-effort one-line description of why an agent process died: the
27327
- * launcher-recorded exit status (preferred), the tmux pane exit status (fallback
27328
- * when the dead pane corpse still exists), and the tail of output.log.
27329
- */
27330
- function describeAgentDeath(agentId) {
27331
- const parts = [];
27332
- const exit = readAgentExitStatus(agentId);
27333
- if (exit) parts.push(`exit=${exit.code}${exit.at ? ` at ${exit.at}` : ""}`);
27334
- else if (sessionExistsSync(agentId)) {
27335
- const paneExit = listPaneValuesSync(agentId, "#{pane_exit_status}").find((v) => v !== "");
27336
- if (paneExit) parts.push(`pane_exit=${paneExit}`);
27337
- }
27338
- try {
27339
- const logPath = join$1(agentDir(agentId), "output.log");
27340
- if (existsSync(logPath)) {
27341
- const tail = readFileSync(logPath, "utf-8").slice(-1500).trim().split("\n").slice(-6).join(" | ").trim();
27342
- if (tail) parts.push(`output.log tail: ${tail}`);
27343
- }
27344
- } catch {}
27345
- return parts.length ? parts.join("; ") : "no exit trace (exit-status + output.log empty)";
27346
- }
27347
- //#endregion
27348
- //#region ../../lib/cloister/stuck-remediation-state.ts
27349
- init_paths();
27350
- function agentStateDir(agentId) {
27351
- return join$1(getOverdeckHome(), "agents", agentId);
27352
- }
27353
- function statePath(agentId) {
27354
- return join$1(agentStateDir(agentId), "stuck-remediation.json");
27355
- }
27356
- function readStuckRemediationState(agentId) {
27357
- const filePath = statePath(agentId);
27358
- if (!existsSync(filePath)) return null;
27359
- try {
27360
- return JSON.parse(readFileSync(filePath, "utf-8"));
27361
- } catch (error) {
27362
- console.warn(`Failed to read stuck-remediation state for ${agentId}:`, error);
27363
- return null;
27364
- }
27365
- }
27366
- function writeStuckRemediationState(agentId, state) {
27367
- mkdirSync(agentStateDir(agentId), { recursive: true });
27368
- writeFileSync(statePath(agentId), `${JSON.stringify(state, null, 2)}\n`, "utf-8");
27369
- }
27370
- function clearStuckRemediationState(agentId) {
27371
- const filePath = statePath(agentId);
27372
- if (!existsSync(filePath)) return;
27373
- unlinkSync(filePath);
27374
- }
27375
- //#endregion
27376
- //#region ../../lib/cloister/stuck-remediation.ts
27377
- init_agents$1();
27378
- init_persistent_logger();
27379
- init_review_status();
27380
- init_tmux();
27381
- init_config();
27382
- init_control_settings();
27383
- init_beads_query();
27384
- function issueIdForAgent(agent) {
27385
- return agent.issueId || agent.id.replace(/^agent-/, "").toUpperCase();
27386
- }
27387
- function shouldSkipReviewStatus(status) {
27388
- if (!status) return false;
27389
- if (status.stuck || status.deaconIgnored || status.mergeStatus === "merged" || status.readyForMerge) return true;
27390
- if (status.reviewStatus === "blocked" || status.reviewStatus === "failed") return true;
27391
- if (status.verificationStatus === "failed" || status.testStatus === "failed") return true;
27392
- if (status.reviewStatus === "reviewing" || status.reviewStatus === "passed") return true;
27393
- return status.reviewStatus === "pending" && !!status.reviewRequestedAt;
27394
- }
27395
- function hasPendingRework(status) {
27396
- if (!status) return false;
27397
- if (status.stuck || status.deaconIgnored || status.mergeStatus === "merged" || status.readyForMerge) return false;
27398
- return status.reviewStatus === "blocked" || status.reviewStatus === "failed" || status.verificationStatus === "failed" || status.testStatus === "failed";
27399
- }
27400
- const STUCK_KILL_REQUEUE_CEILING = 25;
27401
- async function evaluateWedgedReworkAgent(agent, config, now, actions) {
27402
- const agentId = agent.id;
27403
- if (agent.role !== "work" || !agent.workspace) return false;
27404
- const issueId = issueIdForAgent(agent);
27405
- const status = getReviewStatusSync(issueId);
27406
- if (!hasPendingRework(status)) return false;
27407
- const lastActivityMs = getAgentEffectiveLastActivityMs(agentId);
27408
- if (lastActivityMs === null || !Number.isFinite(lastActivityMs)) return false;
27409
- const stuckState = readStuckRemediationState(agentId);
27410
- if (stuckState) {
27411
- const firstStuckMs = new Date(stuckState.firstStuckAt).getTime();
27412
- if (Number.isFinite(firstStuckMs) && lastActivityMs > firstStuckMs) {
27413
- clearStuckRemediationState(agentId);
27414
- return false;
27415
- }
27416
- }
27417
- const idleMinutes = Math.floor((now - lastActivityMs) / 6e4);
27418
- const lastStage = stuckState?.lastStage ?? 0;
27419
- if (idleMinutes < config.stage3_minutes || lastStage >= 3) return false;
27420
- const firstStuck = firstStuckAt(new Date(lastActivityMs).toISOString(), stuckState);
27421
- if ((status?.autoRequeueCount ?? 0) >= STUCK_KILL_REQUEUE_CEILING) {
27422
- markAgentTroubled(agentId);
27423
- writeStuckRemediationState(agentId, stageState(3, now, firstStuck));
27424
- logAction(actions, transitionAction(3, issueId, idleMinutes, "rework-wedge-troubled"));
27425
- surfaceStuckNeedsYou(agent, issueId, firstStuck, actions);
27426
- return true;
27427
- }
27428
- killSessionSync(agentId);
27429
- writeStuckRemediationState(agentId, stageState(3, now, firstStuck));
27430
- logAction(actions, transitionAction(3, issueId, idleMinutes, "killed-for-respawn"));
27431
- return true;
27432
- }
27433
- function hasReadyBeads(readyByQueryRoot, agent, issueLabel) {
27434
- return (readyByQueryRoot.get(resolveBeadsQueryRoot(agent.workspace))?.[issueLabel] ?? []).length > 0;
27435
- }
27436
- function shouldCheckReadyBeadsForAgent(agent, now) {
27437
- const agentId = agent.id;
27438
- if (!agentId) return false;
27439
- if (agent.status !== "running") return false;
27440
- if (agent.role !== "work") return false;
27441
- if (!agent.workspace) return false;
27442
- const completedAt = agent.completedAt;
27443
- if (agent.paused || agent.troubled || completedAt) return false;
27444
- if (!sessionExistsSync(agentId)) return false;
27445
- if (shouldSkipReviewStatus(getReviewStatusSync(issueIdForAgent(agent)))) return false;
27446
- return isAgentIdleForNudge(agentId, 300 * 1e3, now);
27447
- }
27448
- function firstStuckAt(runtimeLastActivity, stuckState) {
27449
- return stuckState?.firstStuckAt ?? runtimeLastActivity;
27450
- }
27451
- function stageState(stage, now, firstStuck, prev) {
27452
- return {
27453
- lastStage: stage,
27454
- lastStageAt: new Date(now).toISOString(),
27455
- firstStuckAt: firstStuck,
27456
- ...prev?.respawnCount !== void 0 ? { respawnCount: prev.respawnCount } : {},
27457
- ...prev?.lastRespawnAt !== void 0 ? { lastRespawnAt: prev.lastRespawnAt } : {}
27458
- };
27459
- }
27460
- function transitionAction(stage, issueId, idleMinutes, action) {
27461
- return `[deacon] stuck-remediation stage=${stage} issue=${issueId} idleMin=${idleMinutes} action=${action}`;
27462
- }
27463
- function logAction(actions, action) {
27464
- actions.push(action);
27465
- console.log(action);
27466
- logDeaconEventSync(action);
27467
- }
27468
- function surfaceStuckNeedsYou(agent, issueId, generation, actions) {
27469
- if (!agent.workspace) return;
27470
- if (recordRecoveryFailure(agent.workspace, issueId, "stuck-remediation", generation, 1).emitNeedsYou) logAction(actions, `[deacon] needs-you ${issueId}: stuck remediation exhausted`);
27471
- }
27472
- async function evaluateAgent(agent, config, now, actions, readyByQueryRoot) {
27473
- const agentId = agent.id;
27474
- if (!agentId) return;
27475
- if (agent.status !== "running") return;
27476
- const completedAt = agent.completedAt;
27477
- if (agent.paused || agent.troubled || completedAt) return;
27478
- if (agent.role === "flywheel") {
27479
- await evaluateFlywheelOrchestrator(agent, config, now, actions);
27480
- return;
27481
- }
27482
- if (!sessionExistsSync(agentId)) return;
27483
- if (agent.role === "plan" && agent.auto === true) {
27484
- await evaluateAutoPlanningAgent(agent, config, now, actions);
27485
- return;
27486
- }
27487
- if (await evaluateWedgedReworkAgent(agent, config, now, actions)) return;
27488
- if (!shouldCheckReadyBeadsForAgent(agent, now)) return;
27489
- if (!agent.workspace) return;
27490
- const issueId = issueIdForAgent(agent);
27491
- if (hasReadyBeads(readyByQueryRoot, agent, issueId.toLowerCase())) return;
27492
- const lastActivityMs = getAgentEffectiveLastActivityMs(agentId);
27493
- if (lastActivityMs === null) return;
27494
- if (!Number.isFinite(lastActivityMs)) return;
27495
- const lastActivity = new Date(lastActivityMs).toISOString();
27496
- const stuckState = readStuckRemediationState(agentId);
27497
- if (stuckState) {
27498
- const firstStuckMs = new Date(stuckState.firstStuckAt).getTime();
27499
- if (Number.isFinite(firstStuckMs) && lastActivityMs > firstStuckMs) {
27500
- clearStuckRemediationState(agentId);
27501
- return;
27502
- }
27503
- }
27504
- const idleMinutes = Math.floor((now - lastActivityMs) / 6e4);
27505
- const lastStage = stuckState?.lastStage ?? 0;
27506
- const firstStuck = firstStuckAt(lastActivity, stuckState);
27507
- if (idleMinutes >= config.stage3_minutes && lastStage < 3) {
27508
- markAgentTroubled(agentId);
27509
- writeStuckRemediationState(agentId, stageState(3, now, firstStuck));
27510
- logAction(actions, transitionAction(3, issueId, idleMinutes, "marked-troubled"));
27511
- surfaceStuckNeedsYou(agent, issueId, firstStuck, actions);
27512
- return;
27513
- }
27514
- if (idleMinutes >= config.stage2_minutes && lastStage < 2) {
27515
- if ((await resumeAgent(agentId, `Resuming after auto-detected stall (${idleMinutes} min idle). Review your last work and decide whether to continue or signal done with \`pan done ${issueId}\`.`)).success) {
27516
- writeStuckRemediationState(agentId, stageState(2, now, firstStuck));
27517
- logAction(actions, transitionAction(2, issueId, idleMinutes, "resumed"));
27518
- } else {
27519
- const action = `${transitionAction(2, issueId, idleMinutes, "resume-failed")} — death: ${describeAgentDeath(agentId)}`;
27520
- console.warn(action);
27521
- logDeaconEventSync(action);
27522
- }
27523
- return;
27524
- }
27525
- if (idleMinutes >= config.stage1_minutes && lastStage < 1) {
27526
- await messageAgent(agentId, `You appear stuck — no tool calls for ${idleMinutes} min. If your implementation is complete, run \`pan done ${issueId}\`. Otherwise reply with a one-line summary of what you're waiting on, then continue.`);
27527
- writeStuckRemediationState(agentId, stageState(1, now, firstStuck));
27528
- logAction(actions, transitionAction(1, issueId, idleMinutes, "poked"));
27529
- }
27530
- }
27531
- async function evaluateAutoPlanningAgent(agent, config, now, actions) {
27532
- const agentId = agent.id;
27533
- if (!isAgentIdleForNudge(agentId, 300 * 1e3, now)) return;
27534
- if (await Effect.runPromise(countPendingAskUserQuestionsForAgent(agentId)) === 0) return;
27535
- const lastActivityMs = getAgentEffectiveLastActivityMs(agentId);
27536
- if (lastActivityMs === null || !Number.isFinite(lastActivityMs)) return;
27537
- const lastActivity = new Date(lastActivityMs).toISOString();
27538
- const stuckState = readStuckRemediationState(agentId);
27539
- if (stuckState) {
27540
- const firstStuckMs = new Date(stuckState.firstStuckAt).getTime();
27541
- if (Number.isFinite(firstStuckMs) && lastActivityMs > firstStuckMs) {
27542
- clearStuckRemediationState(agentId);
27543
- return;
27544
- }
27545
- }
27546
- const idleMinutes = Math.floor((now - lastActivityMs) / 6e4);
27547
- const lastStage = stuckState?.lastStage ?? 0;
27548
- if (idleMinutes < config.stage1_minutes || lastStage >= 1) return;
27549
- const issueId = issueIdForAgent(agent);
27550
- await messageAgent(agentId, `This planning session was launched with \`pan plan ${issueId} --auto\`, so do not wait for operator input. Proceed with the most defensible default from the issue/PRD/comments, record the choice in \`plan.autoDecisions[]\` with rationale, and continue to \`pan plan finalize\`. Only halt for a genuine contradiction between authoritative inputs.`);
27551
- writeStuckRemediationState(agentId, stageState(1, now, firstStuckAt(lastActivity, stuckState)));
27552
- logAction(actions, transitionAction(1, issueId, idleMinutes, "auto-planning-default"));
27553
- }
27554
- const FLYWHEEL_RESPAWN_WINDOW_MS = 1800 * 1e3;
27555
- const FLYWHEEL_MAX_RESPAWNS = 3;
27556
- const FLYWHEEL_ORCHESTRATOR_AGENT_ID = "flywheel-orchestrator";
27557
- /**
27558
- * Pure decision for recovering a dead or wedged flywheel orchestrator (no I/O —
27559
- * side effects live in remediateFlywheelOrchestrator). The respawn cap
27560
- * (FLYWHEEL_MAX_RESPAWNS within FLYWHEEL_RESPAWN_WINDOW_MS) stops an infinite
27561
- * relaunch loop: past the cap, escalate to paused+troubled. `hasActiveRun` false
27562
- * ⇒ the operator stopped the flywheel deliberately ⇒ do not resurrect.
27563
- */
27564
- function decideFlywheelRemediation(opts) {
27565
- if (!opts.hasActiveRun) return { kind: "noop" };
27566
- const lastRespawnMs = opts.prev?.lastRespawnAt ? new Date(opts.prev.lastRespawnAt).getTime() : 0;
27567
- const respawnCount = Number.isFinite(lastRespawnMs) && opts.now - lastRespawnMs < FLYWHEEL_RESPAWN_WINDOW_MS ? opts.prev?.respawnCount ?? 0 : 0;
27568
- if (respawnCount >= FLYWHEEL_MAX_RESPAWNS) return {
27569
- kind: "escalate",
27570
- respawnCount
27571
- };
27572
- return {
27573
- kind: "relaunch",
27574
- respawnCount: respawnCount + 1
27575
- };
27576
- }
27577
- /** True when the orchestrator's process is actually gone (session missing or dead pane). */
27578
- function isFlywheelOrchestratorDead(agentId) {
27579
- if (!sessionExistsSync(agentId)) return true;
27580
- return listPaneValuesSync(agentId, "#{pane_dead}").some((v) => v === "1");
27581
- }
27582
- /**
27583
- * Recover a dead or wedged flywheel orchestrator: relaunch (capped) or, past the
27584
- * cap, pause+trouble. `reason` describes why recovery fired (death vs wedge) for
27585
- * the deacon log. NO_RESUME is intentionally NOT consulted (see header comment) —
27586
- * the operator gate is the active run (`pan flywheel stop`) / patrol freeze.
27587
- */
27588
- async function remediateFlywheelOrchestrator(agentId, now, actions, reason) {
27589
- const decision = decideFlywheelRemediation({
27590
- hasActiveRun: Boolean(getFlywheelActiveRunId()),
27591
- prev: readStuckRemediationState(agentId),
27592
- now
27593
- });
27594
- if (decision.kind === "noop") return;
27595
- const { resumeFlywheel, pauseFlywheel } = await import("./flywheel-DB48X7Nn.js");
27596
- const prev = readStuckRemediationState(agentId);
27597
- const nowIso = new Date(now).toISOString();
27598
- if (decision.kind === "escalate") {
27599
- await pauseFlywheel();
27600
- markAgentTroubled(agentId);
27601
- writeStuckRemediationState(agentId, {
27602
- lastStage: 3,
27603
- lastStageAt: nowIso,
27604
- firstStuckAt: prev?.firstStuckAt ?? nowIso,
27605
- respawnCount: decision.respawnCount,
27606
- lastRespawnAt: prev?.lastRespawnAt
27607
- });
27608
- logAction(actions, `[deacon] FLYWHEEL orchestrator ${reason} and exceeded ${FLYWHEEL_MAX_RESPAWNS} relaunches in ${FLYWHEEL_RESPAWN_WINDOW_MS / 6e4}min — paused + troubled; operator needed`);
27609
- return;
27610
- }
27611
- try {
27612
- killSessionSync(agentId);
27613
- } catch {}
27614
- try {
27615
- await resumeFlywheel();
27616
- writeStuckRemediationState(agentId, {
27617
- lastStage: 0,
27618
- lastStageAt: nowIso,
27619
- firstStuckAt: nowIso,
27620
- respawnCount: decision.respawnCount,
27621
- lastRespawnAt: nowIso
27622
- });
27623
- logAction(actions, `[deacon] FLYWHEEL orchestrator ${reason} — fresh-launched (relaunch ${decision.respawnCount}/${FLYWHEEL_MAX_RESPAWNS})`);
27624
- } catch (error) {
27625
- logAction(actions, `[deacon] FLYWHEEL orchestrator ${reason} — relaunch FAILED: ${error instanceof Error ? error.message : String(error)}`);
27626
- }
27627
- }
27628
- async function evaluateFlywheelOrchestrator(agent, config, now, actions) {
27629
- const agentId = agent.id;
27630
- if (isFlywheelOrchestratorDead(agentId)) {
27631
- await remediateFlywheelOrchestrator(agentId, now, actions, `DIED (${describeAgentDeath(agentId)})`);
27632
- return;
27633
- }
27634
- if (!isAgentIdleForNudge(agentId, 300 * 1e3, now)) return;
27635
- const runtime = getAgentRuntimeStateSync(agentId);
27636
- if (!runtime?.lastActivity) return;
27637
- const lastActivityMs = new Date(runtime.lastActivity).getTime();
27638
- if (!Number.isFinite(lastActivityMs)) return;
27639
- const stuckState = readStuckRemediationState(agentId);
27640
- if (stuckState) {
27641
- const firstStuckMs = new Date(stuckState.firstStuckAt).getTime();
27642
- if (Number.isFinite(firstStuckMs) && lastActivityMs > firstStuckMs) {
27643
- clearStuckRemediationState(agentId);
27644
- return;
27645
- }
27646
- }
27647
- const idleMinutes = Math.floor((now - lastActivityMs) / 6e4);
27648
- const lastStage = stuckState?.lastStage ?? 0;
27649
- const firstStuck = firstStuckAt(runtime.lastActivity, stuckState);
27650
- if (idleMinutes >= config.flywheel_stage3_minutes && lastStage < 3) {
27651
- await remediateFlywheelOrchestrator(agentId, now, actions, `wedged (idle ${idleMinutes}min)`);
27652
- return;
27653
- }
27654
- if (idleMinutes >= config.flywheel_stage2_minutes && lastStage < 2) {
27655
- await messageAgent(agentId, `Stage 2: idle ${idleMinutes} min — run a FULL flywheel tick NOW: inventory -> diagnose -> suggest -> launch ready work -> \`pan flywheel emit-status\`. Then call ScheduleWakeup(delaySeconds:1000) to arm the next tick. Do NOT ask the operator a question, do NOT wait, and do NOT just emit a stale status or pause.`);
27656
- writeStuckRemediationState(agentId, stageState(2, now, firstStuck, stuckState));
27657
- logAction(actions, transitionAction(2, "FLYWHEEL", idleMinutes, "escalated-nudge"));
27658
- return;
27659
- }
27660
- if (idleMinutes >= config.flywheel_stage1_minutes && lastStage < 1) {
27661
- await messageAgent(agentId, `You appear stuck — ${idleMinutes} min since your last tick. Run a FULL flywheel tick NOW: inventory -> diagnose -> suggest -> launch ready work -> \`pan flywheel emit-status\`. Then call ScheduleWakeup(delaySeconds:1000) to arm the next tick. Do NOT ask the operator a question, do NOT wait, and do NOT just emit a stale status or pause.`);
27662
- writeStuckRemediationState(agentId, stageState(1, now, firstStuck, stuckState));
27663
- logAction(actions, transitionAction(1, "FLYWHEEL", idleMinutes, "poked"));
27664
- }
27665
- }
27666
- async function reconcileActiveFlywheelWithoutRunningAgent(now, actions) {
27667
- if (!getFlywheelActiveRunId()) return;
27668
- if (isFlywheelGloballyPaused()) return;
27669
- if (sessionExistsSync(FLYWHEEL_ORCHESTRATOR_AGENT_ID)) return;
27670
- await remediateFlywheelOrchestrator(FLYWHEEL_ORCHESTRATOR_AGENT_ID, now, actions, `DIED (${describeAgentDeath(FLYWHEEL_ORCHESTRATOR_AGENT_ID)})`);
27671
- }
27672
- async function checkStuckAgentRemediation(opts = {}) {
27673
- const config = loadCloisterConfigSync().stuck_remediation ?? DEFAULT_CLOISTER_CONFIG.stuck_remediation;
27674
- if (!config.enabled) return [];
27675
- const actions = [];
27676
- const now = opts.now ?? Date.now();
27677
- const runningAgents = listRunningAgentsSync();
27678
- const readyByQueryRoot = /* @__PURE__ */ new Map();
27679
- const workAgentsByQueryRoot = /* @__PURE__ */ new Map();
27680
- let sawFlywheelOrchestrator = false;
27681
- for (const agent of runningAgents) {
27682
- if (!shouldCheckReadyBeadsForAgent(agent, now)) continue;
27683
- const queryRoot = resolveBeadsQueryRoot(agent.workspace);
27684
- const workspaceAgents = workAgentsByQueryRoot.get(queryRoot) ?? [];
27685
- workspaceAgents.push(agent);
27686
- workAgentsByQueryRoot.set(queryRoot, workspaceAgents);
27687
- }
27688
- for (const [queryRoot, workspaceAgents] of workAgentsByQueryRoot) {
27689
- const issueIds = workspaceAgents.map(issueIdForAgent);
27690
- const ready = await Effect.runPromise(queryReadyBeadsByIssueLabels(queryRoot, issueIds, { acquisitionTimeoutMs: 500 }));
27691
- readyByQueryRoot.set(queryRoot, ready.byIssue);
27692
- }
27693
- for (const agent of runningAgents) {
27694
- if (agent.id === FLYWHEEL_ORCHESTRATOR_AGENT_ID || agent.role === "flywheel") sawFlywheelOrchestrator = true;
27695
- try {
27696
- await evaluateAgent(agent, config, now, actions, readyByQueryRoot);
27697
- } catch (error) {
27698
- const message = `[deacon] stuck-remediation agent=${agent.id || "(unknown)"} error=${error instanceof Error ? error.message : String(error)}`;
27699
- console.error(message, error);
27700
- logDeaconEventSync(message);
27701
- }
27702
- }
27703
- if (!sawFlywheelOrchestrator) try {
27704
- await reconcileActiveFlywheelWithoutRunningAgent(now, actions);
27705
- } catch (error) {
27706
- const message = `[deacon] stuck-remediation agent=${FLYWHEEL_ORCHESTRATOR_AGENT_ID} error=${error instanceof Error ? error.message : String(error)}`;
27707
- console.error(message, error);
27708
- logDeaconEventSync(message);
27709
- }
27710
- return actions;
27711
- }
27712
- //#endregion
27713
26280
  //#region ../../lib/backlog/label-ops.ts
27714
26281
  init_tracker_utils();
27715
26282
  const execAsync$3 = promisify(exec);
@@ -28608,8 +27175,8 @@ async function cleanupStaleAgentState() {
28608
27175
  */
28609
27176
  async function cleanupAbandonedFeedback() {
28610
27177
  const actions = [];
28611
- const { getReviewStatusSync } = await import("./review-status-B0Axo-Ma.js");
28612
- const { clearFeedbackFiles } = await import("./feedback-writer-DCyd75yJ.js");
27178
+ const { getReviewStatusSync } = await import("./review-status-Br6lAFGO.js");
27179
+ const { clearFeedbackFiles } = await import("./feedback-writer-DOUhyIW2.js");
28613
27180
  for (const { issueId, workspacePath } of listFeatureWorkspaces()) {
28614
27181
  const panFeedbackDir = join$1(workspacePath, ".pan", "feedback");
28615
27182
  if (!existsSync(panFeedbackDir)) continue;
@@ -28680,7 +27247,7 @@ async function handleOrphanReviewerSession(sessionName, sessions, creationTimes,
28680
27247
  if (!issueId) return null;
28681
27248
  const agentSession = `agent-${issueId.toLowerCase()}`;
28682
27249
  if (sessions.includes(agentSession)) return null;
28683
- const { getReviewStatusSync } = await import("./review-status-B0Axo-Ma.js");
27250
+ const { getReviewStatusSync } = await import("./review-status-Br6lAFGO.js");
28684
27251
  try {
28685
27252
  if (getReviewStatusSync(issueId)?.reviewStatus === "reviewing") return null;
28686
27253
  } catch {}
@@ -28800,7 +27367,7 @@ async function checkOrphanedCompletions() {
28800
27367
  async function checkPendingTestDispatch() {
28801
27368
  const actions = [];
28802
27369
  try {
28803
- const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-B0Axo-Ma.js");
27370
+ const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Br6lAFGO.js");
28804
27371
  const statuses = loadReviewStatuses();
28805
27372
  const now = Date.now();
28806
27373
  for (const [issueId, status] of Object.entries(statuses)) {
@@ -28833,7 +27400,7 @@ async function checkPendingTestDispatch() {
28833
27400
  console.log(`[deacon] ${issueId}: skipping test re-dispatch — issue is closed`);
28834
27401
  continue;
28835
27402
  }
28836
- const { resolveProjectFromIssueSync } = await import("./projects-BqRMlDOv.js");
27403
+ const { resolveProjectFromIssueSync } = await import("./projects-KJ94e50I.js");
28837
27404
  const resolved = resolveProjectFromIssueSync(issueId);
28838
27405
  if (!resolved) continue;
28839
27406
  const issueLower = issueId.toLowerCase();
@@ -28848,8 +27415,8 @@ async function checkPendingTestDispatch() {
28848
27415
  logDeaconEventSync(`checkPendingTestDispatch: deferred test for ${issueId} — advancing ceiling reached (PAN-1665) — ${describeRunningAgents()}`);
28849
27416
  continue;
28850
27417
  }
28851
- const { spawnRun } = await import("./agents-CxbuBjID.js");
28852
- const { buildTestRolePrompt } = await import("./test-agent-queue-Bq298zZl.js");
27418
+ const { spawnRun } = await import("./agents-DCvyTXNU.js");
27419
+ const { buildTestRolePrompt } = await import("./test-agent-queue-DjsQoV5X.js");
28853
27420
  try {
28854
27421
  const run = await spawnRun(issueId, "test", {
28855
27422
  workspace,
@@ -28972,7 +27539,7 @@ async function checkCompletedButUnsignaledTests() {
28972
27539
  const cmd = `pan admin specialists done test ${issueId} --status ${decision.status}${noteArg}`;
28973
27540
  const nudge = `Your test verdict (${decision.status}) is already written to .pan/test/result.json. Your ONLY remaining task is to execute this Bash command immediately — do not analyze, do not summarize, do not ask questions, just run it:\n\n${cmd}\n\nRun this command NOW. Do not write any other response before executing it.`;
28974
27541
  try {
28975
- const { messageAgent } = await import("./agents-CxbuBjID.js");
27542
+ const { messageAgent } = await import("./agents-DCvyTXNU.js");
28976
27543
  await messageAgent(testSession, nudge);
28977
27544
  unsignaledTestNudges.set(testSession, now);
28978
27545
  const msg = `Nudged ${testSession} to signal ${decision.status} (verdict artifact present)`;
@@ -28986,7 +27553,7 @@ async function checkCompletedButUnsignaledTests() {
28986
27553
  case "nudge-write": {
28987
27554
  const nudge = `Your test run for ${issueId} looks finished but no verdict was recorded. Decide the verdict from the gates/UAT you ran, then do BOTH of these now: (1) write the workspace file .pan/test/result.json as {"status":"passed"|"failed","notes":"<evidence>"}, and (2) run: pan admin specialists done test ${issueId} --status passed|failed. Do this immediately — do not summarize or ask questions, just write the file and run the command.`;
28988
27555
  try {
28989
- const { messageAgent } = await import("./agents-CxbuBjID.js");
27556
+ const { messageAgent } = await import("./agents-DCvyTXNU.js");
28990
27557
  await messageAgent(testSession, nudge);
28991
27558
  unsignaledTestNudges.set(testSession, now);
28992
27559
  const msg = `Nudged ${testSession} to write+signal a test verdict (no artifact yet)`;
@@ -29009,8 +27576,8 @@ async function checkCompletedButUnsignaledTests() {
29009
27576
  async function checkVerificationReviewContradiction() {
29010
27577
  const actions = [];
29011
27578
  try {
29012
- const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-B0Axo-Ma.js");
29013
- const { resolveProjectFromIssueSync } = await import("./projects-BqRMlDOv.js");
27579
+ const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Br6lAFGO.js");
27580
+ const { resolveProjectFromIssueSync } = await import("./projects-KJ94e50I.js");
29014
27581
  const statuses = loadReviewStatuses();
29015
27582
  for (const [issueId, status] of Object.entries(statuses)) if (status.verificationStatus === "passed" && status.reviewStatus === "reviewing" && status.stuckReason === "review_infrastructure_failure") {
29016
27583
  let reviewedAtCommit;
@@ -29059,7 +27626,7 @@ async function checkPostReviewCommits() {
29059
27626
  const actions = [];
29060
27627
  try {
29061
27628
  const statuses = loadReviewStatuses();
29062
- const { resolveProjectFromIssueSync } = await import("./projects-BqRMlDOv.js");
27629
+ const { resolveProjectFromIssueSync } = await import("./projects-KJ94e50I.js");
29063
27630
  for (const [issueId, status] of Object.entries(statuses)) {
29064
27631
  if (status.mergeStatus === "merged") continue;
29065
27632
  if (!status.reviewedAtCommit) continue;
@@ -29114,7 +27681,7 @@ async function checkPostReviewCommits() {
29114
27681
  actions.push(`Deferred post-review re-dispatch for ${issueId} — advancing-role concurrency ceiling reached`);
29115
27682
  logDeaconEventSync(`checkPostReviewCommits: deferred review for ${issueId} — advancing ceiling reached (PAN-1665) — ${describeRunningAgents()}`);
29116
27683
  } else if (freshStatus?.reviewStatus === "pending") {
29117
- const { spawnReviewRoleForIssue } = await import("./review-agent-Bf9XjLnl.js");
27684
+ const { spawnReviewRoleForIssue } = await import("./review-agent-Rub0OpZc.js");
29118
27685
  const branch = `feature/${issueId.toLowerCase()}`;
29119
27686
  const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
29120
27687
  issueId,
@@ -29214,7 +27781,7 @@ async function checkReadyForMergeStuck() {
29214
27781
  const testStatusGreenCiReconcileCooldowns = /* @__PURE__ */ new Map();
29215
27782
  const TEST_STATUS_GREEN_CI_RECONCILE_COOLDOWN_MS = 300 * 1e3;
29216
27783
  async function reconcileTestStatusFromGreenCi() {
29217
- const { getCiCheckRunsState, getPullRequestHeadState, isGitHubAppConfigured } = await import("./github-app-DIr70YLg.js");
27784
+ const { getCiCheckRunsState, getPullRequestHeadState, isGitHubAppConfigured } = await import("./github-app-DRD2woO0.js");
29218
27785
  return reconcileTestStatusFromGreenCiWithDeps({
29219
27786
  isGitHubAppConfigured,
29220
27787
  loadReviewStatuses,
@@ -29235,7 +27802,7 @@ async function reconcileTestStatusFromGreenCi() {
29235
27802
  */
29236
27803
  async function clearStaleCiFeedback(issueId) {
29237
27804
  const { readdir, rm } = await import("fs/promises");
29238
- const { resolveProjectFromIssueSync } = await import("./projects-BqRMlDOv.js");
27805
+ const { resolveProjectFromIssueSync } = await import("./projects-KJ94e50I.js");
29239
27806
  const projectConfig = resolveProjectFromIssueSync(issueId);
29240
27807
  if (!projectConfig) return;
29241
27808
  const repoDir = projectConfig.projectPath;
@@ -29535,7 +28102,7 @@ async function checkWorkspaceContainerHealth(sharedState) {
29535
28102
  }
29536
28103
  }
29537
28104
  try {
29538
- const { resolveProjectFromIssueSync } = await import("./projects-BqRMlDOv.js");
28105
+ const { resolveProjectFromIssueSync } = await import("./projects-KJ94e50I.js");
29539
28106
  const resolved = resolveProjectFromIssueSync(issueLower.toUpperCase());
29540
28107
  if (resolved) await killOrphanedWorkspaceProcesses(`${resolved.projectPath}/workspaces/feature-${issueLower}`);
29541
28108
  } catch {}
@@ -29584,8 +28151,8 @@ async function checkWorkspaceContainerHealth(sharedState) {
29584
28151
  async function checkMergedWorkSessions() {
29585
28152
  const actions = [];
29586
28153
  try {
29587
- const { selectMergedWorkSessions } = await import("./reap-terminal-sessions-BwJb2DLJ.js");
29588
- const { setAgentPaused } = await import("./agents-CxbuBjID.js");
28154
+ const { selectMergedWorkSessions } = await import("./reap-terminal-sessions-D_xvy-Mk.js");
28155
+ const { setAgentPaused } = await import("./agents-DCvyTXNU.js");
29589
28156
  const toKill = selectMergedWorkSessions(loadReviewStatuses(), [...await Effect.runPromise(listSessionNames())]);
29590
28157
  for (const session of toKill) try {
29591
28158
  await Effect.runPromise(setAgentPaused(session, "merged — awaiting close-out (verify on main)", true));
@@ -29625,7 +28192,7 @@ const AWAITING_TEST_IDLE_REAP_MS = 600 * 1e3;
29625
28192
  async function checkAwaitingTestWorkSessions() {
29626
28193
  const actions = [];
29627
28194
  try {
29628
- const { selectAwaitingTestWorkSessions } = await import("./reap-terminal-sessions-BwJb2DLJ.js");
28195
+ const { selectAwaitingTestWorkSessions } = await import("./reap-terminal-sessions-D_xvy-Mk.js");
29629
28196
  const candidates = selectAwaitingTestWorkSessions(loadReviewStatuses(), [...await Effect.runPromise(listSessionNames())]);
29630
28197
  const now = Date.now();
29631
28198
  for (const session of candidates) {
@@ -29681,7 +28248,7 @@ async function runPatrol() {
29681
28248
  const stuckRemediationActions = await checkStuckAgentRemediation();
29682
28249
  actions.push(...stuckRemediationActions);
29683
28250
  for (const a of stuckRemediationActions) addLog("action", a, state.patrolCycle);
29684
- const { reconcileInFlightJournals } = await import("./advancing-selfheal-Bn5QiLtn.js");
28251
+ const { reconcileInFlightJournals } = await import("./advancing-selfheal-CSuZ31bB.js");
29685
28252
  const reconciledJournalActions = await reconcileInFlightJournals();
29686
28253
  actions.push(...reconciledJournalActions);
29687
28254
  for (const a of reconciledJournalActions) addLog("action", a, state.patrolCycle);
@@ -29693,7 +28260,7 @@ async function runPatrol() {
29693
28260
  const age = Date.now() - (pending.timestamp ?? 0);
29694
28261
  if (age < 3600 * 1e3) {
29695
28262
  console.log(`[deacon] Processing pending post-merge lifecycle for ${pending.issueId} (age: ${Math.round(age / 1e3)}s)`);
29696
- const { postMergeLifecycle } = await import("./merge-agent-Bwm34MZ5.js");
28263
+ const { postMergeLifecycle } = await import("./merge-agent-36wfYm2u.js");
29697
28264
  const { unlinkSync } = await import("fs");
29698
28265
  unlinkSync(pendingFile);
29699
28266
  await postMergeLifecycle(pending.issueId, pending.projectPath, pending.sourceBranch, { skipDeploy: true });
@@ -29738,7 +28305,7 @@ async function runPatrol() {
29738
28305
  actions.push(...suspendActions);
29739
28306
  for (const a of suspendActions) addLog("action", a, state.patrolCycle);
29740
28307
  try {
29741
- const { resolveProjectFromIssueSync } = await import("./projects-BqRMlDOv.js");
28308
+ const { resolveProjectFromIssueSync } = await import("./projects-KJ94e50I.js");
29742
28309
  const allStatuses = loadReviewStatuses();
29743
28310
  for (const [issueId, status] of Object.entries(allStatuses)) {
29744
28311
  if (!status.readyForMerge || status.mergeStatus === "merged") continue;
@@ -29758,7 +28325,7 @@ async function runPatrol() {
29758
28325
  } catch (err) {
29759
28326
  console.warn(`[deacon] Failed to check workspace existence: ${err.message}`);
29760
28327
  }
29761
- const { checkMergedAdvancingSessions } = await import("./advancing-selfheal-Bn5QiLtn.js");
28328
+ const { checkMergedAdvancingSessions } = await import("./advancing-selfheal-CSuZ31bB.js");
29762
28329
  const reapedWorkActions = await checkMergedWorkSessions();
29763
28330
  actions.push(...reapedWorkActions);
29764
28331
  for (const a of reapedWorkActions) addLog("action", a, state.patrolCycle);
@@ -29766,7 +28333,7 @@ async function runPatrol() {
29766
28333
  actions.push(...reapedMergedAdvancingActions);
29767
28334
  for (const a of reapedMergedAdvancingActions) addLog("action", a, state.patrolCycle);
29768
28335
  try {
29769
- const { refreshClaudeCredentialsForActiveRemoteAgents } = await import("./remote-completion-B0rmBnbL.js");
28336
+ const { refreshClaudeCredentialsForActiveRemoteAgents } = await import("./remote-completion-BgkiSQmx.js");
29770
28337
  const remoteCredentialActions = await refreshClaudeCredentialsForActiveRemoteAgents();
29771
28338
  actions.push(...remoteCredentialActions);
29772
28339
  for (const a of remoteCredentialActions) addLog(a.includes("failed") ? "warn" : "action", a, state.patrolCycle);
@@ -29774,7 +28341,7 @@ async function runPatrol() {
29774
28341
  addLog("warn", `Remote credential refresh patrol failed: ${err.message}`, state.patrolCycle);
29775
28342
  }
29776
28343
  try {
29777
- const { refreshHostHeartbeatForEphemeralVms } = await import("./remote-agents-B4eWgwNd.js");
28344
+ const { refreshHostHeartbeatForEphemeralVms } = await import("./remote-agents-DlvbzO7m.js");
29778
28345
  const heartbeatActions = await refreshHostHeartbeatForEphemeralVms();
29779
28346
  actions.push(...heartbeatActions);
29780
28347
  for (const a of heartbeatActions) addLog(a.includes("failed") ? "warn" : "action", a, state.patrolCycle);
@@ -29782,7 +28349,7 @@ async function runPatrol() {
29782
28349
  addLog("warn", `Remote heartbeat refresh patrol failed: ${err.message}`, state.patrolCycle);
29783
28350
  }
29784
28351
  try {
29785
- const { reapCompletedRemoteAgents } = await import("./remote-completion-B0rmBnbL.js");
28352
+ const { reapCompletedRemoteAgents } = await import("./remote-completion-BgkiSQmx.js");
29786
28353
  const remoteReap = await reapCompletedRemoteAgents();
29787
28354
  for (const r of remoteReap) if (r.status === "handed-off" || r.status === "error") {
29788
28355
  const msg = `Remote reap ${r.issueId}: ${r.status} (${r.details.join("; ")})`;
@@ -29960,7 +28527,7 @@ async function runPatrol() {
29960
28527
  const issueId = runtimeState.currentIssue;
29961
28528
  try {
29962
28529
  if (getReviewStatusSync(issueId)?.mergeStatus === "merging") {
29963
- const { resolveProjectFromIssueSync } = await import("./projects-BqRMlDOv.js");
28530
+ const { resolveProjectFromIssueSync } = await import("./projects-KJ94e50I.js");
29964
28531
  const resolved = resolveProjectFromIssueSync(issueId);
29965
28532
  if (resolved) {
29966
28533
  const branch = `feature/${issueId.toLowerCase()}`;
@@ -29974,7 +28541,7 @@ async function runPatrol() {
29974
28541
  mergeStatus: "merged",
29975
28542
  readyForMerge: false
29976
28543
  });
29977
- const { postMergeLifecycle } = await import("./merge-agent-Bwm34MZ5.js");
28544
+ const { postMergeLifecycle } = await import("./merge-agent-36wfYm2u.js");
29978
28545
  postMergeLifecycle(issueId, resolved.projectPath).catch((err) => console.warn(`[deacon] postMergeLifecycle failed for ${issueId}: ${err}`));
29979
28546
  actions.push(`Auto-completed stale merge for ${issueId}`);
29980
28547
  } else {
@@ -30154,7 +28721,7 @@ function startDeacon() {
30154
28721
  logDeaconEventSync(`startDeacon: health monitor starting (patrol every ${config.patrolIntervalMs / 1e3}s)`);
30155
28722
  (async () => {
30156
28723
  await reconcileAgentLiveness();
30157
- const { runBootAdvancingSelfHeal } = await import("./advancing-selfheal-Bn5QiLtn.js");
28724
+ const { runBootAdvancingSelfHeal } = await import("./advancing-selfheal-CSuZ31bB.js");
30158
28725
  await runBootAdvancingSelfHeal();
30159
28726
  runScheduledPatrol("startup");
30160
28727
  })().catch((err) => {
@@ -30224,6 +28791,6 @@ function assessDeaconPatrolFreshness(params) {
30224
28791
  };
30225
28792
  }
30226
28793
  //#endregion
30227
- export { isPreKickoffLaunchDeath as $, scanPendingInputsPromise as $t, reconcileAgentLiveness as A, stalledReviewConvoyRecoveryState as At, applyIssueBlocksMainLabel as B, formatUptime as Bt, getLastPatrolResult as C, isSynthesisForActiveReviewRun as Ct, isDeaconRunning as D, handleWorkCompleted as Dt, handleAgentStoppedForOrphanReviewerSessions as E, handleReviewCoordinatorDied as Et, setAgentStatusChangedNotifier as F, INSPECT_TIMEOUT_MS as Ft, applyIssueVetoedLabel as G, isSmeeConfiguredSync as Gt, applyIssueParkedLabel as H, getCurrentDockerStats as Ht, setAgentStoppedNotifier as I, checkInspectAgentTimeouts as It, removeIssueParkedLabel as J, countPendingAskUserQuestionsForAgent as Jt, removeIssueBlocksMainLabel as K, startSmeeProcessSync as Kt, setMergeReadyNotifier as L, getRuntimeForAgent as Lt, resetPatrolHeartbeatForStartup as M, contextOverflowRecoveryState as Mt, runPatrol as N, contextProactiveCompactState as Nt, loadConfig as O, recoverStalledReviewConvoys as Ot, saveState as P, stuckOverflowNativeRecoveryState as Pt, createInFlightGuard as Q, getAgentWorkspace as Qt, startDeacon as R, classifyMemoryPressure as Rt, getDeaconStatus as S, checkStuckReviewing as St, handleAgentStoppedEvent as T, checkOrphanedReviewStatuses as Tt, applyIssueReadyLabel as U, getResourceConfig as Ut, applyIssueObjectionLabel as V, getContainerHistory as Vt, applyIssueReleasedLabel as W, getSystemHealthSnapshot as Wt, removeIssueReleasedLabel as X, getAgentJsonlPath as Xt, removeIssueReadyLabel as Y, getAgentJsonlMtime as Yt, removeIssueVetoedLabel as Z, getAgentPendingQuestions as Zt, cleanupOrphanReviewerSessions as _, withConcurrencyLimit as _t, checkCompletedButUnsignaledTests as a, listBootReconciliationCandidates as at, containerRestartBackoffMs as b, synthesizeReviewFromReports as bt, checkMergedWorkSessions as c, checkFailedMergeRetry as ct, checkPostReviewCommits as d, reconcileClosedPrReadyForMerge as dt, detectAwaitingInputForAgent as en, isRapidPostResumeDeath as et, checkReadyForMergeStuck as f, reconcileFalseMerged as ft, cleanupAbandonedFeedback as g, reconcileStuckReadyForMerge as gt, checkWorkspaceContainerHealth as h, reconcileStaleMergeStatus as ht, checkAwaitingTestWorkSessions as i, isBootReconciliationCandidate as it, reconcileTestStatusFromGreenCi as j, checkApiErrorAgents as jt, loadState as k, reviewConvoyLiveness as kt, checkOrphanedCompletions as l, checkFirstCompletionAgents as lt, checkVerificationReviewContradiction as m, reconcileStaleMergeBlockers as mt, assessDeaconPatrolFreshness as n, normalizeAwaitingInputPrompt as nn, nudgeStalledResumeWorkAgents as nt, checkDeadEndAgents as o, startBootReconciliation as ot, checkStuckWorkAgents as p, reconcileMergedButReviewing as pt, removeIssueObjectionLabel as q, computeAgentEnrichment as qt, checkAndSuspendIdleAgents as r, parseCodexApprovalPrompt as rn, redeliverUndeliveredKickoffs as rt, checkMassDeath as s, autoCloseOut as st, applyBootReconciliationDecision as t, detectAwaitingInputFromPaneSync as tn, nudgeIdleWorkAgentsWithOpenBeads as tt, checkPendingTestDispatch as u, ciRetryMap as ut, cleanupOrphanedPlanningSessions as v, cleanupOrphanedReviewSessions as vt, handleAgentHeartbeatDeadEvent as w, checkMissingReviewStatuses as wt, getDeaconLogs as x, checkCompletedButUnsignaledReviews as xt, cleanupStaleAgentState as y, monitorReviewConvoySignals as yt, stopDeacon as z, getResourceStacks as zt };
28794
+ export { isPreKickoffLaunchDeath as $, reconcileAgentLiveness as A, stalledReviewConvoyRecoveryState as At, applyIssueBlocksMainLabel as B, getContainerHistory as Bt, getLastPatrolResult as C, isSynthesisForActiveReviewRun as Ct, isDeaconRunning as D, handleWorkCompleted as Dt, handleAgentStoppedForOrphanReviewerSessions as E, handleReviewCoordinatorDied as Et, setAgentStatusChangedNotifier as F, INSPECT_TIMEOUT_MS as Ft, applyIssueVetoedLabel as G, startSmeeProcessSync as Gt, applyIssueParkedLabel as H, getResourceConfig as Ht, setAgentStoppedNotifier as I, checkInspectAgentTimeouts as It, removeIssueParkedLabel as J, removeIssueBlocksMainLabel as K, setMergeReadyNotifier as L, classifyMemoryPressure as Lt, resetPatrolHeartbeatForStartup as M, contextOverflowRecoveryState as Mt, runPatrol as N, contextProactiveCompactState as Nt, loadConfig as O, recoverStalledReviewConvoys as Ot, saveState as P, stuckOverflowNativeRecoveryState as Pt, createInFlightGuard as Q, startDeacon as R, getResourceStacks as Rt, getDeaconStatus as S, checkStuckReviewing as St, handleAgentStoppedEvent as T, checkOrphanedReviewStatuses as Tt, applyIssueReadyLabel as U, getSystemHealthSnapshot as Ut, applyIssueObjectionLabel as V, getCurrentDockerStats as Vt, applyIssueReleasedLabel as W, isSmeeConfiguredSync as Wt, removeIssueReleasedLabel as X, removeIssueReadyLabel as Y, removeIssueVetoedLabel as Z, cleanupOrphanReviewerSessions as _, withConcurrencyLimit as _t, checkCompletedButUnsignaledTests as a, listBootReconciliationCandidates as at, containerRestartBackoffMs as b, synthesizeReviewFromReports as bt, checkMergedWorkSessions as c, checkFailedMergeRetry as ct, checkPostReviewCommits as d, reconcileClosedPrReadyForMerge as dt, isRapidPostResumeDeath as et, checkReadyForMergeStuck as f, reconcileFalseMerged as ft, cleanupAbandonedFeedback as g, reconcileStuckReadyForMerge as gt, checkWorkspaceContainerHealth as h, reconcileStaleMergeStatus as ht, checkAwaitingTestWorkSessions as i, isBootReconciliationCandidate as it, reconcileTestStatusFromGreenCi as j, checkApiErrorAgents as jt, loadState as k, reviewConvoyLiveness as kt, checkOrphanedCompletions as l, checkFirstCompletionAgents as lt, checkVerificationReviewContradiction as m, reconcileStaleMergeBlockers as mt, assessDeaconPatrolFreshness as n, nudgeStalledResumeWorkAgents as nt, checkDeadEndAgents as o, startBootReconciliation as ot, checkStuckWorkAgents as p, reconcileMergedButReviewing as pt, removeIssueObjectionLabel as q, checkAndSuspendIdleAgents as r, redeliverUndeliveredKickoffs as rt, checkMassDeath as s, autoCloseOut as st, applyBootReconciliationDecision as t, nudgeIdleWorkAgentsWithOpenBeads as tt, checkPendingTestDispatch as u, ciRetryMap as ut, cleanupOrphanedPlanningSessions as v, cleanupOrphanedReviewSessions as vt, handleAgentHeartbeatDeadEvent as w, checkMissingReviewStatuses as wt, getDeaconLogs as x, checkCompletedButUnsignaledReviews as xt, cleanupStaleAgentState as y, monitorReviewConvoySignals as yt, stopDeacon as z, formatUptime as zt };
30228
28795
 
30229
- //# sourceMappingURL=deacon-2EvA9Ci3.js.map
28796
+ //# sourceMappingURL=deacon-DrKDBeJL.js.map