@overdeck/desktop 0.47.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (444) hide show
  1. package/drizzle/overdeck/0000_overdeck_init.sql +59 -0
  2. package/package.json +1 -1
  3. package/server/{acceptance-criteria-10Ur5Dne.js → acceptance-criteria-DmtLDbtt.js} +2 -2
  4. package/server/{activity-logger-CyteR4JO.js → activity-logger-Co5qljIj.js} +55 -4
  5. package/server/activity-logger-K7FYGF_z.js +3 -0
  6. package/server/{advancing-selfheal-BNwqxseD.js → advancing-selfheal-8AR68Asf.js} +6 -6
  7. package/server/{agent-gc-C3h9Or3a.js → agent-gc-BmYeT6eH.js} +5 -5
  8. package/server/agent-state-Dq3s84-P.js +3 -0
  9. package/server/{agent-state-service-C63p_ftq.js → agent-state-service-DK1Vay1E.js} +1 -1
  10. package/server/{agent-state-service-Ds6OeFvo.js → agent-state-service-rjnzpHDx.js} +6 -6
  11. package/server/agent-state-source-Ds968-j6.js +21 -0
  12. package/server/{agents-J5mEnekq.js → agents-Dls7tfJH.js} +5 -5
  13. package/server/agents-IPSa5kzn.js +3 -0
  14. package/server/{archive-planning-BwhxeP7C.js → archive-planning-Cq7cyinS.js} +51 -24
  15. package/server/archive-planning-MbkGCBIY.js +2 -0
  16. package/server/{artifact-index-jobs-D1q_vR3V.js → artifact-index-jobs-Dj_8kpTd.js} +3 -3
  17. package/server/{assemble-Bgwqv-Ro.js → assemble-BTCmbcfH.js} +20 -13
  18. package/server/{auto-spawn-consent-CQ9Bi9q6.js → auto-spawn-consent-lXqRJ1Dr.js} +304 -121
  19. package/server/{backlog-auto-trigger-n1lzPgN4.js → backlog-auto-trigger-Dn-amzt6.js} +3 -3
  20. package/server/{behavior-td6-xhQk.js → behavior-DIMQMRzs.js} +2 -2
  21. package/server/{boot-reconciled-stop-events-C7gGe3oB.js → boot-reconciled-stop-events-D6SeUTIr.js} +1 -1
  22. package/server/{bridge-pool-patrol-CYH2OLb5.js → bridge-pool-patrol-BEjt-xF3.js} +2 -2
  23. package/server/{briefing-freshness-DRqZ8lAz.js → briefing-freshness-3PNmL_p3.js} +2 -2
  24. package/server/{build-info-7yiEpl6u.js → build-info-CJg813Hm.js} +3 -3
  25. package/server/{build-info-CpG__c63.js → build-info-CXyeFsXu.js} +1 -1
  26. package/server/{checkpoint-manager-CkKmB0wZ.js → checkpoint-manager-9t7G5c1V.js} +1 -1
  27. package/server/{checkpoint-manager-DBcyNR8w.js → checkpoint-manager-B2G38R3p.js} +3 -3
  28. package/server/checkpoint-worker.js +1 -1
  29. package/server/{checkpoints-Wm963lm8.js → checkpoints-CuBgiXO-.js} +1 -1
  30. package/server/{checkpoints-D95apurL.js → checkpoints-VTZMd4Qm.js} +2 -2
  31. package/server/{claude-hooks-provision-Bjitl9aI.js → claude-hooks-provision-55SyQaPz.js} +2 -2
  32. package/server/{claude-hooks-provision-4RPxNkE8.js → claude-hooks-provision-CEUT-CZd.js} +1 -1
  33. package/server/{claude-permissions-CpbpvUQ2.js → claude-permissions-Cn0dIu2i.js} +2 -2
  34. package/server/{claude-settings-overlay-BzkHYDwR.js → claude-settings-overlay-B19hdzSA.js} +1 -1
  35. package/server/{claude-settings-overlay-_H9Yrzab.js → claude-settings-overlay-Yg_ANh81.js} +2 -2
  36. package/server/{cli-Cte9ZFGn.js → cli-C9S84iTy.js} +79 -22
  37. package/server/cli-M1cwZ__d.js +3 -0
  38. package/server/{cliproxy-C5fMJ7rY.js → cliproxy-CJq3KXU6.js} +2 -2
  39. package/server/{cliproxy-DaAbWMjC.js → cliproxy-DgEZlr7Y.js} +1 -1
  40. package/server/{close-issue-BPh1ARCF.js → close-issue-DPxRddGR.js} +5 -5
  41. package/server/{closed-issue-reaper-DoOZqGFK.js → closed-issue-reaper-C5Zn4GRS.js} +13 -13
  42. package/server/{closed-issue-reaper-DHRfRMrp.js → closed-issue-reaper-D-2B48Ri.js} +1 -1
  43. package/server/{codex-o8FJwzmy.js → codex-B3n_rkwn.js} +1 -1
  44. package/server/{codex-BzGDW_d3.js → codex-CjkD1PJu.js} +6 -6
  45. package/server/{codex-parser-Dt-ycU8L.js → codex-parser-DpB1Il-P.js} +2 -2
  46. package/server/{compaction-continuation-CvXpbZ4w.js → compaction-continuation-DZD9ukSE.js} +3 -3
  47. package/server/{config-CL3Gyvja.js → config-C5saf4Ja.js} +1 -1
  48. package/server/{config-BvLe652W.js → config-DnLJATZk.js} +2 -2
  49. package/server/{config-Bi3u1VK7.js → config-DvM8jtQK.js} +2 -2
  50. package/server/{config-yaml-CxdwhAIA.js → config-yaml-BSCqwmX0.js} +11299 -10972
  51. package/server/{conflict-gate-CX80JYYS.js → conflict-gate-DXa_L28t.js} +1 -1
  52. package/server/{conflict-gate-E4nt7ZeS.js → conflict-gate-WfVqgalf.js} +4 -4
  53. package/server/{context-layers-DAG83UZt.js → context-layers-D7UqH9Ab.js} +2 -2
  54. package/server/{context-layers-C_IIysnm.js → context-layers-Dpz3Vd6d.js} +3 -3
  55. package/server/{control-settings-CiqGxXnc.js → control-settings-DVf6pKyv.js} +4 -4
  56. package/server/{conversation-compaction-BE3CNtHF.js → conversation-compaction-5XuH6OBn.js} +1 -1
  57. package/server/{conversation-compaction-D6-yLtqt.js → conversation-compaction-COrbnX1J.js} +8 -8
  58. package/server/{conversation-service-DBxoYMDl.js → conversation-service-BufdtnZF.js} +169 -10
  59. package/server/{conversation-service-D_TS2b1r.js → conversation-service-DnUyIiLb.js} +1 -1
  60. package/server/{conversations-D0UEdLtk.js → conversations-B4rxz-Wl.js} +17 -10
  61. package/server/{conversations-BKDVpB-3.js → conversations-D1bwxQMy.js} +1 -1
  62. package/server/{cost-DpgYmYqR.js → cost-CpFDrJUS.js} +46 -2
  63. package/server/{cost-DS1s0DbG.js → cost-KLuwKCW9.js} +3 -3
  64. package/server/{cost-sync-tOCCGnEt.js → cost-sync-cesi9dp8.js} +3 -3
  65. package/server/{dag-BtkgLeqY.js → dag-BYiFMqpU.js} +2 -2
  66. package/server/{dangerous-git-ops-CFLykHWt.js → dangerous-git-ops-BKvd3-Hk.js} +1 -1
  67. package/server/dashboard-db-worker.js +7 -7
  68. package/server/{deacon-BIblC-WX.js → deacon-BbsWw8a6.js} +3 -3
  69. package/server/{deacon-pLRLbPvR.js → deacon-HdEh0Esp.js} +863 -214
  70. package/server/deacon-event-client-C93rvOT7.js +237 -0
  71. package/server/deacon-event-client-Ck5Ei7Mn.js +3 -0
  72. package/server/{deacon-nudge-log-B08gF0mh.js → deacon-nudge-log-BND_97Wo.js} +4 -3
  73. package/server/{deacon-pending-lifecycle-B-Io84AP.js → deacon-pending-lifecycle-CD3YsiQK.js} +3 -3
  74. package/server/deacon-swarm-DgWADWd_.js +2 -0
  75. package/server/{deacon-swarm-v5PMun-m.js → deacon-swarm-rqrl4TMs.js} +39 -18
  76. package/server/deacon.js +12 -210
  77. package/server/{dead-end-trip-D8A3msX9.js → dead-end-trip-DSF23CLX.js} +4 -3
  78. package/server/dead-end-trip-zKlS4v6f.js +2 -0
  79. package/server/delivery-CsbQdZkS.js +3 -0
  80. package/server/{deploy-patrol-sYgOxLeb.js → deploy-patrol-kARAkji4.js} +17 -21
  81. package/server/{deploy-queue-VfohaPN_.js → deploy-queue-Bj0HJT1i.js} +2 -2
  82. package/server/{deploy-queue-gHJBycaF.js → deploy-queue-rjTUy1RM.js} +1 -1
  83. package/server/{deploy-window-D4DQb8VP.js → deploy-window-B2IM-9G5.js} +10 -44
  84. package/server/{deploy-window-CFRZ0-kt.js → deploy-window-BNFWnA8D.js} +1 -1
  85. package/server/{dev-supervisor-DiOBDM1c.js → dev-supervisor-B1mZYXz4.js} +2 -2
  86. package/server/{devcontainer-renderer-BUOIlfgD.js → devcontainer-renderer-B-o68Z5B.js} +3 -3
  87. package/server/{dist-C3A8B8wM.js → dist-3W--cGMa.js} +1 -1
  88. package/server/dist-BR0QtwmS.js +3 -0
  89. package/server/{dist-src-C0adpegX.js → dist-src-C-Vk2jNk.js} +1 -1
  90. package/server/{docker-Y3PElJb0.js → docker-DH3jUYg1.js} +1 -1
  91. package/server/{docker-BJzlkqYB.js → docker-meuLKLzV.js} +27 -20
  92. package/server/{dod-DlNtcH6n.js → dod-D7-9dCOD.js} +1 -1
  93. package/server/{driver-CKVGi51s.js → driver-CmsY2RLl.js} +1 -1
  94. package/server/{durable-review-pipeline-DP6bIcOY.js → durable-review-pipeline-CStTgOAf.js} +1 -1
  95. package/server/{durable-review-pipeline-Cibps-Rg.js → durable-review-pipeline-Chq0lzjL.js} +1 -1
  96. package/server/{ensure-devcontainer-DMAbWqtQ.js → ensure-devcontainer-BE3llBWP.js} +1 -1
  97. package/server/{ensure-devcontainer-BAofzBPv.js → ensure-devcontainer-BXrY7C2Z.js} +4 -4
  98. package/server/{esm-shims-BeObUkaw.js → esm-shims-Bzy4ZzNU.js} +1 -1
  99. package/server/event-store-COd2tOx8.js +3 -0
  100. package/server/{event-store-CrHcVC5_.js → event-store-D_AR-Y78.js} +184 -11
  101. package/server/{events-CF8QDbuV.js → events-CCkFWa7X.js} +1 -1
  102. package/server/{events-BNrvchBg.js → events-zjDQozet.js} +3 -3
  103. package/server/{factory-Cmm9Hsho.js → factory-DhavwKVc.js} +5 -5
  104. package/server/{feature-registry-population-B6HpNWRy.js → feature-registry-population-DWGBKyWd.js} +4 -4
  105. package/server/{feature-registry-storage-DJEFx1Pf.js → feature-registry-storage-C5DkXmCM.js} +3 -3
  106. package/server/{features-D5km80UI.js → features-CC47YcCX.js} +2 -2
  107. package/server/{feedback-target-BJ5ZADsu.js → feedback-target-D9Tex35_.js} +1 -1
  108. package/server/{feedback-target-DSxEL6lP.js → feedback-target-DoRCR3L-.js} +18 -7
  109. package/server/{feedback-writer-CoB9Z6aU.js → feedback-writer-CTSuA6lw.js} +1 -1
  110. package/server/{feedback-writer-C27Hak8a.js → feedback-writer-DdsBdtNL.js} +5 -5
  111. package/server/{flywheel-DZZdtiOL.js → flywheel-DHWHzaYK.js} +1 -1
  112. package/server/{flywheel-f662Q-y2.js → flywheel-DJQa9az8.js} +14 -14
  113. package/server/{flywheel-BHx8XuMr.js → flywheel-TacAI9MA.js} +21 -17
  114. package/server/{flywheel-merge-order-Dil0LmdN.js → flywheel-merge-order-D2foPh88.js} +1 -1
  115. package/server/{flywheel-merge-order-D_xLMbJU.js → flywheel-merge-order-DRtex2Dt.js} +7 -7
  116. package/server/forge-CdlCG9aS.js +3 -0
  117. package/server/{forge-BaKGCya6.js → forge-c8LeC-tw.js} +2 -2
  118. package/server/{from-B3tZbB55.js → from-BogSwvr2.js} +1 -1
  119. package/server/{fs-lock-Bre3sGoz.js → fs-lock-D_GeJtXl.js} +3 -3
  120. package/server/{fts-operations-B9jG8wa3.js → fts-operations-DP9R-8Q3.js} +3 -3
  121. package/server/{git-utils-Xg4PFN45.js → git-utils-C31x1lpE.js} +1 -1
  122. package/server/{git-utils-CsvYfJU3.js → git-utils-xQ74FoSn.js} +5 -4
  123. package/server/{github-app-Bmg4R9mv.js → github-app-CpQSDlv8.js} +1 -1
  124. package/server/{github-app-CmNk0zLU.js → github-app-D2QuvZ3j.js} +3 -3
  125. package/server/{github-client-qazkPrg0.js → github-client-D9YvJX5D.js} +3 -3
  126. package/server/{github-client-B6KM9_wA.js → github-client-Tpi3PmKX.js} +1 -1
  127. package/server/{github-pr-lookup-DAcVeRLK.js → github-pr-lookup-DvBMv-IW.js} +2 -2
  128. package/server/{harness-binary-BSpiXaLw.js → harness-binary-BHxWf_sX.js} +7 -6
  129. package/server/{harness-resolve-BAJu5MX8.js → harness-resolve-bj9WMABA.js} +4 -4
  130. package/server/{health-events-BwX32k8d.js → health-events-bCDPn59Z.js} +2 -2
  131. package/server/{health-events-2Z6Wa9SM.js → health-events-qo7Ss34U.js} +1 -1
  132. package/server/{hooks-DbtbimEf.js → hooks-Dyxtg5fk.js} +2 -2
  133. package/server/{hooks-D1g1jKLI.js → hooks-X2XHBB2b.js} +1 -1
  134. package/server/{hume-DXNiu6nQ.js → hume-DrZEGpqc.js} +2 -2
  135. package/server/hume-YPsy4UA8.js +3 -0
  136. package/server/{idle-stack-reaper-Cy-dQzW4.js → idle-stack-reaper-CJ1ygW0p.js} +37 -7
  137. package/server/{idle-stack-reaper-CRA1e0jr.js → idle-stack-reaper-uJGOb-vu.js} +1 -1
  138. package/server/{in-flight-guard-D-sSkADM.js → in-flight-guard-CG2Eo-rr.js} +1 -1
  139. package/server/{infra-BDQDRopn.js → infra-CTrmVqc_.js} +111 -6
  140. package/server/{injection-Bl8d_jHZ.js → injection-BisQ0lpX.js} +1 -1
  141. package/server/{injection-6AGnXxlj.js → injection-C9sxqbc2.js} +73 -193
  142. package/server/{inspect-agent-nXdIptyh.js → inspect-agent-BoSO51YC.js} +12 -12
  143. package/server/inspect-agent-BykeOH4a.js +2 -0
  144. package/server/{internal-token-DzK385vD.js → internal-token-AvXePaQT.js} +2 -2
  145. package/server/{internal-token-Ias7N8Kg.js → internal-token-Djkj-yqK.js} +1 -1
  146. package/server/{io-B00PBNku.js → io-mxOWMZ7I.js} +6 -6
  147. package/server/{issue-closed-BehTG1be.js → issue-closed-Bj_bCv_0.js} +7 -7
  148. package/server/{issue-lifecycle-BqSuQvbn.js → issue-lifecycle-A5YIpDZE.js} +1 -1
  149. package/server/{issue-lifecycle-Birk-ifu.js → issue-lifecycle-BXUqaHzF.js} +32 -28
  150. package/server/{issue-service-singleton-C6ZduvuY.js → issue-service-singleton-BPNEXczv.js} +11 -11
  151. package/server/{issue-service-singleton-B2wXiIlw.js → issue-service-singleton-CcaHjKPR.js} +1 -1
  152. package/server/{issues-DQ5-LatB.js → issues-AX-YBeAQ.js} +2 -2
  153. package/server/{jsonl-parser-BDpnGFCl.js → jsonl-parser-CgYWQ20q.js} +7 -3
  154. package/server/kimi-code-BYbme0aV.js +579 -0
  155. package/server/kimi-code-D_Ppt82c.js +3 -0
  156. package/server/kimi-parser-B-JBg3Pv.js +147 -0
  157. package/server/{label-cleanup-Dwnky8FG.js → label-cleanup-sXUlgdM0.js} +3 -3
  158. package/server/{lifecycle-B4Xdb4cY.js → lifecycle-D2X3al0D.js} +2 -2
  159. package/server/{lifecycle-B3s4sM1G.js → lifecycle-DjlljAZ1.js} +6 -6
  160. package/server/{lifecycle-io-CzTHEooc.js → lifecycle-io-C5nVk55o.js} +1 -1
  161. package/server/{lifecycle-io-DCo6s6ks.js → lifecycle-io-NPm1YtIG.js} +5 -5
  162. package/server/{linear-client-CnbtHiic.js → linear-client--luYwCZg.js} +1 -1
  163. package/server/{linear-client-9uq7fhiV.js → linear-client-B8pLegW1.js} +3 -3
  164. package/server/{linear-mcp-auth-BxUOzswy.js → linear-mcp-auth-BQVWV0I3.js} +6 -6
  165. package/server/{linear-mcp-auth-D46fBCLf.js → linear-mcp-auth-Dx81Zl4G.js} +1 -1
  166. package/server/memory-fts-worker.js +1 -1
  167. package/server/{merge-DiW9RdSB.js → merge-Bx5Bh9pi.js} +3 -3
  168. package/server/{merge-sr8Nrnmi.js → merge-Dqmh_zja.js} +1 -1
  169. package/server/{merge-agent-BLUgRsz3.js → merge-agent-DP9AUY29.js} +33 -33
  170. package/server/{merge-agent-DQTXZk8z.js → merge-agent-DWd0KfiS.js} +1 -1
  171. package/server/{merge-batch-Cp_j9BGk.js → merge-batch-BdmvTEAC.js} +1 -1
  172. package/server/{merge-completeness-BLbB5-6n.js → merge-completeness-BfRwFjRx.js} +1 -1
  173. package/server/{merge-completeness-B46KqhtY.js → merge-completeness-C1FevcDT.js} +4 -4
  174. package/server/merge-ops-B98tKc1e.js +2 -0
  175. package/server/merge-rebase-BLykMwPO.js +2 -0
  176. package/server/{merge-rebase-DIkBjgwq.js → merge-rebase-BX1xKsrE.js} +2 -2
  177. package/server/{merge-set-CBgHfwM0.js → merge-set-DsLjjLEV.js} +4 -4
  178. package/server/{merge-set-DeUxFsC3.js → merge-set-H6epHOsw.js} +1 -1
  179. package/server/{merge-sync-kr4vqyjM.js → merge-sync-BEdfsQV4.js} +2 -2
  180. package/server/{merge-sync-CpGmk6Ch.js → merge-sync-BebcWWGA.js} +1 -1
  181. package/server/{merge-train-Dmrcus12.js → merge-train-D1I0lNOT.js} +4 -4
  182. package/server/{merge-train-deps-D_uGX91G.js → merge-train-deps-D_-C0Pk2.js} +4 -4
  183. package/server/{merge-verification-NvaAd8CZ.js → merge-verification-DN1Ov9bU.js} +6 -6
  184. package/server/{merged-docker-cleanup-worker-Y1R06TEl.js → merged-docker-cleanup-worker-CfXSr2pA.js} +4 -4
  185. package/server/{merged-docker-cleanup-worker-DH_hrGPI.js → merged-docker-cleanup-worker-ybsPyHjB.js} +1 -1
  186. package/server/{multipart-parser-R-oC8dQg.js → multipart-parser-CL5QG8iv.js} +2 -2
  187. package/server/{no-resume-mode-BgD0JUmM.js → no-resume-mode-DUR7Hi98.js} +1 -1
  188. package/server/node_modules/.package-lock.json +7 -7
  189. package/server/node_modules/brace-expansion/README.md +23 -1
  190. package/server/node_modules/brace-expansion/index.js +206 -85
  191. package/server/node_modules/brace-expansion/package.json +1 -1
  192. package/server/node_modules/msgpackr/dist/index-no-eval.cjs +34 -28
  193. package/server/node_modules/msgpackr/dist/index-no-eval.cjs.map +1 -1
  194. package/server/node_modules/msgpackr/dist/index-no-eval.min.js +1 -1
  195. package/server/node_modules/msgpackr/dist/index-no-eval.min.js.map +1 -1
  196. package/server/node_modules/msgpackr/dist/index.js +34 -28
  197. package/server/node_modules/msgpackr/dist/index.js.map +1 -1
  198. package/server/node_modules/msgpackr/dist/index.min.js +1 -1
  199. package/server/node_modules/msgpackr/dist/index.min.js.map +1 -1
  200. package/server/node_modules/msgpackr/dist/node.cjs +36 -29
  201. package/server/node_modules/msgpackr/dist/node.cjs.map +1 -1
  202. package/server/node_modules/msgpackr/dist/test.js +63 -32
  203. package/server/node_modules/msgpackr/dist/test.js.map +1 -1
  204. package/server/node_modules/msgpackr/dist/unpack-no-eval.cjs +34 -28
  205. package/server/node_modules/msgpackr/dist/unpack-no-eval.cjs.map +1 -1
  206. package/server/node_modules/msgpackr/package.json +1 -1
  207. package/server/node_modules/msgpackr/unpack.js +34 -28
  208. package/server/{orphan-proposed-reconciler-DcgTPPFY.js → orphan-proposed-reconciler-CEW1maPl.js} +1 -1
  209. package/server/{orphan-proposed-reconciler-B6vJHxtX.js → orphan-proposed-reconciler-DfqHZftT.js} +23 -22
  210. package/server/package-lock.json +8 -8
  211. package/server/package.json +1 -1
  212. package/server/{pan-dir-DMzF5wne.js → pan-dir-DhgKfO86.js} +21 -6
  213. package/server/{paths-sJBSb7Ul.js → paths-BUuhi6jM.js} +17 -17
  214. package/server/{pending-lifecycle-claim-DilzGfgk.js → pending-lifecycle-claim-DJlA1rTR.js} +2 -2
  215. package/server/{persistent-logger-H_VjuOu7.js → persistent-logger-s8cbpFNV.js} +2 -2
  216. package/server/{pickup-DWhqzliO.js → pickup-2AxtB3dW.js} +1 -1
  217. package/server/{pipeline-membership-C88VBnhJ.js → pipeline-membership-2_okL5bm.js} +1 -1
  218. package/server/{pipeline-membership-D9SBvItj.js → pipeline-membership-Dqv6_0ig.js} +1 -1
  219. package/server/{pipeline-membership-gather-4eR-7Tqy.js → pipeline-membership-gather-4F1-tXKI.js} +1 -1
  220. package/server/{pipeline-membership-gather-CeVGnNJ2.js → pipeline-membership-gather-CtJ_7aGf.js} +149 -17
  221. package/server/{pipeline-notifier-DT6xLFao.js → pipeline-notifier-CO9rxJgB.js} +1 -1
  222. package/server/{pipeline-notifier-D0ALV6Nw.js → pipeline-notifier-DDfVBJhJ.js} +2 -2
  223. package/server/{post-merge-lifecycle-worker-8HIeS_J6.js → post-merge-lifecycle-worker-DmSOkeNp.js} +3 -3
  224. package/server/{project-pipelines-9SKt2bEc.js → project-pipelines-72WE8GVK.js} +2 -2
  225. package/server/{project-repos-B5pIphKg.js → project-repos-BAqDwtvi.js} +16 -11
  226. package/server/project-repos-Df90Zw7Y.js +3 -0
  227. package/server/projects-WqMWCdpa.js +3 -0
  228. package/server/{prompts-CgzMBvQF.js → prompts-XkL10m8M.js} +2 -2
  229. package/server/{providers-BJQSnAAp.js → providers-ClGPGkQ8.js} +15 -12
  230. package/server/providers-DFUOed8u.js +3 -0
  231. package/server/public/assets/{chunk-BO2N2NFS-D_pGACYN.js → chunk-BO2N2NFS-CeQUdPxr.js} +4 -4
  232. package/server/public/assets/{diagram-OG6HWLK6-BO6fe3hH.js → diagram-OG6HWLK6-B7rgk4yT.js} +1 -1
  233. package/server/public/assets/{dist-5zingMiA.js → dist-2RPazfXY.js} +3 -3
  234. package/server/public/assets/{dist-CVxhbI2E.js → dist-B9NInrVZ.js} +1 -1
  235. package/server/public/assets/{ganttDiagram-6RSMTGT7-Bgj4A7kp.js → ganttDiagram-6RSMTGT7-Bxp0gV14.js} +1 -1
  236. package/server/public/assets/{highlighted-body-OFNGDK62-DNPK7_cm.js → highlighted-body-OFNGDK62-CzoRTVlC.js} +1 -1
  237. package/server/public/assets/index-Cml-kHo6.css +1 -0
  238. package/server/public/assets/{index-DEpY-D1O.js → index-CvN8cEgs.js} +216 -215
  239. package/server/public/assets/{linear-BB0jQT16.js → linear-CFEEl3ND.js} +1 -1
  240. package/server/public/assets/mermaid-GHXKKRXX-CpV7nCBM.js +1 -0
  241. package/server/public/assets/{pieDiagram-4H26LBE5-DeGIzzpZ.js → pieDiagram-4H26LBE5-BeR8R0cr.js} +1 -1
  242. package/server/public/assets/{prod-XBLvikex.js → prod-CYjzjCrn.js} +4 -4
  243. package/server/public/assets/{quadrantDiagram-W4KKPZXB-BV9SLeWz.js → quadrantDiagram-W4KKPZXB-BpcTkFuW.js} +1 -1
  244. package/server/public/assets/{sankeyDiagram-5OEKKPKP-Dwja0gj8.js → sankeyDiagram-5OEKKPKP-Bx2ETEV5.js} +1 -1
  245. package/server/public/assets/{xychartDiagram-2RQKCTM6-DCB4qvfw.js → xychartDiagram-2RQKCTM6-BKgEAFaj.js} +1 -1
  246. package/server/public/index.html +2 -2
  247. package/server/{pull-requests-7BgLDsIo.js → pull-requests-B-KrUph5.js} +3 -3
  248. package/server/{pull-requests-Dq0y6IxE.js → pull-requests-DK5k92B4.js} +1 -1
  249. package/server/{queries-C-MUZaIy.js → queries-DVpl1vsU.js} +1212 -193
  250. package/server/{rally-CPysR4T_.js → rally-DbE561hD.js} +3 -3
  251. package/server/rally-O_st_X7n.js +3 -0
  252. package/server/{rally-api-8Ptlp2os.js → rally-api-CZLeEd2C.js} +2 -2
  253. package/server/{rally-api-CgosKdKL.js → rally-api-DaHtn5QN.js} +1 -1
  254. package/server/{rally-client-CCX0hADj.js → rally-client-C-MAl8ur.js} +1 -1
  255. package/server/{rally-client-iYMHWQD7.js → rally-client-Ch3zRsBX.js} +5 -5
  256. package/server/{reap-terminal-sessions-Qf-9LVQc.js → reap-terminal-sessions-C1n0ALRb.js} +2 -2
  257. package/server/{reap-terminal-sessions-4Xg9NGA8.js → reap-terminal-sessions-DegFS2p1.js} +2 -2
  258. package/server/{rebuild-stack-CMdgaylx.js → rebuild-stack-C9Li44A3.js} +20 -10
  259. package/server/{rebuild-stack-DqcOVmJO.js → rebuild-stack-qC0jCNm6.js} +2 -2
  260. package/server/{reconstruct-cache-CMZJ_Vjq.js → reconstruct-cache-BHyiAg02.js} +7 -7
  261. package/server/record-aVzu-LGm.js +3 -0
  262. package/server/record-update-CZh46a2f.js +617 -0
  263. package/server/{record-update-DhI7eySG.js → record-update-DtdJK2Iw.js} +1 -1
  264. package/server/recovery-trip-CSNWSLDn.js +77 -0
  265. package/server/recovery-trip-_16hFKv4.js +3 -0
  266. package/server/{release-engine-B2X9AfFC.js → release-engine-Be5MX5GP.js} +5 -5
  267. package/server/{release-set-G4XKyQ8K.js → release-set-DJv_O6PS.js} +3 -3
  268. package/server/{remote-BXarMvqf.js → remote-BMM3uH2J.js} +3 -3
  269. package/server/{remote-CUhyqjXk.js → remote-C0xVTHA5.js} +3 -3
  270. package/server/{remote-agents-CLZB3Coc.js → remote-agents-BIIoc5pD.js} +1 -1
  271. package/server/{remote-agents-Bba-MgSA.js → remote-agents-EUiZ26bj.js} +7 -7
  272. package/server/{remote-completion-CwAp79EC.js → remote-completion-BS4tJUn8.js} +13 -13
  273. package/server/resolver-BvHd6RE4.js +163 -0
  274. package/server/resume-9thEqAQR.js +3 -0
  275. package/server/{review-agent--pOptAEV.js → review-agent-BHGaBoBu.js} +29 -29
  276. package/server/{review-agent-BTCNkq2h.js → review-agent-CD3RQ-tc.js} +1 -1
  277. package/server/{review-artifacts-BNmw8dWE.js → review-artifacts-DyhajWso.js} +6 -6
  278. package/server/{review-context-DFxYOOJW.js → review-context-B-dlsPnx.js} +9 -9
  279. package/server/{review-convoy-liveness-BgU_1jJf.js → review-convoy-liveness-D7M-s_nS.js} +2 -2
  280. package/server/{review-status-Dma9SFaN.js → review-status-B6wYcOtP.js} +1 -1
  281. package/server/{review-status-CGvlA4o_.js → review-status-CKLk5aZ-.js} +308 -58
  282. package/server/{review-status-emit-DURrmGYX.js → review-status-emit-CJ7UmEVU.js} +3 -3
  283. package/server/{review-status-enrichment-8NiNXi5W.js → review-status-enrichment-DJRgGX7-.js} +3 -3
  284. package/server/review-status-limits-4EJDCGHO.js +7 -0
  285. package/server/{review-status-source-DIk1JSow.js → review-status-source-7nU3Z2wL.js} +1 -1
  286. package/server/{review-status-source-BLx_1siH.js → review-status-source-BsDYGfyv.js} +1 -1
  287. package/server/{review-status-sync-muT-EBp2.js → review-status-sync-BLssMTEW.js} +1 -1
  288. package/server/{review-status-sync-0GxOqeqF.js → review-status-sync-BxBeHRde.js} +35 -11
  289. package/server/{review-verdict-feedback-xJNdqBnX.js → review-verdict-feedback-5jWuzgpc.js} +90 -16
  290. package/server/{review-verdict-feedback-HwF6ODFy.js → review-verdict-feedback-HRY9P4bN.js} +1 -1
  291. package/server/{rollup-BQaol5TX.js → rollup-BGIrCEkU.js} +79 -44
  292. package/server/rollup-CZB4UL9q.js +3 -0
  293. package/server/{scanner-C-D2cFdX.js → scanner-DydjXPrz.js} +16 -9
  294. package/server/search-DdtIjAiu.js +395 -0
  295. package/server/{sequence-io-Bmf1EZM5.js → sequence-io-Fw-cLyDs.js} +4 -4
  296. package/server/{sequencer-agent-CigMyKh2.js → sequencer-agent-BcpGMt5x.js} +15 -10
  297. package/server/server.js +1258 -438
  298. package/server/{service-CD0DvFvD.js → service-BFFkGsG4.js} +58 -58
  299. package/server/{session-fork-B6cQ5eya.js → session-fork-D0V-3e5P.js} +2 -2
  300. package/server/{session-history-3ON_IJjm.js → session-history-Bta5l9jY.js} +5 -5
  301. package/server/{settings-PilbFZAM.js → settings-Ce8B1daF.js} +2 -2
  302. package/server/{settings-VN0qOh4U.js → settings-E3FnEIUx.js} +3 -3
  303. package/server/settings-eOOJpxi_.js +2 -0
  304. package/server/{shadow-engineering-DXvx77oE.js → shadow-engineering-Mt9nJO4i.js} +3 -3
  305. package/server/{shadow-state-CZBp7pwq.js → shadow-state-Bzj_AZCV.js} +1 -1
  306. package/server/{shadow-state-BBk_zacw.js → shadow-state-DrkhoVSx.js} +2 -2
  307. package/server/{shadow-utils-DdZ05AJS.js → shadow-utils-H1GfqP06.js} +2 -2
  308. package/server/{ship-log-7kJfjUX2.js → ship-log-CFUIo4PR.js} +1 -1
  309. package/server/{smart-compaction-8fA5k5XN.js → smart-compaction-DSTq-Wua.js} +1 -1
  310. package/server/{smart-compaction-ByhL9cRS.js → smart-compaction-Hzp3KCJX.js} +7 -7
  311. package/server/{spawn-planning-session-vLUJoFjy.js → spawn-planning-session-C0uSA2SL.js} +2 -2
  312. package/server/{spawn-planning-session-pcF-YeFE.js → spawn-planning-session-DN4son31.js} +23 -21
  313. package/server/{specialist-completion-B07XjWD2.js → specialist-completion-Cf6tpIh1.js} +1 -1
  314. package/server/{specialist-context-DJ-zFyL3.js → specialist-context-DEUEkjIQ.js} +5 -5
  315. package/server/{specialist-handoff-logger-aKSxbIgD.js → specialist-handoff-logger-D_LmQDj3.js} +2 -2
  316. package/server/{specialist-logs-Dae-n52_.js → specialist-logs-7Ynue0R7.js} +3 -3
  317. package/server/{specialists-KR3pKulN.js → specialists-CQwBEGlD.js} +1 -1
  318. package/server/{specialists-6PWdtWcg.js → specialists-DAjPgYs_.js} +504 -238
  319. package/server/{specialists-DUiExaxb.js → specialists-Hr6iW9fU.js} +18 -18
  320. package/server/{specialists-Bz-wFT7R.js → specialists-MOoeB4A8.js} +1 -1
  321. package/server/specs-Dl88cbKY.js +3 -0
  322. package/server/{src-B948bGVR.js → src-BYdwL_n-.js} +668 -64
  323. package/server/{src-vHy2-oCv.js → src-DQnkPN2i.js} +3 -3
  324. package/server/{src-rac0Mepv.js → src-DhfDV0o4.js} +6 -6
  325. package/server/{stack-health-DqLTiEu4.js → stack-health-D_iKwNRg.js} +107 -16
  326. package/server/stack-health-deVSdDwn.js +3 -0
  327. package/server/{stale-task-claims-Cab_Fo_Z.js → stale-task-claims-BYJGqhLI.js} +5 -5
  328. package/server/{staleness-CGTZyp6V.js → staleness-CopBDKnA.js} +1 -1
  329. package/server/{staleness-C-a5rBxF.js → staleness-D8WeMUHd.js} +1 -1
  330. package/server/{state-home-722Dkx92.js → state-home-DjN8qduI.js} +24 -3
  331. package/server/{state-mapping-CybR81Uf.js → state-mapping-DlM7OYRW.js} +1 -1
  332. package/server/{state-migrate-2u8wIpoL.js → state-migrate-a2p1gtD7.js} +4 -4
  333. package/server/state-mirror-Cv_XgvT5.js +121 -0
  334. package/server/{stuck-remediation-r1TJu68G.js → stuck-remediation-CXJX_kki.js} +1 -1
  335. package/server/{stuck-remediation-CC6q3eqQ.js → stuck-remediation-CbCRSz1v.js} +31 -732
  336. package/server/{substrate-bug-weights-service-CzIyyWFT.js → substrate-bug-weights-service-DxpopNd9.js} +3 -3
  337. package/server/{summary-fork-BqgmgPDt.js → summary-fork-B61fjRJn.js} +2 -2
  338. package/server/{summary-fork-Df2WFijM.js → summary-fork-B9pszUJN.js} +91 -10
  339. package/server/supervisor/{injection-budget-Cg_KIb3o.js → injection-budget-Ar7hgyJq.js} +1 -1
  340. package/server/supervisor/pty-supervisor.js +12 -3
  341. package/server/supervisor/{pty-token-BbjwEUUM.js → pty-token-CXCFU0Z8.js} +1 -1
  342. package/server/{supervisor-BxqSpjcN.js → supervisor-BvnxbuuF.js} +6 -4
  343. package/server/supervisor-C69kpqvd.js +2 -0
  344. package/server/{swarm-readiness-DfFxa9-n.js → swarm-readiness-vTw1kqGa.js} +3 -3
  345. package/server/{system-prerequisites-ICLSkhhZ.js → system-prerequisites-LLzTEqsK.js} +3 -3
  346. package/server/{teardown-workspace-DRdi_CPa.js → teardown-workspace-CqKKVJr1.js} +15 -15
  347. package/server/{test-agent-queue-A_-p-i0I.js → test-agent-queue-CWMq7oyG.js} +8 -7
  348. package/server/{test-verdict-BHgTAwIG.js → test-verdict-NdtgRBuA.js} +1 -1
  349. package/server/{test-verdict-C4i9aqEP.js → test-verdict-diIWE6hz.js} +15 -3
  350. package/server/{tldr-daemon-CvWXBhX1.js → tldr-daemon-B1Jhrtc8.js} +1 -1
  351. package/server/{tldr-daemon-wvsU6bKv.js → tldr-daemon-Bpls1CJB.js} +2 -2
  352. package/server/{tmux-CfDHob9M.js → tmux-CImZaX4q.js} +10 -16
  353. package/server/tmux-Cjpx8L8u.js +4 -0
  354. package/server/{token-DrxwytsZ.js → token-Bgpjo3tE.js} +2 -2
  355. package/server/token-util-BsjFll-k.js +3 -0
  356. package/server/{token-util-B48BlCba.js → token-util-BymbpkJp.js} +1 -1
  357. package/server/{tracker-config-BcPMElRB.js → tracker-config-4DaKVTfc.js} +2 -2
  358. package/server/{tracker-utils-CJ6BHjcD.js → tracker-utils-BDeAXC-q.js} +2 -2
  359. package/server/{traefik-connect-DZ6nMYMj.js → traefik-connect-CC5FyxYj.js} +1 -1
  360. package/server/{tunnel-Bp-dRHZz.js → tunnel-CDWkeceJ.js} +1 -1
  361. package/server/{tunnel-DUbUPElU.js → tunnel-CPf5M-Pc.js} +3 -3
  362. package/server/{typed-errors-DyjseiB6.js → typed-errors-9K7Dq_Vn.js} +1 -1
  363. package/server/{typed-errors-CKeoDdU3.js → typed-errors-DrS5fb5z.js} +1 -1
  364. package/server/{types-Cm5ASJbq.js → types-DzlUKiuf.js} +4 -3
  365. package/server/{types-Di8wdakq.js → types-kI9ik8XO.js} +1 -1
  366. package/server/{uat-promote-verification-CoJuh7XO.js → uat-promote-verification-c_pxoxEc.js} +5 -5
  367. package/server/{uat-train-4Q0k06CQ.js → uat-train-CWGxBdJO.js} +0 -0
  368. package/server/{uat-train-Dewoatps.js → uat-train-CfCYd2ve.js} +1 -1
  369. package/server/{validate-B0C8p66t.js → validate-f3ItVCfm.js} +3 -3
  370. package/server/{validation-hVOwQk8T.js → validation-5G_wQtea.js} +1 -1
  371. package/server/{validation-B_kIRfNe.js → validation-7tSiCM82.js} +4 -4
  372. package/server/{verification-artifact-BxlxTiYK.js → verification-artifact-9h9dH8uX.js} +1 -1
  373. package/server/{verification-artifact-D70AtckY.js → verification-artifact-C_4WJnf6.js} +1 -1
  374. package/server/{verification-runner-Bc3cJvpC.js → verification-runner-BV5F6wrA.js} +1 -1
  375. package/server/{verification-runner-KZTz6u72.js → verification-runner-D58KmBhK.js} +18 -38
  376. package/server/{vtt-parser-CE_i3Bcw.js → vtt-parser-2iT9OHa9.js} +1 -1
  377. package/server/{work-agent-prompt-ByrPAzOy.js → work-agent-prompt-D03s4DD1.js} +9 -9
  378. package/server/{workflows-D0vP1WrK.js → workflows-BMBwLYPV.js} +281 -98
  379. package/server/workflows-BOmWGpIh.js +2 -0
  380. package/server/{workspace-DQkRPLlQ.js → workspace-BgflNCH0.js} +3 -3
  381. package/server/{workspace-COWvdibH.js → workspace-Cn9ywfSW.js} +1 -1
  382. package/server/{workspace-anchor-drift-pwz23TI1.js → workspace-anchor-drift-C8Fy3shi.js} +1 -1
  383. package/server/{workspace-anchor-drift-DXYIAHzr.js → workspace-anchor-drift-CMiNncwq.js} +5 -8
  384. package/server/{workspace-config-BdZM4PvZ.js → workspace-config-aUc2nIz6.js} +1 -1
  385. package/server/{workspace-manager-BPgTrG66.js → workspace-manager-Bem7ZBs9.js} +521 -292
  386. package/server/workspace-manager-C0CpNh3t.js +3 -0
  387. package/server/{workspace-metadata-CdjzAP8x.js → workspace-metadata-C5iSlPRo.js} +1 -1
  388. package/server/{workspace-metadata-DkO_iTLo.js → workspace-metadata-UKmTYmDQ.js} +2 -2
  389. package/server/{workspaces-CRBJikLp.js → workspaces-DqxgwDZ8.js} +143 -113
  390. package/sync-sources/hooks/notification-hook +12 -1
  391. package/sync-sources/hooks/pan-hook-lib.sh +226 -0
  392. package/sync-sources/hooks/session-start-hook +31 -4
  393. package/sync-sources/hooks/work-agent-stop-hook +23 -1
  394. package/sync-sources/skills/pan-memory/SKILL.md +19 -3
  395. package/sync-sources/skills/pan-projects/SKILL.md +9 -0
  396. package/sync-sources/skills/pan-restart/SKILL.md +26 -7
  397. package/sync-sources/skills/pan-workspace/SKILL.md +77 -0
  398. package/server/activity-logger-CMthG6Vd.js +0 -3
  399. package/server/agent-state-CYXJVG72.js +0 -3
  400. package/server/agents-ePFVoZbu.js +0 -3
  401. package/server/archive-planning-B2XplFzT.js +0 -2
  402. package/server/cli-CjOCSnfj.js +0 -3
  403. package/server/deacon-swarm-B1XkIvfr.js +0 -2
  404. package/server/delivery-BX9HR4wQ.js +0 -3
  405. package/server/dist-B3YPQa5A.js +0 -3
  406. package/server/event-store-5UKzh9Jf.js +0 -3
  407. package/server/forge-B5o319qI.js +0 -3
  408. package/server/fts-db-IVc4_M3f.js +0 -146
  409. package/server/hume-VUCNbTgn.js +0 -3
  410. package/server/inspect-agent-CUwVmr2h.js +0 -2
  411. package/server/merge-ops-1abz6O_P.js +0 -2
  412. package/server/merge-rebase-CJJVAJuz.js +0 -2
  413. package/server/node_modules/brace-expansion/.tap/coverage/8b906b8c-e21f-40b5-8c0d-214d8c2682c5.json +0 -757
  414. package/server/node_modules/brace-expansion/.tap/processinfo/8b906b8c-e21f-40b5-8c0d-214d8c2682c5.json +0 -719
  415. package/server/node_modules/brace-expansion/ADVISORY-CVE-2026-14257.md +0 -107
  416. package/server/node_modules/brace-expansion/dist/commonjs/index.d.ts +0 -8
  417. package/server/node_modules/brace-expansion/dist/commonjs/index.d.ts.map +0 -1
  418. package/server/node_modules/brace-expansion/dist/commonjs/index.js +0 -263
  419. package/server/node_modules/brace-expansion/dist/commonjs/index.js.map +0 -1
  420. package/server/node_modules/brace-expansion/dist/commonjs/package.json +0 -3
  421. package/server/node_modules/brace-expansion/dist/esm/index.d.ts +0 -8
  422. package/server/node_modules/brace-expansion/dist/esm/index.d.ts.map +0 -1
  423. package/server/node_modules/brace-expansion/dist/esm/index.js +0 -259
  424. package/server/node_modules/brace-expansion/dist/esm/index.js.map +0 -1
  425. package/server/node_modules/brace-expansion/dist/esm/package.json +0 -3
  426. package/server/project-repos-DPjOdfPa.js +0 -3
  427. package/server/projects-_n3Zui6K.js +0 -3
  428. package/server/providers-BI1mOBQ4.js +0 -3
  429. package/server/public/assets/index-Ddkcz3WT.css +0 -1
  430. package/server/public/assets/mermaid-GHXKKRXX-BzPfaQJ1.js +0 -1
  431. package/server/rally-D_VW4bJv.js +0 -3
  432. package/server/record-BTwWhtBb.js +0 -3
  433. package/server/record-update-DaOKS7Wb.js +0 -277
  434. package/server/recovery-trip-DDH-02ng.js +0 -44
  435. package/server/resume-mOREjlYu.js +0 -3
  436. package/server/rollup-BR4t_wck.js +0 -3
  437. package/server/settings-CVmWiJ-r.js +0 -2
  438. package/server/specs--enInima.js +0 -3
  439. package/server/stack-health-BikqHSjn.js +0 -3
  440. package/server/supervisor-B4anCCSm.js +0 -2
  441. package/server/tmux-Ctk6RV5l.js +0 -3
  442. package/server/token-util-D411CAq9.js +0 -3
  443. package/server/workflows-DtDX08ed.js +0 -2
  444. package/server/workspace-manager-C1F3XsnS.js +0 -3
@@ -1,66 +1,69 @@
1
1
  import { i as __require, t as __commonJSMin } from "./rolldown-runtime-DNCzzKnI.js";
2
- import { Fr as init_errors, Gn as init_projects, Gr as OVERDECK_HOME, Ir as AGENTS_DIR, Pt as init_record, Yn as listProjectsSync, Zn as loadProjectsConfigSync, ar as resolveProjectFromIssueSync, b as DEFAULT_CONFIG$1, dn as reconcileStatePlaneDrift, f as loadConfigSync, hn as init_state_plane, li as init_paths, ln as init_auto_commit, mn as getMainDivergence, or as resolveProjectPath, pi as sessionFilePath, s as init_load, x as init_defaults, zn as getProjectSync, zt as readIssueRecordSync } from "./config-yaml-CxdwhAIA.js";
3
- import { n as init_build_info, t as getBuildInfo } from "./build-info-7yiEpl6u.js";
4
- import { n as getDashboardIdentity, t as recordDeaconNudge } from "./deacon-nudge-log-B08gF0mh.js";
5
- import { i as emitActivityTtsSync, o as init_activity_logger, r as emitActivityEntrySync } from "./activity-logger-CyteR4JO.js";
6
- import { i as updateIssueRecord, r as init_record_update } from "./record-update-DaOKS7Wb.js";
7
- import { A as listPaneValues, B as sendKeysAsync, D as killSession, E as isPaneDead, H as sessionExists, I as querySessionSync, M as listSessionNames, N as listSessions, U as sessionExistsSync, i as capturePane, w as init_tmux, z as sendKeys } from "./tmux-CfDHob9M.js";
8
- import { a as init_event_store, i as initEventStore } from "./event-store-CrHcVC5_.js";
9
- import { D as projectLegacySystemHealthSummary, t as init_src } from "./src-B948bGVR.js";
10
- import { B as reviewGatesPassedSync, C as setReviewStatusSync, H as findBlockingFindings, K as readJournalStatusSync, R as init_review_dispatch_decision, U as init_review_findings, W as init_review_status_record_sync, d as getReviewStatusSync, h as loadReviewStatuses, p as init_review_status, z as needsReviewDispatch } from "./review-status-CGvlA4o_.js";
11
- import { n as logAgentLifecycleSync, r as logDeaconEventSync, t as init_persistent_logger } from "./persistent-logger-H_VjuOu7.js";
12
- import { c as listAllAgentsSync, d as isTerminalIssueStage, o as init_agents, u as getIssueStageSync } from "./agents-J5mEnekq.js";
13
- import { $n as getAgentDir, Br as saveAgentRuntimeState, Bt as init_transcript_landing, Ct as resetPatrolDispatchBudget, Et as workResumeSlotsAvailable, G as resumeAgent, Gr as init_codex_auth, J as isContextOverflowTail, K as init_context_overflow, Kr as paneShowsCodexAuthBurn, Ln as buildResumeContinueMessage, Lr as getAgentRuntimeState, Ot as init_memory_verdict_cache, Pt as deliverInitialPromptWithRetry, Rr as getAgentRuntimeStateSync, Ur as applyCodexAuthBurnFlag, X as messageAgent, Xn as clearAgentTroubledSync, Y as init_messaging, Zn as clearYieldForResumeSync, _ as init_linux, _r as saveAgentStateSync, _t as describeRunningAgents, a as listRunningAgentsSync, b as init_agents$1, br as setAgentYieldedSync, bt as init_concurrency, c as getRuntimeCensus, fr as recordAgentFailure, ft as init_termination, g as LINUX_MEMORY_PRESSURE_DEFAULTS, gr as saveAgentState, h as init_collector, hr as resetAgentFailureCount, ht as countRunningAgents, i as listRunningAgents, ir as init_agent_state, kt as setCachedMemoryVerdict, lr as markAgentRunningState, m as createHostHealthCollector, n as init_queries, pt as stopAgent, r as listAgentStates, rr as getAgentStateSync, s as descendantPidsForSession, tr as getAgentState, u as init_runtime_census, v as DARWIN_MEMORY_PRESSURE_DEFAULTS, wt as tryReserveAdvancingSlot, xt as releaseAdvancingSlot, y as init_darwin, yr as setAgentPausedSync, yt as getConcurrencyLimits, zr as init_runtime_state, zt as captureTranscriptUserRecordSnapshot } from "./queries-C-MUZaIy.js";
14
- import { o as getRuntimeSnapshot, s as init_agent_runtime_mirror } from "./session-history-3ON_IJjm.js";
15
- import { n as resolveGitHubIssueSync, t as init_tracker_utils } from "./tracker-utils-CJ6BHjcD.js";
16
- import { i as ensureInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-DzK385vD.js";
17
- import { c as init_review_status_sync, l as markWorkspaceStuck } from "./review-status-sync-0GxOqeqF.js";
18
- import { i as readReviewStatusMap, n as init_review_status_source, t as classifyAdvancingSessionLifecycle } from "./review-status-source-DIk1JSow.js";
19
- import { _ as markMerged, c as init_merge_sync, f as listActiveAutoMerges, m as listProblemAutoMerges, t as cancelPending } from "./merge-sync-kr4vqyjM.js";
20
- import { i as init_merge_set, r as getMergeSetSync } from "./merge-set-CBgHfwM0.js";
21
- import { m as readWorkspacePlanSync, o as init_io } from "./io-B00PBNku.js";
22
- import { f as init_config, m as loadConfigSync$1, p as loadConfig$1 } from "./config-BvLe652W.js";
23
- import { D as setSetting, O as stampBootReconciliation, _ as setBootReconciliationGrace, c as init_control_settings, g as setBootReconciliationDecision, o as getLastCleanShutdownAt, r as getBootReconciliationState, s as getSetting, u as isDeaconGloballyPaused } from "./control-settings-CiqGxXnc.js";
24
- import { d as init_docker_stats, u as DockerStatsCollector } from "./stack-health-DqLTiEu4.js";
25
- import { l as init_dag, o as getDispatchableItems } from "./dag-BtkgLeqY.js";
26
- import { a as loadCloisterConfigSync, i as loadCloisterConfig, r as init_config$1 } from "./config-Bi3u1VK7.js";
27
- import { a as findRecreatedLegacyStatePaths, o as init_state_home } from "./state-home-722Dkx92.js";
28
- import { M as withConcurrencyLimit, j as init_concurrency$1 } from "./github-app-CmNk0zLU.js";
29
- import { a as isAgentIdleForNudge, t as checkStuckAgentRemediation } from "./stuck-remediation-CC6q3eqQ.js";
30
- import { n as __filename, r as init_esm_shims } from "./esm-shims-BeObUkaw.js";
31
- import { i as init_staleness, r as computeBuildStaleness } from "./staleness-C-a5rBxF.js";
32
- import { a as pidsWithCwdUnder, i as sweepAutoCloseOutCache, n as pruneTerminalStoppedAgents, r as getAutoCloseOutCanonicalState } from "./agent-gc-C3h9Or3a.js";
33
- import { n as init_issue_closed, r as isIssueClosed } from "./issue-closed-BehTG1be.js";
34
- import { n as getForgeAdapter, r as init_forge } from "./forge-BaKGCya6.js";
35
- import { a as observeForgeMergeState, i as init_merge_completeness } from "./merge-completeness-B46KqhtY.js";
36
- import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-C27Hak8a.js";
37
- import { n as resolveIssueFeedbackTarget, r as surfaceIssueFeedbackNeedsYou, t as init_feedback_target } from "./feedback-target-DSxEL6lP.js";
38
- import { a as init_review_monitor, i as REVIEW_SUB_ROLES, n as init_review_convoy_liveness, r as reviewTimestampMs, t as evaluateReviewConvoyLiveness } from "./review-convoy-liveness-BgU_1jJf.js";
39
- import { J as parseReviewerSessionName, U as getTmuxSessionName, g as getAllProjectSpecialistStatuses, t as init_specialists } from "./specialists-DUiExaxb.js";
40
- import { a as inferBranchFromWorkspace, i as findWorkspacePath } from "./archive-planning-BwhxeP7C.js";
41
- import { n as init_merge_verification, r as shouldSkipDispatchAsMerged } from "./merge-verification-NvaAd8CZ.js";
42
- import { n as init_review_verdict_feedback, t as deliverReviewVerdictFeedback } from "./review-verdict-feedback-xJNdqBnX.js";
43
- import { _ as init_label_reconciler, a as gatherProjectLensSignals, s as init_pipeline_membership_gather, v as reconcilePipelineLabelsPatrol } from "./pipeline-membership-gather-CeVGnNJ2.js";
44
- import { n as init_pipeline_membership, r as resolvePipelineMembership } from "./pipeline-membership-D9SBvItj.js";
45
- import { i as init_conflict_gate, o as probeBranchConflictPaths } from "./conflict-gate-E4nt7ZeS.js";
46
- import { n as reconcileTraefikNetworks, t as init_traefik_connect } from "./traefik-connect-DZ6nMYMj.js";
47
- import { g as decideAgentAutonomousRedrive, r as coordinateSwarmSlots, y as listFeatureWorkspaces } from "./deacon-swarm-v5PMun-m.js";
48
- import { n as isExplicitNoResumeRequest, t as init_no_resume_mode } from "./no-resume-mode-BgD0JUmM.js";
49
- import { r as init_in_flight_guard, t as createInFlightGuard } from "./in-flight-guard-D-sSkADM.js";
50
- import { r as reconcileClosedIssueAgents } from "./closed-issue-reaper-DoOZqGFK.js";
51
- import { t as recordDeadEndNeedsYou } from "./dead-end-trip-D8A3msX9.js";
52
- import { a as spawnWorkAgentThroughAgentsEndpoint, i as reconcileOrphanProposedSpecs, o as triggerRebuildAndStart } from "./orphan-proposed-reconciler-B6vJHxtX.js";
53
- import { n as reconcileIdleWorkspaceStacks } from "./idle-stack-reaper-Cy-dQzW4.js";
54
- import { i as readTestVerdictArtifact, n as decideUnsignaledTestAction, r as init_test_verdict } from "./test-verdict-C4i9aqEP.js";
2
+ import { Cn as resolveProjectPath, Hr as AGENTS_DIR, Ot as getMainDivergence, Q as readIssueRecordSync, Sn as resolveProjectFromIssueSync, St as init_auto_commit, Tt as reconcileStatePlaneDrift, Vr as init_errors, Zr as OVERDECK_HOME, b as DEFAULT_CONFIG$1, cn as init_projects, dn as listProjects, f as loadConfigSync, fn as listProjectsSync, hi as init_paths, kt as init_state_plane, mn as loadProjectsConfigSync, nn as getProjectSync, q as init_record, s as init_load, x as init_defaults, yi as sessionFilePath } from "./config-yaml-BSCqwmX0.js";
3
+ import { n as init_build_info, t as getBuildInfo } from "./build-info-CJg813Hm.js";
4
+ import { n as getDashboardIdentity, t as recordDeaconNudge } from "./deacon-nudge-log-BND_97Wo.js";
5
+ import { f as init_config, m as loadConfigSync$1, p as loadConfig$1 } from "./config-DnLJATZk.js";
6
+ import { a as emitActivityEntrySync, c as init_activity_logger, o as emitActivityTtsSync, r as emitActivityEntryOnce } from "./activity-logger-Co5qljIj.js";
7
+ import { a as recordLockPath, i as readOwner, n as init_fs_lock } from "./fs-lock-D_GeJtXl.js";
8
+ import { i as updateIssueRecord, r as init_record_update } from "./record-update-CZh46a2f.js";
9
+ import { C as init_tmux, E as killSession, F as querySessionSync, H as sessionExistsSync, M as listSessions, R as sendKeys, T as isPaneDead, V as sessionExists, j as listSessionNames, k as listPaneValues, r as capturePane, z as sendKeysAsync } from "./tmux-CImZaX4q.js";
10
+ import { a as init_event_store, i as initEventStore } from "./event-store-D_AR-Y78.js";
11
+ import { D as projectLegacySystemHealthSummary, t as init_src } from "./src-BYdwL_n-.js";
12
+ import { B as reviewGatesPassedSync, C as setReviewStatusSync, G as findWorkspaceVerdictConflicts, H as findBlockingFindings, J as readJournalStatusSync, K as init_review_status_record_sync, R as init_review_dispatch_decision, U as init_review_findings, W as drainWorkspaceVerdictFallback, Y as readWorkspaceVerdictFallback, d as getReviewStatusSync, h as loadReviewStatuses, p as init_review_status, z as needsReviewDispatch } from "./review-status-CKLk5aZ-.js";
13
+ import { n as logAgentLifecycleSync, r as logDeaconEventSync, t as init_persistent_logger } from "./persistent-logger-s8cbpFNV.js";
14
+ import { c as listAllAgentsSync, d as isTerminalIssueStage, o as init_agents, u as getIssueStageSync } from "./agents-Dls7tfJH.js";
15
+ import { At as countRunningAgents, Dt as init_termination, Er as markAgentRunningState, Ft as init_concurrency, Ir as setAgentPausedSync, It as releaseAdvancingSlot, Lr as setAgentYieldedSync, Mr as resetAgentFailureCount, Mt as describeRunningAgents, Nr as saveAgentState, Ot as stopAgent, Pr as saveAgentStateSync, Pt as getConcurrencyLimits, Rt as resetPatrolDispatchBudget, Ut as init_memory_verdict_cache, Vt as workResumeSlotsAvailable, Wt as setCachedMemoryVerdict, Yt as deliverInitialPromptWithRetry, _ as init_linux, a as listRunningAgentsSync, b as init_agents$1, br as getAgentStateSync, c as getRuntimeCensus, ci as init_codex_auth, ct as init_context_overflow, dt as init_messaging, ei as getAgentRuntimeState, er as buildResumeContinueMessage, ft as messageAgent, g as LINUX_MEMORY_PRESSURE_DEFAULTS, gr as getAgentDir, h as init_collector, i as listRunningAgents, kr as recordAgentFailure, li as paneShowsCodexAuthBurn, m as createHostHealthCollector, mr as clearYieldForResumeSync, n as init_queries, ni as init_runtime_state, nn as init_transcript_landing, oi as applyCodexAuthBurnFlag, pr as clearAgentTroubledSync, r as listAgentStates, ri as saveAgentRuntimeState, s as descendantPidsForSession, st as resumeAgent, ti as getAgentRuntimeStateSync, tn as captureTranscriptUserRecordSnapshot, u as init_runtime_census, ut as isContextOverflowTail, v as DARWIN_MEMORY_PRESSURE_DEFAULTS, vr as getAgentState, xr as init_agent_state, y as init_darwin, zt as tryReserveAdvancingSlot } from "./queries-DVpl1vsU.js";
16
+ import { o as getRuntimeSnapshot, s as init_agent_runtime_mirror } from "./session-history-Bta5l9jY.js";
17
+ import { n as resolveGitHubIssueSync, t as init_tracker_utils } from "./tracker-utils-BDeAXC-q.js";
18
+ import { i as ensureInternalTokenSync, o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-AvXePaQT.js";
19
+ import { c as init_review_status_sync, l as markWorkspaceStuck } from "./review-status-sync-BxBeHRde.js";
20
+ import { i as readReviewStatusMap, n as init_review_status_source, t as classifyAdvancingSessionLifecycle } from "./review-status-source-7nU3Z2wL.js";
21
+ import { d as PENDING_PROMOTION_FILENAME, f as WORKSPACE_RUNTIME_DIRNAME, m as init_types } from "./types-DzlUKiuf.js";
22
+ import { _ as markMerged, c as init_merge_sync, f as listActiveAutoMerges, m as listProblemAutoMerges, t as cancelPending } from "./merge-sync-BEdfsQV4.js";
23
+ import { i as init_merge_set, r as getMergeSetSync } from "./merge-set-DsLjjLEV.js";
24
+ import { C as init_specs, S as findSpecByIssue, f as readPlanSync, h as readWorkspacePlanSync, o as findWorkspaceDraftPlanSync, s as init_io } from "./io-mxOWMZ7I.js";
25
+ import { D as setSetting, O as stampBootReconciliation, _ as setBootReconciliationGrace, c as init_control_settings, g as setBootReconciliationDecision, o as getLastCleanShutdownAt, r as getBootReconciliationState, s as getSetting, u as isDeaconGloballyPaused } from "./control-settings-DVf6pKyv.js";
26
+ import { f as DockerStatsCollector, p as init_docker_stats } from "./stack-health-D_iKwNRg.js";
27
+ import { l as init_dag, o as getDispatchableItems } from "./dag-BYiFMqpU.js";
28
+ import { a as loadCloisterConfigSync, i as loadCloisterConfig, r as init_config$1 } from "./config-DvM8jtQK.js";
29
+ import { a as findRecreatedLegacyStatePaths, o as init_state_home } from "./state-home-DjN8qduI.js";
30
+ import { M as withConcurrencyLimit, j as init_concurrency$1 } from "./github-app-D2QuvZ3j.js";
31
+ import { n as __filename, r as init_esm_shims } from "./esm-shims-Bzy4ZzNU.js";
32
+ import { i as init_staleness, r as computeBuildStaleness } from "./staleness-D8WeMUHd.js";
33
+ import { a as isAgentIdleForNudge, t as checkStuckAgentRemediation } from "./stuck-remediation-CbCRSz1v.js";
34
+ import { a as pidsWithCwdUnder, i as sweepAutoCloseOutCache, n as pruneTerminalStoppedAgents, r as getAutoCloseOutCanonicalState } from "./agent-gc-BmYeT6eH.js";
35
+ import { n as init_issue_closed, r as isIssueClosed } from "./issue-closed-Bj_bCv_0.js";
36
+ import { n as getForgeAdapter, r as init_forge } from "./forge-c8LeC-tw.js";
37
+ import { a as observeForgeMergeState, i as init_merge_completeness } from "./merge-completeness-C1FevcDT.js";
38
+ import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-DdsBdtNL.js";
39
+ import { n as resolveIssueFeedbackTarget, r as surfaceIssueFeedbackNeedsYou, t as init_feedback_target } from "./feedback-target-DoRCR3L-.js";
40
+ import { a as init_review_monitor, i as REVIEW_SUB_ROLES, n as init_review_convoy_liveness, r as reviewTimestampMs, t as evaluateReviewConvoyLiveness } from "./review-convoy-liveness-D7M-s_nS.js";
41
+ import { J as parseReviewerSessionName, U as getTmuxSessionName, g as getAllProjectSpecialistStatuses, t as init_specialists } from "./specialists-Hr6iW9fU.js";
42
+ import { a as inferBranchFromWorkspace, i as findWorkspacePath } from "./archive-planning-Cq7cyinS.js";
43
+ import { n as init_merge_verification, r as shouldSkipDispatchAsMerged } from "./merge-verification-DN1Ov9bU.js";
44
+ import { a as findVerdictReportAsync, i as findVerdictReport, n as init_review_verdict_feedback, o as init_review_verdict_report, s as parseVerdictReport, t as deliverReviewVerdictFeedback } from "./review-verdict-feedback-5jWuzgpc.js";
45
+ import { _ as init_label_reconciler, a as gatherProjectLensSignals, s as init_pipeline_membership_gather, v as reconcilePipelineLabelsPatrol } from "./pipeline-membership-gather-CtJ_7aGf.js";
46
+ import { n as init_pipeline_membership, r as resolvePipelineMembership } from "./pipeline-membership-Dqv6_0ig.js";
47
+ import { i as init_conflict_gate, o as probeBranchConflictPaths } from "./conflict-gate-WfVqgalf.js";
48
+ import { n as reconcileTraefikNetworks, t as init_traefik_connect } from "./traefik-connect-CC5FyxYj.js";
49
+ import { g as decideAgentAutonomousRedrive, r as coordinateSwarmSlots, y as listFeatureWorkspaces } from "./deacon-swarm-rqrl4TMs.js";
50
+ import { i as recordRecoveryFailure, n as findRecoveryTrip, r as init_recovery_trip } from "./recovery-trip-CSNWSLDn.js";
51
+ import { n as isExplicitNoResumeRequest, t as init_no_resume_mode } from "./no-resume-mode-DUR7Hi98.js";
52
+ import { r as init_in_flight_guard, t as createInFlightGuard } from "./in-flight-guard-CG2Eo-rr.js";
53
+ import { r as reconcileClosedIssueAgents } from "./closed-issue-reaper-C5Zn4GRS.js";
54
+ import { t as recordDeadEndNeedsYou } from "./dead-end-trip-DSF23CLX.js";
55
+ import { a as spawnWorkAgentThroughAgentsEndpoint, i as reconcileOrphanProposedSpecs, o as triggerRebuildAndStart } from "./orphan-proposed-reconciler-DfqHZftT.js";
56
+ import { n as reconcileIdleWorkspaceStacks } from "./idle-stack-reaper-CJ1ygW0p.js";
57
+ import { a as recordUnsignaledTestEscalation, i as readTestVerdictArtifact, n as decideUnsignaledTestAction, r as init_test_verdict } from "./test-verdict-diIWE6hz.js";
55
58
  import { createRequire } from "node:module";
56
- import { join } from "node:path";
59
+ import { dirname, join } from "node:path";
57
60
  import { Effect } from "effect";
58
61
  import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "fs";
59
62
  import { basename as basename$1, dirname as dirname$1, join as join$1 } from "path";
60
63
  import { cpus, loadavg } from "os";
61
64
  import { freemem as freemem$1, homedir as homedir$1, platform as platform$1, totalmem as totalmem$1 } from "node:os";
62
65
  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";
63
- import { readFile } from "node:fs/promises";
66
+ import { mkdir, readFile, readdir, rename, rm, stat as stat$1, writeFile } from "node:fs/promises";
64
67
  import { readFile as readFile$1, readdir as readdir$1, writeFile as writeFile$1 } from "fs/promises";
65
68
  import { exec, execFile, execFileSync, spawn } from "node:child_process";
66
69
  import { promisify } from "node:util";
@@ -70,11 +73,12 @@ import { layer } from "@effect/platform-node/NodeServices";
70
73
  //#region ../../lib/agents/health.ts
71
74
  init_paths();
72
75
  init_errors();
73
- init_activity_logger();
74
76
  init_projects();
75
77
  init_state_plane();
76
78
  init_auto_commit();
77
79
  init_record();
80
+ init_config();
81
+ init_activity_logger();
78
82
  init_tmux();
79
83
  init_src();
80
84
  init_persistent_logger();
@@ -21785,7 +21789,6 @@ new ((/* @__PURE__ */ __commonJSMin(((exports, module) => {
21785
21789
  * stopSmeeProcess();
21786
21790
  * isSmeeProcessRunning();
21787
21791
  */
21788
- init_config();
21789
21792
  const SMEE_URL_PATH = join(homedir$1(), ".overdeck", "github-app", "smee-url");
21790
21793
  const SMEE_PID_PATH = join(homedir$1(), ".overdeck", "github-app", "smee.pid");
21791
21794
  const SMEE_LOG_PATH = join(homedir$1(), ".overdeck", "logs", "smee.log");
@@ -23158,9 +23161,13 @@ async function assessMemoryPressure() {
23158
23161
  }
23159
23162
  //#endregion
23160
23163
  //#region ../../lib/cloister/agent-grace.ts
23164
+ init_fs_lock();
23161
23165
  init_record_update();
23162
23166
  init_internal_token();
23167
+ init_types();
23163
23168
  init_review_findings();
23169
+ init_specs();
23170
+ init_io();
23164
23171
  init_control_settings();
23165
23172
  const WORK_LAUNCHER_GRACE_MS = 12e4;
23166
23173
  function isStartingWithinGrace(state, now = Date.now(), graceMs = WORK_LAUNCHER_GRACE_MS) {
@@ -23211,7 +23218,7 @@ async function checkInspectAgentTimeouts(now = /* @__PURE__ */ new Date()) {
23211
23218
  console.warn(`[deacon] Failed to kill inspect session ${sessionName}: ${msg}`);
23212
23219
  });
23213
23220
  try {
23214
- const { messageAgent } = await import("./agents-ePFVoZbu.js");
23221
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
23215
23222
  await messageAgent(`agent-${issueId.toLowerCase()}`, verdict, "deacon:inspect-watchdog");
23216
23223
  } catch (err) {
23217
23224
  const msg = err instanceof Error ? err.message : String(err);
@@ -23405,7 +23412,7 @@ async function maybeProactivelyCompactContext(sessionName, now) {
23405
23412
  if (!agentState?.workspace || !sessionId || !agentState.model) return null;
23406
23413
  let usage = null;
23407
23414
  try {
23408
- const { computeContextUsage } = await import("./conversation-service-D_TS2b1r.js");
23415
+ const { computeContextUsage } = await import("./conversation-service-DnUyIiLb.js");
23409
23416
  usage = await computeContextUsage(sessionFilePath(agentState.workspace, sessionId), agentState.model);
23410
23417
  } catch {
23411
23418
  return null;
@@ -23504,9 +23511,9 @@ async function checkApiErrorAgents() {
23504
23511
  }
23505
23512
  if (!tmuxOutput.includes("❯")) continue;
23506
23513
  try {
23507
- const { maybeContinueCompactedAgent } = await import("./compaction-continuation-CvXpbZ4w.js");
23508
- const { findLastCompactBoundary } = await import("./conversation-service-D_TS2b1r.js");
23509
- const { deliverAgentMessage } = await import("./delivery-BX9HR4wQ.js");
23514
+ const { maybeContinueCompactedAgent } = await import("./compaction-continuation-DZD9ukSE.js");
23515
+ const { findLastCompactBoundary } = await import("./conversation-service-DnUyIiLb.js");
23516
+ const { deliverAgentMessage } = await import("./delivery-CsbQdZkS.js");
23510
23517
  const continued = await maybeContinueCompactedAgent({
23511
23518
  agentId: sessionName,
23512
23519
  tmuxOutput,
@@ -23557,13 +23564,13 @@ async function checkApiErrorAgents() {
23557
23564
  const st = getAgentStateSync(sessionName);
23558
23565
  const sid = st?.sessionId ?? runtimeState?.claudeSessionId;
23559
23566
  if (st?.workspace && sid && st.model) {
23560
- const { computeContextUsage } = await import("./conversation-service-D_TS2b1r.js");
23567
+ const { computeContextUsage } = await import("./conversation-service-DnUyIiLb.js");
23561
23568
  const usage = await computeContextUsage(sessionFilePath(st.workspace, sid), st.model);
23562
23569
  if (usage && usage.percentUsed < 85) recoveredPct = usage.percentUsed;
23563
23570
  }
23564
23571
  } catch {}
23565
23572
  if (recoveredPct !== null) {
23566
- const { clearWorkspaceStuck } = await import("./review-status-sync-muT-EBp2.js");
23573
+ const { clearWorkspaceStuck } = await import("./review-status-sync-BLssMTEW.js");
23567
23574
  clearWorkspaceStuck(issueId);
23568
23575
  stuckOverflowNativeRecoveryState.delete(sessionName);
23569
23576
  actions.push(`Context overflow recovery: cleared stuck flag for ${sessionName} (context back to ${Math.round(recoveredPct)}%)`);
@@ -23579,7 +23586,7 @@ async function checkApiErrorAgents() {
23579
23586
  rec.attempts += 1;
23580
23587
  rec.lastAttempt = now;
23581
23588
  stuckOverflowNativeRecoveryState.set(sessionName, rec);
23582
- const { resumeAgent } = await import("./agents-ePFVoZbu.js");
23589
+ const { resumeAgent } = await import("./agents-IPSa5kzn.js");
23583
23590
  const recovered = await resumeAgent(sessionName, void 0, { compact: true });
23584
23591
  if (recovered.success) {
23585
23592
  stuckOverflowNativeRecoveryState.delete(sessionName);
@@ -23627,7 +23634,7 @@ async function checkApiErrorAgents() {
23627
23634
  }
23628
23635
  const compactAttempts = (ov?.compactAttempts ?? 0) + 1;
23629
23636
  if (issueId !== null) {
23630
- const { resumeAgent } = await import("./agents-ePFVoZbu.js");
23637
+ const { resumeAgent } = await import("./agents-IPSa5kzn.js");
23631
23638
  const resumeResult = await resumeAgent(sessionName, void 0, { compact: true });
23632
23639
  contextOverflowRecoveryState.set(sessionName, {
23633
23640
  lastAttempt: now,
@@ -23746,7 +23753,7 @@ function isStuckMergingState(status, now) {
23746
23753
  }
23747
23754
  async function readSpecStatus(projectPath, issueId) {
23748
23755
  try {
23749
- const { findSpecByIssue } = await import("./specs--enInima.js");
23756
+ const { findSpecByIssue } = await import("./specs-Dl88cbKY.js");
23750
23757
  return (await Effect.runPromise(findSpecByIssue(projectPath, issueId)))?.status;
23751
23758
  } catch {
23752
23759
  return;
@@ -23828,7 +23835,7 @@ async function reconcileStuckMergingStates() {
23828
23835
  reviewGatesPassed: reviewGatesPassedSync,
23829
23836
  setReviewStatus: setReviewStatusSync,
23830
23837
  enqueuePostMerge: async (issueId, projectPath, branch) => {
23831
- const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-8HIeS_J6.js");
23838
+ const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-DmSOkeNp.js");
23832
23839
  return enqueuePostMergeLifecycle(issueId, projectPath, branch);
23833
23840
  },
23834
23841
  warn: (message) => console.warn(message)
@@ -24073,7 +24080,7 @@ async function reconcileStaleMergeStatus() {
24073
24080
  ].includes(status.mergeStatus ?? "") || ["merging", "failed"].includes(mergeSet?.status ?? "");
24074
24081
  let specStatus;
24075
24082
  try {
24076
- const { findSpecByIssue } = await import("./specs--enInima.js");
24083
+ const { findSpecByIssue } = await import("./specs-Dl88cbKY.js");
24077
24084
  const spec = await Effect.runPromise(findSpecByIssue(project.projectPath, issueId));
24078
24085
  specStatus = spec?.status;
24079
24086
  if (spec && (spec.status === "completed" || spec.status === "cancelled")) {
@@ -24083,7 +24090,7 @@ async function reconcileStaleMergeStatus() {
24083
24090
  } catch {}
24084
24091
  const branch = `feature/${issueId.toLowerCase()}`;
24085
24092
  if (postMergeIncomplete) {
24086
- const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-8HIeS_J6.js");
24093
+ const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-DmSOkeNp.js");
24087
24094
  const action = enqueuePostMergeLifecycle(issueId, project.projectPath, branch);
24088
24095
  if (action) actions.push(action);
24089
24096
  continue;
@@ -24095,7 +24102,7 @@ async function reconcileStaleMergeStatus() {
24095
24102
  } catch {}
24096
24103
  if (!isMerged) isMerged = (await observeGitHubBranchMerge(issueId, branch, project.projectPath)).merged;
24097
24104
  if (shouldObserveForge && mergeRelevant) try {
24098
- const observation = await (await import("./merge-completeness-BLbB5-6n.js")).observeForgeMergeState(issueId);
24105
+ const observation = await (await import("./merge-completeness-BfRwFjRx.js")).observeForgeMergeState(issueId);
24099
24106
  const blocker = observation.repos.find((repo) => repo.state === "unverifiable");
24100
24107
  if (blocker) {
24101
24108
  console.warn(`[deacon] ${issueId}: forge merge state is unverifiable — ${blocker.reason}`);
@@ -24122,7 +24129,7 @@ async function reconcileStaleMergeStatus() {
24122
24129
  const msg = `Reconciled stale mergeStatus for ${issueId} — branch ${branch} is merged to main`;
24123
24130
  actions.push(msg);
24124
24131
  console.log(`[deacon] ${msg}`);
24125
- const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-8HIeS_J6.js");
24132
+ const { enqueuePostMergeLifecycle } = await import("./post-merge-lifecycle-worker-DmSOkeNp.js");
24126
24133
  const action = enqueuePostMergeLifecycle(issueId, project.projectPath, branch);
24127
24134
  if (action) actions.push(action);
24128
24135
  }
@@ -24145,7 +24152,7 @@ const falseMergedReset = /* @__PURE__ */ new Set();
24145
24152
  async function reconcileFalseMerged() {
24146
24153
  const actions = [];
24147
24154
  try {
24148
- const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-Bmg4R9mv.js");
24155
+ const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-CpQSDlv8.js");
24149
24156
  if (!isGitHubAppConfigured()) return actions;
24150
24157
  const statuses = loadReviewStatuses();
24151
24158
  for (const [issueId, status] of Object.entries(statuses)) {
@@ -24190,7 +24197,7 @@ const CLOSED_PR_RECONCILE_COOLDOWN_MS = 600 * 1e3;
24190
24197
  async function reconcileClosedPrReadyForMerge() {
24191
24198
  const actions = [];
24192
24199
  try {
24193
- const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-Bmg4R9mv.js");
24200
+ const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-CpQSDlv8.js");
24194
24201
  if (!isGitHubAppConfigured()) return actions;
24195
24202
  const statuses = loadReviewStatuses();
24196
24203
  const now = Date.now();
@@ -24262,7 +24269,7 @@ const STALE_MERGE_BLOCKER_COOLDOWN_MS = 120 * 1e3;
24262
24269
  async function reconcileStaleMergeBlockers() {
24263
24270
  const actions = [];
24264
24271
  try {
24265
- const { resolveConflictGate, buildRealConflictGateDeps } = await import("./conflict-gate-CX80JYYS.js");
24272
+ const { resolveConflictGate, buildRealConflictGateDeps } = await import("./conflict-gate-DXa_L28t.js");
24266
24273
  const statuses = loadReviewStatuses();
24267
24274
  const now = Date.now();
24268
24275
  const deps = buildRealConflictGateDeps();
@@ -24405,7 +24412,7 @@ async function checkFailedMergeRetry() {
24405
24412
  if (ciEntry.count === 5) {
24406
24413
  console.log(`[deacon] CI check failure for ${issueId} — retries exhausted, notifying work agent`);
24407
24414
  const ciNotes = status.mergeNotes || "CI checks are failing on the PR";
24408
- const { writeFeedbackFile } = await import("./feedback-writer-CoB9Z6aU.js");
24415
+ const { writeFeedbackFile } = await import("./feedback-writer-CTSuA6lw.js");
24409
24416
  const ciFileResult = await Effect.runPromise(writeFeedbackFile({
24410
24417
  issueId,
24411
24418
  specialist: "merge-agent",
@@ -24437,7 +24444,7 @@ async function checkFailedMergeRetry() {
24437
24444
  ciRetryMap.set(issueId, ciEntry);
24438
24445
  console.log(`[deacon] CI check failure for ${issueId} — notifying agent to re-submit (attempt ${ciEntry.count}/5)`);
24439
24446
  const ciNotes = status.mergeNotes || "CI checks are failing on the PR";
24440
- const { writeFeedbackFile } = await import("./feedback-writer-CoB9Z6aU.js");
24447
+ const { writeFeedbackFile } = await import("./feedback-writer-CTSuA6lw.js");
24441
24448
  const ciFileResult2 = await Effect.runPromise(writeFeedbackFile({
24442
24449
  issueId,
24443
24450
  specialist: "merge-agent",
@@ -24465,7 +24472,7 @@ async function checkFailedMergeRetry() {
24465
24472
  const lastNudge = timeoutNudgeCooldowns.get(issueIdForFb);
24466
24473
  if (!lastNudge || now - lastNudge >= TIMEOUT_NUDGE_COOLDOWN_MS) {
24467
24474
  const timeoutNotes = status.mergeNotes;
24468
- const { writeFeedbackFile } = await import("./feedback-writer-CoB9Z6aU.js");
24475
+ const { writeFeedbackFile } = await import("./feedback-writer-CTSuA6lw.js");
24469
24476
  await Effect.runPromise(writeFeedbackFile({
24470
24477
  issueId: issueIdForFb,
24471
24478
  specialist: "merge-agent",
@@ -24570,7 +24577,7 @@ async function autoCloseOut(now = /* @__PURE__ */ new Date()) {
24570
24577
  } } : {}
24571
24578
  };
24572
24579
  try {
24573
- const { closeOut } = await import("./workflows-DtDX08ed.js");
24580
+ const { closeOut } = await import("./workflows-BOmWGpIh.js");
24574
24581
  const result = await Effect.runPromise(closeOut(ctx));
24575
24582
  if (!result.success) {
24576
24583
  const failed = result.steps.find((step) => !step.success && !step.skipped);
@@ -24864,6 +24871,8 @@ init_concurrency();
24864
24871
  const BLOCKED_REVIEW_MISSING_ANCHOR_LOG_INTERVAL_MS = 3600 * 1e3;
24865
24872
  const blockedReviewMissingAnchorLogs = /* @__PURE__ */ new Map();
24866
24873
  const blockedReviewDriftObservations = /* @__PURE__ */ new Map();
24874
+ const lastResetAnchors = /* @__PURE__ */ new Map();
24875
+ const resetLoopEscalated = /* @__PURE__ */ new Set();
24867
24876
  function uniformReviewerVerdictAnchor(status) {
24868
24877
  const verdicts = Object.values(status.reviewerVerdicts ?? {});
24869
24878
  if (verdicts.length === 0) return void 0;
@@ -24883,12 +24892,14 @@ async function checkPostReviewCommits() {
24883
24892
  const actions = [];
24884
24893
  try {
24885
24894
  const statuses = loadReviewStatuses();
24886
- const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
24895
+ const { resolveProjectFromIssueSync } = await import("./projects-WqMWCdpa.js");
24887
24896
  for (const [issueId, status] of Object.entries(statuses)) {
24888
24897
  const isBlocked = status.reviewStatus === "blocked";
24889
24898
  if (!isBlocked) blockedReviewDriftObservations.delete(issueId);
24890
24899
  if (status.mergeStatus === "merged") {
24891
24900
  blockedReviewDriftObservations.delete(issueId);
24901
+ lastResetAnchors.delete(issueId);
24902
+ resetLoopEscalated.delete(issueId);
24892
24903
  continue;
24893
24904
  }
24894
24905
  if (!isBlocked && status.reviewStatus !== "passed" && !status.readyForMerge) continue;
@@ -24913,8 +24924,8 @@ async function checkPostReviewCommits() {
24913
24924
  if (!project) continue;
24914
24925
  const workspacePath = join$1(project.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
24915
24926
  if (!existsSync(workspacePath)) continue;
24916
- const { formatAnchorShort, rehydrateHeadAnchor } = await import("./git-utils-Xg4PFN45.js");
24917
- const { evaluateWorkspaceAnchorDrift } = await import("./workspace-anchor-drift-pwz23TI1.js");
24927
+ const { formatAnchorShort, rehydrateHeadAnchor } = await import("./git-utils-C31x1lpE.js");
24928
+ const { evaluateWorkspaceAnchorDrift } = await import("./workspace-anchor-drift-C8Fy3shi.js");
24918
24929
  const verdict = await evaluateWorkspaceAnchorDrift(issueId, workspacePath, rehydrateHeadAnchor(reviewedAnchor));
24919
24930
  if (verdict.kind === "unreadable" || verdict.kind === "current") {
24920
24931
  blockedReviewDriftObservations.delete(issueId);
@@ -24927,6 +24938,16 @@ async function checkPostReviewCommits() {
24927
24938
  continue;
24928
24939
  }
24929
24940
  const currentHead = verdict.currentAnchor;
24941
+ if (lastResetAnchors.get(issueId) === currentHead) {
24942
+ if (!resetLoopEscalated.has(issueId)) {
24943
+ resetLoopEscalated.add(issueId);
24944
+ const message = `${issueId} — review reset suppressed: drift against ${formatAnchorShort(currentHead)} already caused a reset and the workspace has not moved since. This indicates an anchor-producer disagreement, not new commits; review will not re-dispatch until the workspace head actually changes.`;
24945
+ logDeaconEventSync(`checkPostReviewCommits: ${message}`);
24946
+ const { recordDeadEndNeedsYou } = await import("./dead-end-trip-zKlS4v6f.js");
24947
+ await recordDeadEndNeedsYou(issueId, "review-reset-loop", currentHead, message);
24948
+ }
24949
+ continue;
24950
+ }
24930
24951
  if (isBlocked) {
24931
24952
  const priorObservation = blockedReviewDriftObservations.get(issueId);
24932
24953
  if (!priorObservation || priorObservation.reviewedAnchor !== reviewedAnchor || priorObservation.currentAnchor !== currentHead) {
@@ -24939,6 +24960,8 @@ async function checkPostReviewCommits() {
24939
24960
  blockedReviewDriftObservations.delete(issueId);
24940
24961
  }
24941
24962
  console.log(`[deacon] Post-review commit detected for ${issueId}: was ${formatAnchorShort(reviewedAnchor)}, now ${formatAnchorShort(currentHead)} — resetting review`);
24963
+ lastResetAnchors.set(issueId, currentHead);
24964
+ resetLoopEscalated.delete(issueId);
24942
24965
  if (isBlocked) setReviewStatusSync(issueId, {
24943
24966
  reviewStatus: "pending",
24944
24967
  readyForMerge: false,
@@ -24964,7 +24987,7 @@ async function checkPostReviewCommits() {
24964
24987
  actions.push(`Deferred post-review re-dispatch for ${issueId} — advancing-role concurrency ceiling reached`);
24965
24988
  logDeaconEventSync(`checkPostReviewCommits: deferred review for ${issueId} — advancing ceiling reached (PAN-1665) — ${describeRunningAgents()}`);
24966
24989
  } else if (freshStatus?.reviewStatus === "pending") {
24967
- const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
24990
+ const { spawnReviewRoleForIssue } = await import("./review-agent-CD3RQ-tc.js");
24968
24991
  const branch = `feature/${issueId.toLowerCase()}`;
24969
24992
  const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
24970
24993
  issueId,
@@ -25345,7 +25368,7 @@ function reviewConvoyLiveness(issueId) {
25345
25368
  */
25346
25369
  async function recoverUnhealthyTestStack(issueId, workspacePath) {
25347
25370
  const key = issueId.toUpperCase();
25348
- const { getWorkspaceStackHealth } = await import("./stack-health-BikqHSjn.js");
25371
+ const { getWorkspaceStackHealth } = await import("./stack-health-deVSdDwn.js");
25349
25372
  const health = await Effect.runPromise(getWorkspaceStackHealth(issueId, { workspacePath }));
25350
25373
  if (health.healthy) {
25351
25374
  testStackRebuildState.delete(key);
@@ -25377,7 +25400,7 @@ async function recoverUnhealthyTestStack(issueId, workspacePath) {
25377
25400
  record.attempts += 1;
25378
25401
  testStackRebuildState.set(key, record);
25379
25402
  console.log(`[deacon] Test stack for ${key} unhealthy (${health.reasons.join("; ")}) — rebuilding (attempt ${record.attempts}/${TEST_STACK_REBUILD_MAX_ATTEMPTS})`);
25380
- const { rebuildWorkspaceStack } = await import("./rebuild-stack-DqcOVmJO.js");
25403
+ const { rebuildWorkspaceStack } = await import("./rebuild-stack-qC0jCNm6.js");
25381
25404
  const result = await Effect.runPromise(rebuildWorkspaceStack(issueId, { onProgress: (m) => console.log(`[deacon] ${key} stack rebuild: ${m}`) }));
25382
25405
  if (!result.success) {
25383
25406
  console.warn(`[deacon] Test stack rebuild failed for ${key}: ${result.error}`);
@@ -25545,7 +25568,7 @@ async function handleReviewCoordinatorDied(issueId, _sessionName, _reason) {
25545
25568
  return actions;
25546
25569
  }
25547
25570
  try {
25548
- const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
25571
+ const { spawnReviewRoleForIssue } = await import("./review-agent-CD3RQ-tc.js");
25549
25572
  const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
25550
25573
  issueId,
25551
25574
  workspace,
@@ -25620,7 +25643,7 @@ async function reconcileReviewStatusOrphan(issueId, rawStatus, options = {}) {
25620
25643
  const issueLower = issueId.toLowerCase();
25621
25644
  const workspace = getAgentStateSync(`agent-${issueLower}`)?.workspace || (resolved ? findWorkspacePath(resolved.projectPath, issueLower) : null);
25622
25645
  if (workspace) try {
25623
- if ((options.readWorkspaceHead ? await options.readWorkspaceHead(workspace) : await (await import("./git-utils-Xg4PFN45.js")).snapshotWorkspaceHeadsPromise(issueId, workspace)) === status.lastVerifiedCommit) {
25646
+ if ((options.readWorkspaceHead ? await options.readWorkspaceHead(workspace) : await (await import("./git-utils-C31x1lpE.js")).snapshotWorkspaceHeadsPromise(issueId, workspace)) === status.lastVerifiedCommit) {
25624
25647
  setReviewStatusSync(issueId, {
25625
25648
  reviewStatus: "pending",
25626
25649
  reviewNotes: void 0
@@ -25642,7 +25665,7 @@ async function reconcileReviewStatusOrphan(issueId, rawStatus, options = {}) {
25642
25665
  if (project) {
25643
25666
  const workspacePath = join$1(project.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
25644
25667
  if (existsSync(workspacePath)) {
25645
- const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-Xg4PFN45.js");
25668
+ const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-C31x1lpE.js");
25646
25669
  reviewUpdate["reviewedAtCommit"] = await snapshotWorkspaceHeadsPromise(issueId, workspacePath);
25647
25670
  }
25648
25671
  }
@@ -25697,7 +25720,7 @@ async function reconcileReviewStatusOrphan(issueId, rawStatus, options = {}) {
25697
25720
  const workspace = agentState?.workspace || (resolved ? findWorkspacePath(resolved.projectPath, issueLower) : null);
25698
25721
  if (workspace && resolved && !tryReserveAdvancingSlot() && !await tryYieldForAdvancingDispatch("review", issueId)) actions.push(`Deferred review re-dispatch for ${issueId} — advancing-role concurrency ceiling reached`);
25699
25722
  else if (workspace && resolved) try {
25700
- const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
25723
+ const { spawnReviewRoleForIssue } = await import("./review-agent-CD3RQ-tc.js");
25701
25724
  const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
25702
25725
  issueId,
25703
25726
  workspace,
@@ -25722,8 +25745,8 @@ async function reconcileReviewStatusOrphan(issueId, rawStatus, options = {}) {
25722
25745
  const workspace = agentState?.workspace || (resolved ? findWorkspacePath(resolved.projectPath, issueLower) : null);
25723
25746
  if (workspace && resolved) {
25724
25747
  const branch = `feature/${issueLower}`;
25725
- const { spawnRun } = await import("./agents-ePFVoZbu.js");
25726
- const { buildTestRolePrompt } = await import("./test-agent-queue-A_-p-i0I.js");
25748
+ const { spawnRun } = await import("./agents-IPSa5kzn.js");
25749
+ const { buildTestRolePrompt } = await import("./test-agent-queue-CWMq7oyG.js");
25727
25750
  const stackRecovery = await recoverUnhealthyTestStack(issueId, workspace);
25728
25751
  if (stackRecovery === "cooldown" || stackRecovery === "exhausted") {
25729
25752
  setReviewStatusSync(issueId, { testStatus: "dispatch_failed" });
@@ -25862,7 +25885,7 @@ async function recoverStalledReviewConvoys(getCanonicalState = getAutoCloseOutCa
25862
25885
  record.lastAttempt = now;
25863
25886
  record.attempts += 1;
25864
25887
  stalledReviewConvoyRecoveryState.set(key, record);
25865
- const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
25888
+ const { spawnReviewRoleForIssue } = await import("./review-agent-CD3RQ-tc.js");
25866
25889
  try {
25867
25890
  const result = await Effect.runPromise(spawnReviewRoleForIssue({
25868
25891
  issueId,
@@ -25933,7 +25956,7 @@ async function checkMissingReviewStatuses() {
25933
25956
  continue;
25934
25957
  }
25935
25958
  try {
25936
- const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
25959
+ const { spawnReviewRoleForIssue } = await import("./review-agent-CD3RQ-tc.js");
25937
25960
  await Effect.runPromise(spawnReviewRoleForIssue({
25938
25961
  issueId,
25939
25962
  workspace,
@@ -25961,11 +25984,14 @@ async function checkMissingReviewStatuses() {
25961
25984
  //#endregion
25962
25985
  //#region ../../lib/cloister/deacon-review-unsignaled.ts
25963
25986
  init_agents$1();
25987
+ init_activity_logger();
25964
25988
  init_projects();
25965
25989
  init_review_status();
25966
25990
  init_specialists();
25967
25991
  init_tmux();
25968
25992
  init_review_convoy_liveness();
25993
+ init_review_verdict_feedback();
25994
+ init_review_verdict_report();
25969
25995
  /**
25970
25996
  * Detect issues stuck in `reviewing` status with no active review session.
25971
25997
  *
@@ -25984,7 +26010,7 @@ async function checkStuckReviewing() {
25984
26010
  const actions = [];
25985
26011
  const REVIEW_STUCK_THRESHOLD_MS = 1800 * 1e3;
25986
26012
  try {
25987
- const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Dma9SFaN.js");
26013
+ const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-B6wYcOtP.js");
25988
26014
  const statuses = loadReviewStatuses();
25989
26015
  const now = Date.now();
25990
26016
  const activeReviewIssues = /* @__PURE__ */ new Set();
@@ -26042,25 +26068,183 @@ async function checkStuckReviewing() {
26042
26068
  * - Only nudges once per review cycle (tracked by runId in the review dir)
26043
26069
  */
26044
26070
  const unsignaledReviewNudges = /* @__PURE__ */ new Map();
26045
- function isSynthesisForActiveReviewRun(dirPath, status, synthesisMtimeMs) {
26071
+ const pendingVerdictNudges = /* @__PURE__ */ new Map();
26072
+ function reviewAnchorFromContext(context) {
26073
+ if (context.repos) {
26074
+ if (context.repos.length === 0) return void 0;
26075
+ const heads = [];
26076
+ for (const repo of context.repos) {
26077
+ if (!repo.repoKey?.trim() || !repo.headSha?.trim()) return void 0;
26078
+ heads.push(`${repo.repoKey.trim()}@${repo.headSha.trim()}`);
26079
+ }
26080
+ return heads.join(" ");
26081
+ }
26082
+ return context.headSha?.trim() || void 0;
26083
+ }
26084
+ function shellQuote(value) {
26085
+ return `'${value.replaceAll("'", "'\\''")}'`;
26086
+ }
26087
+ function buildReviewCompletionCommand(issueId, verdict, notes, runId) {
26088
+ let command = `pan admin specialists done review ${shellQuote(issueId)} --status ${shellQuote(verdict)}`;
26089
+ if (verdict === "blocked" || verdict === "failed") command += ` --notes ${shellQuote(notes)}`;
26090
+ return `${command} --run-id ${shellQuote(runId)}`;
26091
+ }
26092
+ function isReviewContextForActiveRun(context, status, reportMtimeMs) {
26046
26093
  if (!status.reviewSpawnedAt) return true;
26047
26094
  const spawnedAtMs = reviewTimestampMs(status.reviewSpawnedAt);
26048
26095
  if (!Number.isFinite(spawnedAtMs)) return true;
26049
- if (synthesisMtimeMs < spawnedAtMs) return false;
26096
+ if (reportMtimeMs < spawnedAtMs) return false;
26097
+ if (context.generatedAt) {
26098
+ const generatedAtMs = Date.parse(context.generatedAt);
26099
+ if (Number.isFinite(generatedAtMs) && generatedAtMs < spawnedAtMs) return false;
26100
+ }
26101
+ const reviewedAnchor = reviewAnchorFromContext(context);
26102
+ return !status.lastVerifiedCommit || !reviewedAnchor || reviewedAnchor === status.lastVerifiedCommit;
26103
+ }
26104
+ function isSynthesisForActiveReviewRun(dirPath, status, synthesisMtimeMs) {
26105
+ if (!status.reviewSpawnedAt) return true;
26050
26106
  const contextPath = join$1(dirPath, "context.json");
26051
26107
  if (!existsSync(contextPath)) return false;
26052
- let context;
26053
26108
  try {
26054
- context = JSON.parse(readFileSync(contextPath, "utf8"));
26109
+ return isReviewContextForActiveRun(JSON.parse(readFileSync(contextPath, "utf8")), status, synthesisMtimeMs);
26055
26110
  } catch {
26056
26111
  return false;
26057
26112
  }
26058
- if (context.generatedAt) {
26059
- const generatedAtMs = Date.parse(context.generatedAt);
26060
- if (Number.isFinite(generatedAtMs) && generatedAtMs < spawnedAtMs) return false;
26113
+ }
26114
+ /**
26115
+ * Apply settled review verdicts that reached disk after their runtime status
26116
+ * was reset to pending. The live review parent gets one chance to signal the
26117
+ * verdict itself; a dead parent, or one still unsignaled after 30 minutes, is
26118
+ * reconciled directly through the review-status and feedback write doors.
26119
+ */
26120
+ async function reconcileUnappliedReviewVerdicts() {
26121
+ const actions = [];
26122
+ const VERDICT_SETTLE_MS = 300 * 1e3;
26123
+ const NUDGE_GRACE_MS = 1800 * 1e3;
26124
+ try {
26125
+ const statuses = loadReviewStatuses();
26126
+ const now = Date.now();
26127
+ for (const [issueId, status] of Object.entries(statuses)) {
26128
+ if (status.reviewStatus !== "pending" || !status.reviewSpawnedAt) continue;
26129
+ try {
26130
+ const resolved = resolveProjectFromIssueSync(issueId);
26131
+ if (!resolved) continue;
26132
+ const wsPath = findWorkspacePath(resolved.projectPath, issueId.toLowerCase());
26133
+ if (!wsPath) continue;
26134
+ const reviewBaseDir = join$1(wsPath, ".pan", "review");
26135
+ let reviewEntries;
26136
+ try {
26137
+ reviewEntries = await readdir(reviewBaseDir);
26138
+ } catch {
26139
+ continue;
26140
+ }
26141
+ let latestDir = null;
26142
+ let latestReport = null;
26143
+ let latestContext = null;
26144
+ let latestMtime = 0;
26145
+ for (const entry of reviewEntries) {
26146
+ if (!entry.startsWith(`agent-${issueId.toLowerCase()}-review`)) continue;
26147
+ const dirPath = join$1(reviewBaseDir, entry);
26148
+ try {
26149
+ const report = await findVerdictReportAsync(dirPath);
26150
+ if (!report) continue;
26151
+ const [reportStat, contextContent] = await Promise.all([stat$1(report.path), readFile(join$1(dirPath, "context.json"), "utf8")]);
26152
+ const context = JSON.parse(contextContent);
26153
+ if (!isReviewContextForActiveRun(context, status, reportStat.mtimeMs)) continue;
26154
+ if (reportStat.mtimeMs > latestMtime) {
26155
+ latestDir = dirPath;
26156
+ latestReport = report;
26157
+ latestContext = context;
26158
+ latestMtime = reportStat.mtimeMs;
26159
+ }
26160
+ } catch (error) {
26161
+ const msg = error instanceof Error ? error.message : String(error);
26162
+ console.error(`[deacon] Error reading review run ${dirPath}:`, msg);
26163
+ }
26164
+ }
26165
+ if (!latestDir || !latestReport || !latestContext) continue;
26166
+ if (now - latestMtime < VERDICT_SETTLE_MS) continue;
26167
+ const requestedAtMs = status.reviewRequestedAt ? Date.parse(status.reviewRequestedAt) : NaN;
26168
+ if (Number.isFinite(requestedAtMs) && requestedAtMs > latestMtime) continue;
26169
+ let currentHead;
26170
+ let reviewedHead;
26171
+ try {
26172
+ const { rehydrateHeadAnchor, snapshotWorkspaceHeadsPromise } = await import("./git-utils-C31x1lpE.js");
26173
+ currentHead = await snapshotWorkspaceHeadsPromise(issueId, wsPath);
26174
+ const persistedAnchor = reviewAnchorFromContext(latestContext);
26175
+ reviewedHead = persistedAnchor ? rehydrateHeadAnchor(persistedAnchor) : void 0;
26176
+ } catch {
26177
+ continue;
26178
+ }
26179
+ if (!reviewedHead || currentHead !== reviewedHead) continue;
26180
+ let parsed;
26181
+ try {
26182
+ parsed = parseVerdictReport(await readFile(latestReport.path, "utf8"));
26183
+ } catch {
26184
+ continue;
26185
+ }
26186
+ if (!parsed) continue;
26187
+ const reviewSession = `agent-${issueId.toLowerCase()}-review`;
26188
+ const sessionAlive = sessionExistsSync(reviewSession);
26189
+ const paneDead = sessionAlive ? await Effect.runPromise(isPaneDead(reviewSession)).catch(() => true) : true;
26190
+ if (sessionAlive && !paneDead) {
26191
+ const lastNudged = pendingVerdictNudges.get(latestDir);
26192
+ if (!lastNudged) {
26193
+ const notes = parsed.topBlocker || `See ${latestReport.filename}`;
26194
+ const nudge = `Your review verdict is already written on disk but review status is still pending. 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${buildReviewCompletionCommand(issueId, parsed.verdict, notes, basename$1(latestDir))}\n\nRun this command NOW. Do not write any other response before executing it.`;
26195
+ try {
26196
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
26197
+ await messageAgent(reviewSession, nudge);
26198
+ pendingVerdictNudges.set(latestDir, now);
26199
+ const action = `Nudged ${reviewSession} to apply pending ${parsed.verdict} verdict from ${latestReport.filename}`;
26200
+ actions.push(action);
26201
+ console.log(`[deacon] ${action}`);
26202
+ } catch (err) {
26203
+ console.error(`[deacon] Failed to nudge ${reviewSession}:`, err instanceof Error ? err.message : String(err));
26204
+ }
26205
+ continue;
26206
+ }
26207
+ if (now - lastNudged < NUDGE_GRACE_MS) continue;
26208
+ }
26209
+ const attribution = `applied by deacon sweep from on-disk ${latestReport.filename}`;
26210
+ const reviewNotes = parsed.topBlocker ? `${parsed.topBlocker} — ${attribution}` : `Review ${parsed.verdict} ${attribution}`;
26211
+ setReviewStatusSync(issueId, {
26212
+ reviewStatus: parsed.verdict,
26213
+ reviewNotes,
26214
+ ...(parsed.verdict === "passed" || parsed.verdict === "blocked") && currentHead ? { reviewedAtCommit: currentHead } : {}
26215
+ });
26216
+ if (parsed.verdict === "blocked") try {
26217
+ await Effect.runPromise(deliverReviewVerdictFeedback({
26218
+ issueId,
26219
+ verdict: "blocked",
26220
+ notes: parsed.topBlocker || reviewNotes,
26221
+ workspacePath: wsPath,
26222
+ prUrl: status.prUrl,
26223
+ runId: basename$1(latestDir)
26224
+ }));
26225
+ } catch (err) {
26226
+ console.error(`[deacon] Failed to deliver reconciled review verdict for ${issueId}:`, err instanceof Error ? err.message : String(err));
26227
+ }
26228
+ pendingVerdictNudges.delete(latestDir);
26229
+ const action = `reconcileUnappliedReviewVerdicts deacon sweep applied ${parsed.verdict} for ${issueId} from ${latestReport.filename}`;
26230
+ actions.push(action);
26231
+ emitActivityEntrySync({
26232
+ source: "cloister",
26233
+ level: "warn",
26234
+ message: action,
26235
+ issueId
26236
+ });
26237
+ console.log(`[deacon] ${action}`);
26238
+ } catch (error) {
26239
+ const msg = error instanceof Error ? error.message : String(error);
26240
+ console.error(`[deacon] Error reconciling unapplied review verdict for ${issueId}:`, msg);
26241
+ }
26242
+ }
26243
+ } catch (error) {
26244
+ const msg = error instanceof Error ? error.message : String(error);
26245
+ console.error("[deacon] Error reconciling unapplied review verdicts:", msg);
26061
26246
  }
26062
- if (status.lastVerifiedCommit && context.headSha && context.headSha !== status.lastVerifiedCommit) return false;
26063
- return true;
26247
+ return actions;
26064
26248
  }
26065
26249
  async function checkCompletedButUnsignaledReviews() {
26066
26250
  const actions = [];
@@ -26077,20 +26261,22 @@ async function checkCompletedButUnsignaledReviews() {
26077
26261
  const reviewBaseDir = join$1(wsPath, ".pan", "review");
26078
26262
  if (!existsSync(reviewBaseDir)) continue;
26079
26263
  let latestDir = null;
26264
+ let latestReport = null;
26080
26265
  let latestMtime = 0;
26081
26266
  for (const entry of readdirSync(reviewBaseDir)) {
26082
26267
  if (!entry.startsWith(`agent-${issueId.toLowerCase()}-review`)) continue;
26083
26268
  const dirPath = join$1(reviewBaseDir, entry);
26084
- const synthPath = join$1(dirPath, "synthesis.md");
26085
- if (!existsSync(synthPath)) continue;
26086
- const mtime = statSync(synthPath).mtimeMs;
26269
+ const report = findVerdictReport(dirPath);
26270
+ if (!report) continue;
26271
+ const mtime = statSync(report.path).mtimeMs;
26087
26272
  if (!isSynthesisForActiveReviewRun(dirPath, status, mtime)) continue;
26088
26273
  if (mtime > latestMtime) {
26089
26274
  latestMtime = mtime;
26090
26275
  latestDir = dirPath;
26276
+ latestReport = report;
26091
26277
  }
26092
26278
  }
26093
- if (!latestDir) continue;
26279
+ if (!latestDir || !latestReport) continue;
26094
26280
  if (now - latestMtime < SYNTHESIS_SETTLE_MS) continue;
26095
26281
  const lastNudged = unsignaledReviewNudges.get(latestDir);
26096
26282
  if (lastNudged && now - lastNudged < 1800 * 1e3) continue;
@@ -26099,40 +26285,31 @@ async function checkCompletedButUnsignaledReviews() {
26099
26285
  const paneDead = sessionAlive ? await Effect.runPromise(isPaneDead(reviewSession)).catch(() => true) : true;
26100
26286
  const activeReviewState = sessionAlive && !paneDead ? getAgentStateSync(reviewSession) : null;
26101
26287
  if (activeReviewState?.reviewRunId && latestDir !== join$1(reviewBaseDir, activeReviewState.reviewRunId)) continue;
26102
- const synthesisPath = join$1(latestDir, "synthesis.md");
26103
- let verdict = null;
26104
- let topBlocker = "";
26288
+ let parsed;
26105
26289
  try {
26106
- const content = readFileSync(synthesisPath, "utf8");
26107
- const verdictLine = content.match(/## Verdict:\s*(.+)/i);
26108
- if (verdictLine) {
26109
- const v = verdictLine[1].trim().toUpperCase();
26110
- if (v === "PASSED") verdict = "passed";
26111
- else if (v === "CHANGES REQUESTED") verdict = "blocked";
26112
- else if (v === "FAILED") verdict = "failed";
26113
- }
26114
- const blockerMatch = content.match(/## Blocking Findings\s*\n\s*###\s*\[[^\]]+\]\s*(.+)/);
26115
- if (blockerMatch) topBlocker = blockerMatch[1].slice(0, 120);
26290
+ parsed = parseVerdictReport(readFileSync(latestReport.path, "utf8"));
26116
26291
  } catch {
26117
26292
  continue;
26118
26293
  }
26119
- if (!verdict) continue;
26294
+ if (!parsed) continue;
26295
+ const { verdict, topBlocker } = parsed;
26120
26296
  if (sessionAlive && !paneDead) {
26121
26297
  if (lastNudged) {
26122
26298
  setReviewStatusSync(issueId, {
26123
26299
  reviewStatus: verdict,
26124
- reviewNotes: topBlocker || `Review auto-completed by deacon: ${verdict} (agent alive but unresponsive after nudge, synthesis exists)`
26300
+ reviewNotes: topBlocker || `Review auto-completed by deacon: ${verdict} (agent alive but unresponsive after nudge, ${latestReport.filename} exists)`
26125
26301
  });
26126
- actions.push(`Auto-completed review for ${issueId}: ${verdict} (alive but unresponsive after nudge, synthesis written ${Math.round((now - latestMtime) / 6e4)}min ago)`);
26302
+ actions.push(`Auto-completed review for ${issueId}: ${verdict} (alive but unresponsive after nudge, ${latestReport.filename} written ${Math.round((now - latestMtime) / 6e4)}min ago)`);
26127
26303
  console.log(`[deacon] Auto-completed review for ${issueId}: ${verdict} (alive but unresponsive after nudge)`);
26128
26304
  continue;
26129
26305
  }
26130
- 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"}"` : ""} --run-id "${basename$1(latestDir)}"`}\n\nRun this command NOW. Do not write any other response before executing it.`;
26306
+ const cmd = buildReviewCompletionCommand(issueId, verdict, topBlocker || `See ${latestReport.filename}`, basename$1(latestDir));
26307
+ const nudge = `Your review verdict in ${latestReport.filename} 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${cmd}\n\nRun this command NOW. Do not write any other response before executing it.`;
26131
26308
  try {
26132
- const { messageAgent } = await import("./agents-ePFVoZbu.js");
26309
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
26133
26310
  await messageAgent(reviewSession, nudge);
26134
26311
  unsignaledReviewNudges.set(latestDir, now);
26135
- actions.push(`Nudged ${reviewSession} to signal ${verdict} (synthesis written ${Math.round((now - latestMtime) / 6e4)}min ago)`);
26312
+ actions.push(`Nudged ${reviewSession} to signal ${verdict} (${latestReport.filename} written ${Math.round((now - latestMtime) / 6e4)}min ago)`);
26136
26313
  console.log(`[deacon] Nudged ${reviewSession} to signal ${verdict}`);
26137
26314
  } catch (err) {
26138
26315
  console.error(`[deacon] Failed to nudge ${reviewSession}:`, err instanceof Error ? err.message : String(err));
@@ -26140,9 +26317,9 @@ async function checkCompletedButUnsignaledReviews() {
26140
26317
  } else {
26141
26318
  setReviewStatusSync(issueId, {
26142
26319
  reviewStatus: verdict,
26143
- reviewNotes: topBlocker || `Review auto-completed by deacon: ${verdict} (agent dead, synthesis exists)`
26320
+ reviewNotes: topBlocker || `Review auto-completed by deacon: ${verdict} (agent dead, ${latestReport.filename} exists)`
26144
26321
  });
26145
- actions.push(`Auto-completed review for ${issueId}: ${verdict} (dead agent, synthesis written ${Math.round((now - latestMtime) / 6e4)}min ago)`);
26322
+ actions.push(`Auto-completed review for ${issueId}: ${verdict} (dead agent, ${latestReport.filename} written ${Math.round((now - latestMtime) / 6e4)}min ago)`);
26146
26323
  console.log(`[deacon] Auto-completed review for ${issueId}: ${verdict} (dead agent)`);
26147
26324
  }
26148
26325
  }
@@ -26157,6 +26334,7 @@ async function checkCompletedButUnsignaledReviews() {
26157
26334
  init_context_overflow();
26158
26335
  init_agents$1();
26159
26336
  init_review_verdict_feedback();
26337
+ init_review_verdict_report();
26160
26338
  init_paths();
26161
26339
  init_review_status();
26162
26340
  init_persistent_logger();
@@ -26238,7 +26416,7 @@ async function respawnIdleReviewer(state, agentId) {
26238
26416
  return false;
26239
26417
  }
26240
26418
  try {
26241
- const { spawnReviewSubRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
26419
+ const { spawnReviewSubRoleForIssue } = await import("./review-agent-CD3RQ-tc.js");
26242
26420
  const contextManifestPath = join$1(dirname$1(outputPath), "context.json");
26243
26421
  const result = await Effect.runPromise(spawnReviewSubRoleForIssue({
26244
26422
  issueId: state.issueId,
@@ -26276,7 +26454,7 @@ async function nudgeSynthesisForCompleteReviewerReports(states) {
26276
26454
  const status = getReviewStatusSync(state.issueId);
26277
26455
  if (!status || status.reviewStatus !== "reviewing") continue;
26278
26456
  const reviewDir = join$1(state.workspace, ".pan", "review", state.reviewRunId);
26279
- const synthesisAlreadyWritten = existsSync(join$1(reviewDir, "synthesis.md"));
26457
+ const synthesisAlreadyWritten = findVerdictReport(reviewDir) !== null;
26280
26458
  const startedMs = Date.parse(state.startedAt);
26281
26459
  const readyLines = [];
26282
26460
  const reports = [];
@@ -26324,7 +26502,7 @@ async function nudgeSynthesisForCompleteReviewerReports(states) {
26324
26502
  writeFileSync(join$1(reviewDir, "synthesis.md"), synthesis.body);
26325
26503
  let fallbackHead;
26326
26504
  try {
26327
- const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-Xg4PFN45.js");
26505
+ const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-C31x1lpE.js");
26328
26506
  fallbackHead = await snapshotWorkspaceHeadsPromise(state.issueId, state.workspace);
26329
26507
  } catch {}
26330
26508
  const anchoredVerdicts = Object.fromEntries(Object.entries(synthesis.reviewerVerdicts).map(([subRole, v]) => [subRole, {
@@ -26363,7 +26541,7 @@ async function nudgeSynthesisForCompleteReviewerReports(states) {
26363
26541
  "Read the four reports, write synthesis.md, then signal review status exactly as roles/review.md instructs."
26364
26542
  ].join("\n");
26365
26543
  try {
26366
- const { messageAgent } = await import("./agents-ePFVoZbu.js");
26544
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
26367
26545
  await messageAgent(state.id, message);
26368
26546
  reviewReportsPresentNudges.set(nudgeKey, now);
26369
26547
  const action = `Nudged ${state.id} to synthesize from ${REVIEW_SUB_ROLES.length} reviewer reports`;
@@ -26449,7 +26627,7 @@ async function monitorReviewConvoySignals() {
26449
26627
  if (!signal) continue;
26450
26628
  const message = signal === "ready" ? `REVIEWER_READY ${state.reviewSubRole} ${outputPath}` : signal === "timeout" ? `REVIEWER_TIMEOUT ${state.reviewSubRole} ${reason}` : `REVIEWER_FAILED ${state.reviewSubRole} ${reason}`;
26451
26629
  try {
26452
- const { messageAgent } = await import("./agents-ePFVoZbu.js");
26630
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
26453
26631
  await messageAgent(state.reviewSynthesisAgentId, message);
26454
26632
  state.reviewMonitorSignaled = signal;
26455
26633
  saveAgentStateSync(state);
@@ -26457,7 +26635,7 @@ async function monitorReviewConvoySignals() {
26457
26635
  actions.push(action);
26458
26636
  logDeaconEventSync(`monitorReviewConvoySignals: ${action}`);
26459
26637
  if (signal === "ready") try {
26460
- const { notifyPipelineSync } = await import("./pipeline-notifier-DT6xLFao.js");
26638
+ const { notifyPipelineSync } = await import("./pipeline-notifier-CO9rxJgB.js");
26461
26639
  notifyPipelineSync({
26462
26640
  type: "reviewer_completed",
26463
26641
  issueId: state.issueId,
@@ -26465,7 +26643,7 @@ async function monitorReviewConvoySignals() {
26465
26643
  });
26466
26644
  } catch {}
26467
26645
  else if (signal === "timeout") try {
26468
- const { notifyPipelineSync } = await import("./pipeline-notifier-DT6xLFao.js");
26646
+ const { notifyPipelineSync } = await import("./pipeline-notifier-CO9rxJgB.js");
26469
26647
  notifyPipelineSync({
26470
26648
  type: "reviewer_timed_out",
26471
26649
  issueId: state.issueId,
@@ -26565,7 +26743,7 @@ const FORK_CACHE_CHECK_DELAY_MS = 180 * 1e3;
26565
26743
  async function checkStalledReviewDiscovery() {
26566
26744
  const actions = [];
26567
26745
  try {
26568
- const { listAgentStates } = await import("./agents-ePFVoZbu.js");
26746
+ const { listAgentStates } = await import("./agents-IPSa5kzn.js");
26569
26747
  const states = listAgentStates();
26570
26748
  const now = Date.now();
26571
26749
  for (const state of states) {
@@ -26574,7 +26752,7 @@ async function checkStalledReviewDiscovery() {
26574
26752
  const aged = Number.isFinite(startedMs) && now - startedMs > 48e4;
26575
26753
  const dead = !await Effect.runPromise(sessionExists(state.id)).catch(() => false) || await Effect.runPromise(isPaneDead(state.id)).catch(() => true);
26576
26754
  if (!aged && !dead) continue;
26577
- const { handleReviewDiscoveryReady } = await import("./review-agent-BTCNkq2h.js");
26755
+ const { handleReviewDiscoveryReady } = await import("./review-agent-CD3RQ-tc.js");
26578
26756
  const result = await handleReviewDiscoveryReady(state.issueId, { source: dead ? "deacon-backstop (parent dead)" : "deacon-backstop (discovery timeout)" });
26579
26757
  actions.push(result.message);
26580
26758
  logDeaconEventSync(`checkStalledReviewDiscovery: ${result.message}`);
@@ -26597,8 +26775,8 @@ async function checkStalledReviewDiscovery() {
26597
26775
  async function checkStalledReviewParents() {
26598
26776
  const actions = [];
26599
26777
  try {
26600
- const { listAgentStates, markAgentStoppedState } = await import("./agents-ePFVoZbu.js");
26601
- const { PARENT_REVIEW_TIMEOUT_MS } = await import("./review-agent-BTCNkq2h.js");
26778
+ const { listAgentStates, markAgentStoppedState } = await import("./agents-IPSa5kzn.js");
26779
+ const { PARENT_REVIEW_TIMEOUT_MS } = await import("./review-agent-CD3RQ-tc.js");
26602
26780
  const states = listAgentStates();
26603
26781
  const now = Date.now();
26604
26782
  for (const state of states) {
@@ -26622,7 +26800,7 @@ async function checkStalledReviewParents() {
26622
26800
  actions.push(message);
26623
26801
  logDeaconEventSync(message);
26624
26802
  try {
26625
- const { emitActivityEntrySync } = await import("./activity-logger-CMthG6Vd.js");
26803
+ const { emitActivityEntrySync } = await import("./activity-logger-K7FYGF_z.js");
26626
26804
  emitActivityEntrySync({
26627
26805
  source: "review",
26628
26806
  level: "warn",
@@ -26647,9 +26825,9 @@ async function checkStalledReviewParents() {
26647
26825
  async function checkReviewForkCacheMisses() {
26648
26826
  const actions = [];
26649
26827
  try {
26650
- const { listAgentStates, saveAgentState } = await import("./agents-ePFVoZbu.js");
26651
- const { readEventsSync } = await import("./events-CF8QDbuV.js");
26652
- const { emitActivityEntrySync } = await import("./activity-logger-CMthG6Vd.js");
26828
+ const { listAgentStates, saveAgentState } = await import("./agents-IPSa5kzn.js");
26829
+ const { readEventsSync } = await import("./events-CCkFWa7X.js");
26830
+ const { emitActivityEntrySync } = await import("./activity-logger-K7FYGF_z.js");
26653
26831
  const states = listAgentStates();
26654
26832
  const now = Date.now();
26655
26833
  for (const parent of states) {
@@ -27118,7 +27296,6 @@ function startBootReconciliation(options = {}) {
27118
27296
  }
27119
27297
  //#endregion
27120
27298
  //#region ../../lib/agents/pinned-launch.ts
27121
- init_io();
27122
27299
  init_dag();
27123
27300
  init_agent_state();
27124
27301
  function parseFlagValue(content, flag) {
@@ -27511,7 +27688,7 @@ async function nudgeStalledResumeWorkAgents() {
27511
27688
  const message = buildStalledResumePrompt(state);
27512
27689
  if (!message) continue;
27513
27690
  try {
27514
- const { messageAgent } = await import("./agents-ePFVoZbu.js");
27691
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
27515
27692
  await messageAgent(agentId, message);
27516
27693
  recordCooldown(agentId, ".last-stalled-resume-nudge");
27517
27694
  const action = `Re-sent stalled resume prompt to ${agentId} (${state.issueId})`;
@@ -27625,7 +27802,7 @@ async function nudgeIdleWorkAgentsWithOpenBeads() {
27625
27802
  "Continue the per-item workflow without asking — claim it (`pan task claim <item-id>`), implement, commit, push, then complete it through `pan task done <item-id>`. 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."
27626
27803
  ].join("\n");
27627
27804
  try {
27628
- const { messageAgent } = await import("./agents-ePFVoZbu.js");
27805
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
27629
27806
  await messageAgent(agentId, message);
27630
27807
  writeFileSync(join$1(getAgentDir(agentId), ".last-bead-nudge"), String(Date.now()), "utf-8");
27631
27808
  const action = `Nudged idle ${agentId} (${state.issueId}) — ${openTasks.length} ready task(s)`;
@@ -28055,6 +28232,290 @@ function shouldRunRecoveryJanitor(janitor, patrolCycle) {
28055
28232
  return patrolCycle % (janitor === "feedback" ? 5 : 60) === 0;
28056
28233
  }
28057
28234
  //#endregion
28235
+ //#region ../../lib/cloister/pending-promotion-reconciler.ts
28236
+ init_activity_logger();
28237
+ init_internal_token();
28238
+ init_projects();
28239
+ init_io();
28240
+ init_issue_closed();
28241
+ const MARKER_GRACE_MS = 12e4;
28242
+ const MARKERLESS_SPEC_GRACE_MS = 5 * 6e4;
28243
+ const NEEDS_YOU_ATTEMPTS = 5;
28244
+ function normalizeIssueId(value) {
28245
+ return typeof value === "string" && /^[A-Za-z]+-\d+$/.test(value.trim()) ? value.trim().toUpperCase() : null;
28246
+ }
28247
+ function issueIdFromWorkspaceName(name) {
28248
+ const match = name.match(/^feature-([a-z]+-\d+)$/i);
28249
+ return match ? match[1].toUpperCase() : null;
28250
+ }
28251
+ function parseDate(value) {
28252
+ if (typeof value !== "string") return null;
28253
+ const parsed = Date.parse(value);
28254
+ return Number.isFinite(parsed) ? parsed : null;
28255
+ }
28256
+ function parseMarker(value, expectedIssueId) {
28257
+ if (!value || typeof value !== "object") return null;
28258
+ const marker = value;
28259
+ const issueId = normalizeIssueId(marker["issueId"]);
28260
+ if (marker["version"] !== "1" || issueId !== expectedIssueId) return null;
28261
+ if (typeof marker["canonicalFilename"] !== "string" || marker["canonicalFilename"].length === 0) return null;
28262
+ if (parseDate(marker["finalizedAt"]) === null) return null;
28263
+ return {
28264
+ version: "1",
28265
+ issueId,
28266
+ canonicalFilename: marker["canonicalFilename"],
28267
+ noPrd: marker["noPrd"] === true,
28268
+ autoSpawnRequested: marker["autoSpawnRequested"] === true,
28269
+ finalizedAt: marker["finalizedAt"],
28270
+ lastError: typeof marker["lastError"] === "string" ? marker["lastError"] : "complete-planning failed",
28271
+ lastAttemptAt: typeof marker["lastAttemptAt"] === "string" ? marker["lastAttemptAt"] : marker["finalizedAt"],
28272
+ patrolAttempts: Number.isInteger(marker["patrolAttempts"]) && Number(marker["patrolAttempts"]) >= 0 ? Number(marker["patrolAttempts"]) : 0
28273
+ };
28274
+ }
28275
+ async function readMarker(path, issueId) {
28276
+ try {
28277
+ return parseMarker(JSON.parse(await readFile(path, "utf-8")), issueId);
28278
+ } catch {
28279
+ return null;
28280
+ }
28281
+ }
28282
+ async function loadProjects(projects) {
28283
+ if (projects) return projects;
28284
+ return Effect.runPromise(listProjects().pipe(Effect.catch(() => Effect.succeed([]))));
28285
+ }
28286
+ async function defaultFindPromotedSpec(projectPath, issueId) {
28287
+ return Effect.runPromise(findSpecByIssue(projectPath, issueId).pipe(Effect.catch(() => Effect.succeed(null))));
28288
+ }
28289
+ function internalDashboardOrigin() {
28290
+ const port = Number.parseInt(process.env["API_PORT"] ?? process.env["PORT"] ?? "3011", 10);
28291
+ return process.env["OVERDECK_INTERNAL_DASHBOARD_URL"] ?? `http://127.0.0.1:${port}`;
28292
+ }
28293
+ function logDiagnostic(kind, info = {}) {
28294
+ console.debug(`[pending-promotion-reconciler] ${kind}`, info);
28295
+ }
28296
+ function markerPathForWorkspace(workspacePath) {
28297
+ return join(workspacePath, WORKSPACE_RUNTIME_DIRNAME, PENDING_PROMOTION_FILENAME);
28298
+ }
28299
+ function canonicalFilenameFromSpec(doc) {
28300
+ const filename = doc.plan.metadata?.canonicalFilename;
28301
+ return typeof filename === "string" && filename.length > 0 ? filename : null;
28302
+ }
28303
+ async function writeMarker(path, marker) {
28304
+ await mkdir(dirname(path), { recursive: true });
28305
+ const tmp = `${path}.tmp`;
28306
+ await writeFile(tmp, JSON.stringify(marker, null, 2) + "\n", "utf-8");
28307
+ await rename(tmp, path);
28308
+ }
28309
+ const defaultMarkerIo = {
28310
+ read: readMarker,
28311
+ write: writeMarker,
28312
+ remove: (path) => rm(path, { force: true })
28313
+ };
28314
+ async function findPendingPromotionCandidates(options = {}) {
28315
+ const projects = await loadProjects(options.projects);
28316
+ const now = (options.clock ?? (() => /* @__PURE__ */ new Date()))().getTime();
28317
+ const findPromotedSpec = options.findPromotedSpec ?? defaultFindPromotedSpec;
28318
+ const markerIo = options.markerIo ?? defaultMarkerIo;
28319
+ const candidates = [];
28320
+ for (const { key, config } of projects) {
28321
+ const workspacesDir = join(config.path, "workspaces");
28322
+ const workspaces = await readdir(workspacesDir, { withFileTypes: true }).catch(() => []);
28323
+ for (const workspace of workspaces) {
28324
+ if (!workspace.isDirectory() || workspace.name.endsWith("-strike")) continue;
28325
+ const issueId = issueIdFromWorkspaceName(workspace.name);
28326
+ if (!issueId) continue;
28327
+ const workspacePath = join(workspacesDir, workspace.name);
28328
+ const markerPath = markerPathForWorkspace(workspacePath);
28329
+ const marker = await markerIo.read(markerPath, issueId);
28330
+ const specPath = findWorkspaceDraftPlanSync(workspacePath);
28331
+ if (!specPath) continue;
28332
+ let spec;
28333
+ try {
28334
+ spec = readPlanSync(specPath);
28335
+ } catch {
28336
+ logDiagnostic("candidate-skipped", {
28337
+ issueId,
28338
+ reason: "spec-unreadable"
28339
+ });
28340
+ continue;
28341
+ }
28342
+ if (spec.plan.status !== "proposed" || normalizeIssueId(spec.plan.id) !== issueId) continue;
28343
+ if (marker) {
28344
+ candidates.push({
28345
+ projectKey: key,
28346
+ projectName: config.name,
28347
+ projectPath: config.path,
28348
+ workspacePath,
28349
+ issueId,
28350
+ specPath,
28351
+ markerPath,
28352
+ marker,
28353
+ canonicalFilename: marker.canonicalFilename,
28354
+ noPrd: marker.noPrd,
28355
+ autoSpawnRequested: marker.autoSpawnRequested,
28356
+ finalizedAt: marker.finalizedAt,
28357
+ patrolAttempts: marker.patrolAttempts
28358
+ });
28359
+ continue;
28360
+ }
28361
+ if (spec.plan.metadata?.promotionIntent === "manual") continue;
28362
+ const specInfo = await stat$1(specPath).catch(() => null);
28363
+ if (!specInfo || now - specInfo.mtimeMs < MARKERLESS_SPEC_GRACE_MS) continue;
28364
+ if (await findPromotedSpec(config.path, issueId)) continue;
28365
+ const canonicalFilename = canonicalFilenameFromSpec(spec);
28366
+ if (!canonicalFilename) {
28367
+ logDiagnostic("candidate-skipped", {
28368
+ issueId,
28369
+ reason: "canonical-filename-missing"
28370
+ });
28371
+ continue;
28372
+ }
28373
+ candidates.push({
28374
+ projectKey: key,
28375
+ projectName: config.name,
28376
+ projectPath: config.path,
28377
+ workspacePath,
28378
+ issueId,
28379
+ specPath,
28380
+ markerPath,
28381
+ marker: null,
28382
+ canonicalFilename,
28383
+ noPrd: false,
28384
+ autoSpawnRequested: false,
28385
+ finalizedAt: specInfo.mtime.toISOString(),
28386
+ patrolAttempts: 0
28387
+ });
28388
+ }
28389
+ }
28390
+ return candidates;
28391
+ }
28392
+ function parseResponseBody(text) {
28393
+ try {
28394
+ const parsed = JSON.parse(text);
28395
+ return parsed && typeof parsed === "object" ? parsed : {};
28396
+ } catch {
28397
+ return {};
28398
+ }
28399
+ }
28400
+ function responseError(status, body, text) {
28401
+ if (typeof body["error"] === "string") return body["error"];
28402
+ if (typeof body["message"] === "string") return body["message"];
28403
+ return text.slice(0, 200) || `complete-planning returned HTTP ${status}`;
28404
+ }
28405
+ function responseStillPending(status, body) {
28406
+ return status === 202 || body["inFlight"] === true || typeof body["skipped"] === "string";
28407
+ }
28408
+ async function reconcilePendingPromotions(options = {}) {
28409
+ const now = (options.clock ?? (() => /* @__PURE__ */ new Date()))();
28410
+ const nowMs = now.getTime();
28411
+ const fetchImpl = options.fetch ?? fetch;
28412
+ const dashboardOrigin = options.dashboardOrigin ?? internalDashboardOrigin();
28413
+ const internalToken = (options.getInternalToken ?? getInternalTokenSync)();
28414
+ const findPromotedSpec = options.findPromotedSpec ?? defaultFindPromotedSpec;
28415
+ const isClosed = options.isClosed ?? ((issueId) => isIssueClosed(issueId));
28416
+ const recordNeedsYou = options.recordNeedsYou ?? recordDeadEndNeedsYou;
28417
+ const emitActivity = options.emitActivity ?? emitActivityEntrySync;
28418
+ const markerIo = options.markerIo ?? defaultMarkerIo;
28419
+ const candidates = await findPendingPromotionCandidates({
28420
+ ...options,
28421
+ clock: () => now,
28422
+ findPromotedSpec,
28423
+ markerIo
28424
+ });
28425
+ const actions = [];
28426
+ for (const candidate of candidates) {
28427
+ if (await isClosed(candidate.issueId)) {
28428
+ logDiagnostic("candidate-skipped", {
28429
+ issueId: candidate.issueId,
28430
+ reason: "closed"
28431
+ });
28432
+ continue;
28433
+ }
28434
+ if (await findPromotedSpec(candidate.projectPath, candidate.issueId)) {
28435
+ await markerIo.remove(candidate.markerPath);
28436
+ actions.push(`Cleared resolved pending-promotion marker for ${candidate.issueId}`);
28437
+ continue;
28438
+ }
28439
+ const finalizedAtMs = parseDate(candidate.finalizedAt);
28440
+ if (finalizedAtMs === null || nowMs - finalizedAtMs < MARKER_GRACE_MS) {
28441
+ logDiagnostic("candidate-skipped", {
28442
+ issueId: candidate.issueId,
28443
+ reason: "grace-window"
28444
+ });
28445
+ continue;
28446
+ }
28447
+ let response = null;
28448
+ let body = {};
28449
+ let error = null;
28450
+ try {
28451
+ response = await fetchImpl(new URL(`/api/issues/${encodeURIComponent(candidate.issueId)}/complete-planning`, dashboardOrigin), {
28452
+ method: "POST",
28453
+ headers: {
28454
+ "content-type": "application/json",
28455
+ origin: dashboardOrigin,
28456
+ ...internalToken ? { [INTERNAL_TOKEN_HEADER]: internalToken } : {}
28457
+ },
28458
+ body: JSON.stringify({
28459
+ noPrd: candidate.noPrd,
28460
+ startedBy: "pending-promotion-reconciler"
28461
+ })
28462
+ });
28463
+ const text = await response.text();
28464
+ body = parseResponseBody(text);
28465
+ if (responseStillPending(response.status, body)) {
28466
+ logDiagnostic("promotion-deferred", {
28467
+ issueId: candidate.issueId,
28468
+ status: response.status,
28469
+ body
28470
+ });
28471
+ continue;
28472
+ }
28473
+ if (response.status !== 200 || !response.ok || body["success"] === false || body["ok"] === false) error = responseError(response.status, body, text);
28474
+ } catch (cause) {
28475
+ error = cause instanceof Error ? cause.message : String(cause);
28476
+ }
28477
+ if (!error && response?.status === 200) {
28478
+ await markerIo.remove(candidate.markerPath);
28479
+ const action = `Recovered pending planning promotion for ${candidate.issueId}`;
28480
+ actions.push(action);
28481
+ emitActivity({
28482
+ source: "cloister",
28483
+ level: "success",
28484
+ issueId: candidate.issueId,
28485
+ message: `${candidate.issueId} planning promotion recovered automatically`,
28486
+ details: JSON.stringify({
28487
+ issueId: candidate.issueId,
28488
+ workspacePath: candidate.workspacePath,
28489
+ reconciler: "pending-promotion",
28490
+ timestamp: now.toISOString()
28491
+ })
28492
+ });
28493
+ continue;
28494
+ }
28495
+ const nextAttempts = candidate.patrolAttempts + 1;
28496
+ const lastError = error ?? "complete-planning did not converge";
28497
+ await markerIo.write(candidate.markerPath, {
28498
+ version: "1",
28499
+ issueId: candidate.issueId,
28500
+ canonicalFilename: candidate.canonicalFilename,
28501
+ noPrd: candidate.noPrd,
28502
+ autoSpawnRequested: candidate.autoSpawnRequested,
28503
+ finalizedAt: candidate.finalizedAt,
28504
+ lastError,
28505
+ lastAttemptAt: now.toISOString(),
28506
+ patrolAttempts: nextAttempts
28507
+ });
28508
+ logDiagnostic("promotion-failed", {
28509
+ issueId: candidate.issueId,
28510
+ patrolAttempts: nextAttempts,
28511
+ error: lastError
28512
+ });
28513
+ actions.push(`Pending planning promotion for ${candidate.issueId} failed attempt ${nextAttempts}: ${lastError}`);
28514
+ if (nextAttempts >= NEEDS_YOU_ATTEMPTS) await recordNeedsYou(candidate.issueId, "pending-promotion", candidate.finalizedAt, `Planning promotion for ${candidate.issueId} has failed ${nextAttempts} patrol attempts. The finalized plan remains unpromoted. Run \`pan plan done ${candidate.issueId}\` to retry manually, then inspect the complete-planning error if it still fails.`);
28515
+ }
28516
+ return actions;
28517
+ }
28518
+ //#endregion
28058
28519
  //#region ../../lib/cloister/test-status-green-ci-reconciler.ts
28059
28520
  const terminalMergeStatuses = new Set([
28060
28521
  "merged",
@@ -28554,6 +29015,175 @@ async function cleanupOrphanedInspectSessions() {
28554
29015
  return actions;
28555
29016
  }
28556
29017
  //#endregion
29018
+ //#region ../../lib/cloister/deacon-verdict-fallback-sweep.ts
29019
+ init_test_verdict();
29020
+ init_review_status();
29021
+ init_review_status_record_sync();
29022
+ init_projects();
29023
+ init_recovery_trip();
29024
+ init_activity_logger();
29025
+ /**
29026
+ * Total time this sweep may spend waiting on warning delivery, across ALL issues.
29027
+ *
29028
+ * Bounding each request alone is not enough: the sweep visits issues serially,
29029
+ * so N stranded fallbacks against a stalled dashboard would cost N × the
29030
+ * per-request deadline — six would consume a whole 60s patrol interval and dozens
29031
+ * would hold it for many minutes, starving every later issue and later patrol
29032
+ * phase while the patrol heartbeat still reported healthy. The systemic
29033
+ * degradation that strands several verdicts at once is exactly the state that
29034
+ * makes every loopback request hit its deadline, so the budget is shared.
29035
+ */
29036
+ const SWEEP_WARNING_BUDGET_MS = 30 * 1e3;
29037
+ /**
29038
+ * Resolve `attempt`, or give up at `deadlineMs` and report `failed`.
29039
+ *
29040
+ * Abandoning a warning is always safe: nothing is marked warned on `failed`, and
29041
+ * a later retry carries the same idempotency key, so a call that lands after we
29042
+ * stopped waiting returns `duplicate` rather than emitting a second warning.
29043
+ */
29044
+ async function withWarningDeadline(attempt, deadlineMs) {
29045
+ let timer;
29046
+ try {
29047
+ return await Promise.race([attempt, new Promise((resolve) => {
29048
+ timer = setTimeout(() => {
29049
+ resolve("failed");
29050
+ }, deadlineMs);
29051
+ })]);
29052
+ } finally {
29053
+ if (timer) clearTimeout(timer);
29054
+ }
29055
+ }
29056
+ /**
29057
+ * Episodes already warned about in THIS process, keyed by recovery path + issue
29058
+ * + the fallback's own `updatedAt`.
29059
+ *
29060
+ * Only an optimisation, never the dedupe of record: it saves re-querying the
29061
+ * event log every patrol. Correctness across restarts comes from the two
29062
+ * durable planes — the open recovery trip, and `emitActivityEntryOnce`'s
29063
+ * event-log check on the episode id. An episode is added here only after the
29064
+ * warning is confirmed durable, so a failed append is retried rather than
29065
+ * suppressed, and entries are dropped once the trip lands.
29066
+ */
29067
+ const warnedEpisodes = /* @__PURE__ */ new Set();
29068
+ /**
29069
+ * Describe a verdict conflict and the one action that reliably clears it.
29070
+ *
29071
+ * Deliberately does NOT hand out a `pan admin specialists done` command. That
29072
+ * command is not a general conflict resolver: `merge` takes passed|failed and
29073
+ * maps them to merged|failed (so the displayed `merged` is rejected), `inspect`
29074
+ * requires an `--item` this pipeline-level conflict cannot identify, `review`
29075
+ * does not accept `skipped`, verification has no specialist at all, and
29076
+ * re-signalling the value already in the journal writes no replacement fallback
29077
+ * — so the conflicting one survives and every later drain withholds it again.
29078
+ * A conflict can also span several gates, which one command cannot settle.
29079
+ *
29080
+ * A strictly newer review cycle is the only instruction correct for every gate
29081
+ * and every choice, so that is what the operator is told, along with what it
29082
+ * costs. A dedicated resolve-this-generation operation through the verdict write
29083
+ * door would let an operator adopt a specific written verdict instead; until
29084
+ * that exists, promising it here would be a lie.
29085
+ */
29086
+ function conflictMessage(issueId, conflicts, ageMinutes) {
29087
+ const detail = conflicts.map((c) => `${c.gate} (the record holds "${c.journalValue}", the workspace fallback holds "${c.fallbackValue}")`).join("; ");
29088
+ return `${issueId} — two different verdicts have been written for ${conflicts.length === 1 ? "one gate" : `${conflicts.length} gates`} and Overdeck cannot tell which is newer, so it refuses to choose: ${detail}. This has been unresolved for ${ageMinutes}min and will NOT clear on its own: the fold is withheld on every patrol, by design, so that neither written verdict is destroyed. An operator must decide. The one action that reliably clears it for every gate is to dispatch a strictly newer review cycle for ${issueId} — that supersedes the stranded fallback and re-runs the gates, rather than adopting either of the verdicts already written. Overdeck has no command today that adopts one specific written verdict, so do not expect a re-signal of an existing value to clear this.`;
29089
+ }
29090
+ async function lockOwnerDescription(issueId) {
29091
+ try {
29092
+ const resolved = resolveProjectFromIssueSync(issueId);
29093
+ if (!resolved) return "unknown writer";
29094
+ const project = getProjectSync(resolved.projectKey);
29095
+ if (!project) return "unknown writer";
29096
+ return (await readOwner(recordLockPath(project, issueId))).description;
29097
+ } catch {
29098
+ return "unknown writer";
29099
+ }
29100
+ }
29101
+ /**
29102
+ * Drain every pending workspace verdict fallback, and surface the ones that stay
29103
+ * stuck. Returns one action line per drain or escalation, for the patrol log.
29104
+ *
29105
+ * `budgetMs` bounds the total time spent waiting on warning delivery. The deacon
29106
+ * derives it from the resolved patrol interval so a shortened interval cannot be
29107
+ * overrun by the sweep.
29108
+ */
29109
+ async function sweepStrandedVerdictFallbacks(now = Date.now(), budgetMs = SWEEP_WARNING_BUDGET_MS) {
29110
+ const actions = [];
29111
+ let statuses;
29112
+ try {
29113
+ statuses = loadReviewStatuses();
29114
+ } catch {
29115
+ return actions;
29116
+ }
29117
+ const candidates = [];
29118
+ for (const [issueId, status] of Object.entries(statuses)) {
29119
+ if (status.mergeStatus === "merged" || status.closedOut) continue;
29120
+ try {
29121
+ const fallback = await readWorkspaceVerdictFallback(issueId);
29122
+ if (!fallback) continue;
29123
+ if (await drainWorkspaceVerdictFallback(issueId)) {
29124
+ actions.push(`Drained stranded verdict fallback for ${issueId}`);
29125
+ continue;
29126
+ }
29127
+ const ageMs = now - Date.parse(fallback.updatedAt);
29128
+ if (!Number.isFinite(ageMs) || ageMs < 6e5) continue;
29129
+ if (status.stuck || status.deaconIgnored) continue;
29130
+ const resolved = resolveProjectFromIssueSync(issueId);
29131
+ const workspacePath = resolved ? findWorkspacePath(resolved.projectPath, issueId.toLowerCase()) : null;
29132
+ if (!workspacePath) continue;
29133
+ const ageMinutes = Math.round(ageMs / 6e4);
29134
+ const conflicts = await findWorkspaceVerdictConflicts(issueId, fallback);
29135
+ const conflicted = conflicts.length > 0;
29136
+ const recoveryPath = conflicted ? "verdict-fallback-conflict" : "verdict-fallback-contention";
29137
+ const episode = `${recoveryPath}:${issueId}:${fallback.updatedAt}`;
29138
+ let message;
29139
+ let summary;
29140
+ if (conflicted) {
29141
+ message = conflictMessage(issueId, conflicts, ageMinutes);
29142
+ summary = `${issueId}: verdict conflict on ${conflicts.map((c) => c.gate).join(", ")} — needs operator adjudication`;
29143
+ } else {
29144
+ const owner = await lockOwnerDescription(issueId);
29145
+ message = `${issueId} — verdict fallback undrained for ${ageMinutes}min; the per-issue record lock is contended (current owner: ${owner}). The verdict is durable in the workspace fallback and folds automatically once the lock frees.`;
29146
+ summary = `${issueId}: verdict contended ${ageMinutes}min (lock owner: ${owner})`;
29147
+ }
29148
+ if ((await findRecoveryTrip(issueId, recoveryPath, fallback.updatedAt))?.open === true) {
29149
+ warnedEpisodes.delete(episode);
29150
+ continue;
29151
+ }
29152
+ candidates.push({
29153
+ issueId,
29154
+ workspacePath,
29155
+ recoveryPath,
29156
+ generation: fallback.updatedAt,
29157
+ episode,
29158
+ message,
29159
+ summary
29160
+ });
29161
+ } catch {}
29162
+ }
29163
+ const pending = candidates.filter((c) => !warnedEpisodes.has(c.episode));
29164
+ if (pending.length > 0) (await Promise.all(pending.map((candidate) => withWarningDeadline(emitActivityEntryOnce({
29165
+ id: `verdict-fallback:${candidate.episode}`,
29166
+ source: "cloister",
29167
+ level: "warn",
29168
+ issueId: candidate.issueId,
29169
+ message: candidate.message
29170
+ }), budgetMs).catch(() => "failed")))).forEach((outcome, index) => {
29171
+ const candidate = pending[index];
29172
+ if (outcome === "appended" || outcome === "duplicate") {
29173
+ warnedEpisodes.add(candidate.episode);
29174
+ if (outcome === "appended") actions.push(candidate.summary);
29175
+ } else actions.push(`${candidate.issueId}: verdict-fallback warning could not be confirmed — retrying next patrol`);
29176
+ });
29177
+ for (const candidate of candidates) try {
29178
+ const { emitNeedsYou } = await recordRecoveryFailure(candidate.workspacePath, candidate.issueId, candidate.recoveryPath, candidate.generation, 1);
29179
+ warnedEpisodes.delete(candidate.episode);
29180
+ if (emitNeedsYou) actions.push(`needs-you ${candidate.summary}`);
29181
+ } catch {
29182
+ actions.push(`${candidate.issueId}: ${candidate.recoveryPath} needs-you trip could not be recorded (record lock contended) — retrying next patrol`);
29183
+ }
29184
+ return actions;
29185
+ }
29186
+ //#endregion
28557
29187
  //#region ../../lib/cloister/deacon.ts
28558
29188
  /**
28559
29189
  * Cloister Deacon - Health Monitor for Specialist Agents
@@ -28580,7 +29210,6 @@ init_specialists();
28580
29210
  init_agents$1();
28581
29211
  init_tmux();
28582
29212
  init_issue_closed();
28583
- init_test_verdict();
28584
29213
  const execAsync = promisify$1(exec$1);
28585
29214
  promisify$1(execFile$1);
28586
29215
  /**
@@ -28843,8 +29472,8 @@ async function cleanupStaleAgentState() {
28843
29472
  */
28844
29473
  async function cleanupAbandonedFeedback() {
28845
29474
  const actions = [];
28846
- const { getReviewStatusSync } = await import("./review-status-Dma9SFaN.js");
28847
- const { clearFeedbackFiles } = await import("./feedback-writer-CoB9Z6aU.js");
29475
+ const { getReviewStatusSync } = await import("./review-status-B6wYcOtP.js");
29476
+ const { clearFeedbackFiles } = await import("./feedback-writer-CTSuA6lw.js");
28848
29477
  for (const { issueId, workspacePath } of listFeatureWorkspaces()) {
28849
29478
  const panFeedbackDir = join$1(workspacePath, ".pan", "feedback");
28850
29479
  if (!existsSync(panFeedbackDir)) continue;
@@ -28915,7 +29544,7 @@ async function handleOrphanReviewerSession(sessionName, sessions, creationTimes,
28915
29544
  if (!issueId) return null;
28916
29545
  const agentSession = `agent-${issueId.toLowerCase()}`;
28917
29546
  if (sessions.includes(agentSession)) return null;
28918
- const { getReviewStatusSync } = await import("./review-status-Dma9SFaN.js");
29547
+ const { getReviewStatusSync } = await import("./review-status-B6wYcOtP.js");
28919
29548
  try {
28920
29549
  if (getReviewStatusSync(issueId)?.reviewStatus === "reviewing") return null;
28921
29550
  } catch {}
@@ -29037,7 +29666,7 @@ async function checkOrphanedCompletions() {
29037
29666
  async function checkPendingTestDispatch() {
29038
29667
  const actions = [];
29039
29668
  try {
29040
- const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Dma9SFaN.js");
29669
+ const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-B6wYcOtP.js");
29041
29670
  const statuses = loadReviewStatuses();
29042
29671
  const now = Date.now();
29043
29672
  for (const [issueId, status] of Object.entries(statuses)) {
@@ -29070,7 +29699,7 @@ async function checkPendingTestDispatch() {
29070
29699
  console.log(`[deacon] ${issueId}: skipping test re-dispatch — issue is closed`);
29071
29700
  continue;
29072
29701
  }
29073
- const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
29702
+ const { resolveProjectFromIssueSync } = await import("./projects-WqMWCdpa.js");
29074
29703
  const resolved = resolveProjectFromIssueSync(issueId);
29075
29704
  if (!resolved) continue;
29076
29705
  const issueLower = issueId.toLowerCase();
@@ -29085,8 +29714,8 @@ async function checkPendingTestDispatch() {
29085
29714
  logDeaconEventSync(`checkPendingTestDispatch: deferred test for ${issueId} — advancing ceiling reached (PAN-1665) — ${describeRunningAgents()}`);
29086
29715
  continue;
29087
29716
  }
29088
- const { spawnRun } = await import("./agents-ePFVoZbu.js");
29089
- const { buildTestRolePrompt } = await import("./test-agent-queue-A_-p-i0I.js");
29717
+ const { spawnRun } = await import("./agents-IPSa5kzn.js");
29718
+ const { buildTestRolePrompt } = await import("./test-agent-queue-CWMq7oyG.js");
29090
29719
  try {
29091
29720
  const run = await spawnRun(issueId, "test", {
29092
29721
  workspace,
@@ -29162,6 +29791,8 @@ async function checkPendingTestDispatch() {
29162
29791
  * - Only honors an artifact newer than the current test dispatch (H3)
29163
29792
  */
29164
29793
  const unsignaledTestNudges = /* @__PURE__ */ new Map();
29794
+ /** PAN-3092: test dispatch generations already escalated — never nudged again. */
29795
+ const unsignaledTestEscalations = /* @__PURE__ */ new Set();
29165
29796
  async function checkCompletedButUnsignaledTests() {
29166
29797
  const actions = [];
29167
29798
  const TEST_SETTLE_MS = 300 * 1e3;
@@ -29184,13 +29815,13 @@ async function checkCompletedButUnsignaledTests() {
29184
29815
  const paneDead = sessionAlive ? await Effect.runPromise(isPaneDead(testSession)).catch(() => true) : true;
29185
29816
  const sessionLive = sessionAlive && !paneDead;
29186
29817
  const idle = sessionLive ? isAgentIdleForNudge(testSession, TEST_SETTLE_MS, now) : false;
29187
- const lastNudged = unsignaledTestNudges.get(testSession);
29188
- const alreadyNudged = !!(lastNudged && now - lastNudged < NUDGE_DEDUP_MS);
29189
29818
  const lastDispatchAt = status.history?.filter((h) => h.type === "test" && h.status === "testing").pop()?.timestamp;
29819
+ const lastNudged = unsignaledTestNudges.get(testSession);
29820
+ const escalationKey = `${testSession}:${lastDispatchAt ?? "unknown"}`;
29190
29821
  const decision = decideUnsignaledTestAction({
29191
29822
  sessionLive,
29192
29823
  idle,
29193
- alreadyNudged,
29824
+ alreadyNudged: unsignaledTestEscalations.has(escalationKey) || !!(lastNudged && now - lastNudged < NUDGE_DEDUP_MS),
29194
29825
  artifact: readTestVerdictArtifact(wsPath, lastDispatchAt ? new Date(lastDispatchAt).getTime() : void 0)
29195
29826
  });
29196
29827
  switch (decision.action) {
@@ -29210,7 +29841,7 @@ async function checkCompletedButUnsignaledTests() {
29210
29841
  const cmd = `pan admin specialists done test ${issueId} --status ${decision.status}${noteArg}`;
29211
29842
  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.`;
29212
29843
  try {
29213
- const { messageAgent } = await import("./agents-ePFVoZbu.js");
29844
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
29214
29845
  await messageAgent(testSession, nudge);
29215
29846
  unsignaledTestNudges.set(testSession, now);
29216
29847
  const msg = `Nudged ${testSession} to signal ${decision.status} (verdict artifact present)`;
@@ -29224,7 +29855,7 @@ async function checkCompletedButUnsignaledTests() {
29224
29855
  case "nudge-write": {
29225
29856
  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.`;
29226
29857
  try {
29227
- const { messageAgent } = await import("./agents-ePFVoZbu.js");
29858
+ const { messageAgent } = await import("./agents-IPSa5kzn.js");
29228
29859
  await messageAgent(testSession, nudge);
29229
29860
  unsignaledTestNudges.set(testSession, now);
29230
29861
  const msg = `Nudged ${testSession} to write+signal a test verdict (no artifact yet)`;
@@ -29235,6 +29866,15 @@ async function checkCompletedButUnsignaledTests() {
29235
29866
  }
29236
29867
  break;
29237
29868
  }
29869
+ case "escalate": {
29870
+ unsignaledTestEscalations.add(escalationKey);
29871
+ const msg = await recordUnsignaledTestEscalation(wsPath, issueId, testSession, lastDispatchAt ?? "unknown");
29872
+ if (msg) {
29873
+ actions.push(msg);
29874
+ console.warn(`[deacon] ${msg}`);
29875
+ }
29876
+ break;
29877
+ }
29238
29878
  default: break;
29239
29879
  }
29240
29880
  }
@@ -29247,8 +29887,8 @@ async function checkCompletedButUnsignaledTests() {
29247
29887
  async function checkVerificationReviewContradiction() {
29248
29888
  const actions = [];
29249
29889
  try {
29250
- const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Dma9SFaN.js");
29251
- const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
29890
+ const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-B6wYcOtP.js");
29891
+ const { resolveProjectFromIssueSync } = await import("./projects-WqMWCdpa.js");
29252
29892
  const statuses = loadReviewStatuses();
29253
29893
  for (const [issueId, status] of Object.entries(statuses)) if (status.verificationStatus === "passed" && status.reviewStatus === "reviewing" && status.stuckReason === "review_infrastructure_failure") {
29254
29894
  let reviewedAtCommit;
@@ -29257,7 +29897,7 @@ async function checkVerificationReviewContradiction() {
29257
29897
  if (project) {
29258
29898
  const workspacePath = join$1(project.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
29259
29899
  if (existsSync(workspacePath)) {
29260
- const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-Xg4PFN45.js");
29900
+ const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-C31x1lpE.js");
29261
29901
  reviewedAtCommit = await snapshotWorkspaceHeadsPromise(issueId, workspacePath);
29262
29902
  }
29263
29903
  }
@@ -29353,7 +29993,7 @@ async function checkReadyForMergeStuck() {
29353
29993
  const testStatusGreenCiReconcileCooldowns = /* @__PURE__ */ new Map();
29354
29994
  const TEST_STATUS_GREEN_CI_RECONCILE_COOLDOWN_MS = 300 * 1e3;
29355
29995
  async function reconcileTestStatusFromGreenCi() {
29356
- const { getCiCheckRunsState, getPullRequestHeadState, isGitHubAppConfigured } = await import("./github-app-Bmg4R9mv.js");
29996
+ const { getCiCheckRunsState, getPullRequestHeadState, isGitHubAppConfigured } = await import("./github-app-CpQSDlv8.js");
29357
29997
  return reconcileTestStatusFromGreenCiWithDeps({
29358
29998
  isGitHubAppConfigured,
29359
29999
  loadReviewStatuses,
@@ -29374,7 +30014,7 @@ async function reconcileTestStatusFromGreenCi() {
29374
30014
  */
29375
30015
  async function clearStaleCiFeedback(issueId) {
29376
30016
  const { readdir, rm } = await import("fs/promises");
29377
- const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
30017
+ const { resolveProjectFromIssueSync } = await import("./projects-WqMWCdpa.js");
29378
30018
  const projectConfig = resolveProjectFromIssueSync(issueId);
29379
30019
  if (!projectConfig) return;
29380
30020
  const repoDir = projectConfig.projectPath;
@@ -29395,26 +30035,21 @@ async function clearStaleCiFeedback(issueId) {
29395
30035
  const deadEndCooldowns = /* @__PURE__ */ new Map();
29396
30036
  const DEAD_END_STALENESS_MS = 300 * 1e3;
29397
30037
  const DEAD_END_COOLDOWN_MS = 600 * 1e3;
29398
- /**
29399
- * Detect dead-end agents: review blocked, tests failed, or merge failed (CI)
29400
- * but work agent is idle.
29401
- *
29402
- * This happens when:
29403
- * - Review feedback was delivered with a wrong URL (now fixed, but old feedback persists)
29404
- * - Agent forgot how to resubmit (context compaction lost instructions)
29405
- * - Feedback delivery to tmux failed silently
29406
- * - Merge failed due to CI checks (now handled in checkFailedMergeRetry by routing
29407
- * to the work agent with feedback; dead-end catches cases where the agent is idle)
29408
- *
29409
- * Recovery: re-queue the review via the request-review API endpoint and
29410
- * send the agent a nudge message with the correct resubmit command.
29411
- * For CI-blocked merges: clear the stale merge failure and feedback files.
29412
- */
29413
- async function checkDeadEndAgents() {
30038
+ async function checkDeadEndAgents(deps = {}) {
29414
30039
  const actions = [];
30040
+ const readReviewStatuses = deps.loadReviewStatuses ?? loadReviewStatuses;
30041
+ const hasSession = deps.sessionExistsSync ?? sessionExistsSync;
30042
+ const readAgentState = deps.getAgentStateSync ?? getAgentStateSync;
30043
+ const resolveAgentDir = deps.getAgentDir ?? getAgentDir;
30044
+ const decideRedrive = deps.decideAgentAutonomousRedrive ?? decideAgentAutonomousRedrive;
30045
+ const recordNeedsYou = deps.recordDeadEndNeedsYou ?? recordDeadEndNeedsYou;
30046
+ const spawnWorkAgent = deps.spawnWorkAgentThroughAgentsEndpoint ?? spawnWorkAgentThroughAgentsEndpoint;
30047
+ const updateReviewStatus = deps.setReviewStatusSync ?? setReviewStatusSync;
30048
+ const clearAgentTroubled = deps.clearAgentTroubledSync ?? clearAgentTroubledSync;
30049
+ const saveAgentState = deps.saveAgentStateSync ?? saveAgentStateSync;
29415
30050
  try {
29416
- const statuses = loadReviewStatuses();
29417
- const now = Date.now();
30051
+ const statuses = readReviewStatuses();
30052
+ const now = deps.now?.() ?? Date.now();
29418
30053
  for (const [key, status] of Object.entries(statuses)) {
29419
30054
  const isReviewBlocked = status.reviewStatus === "blocked" || status.reviewStatus === "failed";
29420
30055
  const isVerificationFailed = status.verificationStatus === "failed";
@@ -29445,24 +30080,27 @@ async function checkDeadEndAgents() {
29445
30080
  else if (isVerificationFailed) statusType = status.reviewStatus === "pending" ? "verification failed while review pending" : "verification failed";
29446
30081
  else if (isTestFailed) statusType = "tests failed";
29447
30082
  else statusType = "merge CI blocked";
29448
- if (!sessionExistsSync(agentSessionName)) {
30083
+ if (!hasSession(agentSessionName)) {
29449
30084
  if (isReviewBlocked || isVerificationFailed || isTestFailed) {
29450
- const agentState = getAgentStateSync(agentSessionName);
29451
- const gateDecision = decideAgentAutonomousRedrive(agentState ?? {}, getAgentDir(agentSessionName), true);
30085
+ const agentState = readAgentState(agentSessionName);
30086
+ const gateDecision = await decideRedrive(agentState ?? {}, resolveAgentDir(agentSessionName), true);
29452
30087
  if (gateDecision.decision === "defer") {
29453
30088
  console.log(`[deacon] PAN-2209: ${issueId} (${statusType}) re-drive deferred — ${gateDecision.reason}`);
29454
- const trip = gateDecision.needsYou && await recordDeadEndNeedsYou(issueId, "operator-stopped-rework", status.updatedAt ?? statusType, `Dead-end recovery needs-you: ${issueId} was explicitly stopped before handoff`);
30089
+ const pendingOperatorDecision = gateDecision.reason.startsWith("agent is waiting on an operator decision");
30090
+ const recoveryPath = pendingOperatorDecision ? "pending-operator-decision" : "operator-stopped-rework";
30091
+ const needsYouMessage = pendingOperatorDecision ? `Dead-end recovery needs-you: ${issueId} ${gateDecision.reason}. Answer it with 'pan answer ${issueId}'.` : `Dead-end recovery needs-you: ${issueId} was explicitly stopped before handoff`;
30092
+ const trip = gateDecision.needsYou && await recordNeedsYou(issueId, recoveryPath, status.updatedAt ?? statusType, needsYouMessage);
29455
30093
  if (trip) actions.push(trip);
29456
30094
  } else {
29457
30095
  if (gateDecision.gateDecision.clearStoppedByUser && agentState) {
29458
30096
  delete agentState.stoppedByUser;
29459
- saveAgentStateSync(agentState);
30097
+ saveAgentState(agentState);
29460
30098
  }
29461
30099
  deadEndCooldowns.set(key, now);
29462
- setReviewStatusSync(issueId, { autoRequeueCount: autoRequeueCount + 1 });
29463
- clearAgentTroubledSync(agentSessionName);
30100
+ updateReviewStatus(issueId, { autoRequeueCount: autoRequeueCount + 1 });
30101
+ clearAgentTroubled(agentSessionName);
29464
30102
  try {
29465
- const spawn = await spawnWorkAgentThroughAgentsEndpoint(issueId);
30103
+ const spawn = await spawnWorkAgent(issueId);
29466
30104
  if (spawn.spawned) {
29467
30105
  actions.push(`Dead-end recovery (PAN-2209): respawned dead work agent for ${issueId} (${statusType}) to address feedback`);
29468
30106
  console.log(`[deacon] PAN-2209: respawned dead work agent for ${issueId} (${statusType})`);
@@ -29618,7 +30256,7 @@ async function killOrphanedWorkspaceProcesses(workspacePath) {
29618
30256
  async function checkWorkspaceContainerHealth(sharedState) {
29619
30257
  const actions = [];
29620
30258
  try {
29621
- const { stdout } = await execAsync("docker ps -a --filter \"status=exited\" --filter \"name=overdeck-feature-\" --format \"{{.Names}}|{{.Status}}\" 2>/dev/null || true", {
30259
+ const { stdout } = await execAsync("docker ps -a --filter \"status=exited\" --filter \"name=feature-\" --format \"{{.Names}}|{{.Status}}\" 2>/dev/null || true", {
29622
30260
  encoding: "utf-8",
29623
30261
  timeout: 1e4
29624
30262
  });
@@ -29631,7 +30269,7 @@ async function checkWorkspaceContainerHealth(sharedState) {
29631
30269
  for (const line of crashed) {
29632
30270
  const [name, status] = line.split("|");
29633
30271
  if (!name) continue;
29634
- const match = name.match(/overdeck-feature-([\w-]+?)-(frontend|server)-/);
30272
+ const match = name.match(/feature-((?:[a-z]+-\d+)|(?:(?:f|us|de|ta|tc)\d+))-(frontend|server)-\d+$/i);
29635
30273
  if (!match) continue;
29636
30274
  const exitMatch = status?.match(/Exited \((\d+)\)/);
29637
30275
  if (exitMatch && exitMatch[1] === "0") continue;
@@ -29670,7 +30308,7 @@ async function checkWorkspaceContainerHealth(sharedState) {
29670
30308
  }
29671
30309
  }
29672
30310
  try {
29673
- const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
30311
+ const { resolveProjectFromIssueSync } = await import("./projects-WqMWCdpa.js");
29674
30312
  const resolved = resolveProjectFromIssueSync(issueLower.toUpperCase());
29675
30313
  if (resolved) await killOrphanedWorkspaceProcesses(`${resolved.projectPath}/workspaces/feature-${issueLower}`);
29676
30314
  } catch {}
@@ -29719,8 +30357,8 @@ async function checkWorkspaceContainerHealth(sharedState) {
29719
30357
  async function checkMergedWorkSessions() {
29720
30358
  const actions = [];
29721
30359
  try {
29722
- const { selectMergedWorkSessions } = await import("./reap-terminal-sessions-4Xg9NGA8.js");
29723
- const { setAgentPaused } = await import("./agents-ePFVoZbu.js");
30360
+ const { selectMergedWorkSessions } = await import("./reap-terminal-sessions-DegFS2p1.js");
30361
+ const { setAgentPaused } = await import("./agents-IPSa5kzn.js");
29724
30362
  const toKill = selectMergedWorkSessions(loadReviewStatuses(), [...await Effect.runPromise(listSessionNames())]);
29725
30363
  for (const session of toKill) try {
29726
30364
  await Effect.runPromise(setAgentPaused(session, "merged — awaiting close-out (verify on main)", true));
@@ -29760,7 +30398,7 @@ const AWAITING_TEST_IDLE_REAP_MS = 600 * 1e3;
29760
30398
  async function checkAwaitingTestWorkSessions() {
29761
30399
  const actions = [];
29762
30400
  try {
29763
- const { selectAwaitingTestWorkSessions } = await import("./reap-terminal-sessions-4Xg9NGA8.js");
30401
+ const { selectAwaitingTestWorkSessions } = await import("./reap-terminal-sessions-DegFS2p1.js");
29764
30402
  const candidates = selectAwaitingTestWorkSessions(loadReviewStatuses(), [...await Effect.runPromise(listSessionNames())]);
29765
30403
  const now = Date.now();
29766
30404
  for (const session of candidates) {
@@ -29813,32 +30451,37 @@ async function runPatrol() {
29813
30451
  hasLoggedGlobalPauseSkip = false;
29814
30452
  addLog("info", `Patrol cycle ${state.patrolCycle} — checking per-project specialists`, state.patrolCycle);
29815
30453
  console.log(`[deacon] Patrol cycle ${state.patrolCycle} - checking per-project specialists`);
29816
- for (const a of await (await import("./stale-task-claims-Cab_Fo_Z.js")).patrolStaleTaskClaims()) {
30454
+ for (const a of await (await import("./stale-task-claims-BYJGqhLI.js")).patrolStaleTaskClaims()) {
29817
30455
  actions.push(a);
29818
30456
  addLog("action", a, state.patrolCycle);
29819
30457
  }
29820
30458
  const stuckRemediationActions = await checkStuckAgentRemediation();
29821
30459
  actions.push(...stuckRemediationActions);
29822
30460
  for (const a of stuckRemediationActions) addLog("action", a, state.patrolCycle);
29823
- const { reconcileInFlightJournals } = await import("./advancing-selfheal-BNwqxseD.js");
30461
+ const { reconcileInFlightJournals } = await import("./advancing-selfheal-8AR68Asf.js");
29824
30462
  const reconciledJournalActions = await reconcileInFlightJournals();
29825
30463
  actions.push(...reconciledJournalActions);
29826
30464
  for (const a of reconciledJournalActions) addLog("action", a, state.patrolCycle);
29827
30465
  try {
29828
30466
  const pendingFile = join$1(OVERDECK_HOME, "pending-post-merge.json");
29829
- const { processPendingLifecycleForPatrol } = await import("./deacon-pending-lifecycle-B-Io84AP.js");
30467
+ const { processPendingLifecycleForPatrol } = await import("./deacon-pending-lifecycle-CD3YsiQK.js");
29830
30468
  const action = await processPendingLifecycleForPatrol(pendingFile);
29831
30469
  if (action) actions.push(action);
29832
30470
  } catch (err) {
29833
30471
  console.warn(`[deacon] Failed to process pending lifecycle: ${err.message}`);
29834
30472
  }
29835
- if (state.patrolCycle % 5 === 0) await (await import("./deploy-patrol-sYgOxLeb.js")).runScheduledDeployPatrol();
30473
+ if (state.patrolCycle % 5 === 0) await (await import("./deploy-patrol-kARAkji4.js")).runScheduledDeployPatrol();
29836
30474
  const livenessActions = await reconcileAgentLiveness();
29837
30475
  actions.push(...livenessActions);
29838
30476
  for (const a of livenessActions) addLog("action", a, state.patrolCycle);
29839
- const orphanProposedActions = await reconcileOrphanProposedSpecs();
29840
- actions.push(...orphanProposedActions);
29841
- for (const a of orphanProposedActions) addLog("action", a, state.patrolCycle);
30477
+ for (const a of await reconcileOrphanProposedSpecs()) {
30478
+ actions.push(a);
30479
+ addLog("action", a, state.patrolCycle);
30480
+ }
30481
+ for (const a of await reconcilePendingPromotions()) {
30482
+ actions.push(a);
30483
+ addLog("action", a, state.patrolCycle);
30484
+ }
29842
30485
  const closedIssueAgentActions = await reconcileClosedIssueAgents();
29843
30486
  actions.push(...closedIssueAgentActions);
29844
30487
  for (const a of closedIssueAgentActions) addLog("action", a, state.patrolCycle);
@@ -29848,7 +30491,7 @@ async function runPatrol() {
29848
30491
  const idleStackActions = await reconcileIdleWorkspaceStacks();
29849
30492
  actions.push(...idleStackActions);
29850
30493
  for (const a of idleStackActions) addLog("action", a, state.patrolCycle);
29851
- for (const a of await (await import("./bridge-pool-patrol-CYH2OLb5.js")).patrolDockerBridgePool()) {
30494
+ for (const a of await (await import("./bridge-pool-patrol-BEjt-xF3.js")).patrolDockerBridgePool()) {
29852
30495
  actions.push(a);
29853
30496
  addLog("action", a, state.patrolCycle);
29854
30497
  }
@@ -29868,7 +30511,7 @@ async function runPatrol() {
29868
30511
  actions.push(...suspendActions);
29869
30512
  for (const a of suspendActions) addLog("action", a, state.patrolCycle);
29870
30513
  try {
29871
- const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
30514
+ const { resolveProjectFromIssueSync } = await import("./projects-WqMWCdpa.js");
29872
30515
  const allStatuses = loadReviewStatuses();
29873
30516
  for (const [issueId, status] of Object.entries(allStatuses)) {
29874
30517
  if (!status.readyForMerge || status.mergeStatus === "merged") continue;
@@ -29888,7 +30531,7 @@ async function runPatrol() {
29888
30531
  } catch (err) {
29889
30532
  console.warn(`[deacon] Failed to check workspace existence: ${err.message}`);
29890
30533
  }
29891
- const { checkMergedAdvancingSessions } = await import("./advancing-selfheal-BNwqxseD.js");
30534
+ const { checkMergedAdvancingSessions } = await import("./advancing-selfheal-8AR68Asf.js");
29892
30535
  const reapedWorkActions = await checkMergedWorkSessions();
29893
30536
  actions.push(...reapedWorkActions);
29894
30537
  for (const a of reapedWorkActions) addLog("action", a, state.patrolCycle);
@@ -29896,7 +30539,7 @@ async function runPatrol() {
29896
30539
  actions.push(...reapedMergedAdvancingActions);
29897
30540
  for (const a of reapedMergedAdvancingActions) addLog("action", a, state.patrolCycle);
29898
30541
  try {
29899
- const { refreshClaudeCredentialsForActiveRemoteAgents } = await import("./remote-completion-CwAp79EC.js");
30542
+ const { refreshClaudeCredentialsForActiveRemoteAgents } = await import("./remote-completion-BS4tJUn8.js");
29900
30543
  const remoteCredentialActions = await refreshClaudeCredentialsForActiveRemoteAgents();
29901
30544
  actions.push(...remoteCredentialActions);
29902
30545
  for (const a of remoteCredentialActions) addLog(a.includes("failed") ? "warn" : "action", a, state.patrolCycle);
@@ -29904,7 +30547,7 @@ async function runPatrol() {
29904
30547
  addLog("warn", `Remote credential refresh patrol failed: ${err.message}`, state.patrolCycle);
29905
30548
  }
29906
30549
  try {
29907
- const { refreshHostHeartbeatForEphemeralVms } = await import("./remote-agents-CLZB3Coc.js");
30550
+ const { refreshHostHeartbeatForEphemeralVms } = await import("./remote-agents-BIIoc5pD.js");
29908
30551
  const heartbeatActions = await refreshHostHeartbeatForEphemeralVms();
29909
30552
  actions.push(...heartbeatActions);
29910
30553
  for (const a of heartbeatActions) addLog(a.includes("failed") ? "warn" : "action", a, state.patrolCycle);
@@ -29912,7 +30555,7 @@ async function runPatrol() {
29912
30555
  addLog("warn", `Remote heartbeat refresh patrol failed: ${err.message}`, state.patrolCycle);
29913
30556
  }
29914
30557
  try {
29915
- const { reapCompletedRemoteAgents } = await import("./remote-completion-CwAp79EC.js");
30558
+ const { reapCompletedRemoteAgents } = await import("./remote-completion-BS4tJUn8.js");
29916
30559
  const remoteReap = await reapCompletedRemoteAgents();
29917
30560
  for (const r of remoteReap) if (r.status === "handed-off" || r.status === "error") {
29918
30561
  const msg = `Remote reap ${r.issueId}: ${r.status} (${r.details.join("; ")})`;
@@ -29961,6 +30604,12 @@ async function runPatrol() {
29961
30604
  const unsignaledReviewActions = await checkCompletedButUnsignaledReviews();
29962
30605
  actions.push(...unsignaledReviewActions);
29963
30606
  for (const a of unsignaledReviewActions) addLog("action", a, state.patrolCycle);
30607
+ const unappliedReviewActions = await reconcileUnappliedReviewVerdicts();
30608
+ actions.push(...unappliedReviewActions);
30609
+ for (const a of unappliedReviewActions) addLog("action", a, state.patrolCycle);
30610
+ const verdictFallbackActions = await sweepStrandedVerdictFallbacks(Date.now(), Math.max(1e3, Math.floor(config.patrolIntervalMs / 2)));
30611
+ actions.push(...verdictFallbackActions);
30612
+ for (const a of verdictFallbackActions) addLog("action", a, state.patrolCycle);
29964
30613
  const verifContradictionActions = await checkVerificationReviewContradiction();
29965
30614
  actions.push(...verifContradictionActions);
29966
30615
  for (const a of verifContradictionActions) addLog("action", a, state.patrolCycle);
@@ -30105,7 +30754,7 @@ async function runPatrol() {
30105
30754
  const issueId = runtimeState.currentIssue;
30106
30755
  try {
30107
30756
  if (getReviewStatusSync(issueId)?.mergeStatus === "merging") {
30108
- const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
30757
+ const { resolveProjectFromIssueSync } = await import("./projects-WqMWCdpa.js");
30109
30758
  const resolved = resolveProjectFromIssueSync(issueId);
30110
30759
  if (resolved) {
30111
30760
  const branch = `feature/${issueId.toLowerCase()}`;
@@ -30119,7 +30768,7 @@ async function runPatrol() {
30119
30768
  mergeStatus: "merged",
30120
30769
  readyForMerge: false
30121
30770
  });
30122
- const { postMergeLifecycle } = await import("./merge-agent-DQTXZk8z.js");
30771
+ const { postMergeLifecycle } = await import("./merge-agent-DWd0KfiS.js");
30123
30772
  postMergeLifecycle(issueId, resolved.projectPath).catch((err) => console.warn(`[deacon] postMergeLifecycle failed for ${issueId}: ${err}`));
30124
30773
  actions.push(`Auto-completed stale merge for ${issueId}`);
30125
30774
  } else {
@@ -30299,7 +30948,7 @@ function startDeacon() {
30299
30948
  logDeaconEventSync(`startDeacon: health monitor starting (patrol every ${config.patrolIntervalMs / 1e3}s)`);
30300
30949
  (async () => {
30301
30950
  await reconcileAgentLiveness();
30302
- const { runBootAdvancingSelfHeal } = await import("./advancing-selfheal-BNwqxseD.js");
30951
+ const { runBootAdvancingSelfHeal } = await import("./advancing-selfheal-8AR68Asf.js");
30303
30952
  await runBootAdvancingSelfHeal();
30304
30953
  runScheduledPatrol("startup");
30305
30954
  })().catch((err) => {
@@ -30369,6 +31018,6 @@ function assessDeaconPatrolFreshness(params) {
30369
31018
  };
30370
31019
  }
30371
31020
  //#endregion
30372
- export { checkStuckReviewing as $, reconcileTestStatusFromGreenCi as A, classifyMemoryPressure as At, isRapidPostResumeDeath as B, isSmeeConfiguredSync as Bt, handleAgentHeartbeatDeadEvent as C, contextProactiveCompactState as Ct, loadConfig as D, INSPECT_TIMEOUT_MS as Dt, isDeaconRunning as E, paneShowsClaudeBootBlockingScreen as Et, setAgentStoppedNotifier as F, getAcceptedSystemHealthSnapshot as Ft, isAutoResumableRole as G, nudgeStalledResumeWorkAgents as H, classifyAgentHealth as Ht, setMergeReadyNotifier as I, getDeployStaleness as It, startBootReconciliation as J, isBootReconciliationCandidate as K, startDeacon as L, getResourceConfig as Lt, runPatrol as M, formatUptime as Mt, saveState as N, getContainerHistory as Nt, loadState as O, checkInspectAgentTimeouts as Ot, setAgentStatusChangedNotifier as P, getCurrentDockerStats as Pt, checkCompletedButUnsignaledReviews as Q, stopDeacon as R, getSystemHealthEvidenceSnapshot as Rt, getLastPatrolResult as S, contextOverflowRecoveryState as St, handleAgentStoppedForOrphanReviewerSessions as T, deliverOrchestratedCompact as Tt, redeliverUndeliveredKickoffs as U, nudgeIdleWorkAgentsWithOpenBeads as V, startSmeeProcessSync as Vt, extendBootReconciliationGrace as W, monitorReviewConvoySignals as X, cleanupOrphanedReviewSessions as Y, synthesizeReviewFromReports as Z, cleanupOrphanedPlanningSessions as _, reconcileStaleMergeStatus as _t, checkCompletedButUnsignaledTests as a, recoverStalledReviewConvoys as at, getDeaconLogs as b, reconcileStuckMergingStates as bt, checkMergedWorkSessions as c, checkPostReviewCommits as ct, checkReadyForMergeStuck as d, checkFirstCompletionAgents as dt, isSynthesisForActiveReviewRun as et, checkStuckWorkAgents as f, ciRetryMap as ft, cleanupOrphanReviewerSessions as g, reconcileStaleMergeBlockers as gt, cleanupAbandonedFeedback as h, reconcileMergedButReviewing as ht, checkAwaitingTestWorkSessions as i, handleWorkCompleted as it, resetPatrolHeartbeatForStartup as j, getResourceStacks as jt, reconcileAgentLiveness as k, WORK_LAUNCHER_GRACE_MS as kt, checkOrphanedCompletions as l, autoCloseOut as lt, checkWorkspaceContainerHealth as m, reconcileFalseMerged as mt, assessDeaconPatrolFreshness as n, checkOrphanedReviewStatuses as nt, checkDeadEndAgents as o, reviewConvoyLiveness as ot, checkVerificationReviewContradiction as p, reconcileClosedPrReadyForMerge as pt, listBootReconciliationCandidates as q, checkAndSuspendIdleAgents as r, handleReviewCoordinatorDied as rt, checkMassDeath as s, stalledReviewConvoyRecoveryState as st, applyBootReconciliationDecision as t, checkMissingReviewStatuses as tt, checkPendingTestDispatch as u, checkFailedMergeRetry as ut, cleanupStaleAgentState as v, reconcileStuckReadyForMerge as vt, handleAgentStoppedEvent as w, stuckOverflowNativeRecoveryState as wt, getDeaconStatus as x, checkApiErrorAgents as xt, containerRestartBackoffMs as y, reconcileAutoMergeRows as yt, isPreKickoffLaunchDeath as z, getSystemHealthSnapshot as zt };
31021
+ export { checkStuckReviewing as $, reconcileTestStatusFromGreenCi as A, WORK_LAUNCHER_GRACE_MS as At, isRapidPostResumeDeath as B, getSystemHealthSnapshot as Bt, handleAgentHeartbeatDeadEvent as C, contextOverflowRecoveryState as Ct, loadConfig as D, paneShowsClaudeBootBlockingScreen as Dt, isDeaconRunning as E, deliverOrchestratedCompact as Et, setAgentStoppedNotifier as F, getCurrentDockerStats as Ft, isAutoResumableRole as G, nudgeStalledResumeWorkAgents as H, startSmeeProcessSync as Ht, setMergeReadyNotifier as I, getAcceptedSystemHealthSnapshot as It, startBootReconciliation as J, isBootReconciliationCandidate as K, startDeacon as L, getDeployStaleness as Lt, runPatrol as M, getResourceStacks as Mt, saveState as N, formatUptime as Nt, loadState as O, INSPECT_TIMEOUT_MS as Ot, setAgentStatusChangedNotifier as P, getContainerHistory as Pt, checkCompletedButUnsignaledReviews as Q, stopDeacon as R, getResourceConfig as Rt, getLastPatrolResult as S, checkApiErrorAgents as St, handleAgentStoppedForOrphanReviewerSessions as T, stuckOverflowNativeRecoveryState as Tt, redeliverUndeliveredKickoffs as U, classifyAgentHealth as Ut, nudgeIdleWorkAgentsWithOpenBeads as V, isSmeeConfiguredSync as Vt, extendBootReconciliationGrace as W, monitorReviewConvoySignals as X, cleanupOrphanedReviewSessions as Y, synthesizeReviewFromReports as Z, cleanupOrphanedPlanningSessions as _, reconcileStaleMergeBlockers as _t, checkCompletedButUnsignaledTests as a, handleWorkCompleted as at, getDeaconLogs as b, reconcileAutoMergeRows as bt, checkMergedWorkSessions as c, stalledReviewConvoyRecoveryState as ct, checkReadyForMergeStuck as d, checkFailedMergeRetry as dt, isSynthesisForActiveReviewRun as et, checkStuckWorkAgents as f, checkFirstCompletionAgents as ft, cleanupOrphanReviewerSessions as g, reconcileMergedButReviewing as gt, cleanupAbandonedFeedback as h, reconcileFalseMerged as ht, checkAwaitingTestWorkSessions as i, handleReviewCoordinatorDied as it, resetPatrolHeartbeatForStartup as j, classifyMemoryPressure as jt, reconcileAgentLiveness as k, checkInspectAgentTimeouts as kt, checkOrphanedCompletions as l, checkPostReviewCommits as lt, checkWorkspaceContainerHealth as m, reconcileClosedPrReadyForMerge as mt, assessDeaconPatrolFreshness as n, checkMissingReviewStatuses as nt, checkDeadEndAgents as o, recoverStalledReviewConvoys as ot, checkVerificationReviewContradiction as p, ciRetryMap as pt, listBootReconciliationCandidates as q, checkAndSuspendIdleAgents as r, checkOrphanedReviewStatuses as rt, checkMassDeath as s, reviewConvoyLiveness as st, applyBootReconciliationDecision as t, reconcileUnappliedReviewVerdicts as tt, checkPendingTestDispatch as u, autoCloseOut as ut, cleanupStaleAgentState as v, reconcileStaleMergeStatus as vt, handleAgentStoppedEvent as w, contextProactiveCompactState as wt, getDeaconStatus as x, reconcileStuckMergingStates as xt, containerRestartBackoffMs as y, reconcileStuckReadyForMerge as yt, isPreKickoffLaunchDeath as z, getSystemHealthEvidenceSnapshot as zt };
30373
31022
 
30374
- //# sourceMappingURL=deacon-pLRLbPvR.js.map
31023
+ //# sourceMappingURL=deacon-HdEh0Esp.js.map