@overdeck/desktop 0.46.0 → 0.47.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 (387) hide show
  1. package/drizzle/overdeck/0000_overdeck_init.sql +4 -1
  2. package/package.json +1 -1
  3. package/server/{acceptance-criteria-CCwFGICj.js → acceptance-criteria-10Ur5Dne.js} +2 -2
  4. package/server/{advancing-selfheal-De1L-Sb4.js → advancing-selfheal-BNwqxseD.js} +6 -6
  5. package/server/{agent-gc-CBULruzm.js → agent-gc-C3h9Or3a.js} +5 -5
  6. package/server/{agent-state-VQk8fY9F.js → agent-state-CYXJVG72.js} +1 -1
  7. package/server/agent-state-service-C63p_ftq.js +2 -0
  8. package/server/{agent-state-service-BlnSkRFA.js → agent-state-service-Ds6OeFvo.js} +15 -9
  9. package/server/{agents-C5rWYhb6.js → agents-J5mEnekq.js} +23 -16
  10. package/server/{agents-BKKkxKgK.js → agents-ePFVoZbu.js} +1 -1
  11. package/server/archive-planning-B2XplFzT.js +2 -0
  12. package/server/{archive-planning-C0lAbNB_.js → archive-planning-BwhxeP7C.js} +10 -6
  13. package/server/{artifact-index-jobs-ug6ZxIP5.js → artifact-index-jobs-D1q_vR3V.js} +2 -2
  14. package/server/{assemble-DnffNpOo.js → assemble-Bgwqv-Ro.js} +2 -2
  15. package/server/{tmux-dedup-DbN6MGzM.js → auto-spawn-consent-CQ9Bi9q6.js} +262 -13
  16. package/server/{backlog-auto-trigger-Dh-i9PQf.js → backlog-auto-trigger-n1lzPgN4.js} +3 -3
  17. package/server/{behavior-CfIg6pKp.js → behavior-td6-xhQk.js} +2 -2
  18. package/server/boot-reconciled-stop-events-C7gGe3oB.js +44 -0
  19. package/server/{bridge-pool-patrol-CUFmjVDN.js → bridge-pool-patrol-CYH2OLb5.js} +1 -1
  20. package/server/{briefing-freshness-DHmCSLar.js → briefing-freshness-DRqZ8lAz.js} +2 -2
  21. package/server/{build-info-CuFfxZxp.js → build-info-7yiEpl6u.js} +3 -3
  22. package/server/{build-info-BP160gU7.js → build-info-CpG__c63.js} +1 -1
  23. package/server/{checkpoint-manager-Dxh0FYsv.js → checkpoint-manager-CkKmB0wZ.js} +1 -1
  24. package/server/{checkpoint-manager-DEWD82qK.js → checkpoint-manager-DBcyNR8w.js} +2 -2
  25. package/server/checkpoint-worker.js +1 -1
  26. package/server/{checkpoints-CZvbtLnr.js → checkpoints-D95apurL.js} +2 -2
  27. package/server/{checkpoints-DMTgXuLG.js → checkpoints-Wm963lm8.js} +1 -1
  28. package/server/{claude-hooks-provision-CN-xo-do.js → claude-hooks-provision-4RPxNkE8.js} +1 -1
  29. package/server/{claude-hooks-provision-fvy4RD2b.js → claude-hooks-provision-Bjitl9aI.js} +2 -2
  30. package/server/{claude-permissions-CN0cSCPp.js → claude-permissions-CpbpvUQ2.js} +2 -2
  31. package/server/{claude-settings-overlay-Dabi9slj.js → claude-settings-overlay-BzkHYDwR.js} +1 -1
  32. package/server/{claude-settings-overlay-CJn35FHQ.js → claude-settings-overlay-_H9Yrzab.js} +2 -2
  33. package/server/cli-CjOCSnfj.js +3 -0
  34. package/server/{cli-oCWYA1pE.js → cli-Cte9ZFGn.js} +9 -9
  35. package/server/{cliproxy-C8mB3KuB.js → cliproxy-C5fMJ7rY.js} +2 -2
  36. package/server/{cliproxy-PGwTX_o8.js → cliproxy-DaAbWMjC.js} +1 -1
  37. package/server/{close-issue-D5MF5GqF.js → close-issue-BPh1ARCF.js} +5 -5
  38. package/server/{closed-issue-reaper-CJ24u0Zt.js → closed-issue-reaper-DHRfRMrp.js} +1 -1
  39. package/server/{closed-issue-reaper-Cltx86x5.js → closed-issue-reaper-DoOZqGFK.js} +62 -12
  40. package/server/{codex-Drlf5Xhf.js → codex-BzGDW_d3.js} +6 -6
  41. package/server/{codex-BdEsUFWh.js → codex-o8FJwzmy.js} +1 -1
  42. package/server/{codex-parser-DpB89Vqa.js → codex-parser-Dt-ycU8L.js} +2 -2
  43. package/server/{compaction-continuation-K2AxQX4H.js → compaction-continuation-CvXpbZ4w.js} +3 -3
  44. package/server/{config-B2IMcBxx.js → config-Bi3u1VK7.js} +2 -2
  45. package/server/{config-Dr3pW6w6.js → config-BvLe652W.js} +2 -2
  46. package/server/{config-DV-grfQc.js → config-CL3Gyvja.js} +1 -1
  47. package/server/{config-yaml-CmOPzmBb.js → config-yaml-CxdwhAIA.js} +10 -2
  48. package/server/conflict-gate-CX80JYYS.js +3 -0
  49. package/server/{conflict-gate-B9cN3SBi.js → conflict-gate-E4nt7ZeS.js} +59 -13
  50. package/server/{context-layers-dR5YxHYB.js → context-layers-C_IIysnm.js} +3 -3
  51. package/server/{context-layers-D6LZo3l1.js → context-layers-DAG83UZt.js} +2 -2
  52. package/server/{control-settings-C7DUehE1.js → control-settings-CiqGxXnc.js} +13 -6
  53. package/server/{conversation-compaction-Dj4FAKoZ.js → conversation-compaction-BE3CNtHF.js} +1 -1
  54. package/server/{conversation-compaction-BoqdDXWF.js → conversation-compaction-D6-yLtqt.js} +8 -8
  55. package/server/{conversation-service-5aCnq1zR.js → conversation-service-DBxoYMDl.js} +8 -7
  56. package/server/{conversation-service-BCxl4f8Z.js → conversation-service-D_TS2b1r.js} +1 -1
  57. package/server/{conversations-C34dyIb9.js → conversations-BKDVpB-3.js} +1 -1
  58. package/server/{conversations-BUpYsOZg.js → conversations-D0UEdLtk.js} +4 -4
  59. package/server/{cost-CvxRrucd.js → cost-DS1s0DbG.js} +3 -3
  60. package/server/{cost-Bgcub5kW.js → cost-DpgYmYqR.js} +2 -2
  61. package/server/{cost-sync-Dv3LUaNW.js → cost-sync-tOCCGnEt.js} +3 -3
  62. package/server/{dag-ombYYt4s.js → dag-BtkgLeqY.js} +2 -2
  63. package/server/{dangerous-git-ops-BcJPC5Rr.js → dangerous-git-ops-CFLykHWt.js} +1 -1
  64. package/server/dashboard-db-worker.js +7 -7
  65. package/server/{deacon-DrXqT9LQ.js → deacon-BIblC-WX.js} +3 -3
  66. package/server/{deacon-nudge-log-BNBebzeL.js → deacon-nudge-log-B08gF0mh.js} +3 -3
  67. package/server/{deacon-hi9KLPLT.js → deacon-pLRLbPvR.js} +548 -176
  68. package/server/{deacon-pending-lifecycle-Cpk0k7Hi.js → deacon-pending-lifecycle-B-Io84AP.js} +3 -3
  69. package/server/deacon-swarm-B1XkIvfr.js +2 -0
  70. package/server/{deacon-swarm-DBxUaO-A.js → deacon-swarm-v5PMun-m.js} +15 -14
  71. package/server/deacon.js +8 -8
  72. package/server/{dead-end-trip-CQcP70ND.js → dead-end-trip-D8A3msX9.js} +3 -3
  73. package/server/{delivery-Da0zEMY4.js → delivery-BX9HR4wQ.js} +1 -1
  74. package/server/{deploy-patrol-Df-Tmaq0.js → deploy-patrol-sYgOxLeb.js} +8 -8
  75. package/server/{deploy-queue-UjKGYsDe.js → deploy-queue-VfohaPN_.js} +2 -2
  76. package/server/{deploy-queue-9SrhZR63.js → deploy-queue-gHJBycaF.js} +1 -1
  77. package/server/{deploy-window-jOiPRHL0.js → deploy-window-CFRZ0-kt.js} +1 -1
  78. package/server/{deploy-window-rpqpWqHA.js → deploy-window-D4DQb8VP.js} +6 -6
  79. package/server/{dev-supervisor-CC46Ig8q.js → dev-supervisor-DiOBDM1c.js} +2 -2
  80. package/server/{devcontainer-renderer-68CSCRnu.js → devcontainer-renderer-BUOIlfgD.js} +3 -3
  81. package/server/dist-B3YPQa5A.js +3 -0
  82. package/server/{dist-CJy72uEg.js → dist-C3A8B8wM.js} +1 -1
  83. package/server/{dist-src-Bik83hFi.js → dist-src-C0adpegX.js} +1 -1
  84. package/server/{docker-Dam7mbIB.js → docker-BJzlkqYB.js} +2 -2
  85. package/server/{docker-BMVTSFL5.js → docker-Y3PElJb0.js} +1 -1
  86. package/server/{dod-Dar-yheg.js → dod-DlNtcH6n.js} +26 -5
  87. package/server/{durable-review-pipeline-CGZ5QBxh.js → durable-review-pipeline-Cibps-Rg.js} +5 -2
  88. package/server/durable-review-pipeline-DP6bIcOY.js +3 -0
  89. package/server/{ensure-devcontainer-B057YA81.js → ensure-devcontainer-BAofzBPv.js} +4 -4
  90. package/server/{ensure-devcontainer-C98V8yW-.js → ensure-devcontainer-DMAbWqtQ.js} +1 -1
  91. package/server/{esm-shims-Br9BPdkR.js → esm-shims-BeObUkaw.js} +1 -1
  92. package/server/{event-store-ELqkVOn0.js → event-store-5UKzh9Jf.js} +1 -1
  93. package/server/{event-store-zY5MJHgF.js → event-store-CrHcVC5_.js} +3 -3
  94. package/server/{events-D9PR1IC0.js → events-BNrvchBg.js} +3 -3
  95. package/server/{events-D6pyqhzM.js → events-CF8QDbuV.js} +1 -1
  96. package/server/{factory-CRoOpGsF.js → factory-Cmm9Hsho.js} +5 -5
  97. package/server/{feature-registry-population--YUXU999.js → feature-registry-population-B6HpNWRy.js} +4 -4
  98. package/server/{feature-registry-storage-BORBTo0y.js → feature-registry-storage-DJEFx1Pf.js} +2 -2
  99. package/server/{features--nFkJY8v.js → features-D5km80UI.js} +2 -2
  100. package/server/{feedback-target-C0ZzyHvU.js → feedback-target-BJ5ZADsu.js} +1 -1
  101. package/server/{feedback-target-Dt9BsapX.js → feedback-target-DSxEL6lP.js} +7 -7
  102. package/server/{feedback-writer-BG0RUZiu.js → feedback-writer-C27Hak8a.js} +5 -5
  103. package/server/{feedback-writer-D1fm-5Z8.js → feedback-writer-CoB9Z6aU.js} +1 -1
  104. package/server/{flywheel-BiT3odRb.js → flywheel-BHx8XuMr.js} +38 -19
  105. package/server/{flywheel-BekukH4i.js → flywheel-DZZdtiOL.js} +1 -1
  106. package/server/{flywheel-CLVB55Be.js → flywheel-f662Q-y2.js} +14 -14
  107. package/server/{flywheel-merge-order-BJv1DZz1.js → flywheel-merge-order-D_xLMbJU.js} +7 -7
  108. package/server/{flywheel-merge-order-BKw9o6ku.js → flywheel-merge-order-Dil0LmdN.js} +1 -1
  109. package/server/forge-B5o319qI.js +3 -0
  110. package/server/{forge-CZbSg6Ds.js → forge-BaKGCya6.js} +2 -2
  111. package/server/{from-D_4_dk7i.js → from-B3tZbB55.js} +1 -1
  112. package/server/fs-lock-Bre3sGoz.js +130 -0
  113. package/server/{fts-db-BeOomFa-.js → fts-db-IVc4_M3f.js} +2 -2
  114. package/server/{fts-operations-BdewJ_g9.js → fts-operations-B9jG8wa3.js} +2 -2
  115. package/server/{git-utils-ameCgDdy.js → git-utils-CsvYfJU3.js} +4 -4
  116. package/server/{git-utils-CI6cwyyC.js → git-utils-Xg4PFN45.js} +1 -1
  117. package/server/{github-app-DtAsvwzK.js → github-app-Bmg4R9mv.js} +1 -1
  118. package/server/{github-app-CQ1Lo6LA.js → github-app-CmNk0zLU.js} +2 -2
  119. package/server/{github-client-Cj0yl_07.js → github-client-B6KM9_wA.js} +1 -1
  120. package/server/{github-client-BfyDxuRN.js → github-client-qazkPrg0.js} +3 -3
  121. package/server/{github-pr-lookup-BDq6Wznz.js → github-pr-lookup-DAcVeRLK.js} +2 -2
  122. package/server/{harness-binary-DqkftwTb.js → harness-binary-BSpiXaLw.js} +2 -2
  123. package/server/{harness-resolve-CqMqM1Mb.js → harness-resolve-BAJu5MX8.js} +4 -4
  124. package/server/{health-events-_xfTaOUs.js → health-events-2Z6Wa9SM.js} +1 -1
  125. package/server/{health-events-CazRxJUS.js → health-events-BwX32k8d.js} +2 -2
  126. package/server/{hooks-BnJsxlSq.js → hooks-D1g1jKLI.js} +1 -1
  127. package/server/{hooks-BO3QT1sn.js → hooks-DbtbimEf.js} +2 -2
  128. package/server/{hume-CDYJxqx-.js → hume-DXNiu6nQ.js} +2 -2
  129. package/server/hume-VUCNbTgn.js +3 -0
  130. package/server/{idle-stack-reaper-BYqERdkE.js → idle-stack-reaper-CRA1e0jr.js} +1 -1
  131. package/server/{idle-stack-reaper-CnGx_PO_.js → idle-stack-reaper-Cy-dQzW4.js} +2 -2
  132. package/server/{in-flight-guard-Bq3epG58.js → in-flight-guard-D-sSkADM.js} +1 -1
  133. package/server/{infra-BjuxvjdS.js → infra-BDQDRopn.js} +15 -4
  134. package/server/{injection-UCf8EsjX.js → injection-6AGnXxlj.js} +7 -7
  135. package/server/{injection-DZxlV2al.js → injection-Bl8d_jHZ.js} +1 -1
  136. package/server/inspect-agent-CUwVmr2h.js +2 -0
  137. package/server/{inspect-agent-6kylZnrm.js → inspect-agent-nXdIptyh.js} +12 -12
  138. package/server/{internal-token-DvMTQSOS.js → internal-token-DzK385vD.js} +2 -2
  139. package/server/{internal-token-M9omeXM1.js → internal-token-Ias7N8Kg.js} +1 -1
  140. package/server/{io-VHvc0Ssp.js → io-B00PBNku.js} +4 -4
  141. package/server/{issue-closed-B6KJkmHZ.js → issue-closed-BehTG1be.js} +8 -8
  142. package/server/{issue-lifecycle-C4Zj0WmE.js → issue-lifecycle-Birk-ifu.js} +29 -23
  143. package/server/{issue-lifecycle-9gk3fnXN.js → issue-lifecycle-BqSuQvbn.js} +1 -1
  144. package/server/{issue-service-singleton-PMx8F1jr.js → issue-service-singleton-B2wXiIlw.js} +1 -1
  145. package/server/{issue-service-singleton-DmCh7EHj.js → issue-service-singleton-C6ZduvuY.js} +10 -10
  146. package/server/{issues-CgnQ1OGQ.js → issues-DQ5-LatB.js} +2 -2
  147. package/server/{jsonl-parser-DJOH_O-w.js → jsonl-parser-BDpnGFCl.js} +3 -3
  148. package/server/{label-cleanup-Dv7AV_R1.js → label-cleanup-Dwnky8FG.js} +3 -3
  149. package/server/{lifecycle-DDN8ApVY.js → lifecycle-B3s4sM1G.js} +6 -6
  150. package/server/{lifecycle-CTdOWYMi.js → lifecycle-B4Xdb4cY.js} +2 -2
  151. package/server/{lifecycle-io-D_zTLvP1.js → lifecycle-io-CzTHEooc.js} +1 -1
  152. package/server/{lifecycle-io-D-lGdzK3.js → lifecycle-io-DCo6s6ks.js} +5 -5
  153. package/server/{linear-client-BQU36QqE.js → linear-client-9uq7fhiV.js} +3 -3
  154. package/server/{linear-client-CY4O_Tu3.js → linear-client-CnbtHiic.js} +1 -1
  155. package/server/{linear-mcp-auth-BnU4TYfY.js → linear-mcp-auth-BxUOzswy.js} +5 -5
  156. package/server/{linear-mcp-auth-NYBq_oHZ.js → linear-mcp-auth-D46fBCLf.js} +1 -1
  157. package/server/memory-fts-worker.js +1 -1
  158. package/server/{merge-Bpx4jjht.js → merge-DiW9RdSB.js} +3 -3
  159. package/server/{merge-agent-DdMVSV2Y.js → merge-agent-BLUgRsz3.js} +31 -31
  160. package/server/{merge-agent-DrXa1CpW.js → merge-agent-DQTXZk8z.js} +1 -1
  161. package/server/{merge-batch-C5q1c1GX.js → merge-batch-Cp_j9BGk.js} +1 -1
  162. package/server/{merge-completeness-BMm8tMyZ.js → merge-completeness-B46KqhtY.js} +4 -4
  163. package/server/{merge-completeness-D0ljXbk3.js → merge-completeness-BLbB5-6n.js} +1 -1
  164. package/server/merge-ops-1abz6O_P.js +2 -0
  165. package/server/merge-rebase-CJJVAJuz.js +2 -0
  166. package/server/{merge-rebase-xLnMlw5h.js → merge-rebase-DIkBjgwq.js} +2 -2
  167. package/server/{merge-set-DH7ot3yz.js → merge-set-CBgHfwM0.js} +4 -4
  168. package/server/{merge-set-DzsOTBg5.js → merge-set-DeUxFsC3.js} +1 -1
  169. package/server/{merge-idOG--29.js → merge-sr8Nrnmi.js} +1 -1
  170. package/server/merge-sync-CpGmk6Ch.js +3 -0
  171. package/server/{merge-sync-CQ-LgZ1_.js → merge-sync-kr4vqyjM.js} +7 -4
  172. package/server/{merge-train-DTEMyIu4.js → merge-train-Dmrcus12.js} +4 -4
  173. package/server/{merge-train-deps-CNPJzepw.js → merge-train-deps-D_uGX91G.js} +21 -15
  174. package/server/{merge-verification-x3JO8Dtz.js → merge-verification-NvaAd8CZ.js} +6 -6
  175. package/server/{merged-docker-cleanup-worker-Cdi9apm-.js → merged-docker-cleanup-worker-DH_hrGPI.js} +1 -1
  176. package/server/{merged-docker-cleanup-worker-CTpC27Bs.js → merged-docker-cleanup-worker-Y1R06TEl.js} +3 -3
  177. package/server/{multipart-parser-IMSBfePV.js → multipart-parser-R-oC8dQg.js} +2 -2
  178. package/server/{no-resume-mode-C5ULAXwO.js → no-resume-mode-BgD0JUmM.js} +1 -1
  179. package/server/node_modules/.package-lock.json +4 -4
  180. package/server/node_modules/@types/node/README.md +1 -1
  181. package/server/node_modules/@types/node/crypto.d.ts +1 -1
  182. package/server/node_modules/@types/node/package.json +2 -2
  183. package/server/{orphan-proposed-reconciler-Dg6U4ADZ.js → orphan-proposed-reconciler-B6vJHxtX.js} +230 -31
  184. package/server/{orphan-proposed-reconciler-CWmOdM9-.js → orphan-proposed-reconciler-DcgTPPFY.js} +1 -1
  185. package/server/package-lock.json +5 -5
  186. package/server/package.json +1 -1
  187. package/server/{pan-dir-ubraCiUg.js → pan-dir-DMzF5wne.js} +4 -4
  188. package/server/{paths-cXmOwSbh.js → paths-sJBSb7Ul.js} +2 -2
  189. package/server/{pending-lifecycle-claim-DEteYdS9.js → pending-lifecycle-claim-DilzGfgk.js} +2 -2
  190. package/server/persistent-logger-H_VjuOu7.js +57 -0
  191. package/server/{pickup-D8xtG1J2.js → pickup-DWhqzliO.js} +4 -3
  192. package/server/{pipeline-membership-BGSvkT2M.js → pipeline-membership-C88VBnhJ.js} +1 -1
  193. package/server/{pipeline-membership-CrAPLYtf.js → pipeline-membership-D9SBvItj.js} +1 -1
  194. package/server/{pipeline-membership-gather-DTfcgxLl.js → pipeline-membership-gather-4eR-7Tqy.js} +1 -1
  195. package/server/{pipeline-membership-gather-CET40frr.js → pipeline-membership-gather-CeVGnNJ2.js} +114 -9
  196. package/server/{pipeline-notifier-BuQ0e4hF.js → pipeline-notifier-D0ALV6Nw.js} +2 -2
  197. package/server/{pipeline-notifier-ImNXknf0.js → pipeline-notifier-DT6xLFao.js} +1 -1
  198. package/server/{post-merge-lifecycle-worker-DbO10pum.js → post-merge-lifecycle-worker-8HIeS_J6.js} +3 -3
  199. package/server/{project-pipelines-Bim6bThI.js → project-pipelines-9SKt2bEc.js} +2 -2
  200. package/server/{project-repos-C0nuoBGv.js → project-repos-B5pIphKg.js} +2 -2
  201. package/server/{project-repos-CRE6Ykow.js → project-repos-DPjOdfPa.js} +1 -1
  202. package/server/{projects-B03Wr-xc.js → projects-_n3Zui6K.js} +1 -1
  203. package/server/{prompts-BEx08AIu.js → prompts-CgzMBvQF.js} +2 -2
  204. package/server/{providers-D7IluJe0.js → providers-BI1mOBQ4.js} +1 -1
  205. package/server/{providers-evXhiQeg.js → providers-BJQSnAAp.js} +7 -7
  206. package/server/public/assets/{chunk-BO2N2NFS-D1s4-Sqp.js → chunk-BO2N2NFS-D_pGACYN.js} +4 -4
  207. package/server/public/assets/{diagram-OG6HWLK6-1gdMoSF7.js → diagram-OG6HWLK6-BO6fe3hH.js} +1 -1
  208. package/server/public/assets/{dist-DqDRYW6P.js → dist-5zingMiA.js} +3 -3
  209. package/server/public/assets/{dist-CxAOHbil.js → dist-CVxhbI2E.js} +1 -1
  210. package/server/public/assets/{ganttDiagram-6RSMTGT7-BYex-Ec7.js → ganttDiagram-6RSMTGT7-Bgj4A7kp.js} +1 -1
  211. package/server/public/assets/{highlighted-body-OFNGDK62-DlVkiG0S.js → highlighted-body-OFNGDK62-DNPK7_cm.js} +1 -1
  212. package/server/public/assets/{index-K0hAYCgV.js → index-DEpY-D1O.js} +148 -148
  213. package/server/public/assets/index-Ddkcz3WT.css +1 -0
  214. package/server/public/assets/{linear-B4cuEFmO.js → linear-BB0jQT16.js} +1 -1
  215. package/server/public/assets/mermaid-GHXKKRXX-BzPfaQJ1.js +1 -0
  216. package/server/public/assets/{pieDiagram-4H26LBE5-CBHNBIJQ.js → pieDiagram-4H26LBE5-DeGIzzpZ.js} +1 -1
  217. package/server/public/assets/{prod-CN2nHBvX.js → prod-XBLvikex.js} +4 -4
  218. package/server/public/assets/{quadrantDiagram-W4KKPZXB-Bom87VOQ.js → quadrantDiagram-W4KKPZXB-BV9SLeWz.js} +1 -1
  219. package/server/public/assets/{sankeyDiagram-5OEKKPKP-UrBeyLxk.js → sankeyDiagram-5OEKKPKP-Dwja0gj8.js} +1 -1
  220. package/server/public/assets/{xychartDiagram-2RQKCTM6-DhkbrIxR.js → xychartDiagram-2RQKCTM6-DCB4qvfw.js} +1 -1
  221. package/server/public/index.html +2 -2
  222. package/server/{pull-requests-DHWiKxo7.js → pull-requests-7BgLDsIo.js} +3 -3
  223. package/server/{pull-requests-Cv7LxzUN.js → pull-requests-Dq0y6IxE.js} +1 -1
  224. package/server/{queries-DHJm7bTd.js → queries-C-MUZaIy.js} +266 -155
  225. package/server/{rally-B71M9f4o.js → rally-CPysR4T_.js} +3 -3
  226. package/server/rally-D_VW4bJv.js +3 -0
  227. package/server/{rally-api-Dkqmok65.js → rally-api-8Ptlp2os.js} +2 -2
  228. package/server/{rally-api-D5uXN08-.js → rally-api-CgosKdKL.js} +1 -1
  229. package/server/{rally-client-CxsA6ExK.js → rally-client-CCX0hADj.js} +1 -1
  230. package/server/{rally-client-Bfqm6XI4.js → rally-client-iYMHWQD7.js} +5 -5
  231. package/server/{reap-terminal-sessions-BQ23nriz.js → reap-terminal-sessions-4Xg9NGA8.js} +2 -2
  232. package/server/{reap-terminal-sessions-CvmwaqKv.js → reap-terminal-sessions-Qf-9LVQc.js} +2 -2
  233. package/server/{rebuild-stack-0EEYReVZ.js → rebuild-stack-CMdgaylx.js} +7 -7
  234. package/server/{rebuild-stack-qeRqHZxH.js → rebuild-stack-DqcOVmJO.js} +2 -2
  235. package/server/{reconstruct-cache-BbYFsqLa.js → reconstruct-cache-CMZJ_Vjq.js} +9 -8
  236. package/server/{record-CtroO946.js → record-BTwWhtBb.js} +1 -1
  237. package/server/{record-update-Z0QCxmMp.js → record-update-DaOKS7Wb.js} +5 -128
  238. package/server/{record-update-DH6dLJID.js → record-update-DhI7eySG.js} +1 -1
  239. package/server/{recovery-trip-eJe26h-f.js → recovery-trip-DDH-02ng.js} +2 -2
  240. package/server/{release-engine-lPUp-MTd.js → release-engine-B2X9AfFC.js} +5 -5
  241. package/server/{release-set-BwGeyZKX.js → release-set-G4XKyQ8K.js} +3 -3
  242. package/server/{remote-BCd02Es1.js → remote-BXarMvqf.js} +3 -3
  243. package/server/{remote-CVGUhXMV.js → remote-CUhyqjXk.js} +3 -3
  244. package/server/{remote-agents-C_VxssLU.js → remote-agents-Bba-MgSA.js} +17 -8
  245. package/server/{remote-agents-C1bssi41.js → remote-agents-CLZB3Coc.js} +1 -1
  246. package/server/{remote-completion-DAB0P706.js → remote-completion-CwAp79EC.js} +13 -13
  247. package/server/resume-mOREjlYu.js +3 -0
  248. package/server/{review-agent-CHhI66UP.js → review-agent--pOptAEV.js} +31 -29
  249. package/server/{review-agent-CD4RCI0Y.js → review-agent-BTCNkq2h.js} +1 -1
  250. package/server/{review-artifacts-DSMRIfuJ.js → review-artifacts-BNmw8dWE.js} +5 -5
  251. package/server/{review-context-oFuBbiEE.js → review-context-DFxYOOJW.js} +9 -9
  252. package/server/{review-convoy-liveness-CpzrcJ5F.js → review-convoy-liveness-BgU_1jJf.js} +2 -2
  253. package/server/{review-status-yljtTd-q.js → review-status-CGvlA4o_.js} +326 -110
  254. package/server/review-status-Dma9SFaN.js +3 -0
  255. package/server/{review-status-emit-CUExtHd5.js → review-status-emit-DURrmGYX.js} +3 -3
  256. package/server/{review-status-enrichment-QV_hQkgS.js → review-status-enrichment-8NiNXi5W.js} +3 -3
  257. package/server/{review-status-source-ylw5QZUR.js → review-status-source-BLx_1siH.js} +1 -1
  258. package/server/{review-status-source-CpvJnvnQ.js → review-status-source-DIk1JSow.js} +1 -1
  259. package/server/{review-status-sync-483sujRo.js → review-status-sync-0GxOqeqF.js} +11 -6
  260. package/server/{review-status-sync-NaWvI9Xf.js → review-status-sync-muT-EBp2.js} +1 -1
  261. package/server/{review-verdict-feedback-BPDn4li_.js → review-verdict-feedback-HwF6ODFy.js} +1 -1
  262. package/server/{review-verdict-feedback-CELeUinh.js → review-verdict-feedback-xJNdqBnX.js} +23 -9
  263. package/server/{rollup-DTNvelz9.js → rollup-BQaol5TX.js} +8 -8
  264. package/server/{rollup-DYZfq1c4.js → rollup-BR4t_wck.js} +1 -1
  265. package/server/{scanner-CV35oSn4.js → scanner-C-D2cFdX.js} +7 -7
  266. package/server/{sequence-io-DF_8iuhV.js → sequence-io-Bmf1EZM5.js} +4 -4
  267. package/server/{sequencer-agent-B2WeCtGi.js → sequencer-agent-CigMyKh2.js} +7 -6
  268. package/server/server.js +435 -418
  269. package/server/{service-Br9rpBNA.js → service-CD0DvFvD.js} +88 -59
  270. package/server/{session-fork-D0LY152N.js → session-fork-B6cQ5eya.js} +2 -2
  271. package/server/{session-history-BUyK29eq.js → session-history-3ON_IJjm.js} +7 -55
  272. package/server/settings-CVmWiJ-r.js +2 -0
  273. package/server/{settings-CvVGqNEs.js → settings-PilbFZAM.js} +2 -2
  274. package/server/{settings-Bse1Pdcj.js → settings-VN0qOh4U.js} +3 -3
  275. package/server/{shadow-engineering-BWLa8ODz.js → shadow-engineering-DXvx77oE.js} +3 -3
  276. package/server/{shadow-state-B4fpKxOO.js → shadow-state-BBk_zacw.js} +2 -2
  277. package/server/{shadow-state-FV6PHfEW.js → shadow-state-CZBp7pwq.js} +1 -1
  278. package/server/{shadow-utils-D7asqxOZ.js → shadow-utils-DdZ05AJS.js} +2 -2
  279. package/server/{ship-log-xplJ8t75.js → ship-log-7kJfjUX2.js} +1 -1
  280. package/server/{smart-compaction-CPp2Ykf6.js → smart-compaction-8fA5k5XN.js} +1 -1
  281. package/server/{smart-compaction-D3U_79f-.js → smart-compaction-ByhL9cRS.js} +7 -7
  282. package/server/{spawn-planning-session-DGfZ5B8D.js → spawn-planning-session-pcF-YeFE.js} +38 -50
  283. package/server/spawn-planning-session-vLUJoFjy.js +3 -0
  284. package/server/{specialist-completion-Br48eiDP.js → specialist-completion-B07XjWD2.js} +1 -1
  285. package/server/{specialist-context-cVbGnTa3.js → specialist-context-DJ-zFyL3.js} +5 -5
  286. package/server/{specialist-handoff-logger-DK-GTz4s.js → specialist-handoff-logger-aKSxbIgD.js} +2 -2
  287. package/server/{specialist-logs-Cl5-hqT8.js → specialist-logs-Dae-n52_.js} +3 -3
  288. package/server/{specialists-CNfYO3G2.js → specialists-6PWdtWcg.js} +298 -180
  289. package/server/{specialists-Tdezg_6N.js → specialists-Bz-wFT7R.js} +1 -1
  290. package/server/{specialists-Cicieuzu.js → specialists-DUiExaxb.js} +18 -18
  291. package/server/{specialists-JHsdU3pA.js → specialists-KR3pKulN.js} +1 -1
  292. package/server/specs--enInima.js +3 -0
  293. package/server/{src-CRmCHlma.js → src-B948bGVR.js} +57 -13
  294. package/server/{src-Ck028hjO.js → src-rac0Mepv.js} +6 -6
  295. package/server/{src-UWcGe0Ix.js → src-vHy2-oCv.js} +3 -3
  296. package/server/{stack-health-CJLMrLBl.js → stack-health-BikqHSjn.js} +1 -1
  297. package/server/{stack-health-DqSqx0zv.js → stack-health-DqLTiEu4.js} +2 -2
  298. package/server/{stale-task-claims-CYFOUNlT.js → stale-task-claims-Cab_Fo_Z.js} +5 -4
  299. package/server/{staleness-D47CUJok.js → staleness-C-a5rBxF.js} +1 -1
  300. package/server/{staleness-BQ-0gMYK.js → staleness-CGTZyp6V.js} +1 -1
  301. package/server/{state-home-BYV7qZTW.js → state-home-722Dkx92.js} +2 -2
  302. package/server/{state-mapping-BVldLhBf.js → state-mapping-CybR81Uf.js} +1 -1
  303. package/server/{state-migrate-CvvBtS0Y.js → state-migrate-2u8wIpoL.js} +4 -4
  304. package/server/{stuck-remediation-mkLC6G_t.js → stuck-remediation-CC6q3eqQ.js} +24 -23
  305. package/server/{stuck-remediation-Wt0UVvu1.js → stuck-remediation-r1TJu68G.js} +1 -1
  306. package/server/{substrate-bug-weights-service-XfLAKnmK.js → substrate-bug-weights-service-CzIyyWFT.js} +3 -3
  307. package/server/{summary-fork-CD7GOts0.js → summary-fork-BqgmgPDt.js} +2 -2
  308. package/server/{summary-fork-xiXBnWG9.js → summary-fork-Df2WFijM.js} +8 -8
  309. package/server/supervisor/{injection-budget-B5SbvDx2.js → injection-budget-Cg_KIb3o.js} +1 -1
  310. package/server/supervisor/{paths-K3noE4N_.js → paths-BBOnCYlO.js} +10 -2
  311. package/server/supervisor/pty-supervisor.js +4 -4
  312. package/server/supervisor/{pty-token-B7lp0ElT.js → pty-token-BbjwEUUM.js} +3 -3
  313. package/server/supervisor-B4anCCSm.js +2 -0
  314. package/server/{supervisor-DL788vos.js → supervisor-BxqSpjcN.js} +3 -3
  315. package/server/{swarm-readiness-BV14DF5N.js → swarm-readiness-DfFxa9-n.js} +3 -3
  316. package/server/{system-prerequisites-pdWG6ZQs.js → system-prerequisites-ICLSkhhZ.js} +2 -2
  317. package/server/{teardown-workspace-l2F4_zim.js → teardown-workspace-DRdi_CPa.js} +15 -15
  318. package/server/{test-agent-queue-qakFIIGz.js → test-agent-queue-A_-p-i0I.js} +8 -7
  319. package/server/{test-verdict-Gw-btEfb.js → test-verdict-BHgTAwIG.js} +1 -1
  320. package/server/{test-verdict-BJYDggMm.js → test-verdict-C4i9aqEP.js} +1 -1
  321. package/server/{tldr-daemon-BKOYB616.js → tldr-daemon-CvWXBhX1.js} +1 -1
  322. package/server/{tldr-daemon-CBaWkV9k.js → tldr-daemon-wvsU6bKv.js} +2 -2
  323. package/server/{tmux-B1Wbxz5o.js → tmux-CfDHob9M.js} +174 -4
  324. package/server/{tmux-DQ6jB76i.js → tmux-Ctk6RV5l.js} +1 -1
  325. package/server/{token-Cxbk023d.js → token-DrxwytsZ.js} +2 -2
  326. package/server/{token-util-CLq2MmQt.js → token-util-B48BlCba.js} +1 -1
  327. package/server/token-util-D411CAq9.js +3 -0
  328. package/server/{tracker-config-DZ8Zn2nQ.js → tracker-config-BcPMElRB.js} +2 -2
  329. package/server/{tracker-utils-L0FKtjq2.js → tracker-utils-CJ6BHjcD.js} +2 -2
  330. package/server/{traefik-connect-bNX6jKkb.js → traefik-connect-DZ6nMYMj.js} +1 -1
  331. package/server/{tunnel-CjSnHdTc.js → tunnel-Bp-dRHZz.js} +1 -1
  332. package/server/{tunnel-BAm1XgjG.js → tunnel-DUbUPElU.js} +3 -3
  333. package/server/{typed-errors-BHhE85Ul.js → typed-errors-CKeoDdU3.js} +1 -1
  334. package/server/{typed-errors-2BTMxkZq.js → typed-errors-DyjseiB6.js} +1 -1
  335. package/server/{types-hraoaQIp.js → types-Cm5ASJbq.js} +1 -1
  336. package/server/{types-q67TYYg5.js → types-Di8wdakq.js} +1 -1
  337. package/server/{uat-promote-verification-CKB9ZrKC.js → uat-promote-verification-CoJuh7XO.js} +5 -5
  338. package/server/{uat-train-D5UjcyAa.js → uat-train-4Q0k06CQ.js} +0 -0
  339. package/server/{uat-train-Cu-4nvbf.js → uat-train-Dewoatps.js} +1 -1
  340. package/server/{validate-Cxsx5Uz1.js → validate-B0C8p66t.js} +3 -3
  341. package/server/{validation-VZgJxmqc.js → validation-B_kIRfNe.js} +4 -4
  342. package/server/{validation-DEaTZafj.js → validation-hVOwQk8T.js} +1 -1
  343. package/server/{verification-artifact-C85cRTc_.js → verification-artifact-BxlxTiYK.js} +1 -1
  344. package/server/{verification-artifact-g3yuxQDL.js → verification-artifact-D70AtckY.js} +1 -1
  345. package/server/{verification-runner-DlZI8yhw.js → verification-runner-Bc3cJvpC.js} +1 -1
  346. package/server/{verification-runner-KDZIsBj4.js → verification-runner-KZTz6u72.js} +19 -19
  347. package/server/{vtt-parser-Jr94BF3Y.js → vtt-parser-CE_i3Bcw.js} +1 -1
  348. package/server/{work-agent-prompt-C-vuP3_J.js → work-agent-prompt-ByrPAzOy.js} +9 -9
  349. package/server/{workflows-D0oip4eV.js → workflows-D0vP1WrK.js} +113 -43
  350. package/server/workflows-DtDX08ed.js +2 -0
  351. package/server/{workspace-BqFg__wH.js → workspace-COWvdibH.js} +1 -1
  352. package/server/{workspace-C0fH3aek.js → workspace-DQkRPLlQ.js} +3 -3
  353. package/server/{workspace-anchor-drift-CZKofakh.js → workspace-anchor-drift-DXYIAHzr.js} +4 -4
  354. package/server/{workspace-anchor-drift-B4gMRHl4.js → workspace-anchor-drift-pwz23TI1.js} +1 -1
  355. package/server/{workspace-config-B123aZl-.js → workspace-config-BdZM4PvZ.js} +1 -1
  356. package/server/{workspace-manager-CwO-Hek7.js → workspace-manager-BPgTrG66.js} +13 -13
  357. package/server/{workspace-manager-CDTKjjdU.js → workspace-manager-C1F3XsnS.js} +1 -1
  358. package/server/{workspace-metadata-D4M8BM4W.js → workspace-metadata-CdjzAP8x.js} +1 -1
  359. package/server/{workspace-metadata-CQv00QwK.js → workspace-metadata-DkO_iTLo.js} +2 -2
  360. package/server/{workspaces-j1e_6aAT.js → workspaces-CRBJikLp.js} +136 -113
  361. package/sync-sources/skills/pan-merge/SKILL.md +7 -5
  362. package/sync-sources/skills/pan-release/SKILL.md +57 -0
  363. package/server/agent-state-service-hZpxIw1E.js +0 -2
  364. package/server/archive-planning-0FJ6Xd3b.js +0 -2
  365. package/server/cli-DmXETsw-.js +0 -3
  366. package/server/conflict-gate-Dh754uyA.js +0 -3
  367. package/server/deacon-swarm-I2JfX5Tg.js +0 -2
  368. package/server/dist-DSlxIU1H.js +0 -3
  369. package/server/durable-review-pipeline-jpgCJZFp.js +0 -3
  370. package/server/forge-DK3blQb_.js +0 -3
  371. package/server/hume-Dq--7rOQ.js +0 -3
  372. package/server/inspect-agent-BVwDrVrz.js +0 -2
  373. package/server/label-reconciler--F85rufp.js +0 -113
  374. package/server/merge-ops-DdpTiEMt.js +0 -2
  375. package/server/merge-rebase-DGQpYJU3.js +0 -2
  376. package/server/merge-sync-Ca7F5JnQ.js +0 -3
  377. package/server/public/assets/index-Cc7cnFC4.css +0 -1
  378. package/server/public/assets/mermaid-GHXKKRXX-DyDHFXHV.js +0 -1
  379. package/server/rally-YDjU513q.js +0 -3
  380. package/server/resume-u9byntrq.js +0 -3
  381. package/server/review-status-BZH8h-6W.js +0 -3
  382. package/server/settings-CdvIF84R.js +0 -2
  383. package/server/spawn-planning-session-1nFi3gfk.js +0 -2
  384. package/server/specs-Bt7WJDoC.js +0 -3
  385. package/server/supervisor-UWiQNK-y.js +0 -2
  386. package/server/token-util-zlz9U0ki.js +0 -3
  387. package/server/workflows-CHrx_hcW.js +0 -2
@@ -1,21 +1,23 @@
1
1
  import { n as __esmMin } from "./rolldown-runtime-DNCzzKnI.js";
2
- import { Cn as resolveStateReadHomeSync, Gn as init_projects, Lt as readIssueRecord, Mn as findProjectByPathSync, Mt as getIssueWorkspacePath, Pt as init_record, Sn as init_state_read_home, ar as resolveProjectFromIssueSync, ci as init_paths, f as loadConfigSync, si as getOverdeckHome, t as init_config_yaml, ui as packageRoot, zn as getProjectSync, zt as readIssueRecordSync } from "./config-yaml-CmOPzmBb.js";
2
+ import { Cn as resolveStateReadHomeSync, Gn as init_projects, Lt as readIssueRecord, Mn as findProjectByPathSync, Mt as getIssueWorkspacePath, Pt as init_record, Sn as init_state_read_home, ar as resolveProjectFromIssueSync, ci as getOverdeckHome, di as packageRoot, f as loadConfigSync, li as init_paths, t as init_config_yaml, zn as getProjectSync, zt as readIssueRecordSync } from "./config-yaml-CxdwhAIA.js";
3
3
  import { i as emitActivityTtsSync, o as init_activity_logger, r as emitActivityEntrySync } from "./activity-logger-CyteR4JO.js";
4
- import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-BjuxvjdS.js";
5
- import { i as updateIssueRecord, r as init_record_update } from "./record-update-Z0QCxmMp.js";
6
- import { d as init_cost_sync, i as getCostBreakdownByStageAndModelSync, o as getCostForIssueSync } from "./cost-sync-Dv3LUaNW.js";
7
- import { r as notifyPipelineSync, t as init_pipeline_notifier } from "./pipeline-notifier-BuQ0e4hF.js";
8
- import { c as init_review_status_sync, d as init_review_status_normalize, f as normalizeReviewStatusSync, l as markWorkspaceStuck$1, n as deleteReviewStatus, o as getReviewStatusFromDbSync, r as getAllReviewStatusesFromDb, s as getReviewStatusesFromDb, t as clearWorkspaceStuck$1, u as upsertReviewStatusSync } from "./review-status-sync-483sujRo.js";
9
- import { a as registerCanonicalReviewStatusResolver, n as init_review_status_source, o as registerReviewStatusMapReader } from "./review-status-source-CpvJnvnQ.js";
10
- import { a as PAN_DIRNAME, p as init_types$3, r as PAN_CONTINUES_DIRNAME } from "./types-hraoaQIp.js";
11
- import { i as init_merge_set, r as getMergeSetSync } from "./merge-set-DH7ot3yz.js";
12
- import { o as init_lifecycle, r as XBRIEF_FILENAME_SUFFIX, t as LEGACY_VBRIEF_FILENAME_SUFFIX } from "./lifecycle-CTdOWYMi.js";
4
+ import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-BDQDRopn.js";
5
+ import { i as updateIssueRecord, r as init_record_update } from "./record-update-DaOKS7Wb.js";
6
+ import { d as init_cost_sync, i as getCostBreakdownByStageAndModelSync, o as getCostForIssueSync } from "./cost-sync-tOCCGnEt.js";
7
+ import { r as notifyPipelineSync, t as init_pipeline_notifier } from "./pipeline-notifier-D0ALV6Nw.js";
8
+ import { c as init_review_status_sync, d as init_review_status_normalize, f as normalizeReviewStatusSync, l as markWorkspaceStuck$1, n as deleteReviewStatus, o as getReviewStatusFromDbSync, r as getAllReviewStatusesFromDb, s as getReviewStatusesFromDb, t as clearWorkspaceStuck$1, u as upsertReviewStatusSync } from "./review-status-sync-0GxOqeqF.js";
9
+ import { a as registerCanonicalReviewStatusResolver, n as init_review_status_source, o as registerReviewStatusMapReader } from "./review-status-source-DIk1JSow.js";
10
+ import { a as PAN_DIRNAME, d as WORKSPACE_RUNTIME_DIRNAME, p as init_types$3, r as PAN_CONTINUES_DIRNAME } from "./types-Cm5ASJbq.js";
11
+ import { i as init_merge_set, r as getMergeSetSync } from "./merge-set-CBgHfwM0.js";
12
+ import { o as init_lifecycle, r as XBRIEF_FILENAME_SUFFIX, t as LEGACY_VBRIEF_FILENAME_SUFFIX } from "./lifecycle-B4Xdb4cY.js";
13
13
  import { basename, dirname, join } from "node:path";
14
14
  import { Data, Effect } from "effect";
15
+ import { existsSync, readFileSync, readdirSync, statSync } from "fs";
15
16
  import { dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, posix, relative as relative$1, sep as sep$1 } from "path";
16
17
  import { homedir } from "os";
17
18
  import { hostname } from "node:os";
18
- import { chmodSync, createReadStream, existsSync, linkSync, mkdirSync, promises, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
19
+ import { chmodSync as chmodSync$1, createReadStream as createReadStream$1, existsSync as existsSync$1, linkSync, mkdirSync as mkdirSync$1, promises as promises$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, renameSync as renameSync$1, rmSync as rmSync$1, statSync as statSync$1, writeFileSync as writeFileSync$1 } from "node:fs";
20
+ import { readFile, readdir } from "node:fs/promises";
19
21
  import { inspect } from "node:util";
20
22
  import { randomUUID } from "node:crypto";
21
23
  import { createInterface } from "node:readline";
@@ -76,6 +78,7 @@ function overdeckRowToAgentState(row) {
76
78
  phase: row.phase == null ? void 0 : row.phase,
77
79
  roleRunHead: row.role_run_head ?? void 0,
78
80
  flywheelRunId: row.flywheel_run_id ?? void 0,
81
+ startedBy: row.started_by ?? void 0,
79
82
  costSoFar: row.cost_so_far ?? void 0,
80
83
  reviewSubRole: row.review_sub_role ?? void 0,
81
84
  reviewRunId: row.review_run_id ?? void 0,
@@ -129,6 +132,7 @@ function stateToOverdeckParamsForDb(state, updatedAt) {
129
132
  state.phase ?? null,
130
133
  state.roleRunHead ?? null,
131
134
  state.flywheelRunId ?? null,
135
+ state.startedBy ?? null,
132
136
  state.costSoFar ?? null,
133
137
  state.reviewSubRole ?? null,
134
138
  state.reviewRunId ?? null,
@@ -196,6 +200,7 @@ var init_agent_state_sync = __esmMin((() => {
196
200
  "phase",
197
201
  "role_run_head",
198
202
  "flywheel_run_id",
203
+ "started_by",
199
204
  "cost_so_far",
200
205
  "review_sub_role",
201
206
  "review_run_id",
@@ -259,6 +264,7 @@ function projectPipeline(issueId, status, existing) {
259
264
  inspectNotes: status.inspectNotes,
260
265
  mergeNotes: status.mergeNotes,
261
266
  blockerReasons: status.blockerReasons,
267
+ conflictsSince: status.conflictsSince,
262
268
  prUrl: status.prUrl,
263
269
  prNumber: status.prNumber,
264
270
  prHeadSha: status.prHeadSha,
@@ -272,6 +278,7 @@ function projectPipeline(issueId, status, existing) {
272
278
  deaconIgnoredAt: status.deaconIgnoredAt,
273
279
  deaconIgnoredReason: status.deaconIgnoredReason,
274
280
  reviewerVerdicts: status.reviewerVerdicts,
281
+ reviewCycleHistory: status.reviewCycleHistory,
275
282
  strikeReadyHead: status.strikeReadyHead,
276
283
  strikeReadyAt: status.strikeReadyAt,
277
284
  strikeLandingState: status.strikeLandingState,
@@ -305,13 +312,13 @@ function resolveContinuePath(projectRoot, issueId) {
305
312
  const basePath = join(stateHome.migrated ? join(stateHome.root, PAN_CONTINUES_DIRNAME) : join(stateHome.root, PAN_DIRNAME, PAN_CONTINUES_DIRNAME), issueId.toLowerCase());
306
313
  const canonicalPath = `${basePath}${XBRIEF_FILENAME_SUFFIX}`;
307
314
  const legacyPath = `${basePath}${LEGACY_VBRIEF_FILENAME_SUFFIX}`;
308
- if (existsSync(canonicalPath)) return canonicalPath;
309
- if (existsSync(legacyPath)) return legacyPath;
315
+ if (existsSync$1(canonicalPath)) return canonicalPath;
316
+ if (existsSync$1(legacyPath)) return legacyPath;
310
317
  return canonicalPath;
311
318
  }
312
319
  async function readLegacyContinueText(projectRoot, issueId) {
313
320
  try {
314
- return await promises.readFile(resolveContinuePath(projectRoot, issueId), "utf-8");
321
+ return await promises$1.readFile(resolveContinuePath(projectRoot, issueId), "utf-8");
315
322
  } catch {
316
323
  return null;
317
324
  }
@@ -319,10 +326,10 @@ async function readLegacyContinueText(projectRoot, issueId) {
319
326
  /** Read workspace continue.json and return its statusOverrides (if any). */
320
327
  async function readWorkspaceContinueStatusOverrides(issueId) {
321
328
  const workspacePath = getIssueWorkspacePath(issueId);
322
- if (!workspacePath || !existsSync(workspacePath)) return void 0;
329
+ if (!workspacePath || !existsSync$1(workspacePath)) return void 0;
323
330
  const continuePath = join(workspacePath, ".pan", "continue.json");
324
331
  try {
325
- const text = await promises.readFile(continuePath, "utf-8");
332
+ const text = await promises$1.readFile(continuePath, "utf-8");
326
333
  return JSON.parse(text).statusOverrides ?? void 0;
327
334
  } catch {
328
335
  return;
@@ -459,6 +466,17 @@ function readPipelineSync(issueId) {
459
466
  return null;
460
467
  }
461
468
  }
469
+ async function readPipeline(issueId) {
470
+ try {
471
+ const resolved = resolveProjectFromIssueSync(issueId);
472
+ if (!resolved) return null;
473
+ const project = getProjectSync(resolved.projectKey);
474
+ if (!project) return null;
475
+ return (await readIssueRecord(project, issueId))?.pipeline ?? null;
476
+ } catch {
477
+ return null;
478
+ }
479
+ }
462
480
  /**
463
481
  * PAN-1988: feedback TEXT (review / test / merge / inspect / verification notes) is durable
464
482
  * JOURNAL state, not DB-cache state. The SQLite row holds only the queryable status flags;
@@ -507,6 +525,7 @@ function durableSubset(p) {
507
525
  reviewRequestedAt: p.reviewRequestedAt,
508
526
  reviewSpawnedAt: p.reviewSpawnedAt,
509
527
  reviewerVerdicts: p.reviewerVerdicts,
528
+ reviewCycleHistory: p.reviewCycleHistory,
510
529
  autoMerge: p.autoMerge,
511
530
  deaconIgnored: p.deaconIgnored,
512
531
  deaconIgnoredAt: p.deaconIgnoredAt,
@@ -518,6 +537,7 @@ function durableSubset(p) {
518
537
  strikeTransportRetryCount: p.strikeTransportRetryCount,
519
538
  strikeNextAttemptAt: p.strikeNextAttemptAt,
520
539
  strikeLandingAttempts: p.strikeLandingAttempts,
540
+ conflictsSince: p.conflictsSince,
521
541
  closedOut: p.closedOut,
522
542
  closedOutAt: p.closedOutAt
523
543
  };
@@ -538,7 +558,7 @@ function writeWorkspaceVerdictFallbackSync(issueId, status) {
538
558
  console.error(`[review-status] PAN-2583: journal write failed for ${issueId} and no workspace could be resolved — the verdict is NOT durable`);
539
559
  return;
540
560
  }
541
- mkdirSync(dirname(path), { recursive: true });
561
+ mkdirSync$1(dirname(path), { recursive: true });
542
562
  const clearedFields = FALLBACK_CLEARABLE_FIELDS.filter((field) => status[field] === void 0);
543
563
  const payload = {
544
564
  issueId: issueId.toUpperCase(),
@@ -547,16 +567,16 @@ function writeWorkspaceVerdictFallbackSync(issueId, status) {
547
567
  ...clearedFields.length > 0 ? { clearedFields } : {}
548
568
  };
549
569
  const tmpPath = `${path}.tmp-${process.pid}`;
550
- writeFileSync(tmpPath, JSON.stringify(payload, null, 2));
551
- renameSync(tmpPath, path);
570
+ writeFileSync$1(tmpPath, JSON.stringify(payload, null, 2));
571
+ renameSync$1(tmpPath, path);
552
572
  console.warn(`[review-status] journal write failed for ${issueId} — durable verdict written to workspace fallback ${path}; the host sweeps it on the next status read (PAN-2583)`);
553
573
  } catch (err) {
554
574
  console.error(`[review-status] PAN-2583: could not persist verdict for ${issueId} anywhere durable: ${err.message}`);
555
575
  }
556
576
  }
557
- function parseWorkspaceVerdictFallback(path) {
577
+ function decodeWorkspaceVerdictFallback(raw) {
558
578
  try {
559
- const parsed = JSON.parse(readFileSync(path, "utf-8"));
579
+ const parsed = JSON.parse(raw);
560
580
  if (!parsed?.updatedAt || !parsed.pipeline) return null;
561
581
  const clearedFields = Array.isArray(parsed.clearedFields) ? parsed.clearedFields.filter((field) => typeof field === "string" && FALLBACK_CLEARABLE_FIELDS.includes(field)) : [];
562
582
  return {
@@ -567,6 +587,20 @@ function parseWorkspaceVerdictFallback(path) {
567
587
  return null;
568
588
  }
569
589
  }
590
+ function parseWorkspaceVerdictFallback(path) {
591
+ try {
592
+ return decodeWorkspaceVerdictFallback(readFileSync$1(path, "utf-8"));
593
+ } catch {
594
+ return null;
595
+ }
596
+ }
597
+ async function parseWorkspaceVerdictFallbackAsync(path) {
598
+ try {
599
+ return decodeWorkspaceVerdictFallback(await readFile(path, "utf-8"));
600
+ } catch {
601
+ return null;
602
+ }
603
+ }
570
604
  function isPidAlive(pid) {
571
605
  try {
572
606
  process.kill(pid, 0);
@@ -597,7 +631,7 @@ function claimWorkspaceVerdictFallbackSync(issueId) {
597
631
  const prefix = `${basename(path)}.drain-`;
598
632
  let entries;
599
633
  try {
600
- entries = readdirSync(dir);
634
+ entries = readdirSync$1(dir);
601
635
  } catch {
602
636
  return null;
603
637
  }
@@ -614,13 +648,13 @@ function claimWorkspaceVerdictFallbackSync(issueId) {
614
648
  drainClaimCounter += 1;
615
649
  const claimPath = `${path}.drain-${process.pid}-${drainClaimCounter}`;
616
650
  try {
617
- renameSync(candidate, claimPath);
651
+ renameSync$1(candidate, claimPath);
618
652
  } catch {
619
653
  continue;
620
654
  }
621
655
  const fallback = parseWorkspaceVerdictFallback(claimPath);
622
656
  if (!fallback) {
623
- rmSync(claimPath, { force: true });
657
+ rmSync$1(claimPath, { force: true });
624
658
  continue;
625
659
  }
626
660
  claims.push({
@@ -638,9 +672,9 @@ function readWorkspaceVerdictFallbackSync(issueId) {
638
672
  const consider = (candidate) => {
639
673
  if (candidate && (!newest || newest.updatedAt < candidate.updatedAt)) newest = candidate;
640
674
  };
641
- if (existsSync(path)) consider(parseWorkspaceVerdictFallback(path));
675
+ if (existsSync$1(path)) consider(parseWorkspaceVerdictFallback(path));
642
676
  const prefix = `${basename(path)}.drain-`;
643
- for (const entry of readdirSync(dirname(path))) {
677
+ for (const entry of readdirSync$1(dirname(path))) {
644
678
  if (!entry.startsWith(prefix)) continue;
645
679
  consider(parseWorkspaceVerdictFallback(join(dirname(path), entry)));
646
680
  }
@@ -649,6 +683,18 @@ function readWorkspaceVerdictFallbackSync(issueId) {
649
683
  return null;
650
684
  }
651
685
  }
686
+ async function readWorkspaceVerdictFallback(issueId) {
687
+ try {
688
+ const path = workspaceVerdictFallbackPath(issueId);
689
+ if (!path) return null;
690
+ const dir = dirname(path);
691
+ const prefix = `${basename(path)}.drain-`;
692
+ const candidates = [path, ...(await readdir(dir)).filter((entry) => entry.startsWith(prefix)).map((entry) => join(dir, entry))];
693
+ return (await Promise.all(candidates.map(parseWorkspaceVerdictFallbackAsync))).reduce((newest, candidate) => candidate && (!newest || newest.updatedAt < candidate.updatedAt) ? candidate : newest, null);
694
+ } catch {
695
+ return null;
696
+ }
697
+ }
652
698
  /**
653
699
  * Fold a pending workspace verdict fallback into the canonical record and delete
654
700
  * it, without waiting for the next status read. Newer-wins on ISO `updatedAt` —
@@ -671,7 +717,7 @@ async function drainWorkspaceVerdictFallback(issueId) {
671
717
  const { fallback } = winner;
672
718
  const journal = readPipelineSync(issueId);
673
719
  if (journal?.updatedAt && !(journal.updatedAt < fallback.updatedAt)) {
674
- for (const claim of claims) rmSync(claim.claimPath, { force: true });
720
+ for (const claim of claims) rmSync$1(claim.claimPath, { force: true });
675
721
  return true;
676
722
  }
677
723
  if (await updateIssueRecordForIssue(issueId, {
@@ -680,10 +726,10 @@ async function drainWorkspaceVerdictFallback(issueId) {
680
726
  updatedAt: fallback.updatedAt,
681
727
  readyForMerge: false
682
728
  })) {
683
- for (const claim of claims) rmSync(claim.claimPath, { force: true });
729
+ for (const claim of claims) rmSync$1(claim.claimPath, { force: true });
684
730
  return true;
685
731
  }
686
- for (const claim of losers) rmSync(claim.claimPath, { force: true });
732
+ for (const claim of losers) rmSync$1(claim.claimPath, { force: true });
687
733
  const livePath = workspaceVerdictFallbackPath(issueId);
688
734
  if (livePath) {
689
735
  let published = false;
@@ -692,18 +738,18 @@ async function drainWorkspaceVerdictFallback(issueId) {
692
738
  published = true;
693
739
  } catch {}
694
740
  if (published) {
695
- rmSync(winner.claimPath, { force: true });
741
+ rmSync$1(winner.claimPath, { force: true });
696
742
  return false;
697
743
  }
698
- const live = existsSync(livePath) ? parseWorkspaceVerdictFallback(livePath) : null;
744
+ const live = existsSync$1(livePath) ? parseWorkspaceVerdictFallback(livePath) : null;
699
745
  if (live && !(live.updatedAt < fallback.updatedAt)) {
700
- rmSync(winner.claimPath, { force: true });
746
+ rmSync$1(winner.claimPath, { force: true });
701
747
  return false;
702
748
  }
703
749
  }
704
750
  drainClaimCounter += 1;
705
751
  try {
706
- renameSync(winner.claimPath, `${winner.claimPath.split(".drain-")[0]}.drain-republish-${drainClaimCounter}`);
752
+ renameSync$1(winner.claimPath, `${winner.claimPath.split(".drain-")[0]}.drain-republish-${drainClaimCounter}`);
707
753
  } catch {}
708
754
  return false;
709
755
  }
@@ -739,28 +785,10 @@ function scheduleVerdictFallbackDrain(issueId) {
739
785
  };
740
786
  attempt(0);
741
787
  }
742
- /**
743
- * PAN-1988: read the journal record's durable verdict for an issue — the SOURCE OF TRUTH.
744
- * Returns the record `updatedAt` (used to decide whether the journal is newer than the DB
745
- * cache) plus the durable status fields (flags + feedback notes). Derived/live columns
746
- * (readyForMerge, blockerReasons) are intentionally omitted — the reader recomputes them.
747
- *
748
- * This is what makes verdict writes host-owned: a sandboxed agent can always write the journal
749
- * (workspace-local) even when it cannot write `~/.overdeck/overdeck.db`. The host reconciles
750
- * the cache from this on read, so no agent has to escalate out of its sandbox to record a verdict.
751
- *
752
- * PAN-2583: since the records migration (PAN-2541) the journal itself lives in
753
- * ${OVERDECK_HOME}/state, which a sandboxed reviewer cannot write either. When such a
754
- * writer dropped its verdict into the workspace fallback instead, overlay it here —
755
- * a strictly newer fallback wins over the record, and the host's own next journal
756
- * write folds it back into the canonical record.
757
- */
758
- function readJournalStatusSync(issueId) {
759
- const p = readPipelineSync(issueId);
760
- const fallback = readWorkspaceVerdictFallbackSync(issueId);
761
- const fallbackNewer = !!fallback && (!p || (p.updatedAt ?? "") < fallback.updatedAt);
788
+ function projectJournalStatus(pipeline, fallback) {
789
+ const fallbackNewer = !!fallback && (!pipeline || (pipeline.updatedAt ?? "") < fallback.updatedAt);
762
790
  if (fallback && fallbackNewer) {
763
- const base = p ? durableSubset(p) : {};
791
+ const base = pipeline ? durableSubset(pipeline) : {};
764
792
  const overlay = Object.fromEntries(Object.entries(fallback.pipeline).filter(([, value]) => value !== void 0));
765
793
  const durable = {
766
794
  ...base,
@@ -773,12 +801,20 @@ function readJournalStatusSync(issueId) {
773
801
  ...fallback.clearedFields?.length ? { clearedFields: fallback.clearedFields } : {}
774
802
  };
775
803
  }
776
- if (!p) return null;
804
+ if (!pipeline) return null;
777
805
  return {
778
- updatedAt: p.updatedAt,
779
- durable: durableSubset(p)
806
+ updatedAt: pipeline.updatedAt,
807
+ durable: durableSubset(pipeline)
780
808
  };
781
809
  }
810
+ function readJournalStatusSync(issueId) {
811
+ return projectJournalStatus(readPipelineSync(issueId), readWorkspaceVerdictFallbackSync(issueId));
812
+ }
813
+ /** Async journal reader for patrols that must not block the dashboard event loop. */
814
+ async function readJournalStatus(issueId) {
815
+ const [pipeline, fallback] = await Promise.all([readPipeline(issueId), readWorkspaceVerdictFallback(issueId)]);
816
+ return projectJournalStatus(pipeline, fallback);
817
+ }
782
818
  var pendingJournalWrites, FALLBACK_CLEARABLE_FIELDS, drainClaimCounter, DRAIN_RETRY_DELAYS_MS, drainTimers;
783
819
  var init_review_status_record_sync = __esmMin((() => {
784
820
  init_records();
@@ -799,6 +835,117 @@ var init_review_status_record_sync = __esmMin((() => {
799
835
  drainTimers = /* @__PURE__ */ new Map();
800
836
  }));
801
837
  //#endregion
838
+ //#region ../../lib/review-findings.ts
839
+ /**
840
+ * Extract a markdown section by heading.
841
+ * Returns the content between a heading (e.g., "## Findings") and the next heading or EOF.
842
+ */
843
+ function extractMarkdownSection(markdown, heading) {
844
+ const pattern = new RegExp(`^##\\s+${heading}\\s*\\r?\\n([\\s\\S]*?)(?=^##\\s+|(?![\\s\\S]))`, "im");
845
+ return markdown.match(pattern)?.[1]?.trim() ?? "";
846
+ }
847
+ /**
848
+ * Find blocking findings in a report markdown section.
849
+ * Returns titles of findings marked with '!' or '⊗'.
850
+ */
851
+ function findBlockingFindings(markdown) {
852
+ const findings = extractMarkdownSection(markdown, "Findings");
853
+ if (!findings || /^none\.?$/i.test(findings)) return [];
854
+ const blockers = [];
855
+ const headingPattern = /^###\s*(?:!|⊗)\s+(.+)$/gm;
856
+ let match;
857
+ while ((match = headingPattern.exec(findings)) !== null) blockers.push(match[1].trim());
858
+ return blockers;
859
+ }
860
+ /**
861
+ * Count blocking findings in a synthesis body.
862
+ * Returns the count of '## Blocking Findings' section headings (### markers),
863
+ * or 0 if the section is absent, empty, or contains only 'None'.
864
+ */
865
+ function countSynthesisBlockingFindings(body) {
866
+ const findings = extractMarkdownSection(body, "Blocking Findings");
867
+ if (!findings || /^none\.?$/i.test(findings)) return 0;
868
+ const headingPattern = /^###\s+/gm;
869
+ let count = 0;
870
+ while (headingPattern.exec(findings) !== null) count++;
871
+ return count;
872
+ }
873
+ var init_review_findings = __esmMin((() => {}));
874
+ //#endregion
875
+ //#region ../../lib/cloister/review-convergence.ts
876
+ /**
877
+ * Review convergence detection and cycle tracking.
878
+ * Detects when a review loop is not making progress and should be gated.
879
+ */
880
+ /**
881
+ * Find the latest review run directory in a workspace.
882
+ * Looks for 'agent-*-review-*' directories under .pan/review, falling back to .overdeck/review.
883
+ * Returns null if no run directory is found.
884
+ */
885
+ function findLatestReviewRunDir(workspacePath) {
886
+ const paths = [join$1(workspacePath, PAN_DIRNAME, "review"), join$1(workspacePath, WORKSPACE_RUNTIME_DIRNAME, "review")];
887
+ for (const reviewDir of paths) {
888
+ if (!existsSync(reviewDir)) continue;
889
+ try {
890
+ const reviewDirs = readdirSync(reviewDir).filter((name) => /^agent-.*-review-/.test(name));
891
+ if (reviewDirs.length === 0) continue;
892
+ return join$1(reviewDir, reviewDirs.map((name) => ({
893
+ name,
894
+ mtime: statSync(join$1(reviewDir, name)).mtime.getTime()
895
+ })).sort((a, b) => b.mtime - a.mtime)[0].name);
896
+ } catch {
897
+ continue;
898
+ }
899
+ }
900
+ return null;
901
+ }
902
+ /**
903
+ * Count blocking findings for a specific review run.
904
+ * First tries synthesis.md '## Blocking Findings' heading count,
905
+ * falls back to summing findBlockingFindings across .md report files,
906
+ * returns null if no artifacts exist.
907
+ */
908
+ function countBlockingFindingsForRun(runDir) {
909
+ const synthesisPath = join$1(runDir, "synthesis.md");
910
+ if (existsSync(synthesisPath)) try {
911
+ const synthBody = readFileSync(synthesisPath, "utf8");
912
+ const count = countSynthesisBlockingFindings(synthBody);
913
+ if (count > 0 || synthBody.includes("## Blocking Findings")) return count;
914
+ } catch {}
915
+ try {
916
+ const reportFiles = readdirSync(runDir).filter((name) => name.endsWith(".md") && name !== "synthesis.md");
917
+ if (reportFiles.length === 0) return null;
918
+ let totalCount = 0;
919
+ for (const file of reportFiles) {
920
+ const findings = findBlockingFindings(readFileSync(join$1(runDir, file), "utf8"));
921
+ totalCount += findings.length;
922
+ }
923
+ return totalCount;
924
+ } catch {
925
+ return null;
926
+ }
927
+ }
928
+ /**
929
+ * Evaluate whether a review cycle series is converging.
930
+ * Returns 'not-converging' when:
931
+ * - counts.length >= 3 AND the series shows a reversal (count[n-1] > count[n-2]), OR
932
+ * - the last two transitions are both non-decreases (going backwards)
933
+ * Otherwise returns 'converging'.
934
+ */
935
+ function evaluateReviewConvergence(counts) {
936
+ if (counts.length < 3) return "converging";
937
+ const n = counts.length;
938
+ if (counts[n - 1] > counts[n - 2]) return "not-converging";
939
+ const isFirstNonDecreasing = counts[n - 2] >= counts[n - 3];
940
+ const isSecondNonDecreasing = counts[n - 1] >= counts[n - 2];
941
+ if (isFirstNonDecreasing && isSecondNonDecreasing) return "not-converging";
942
+ return "converging";
943
+ }
944
+ var init_review_convergence = __esmMin((() => {
945
+ init_types$3();
946
+ init_review_findings();
947
+ }));
948
+ //#endregion
802
949
  //#region ../../lib/review-status-reconcile.ts
803
950
  function verificationSatisfied(status) {
804
951
  return status.verificationStatus !== "failed";
@@ -827,7 +974,59 @@ function reconcileJournalIntoCacheSync(issueId, dbStatus, journal, hooks) {
827
974
  hooks.notifyStatusChanged(issueId, reconciled);
828
975
  } catch {}
829
976
  const wasBlocked = dbStatus?.reviewStatus === "blocked" || dbStatus?.reviewStatus === "failed";
830
- if ((reconciled.reviewStatus === "blocked" || reconciled.reviewStatus === "failed") && !wasBlocked) hooks.deliverReviewVerdictFeedbackHostSide(issueId, reconciled);
977
+ if ((reconciled.reviewStatus === "blocked" || reconciled.reviewStatus === "failed") && !wasBlocked) try {
978
+ const project = resolveProjectFromIssueSync(issueId);
979
+ if (!project) {
980
+ console.warn(`[review-status] reconcile: cannot resolve project for ${issueId}, skipping cycle recording`);
981
+ hooks.deliverReviewVerdictFeedbackHostSide(issueId, reconciled);
982
+ } else {
983
+ const issueLower = issueId.toLowerCase();
984
+ const reviewRunDir = findLatestReviewRunDir(`${project.projectPath}/workspaces/feature-${issueLower}`);
985
+ if (!reviewRunDir) {
986
+ console.warn(`[review-status] reconcile: no review run dir found for ${issueId}, skipping cycle recording`);
987
+ hooks.deliverReviewVerdictFeedbackHostSide(issueId, reconciled);
988
+ } else {
989
+ const blockingCount = countBlockingFindingsForRun(reviewRunDir);
990
+ if (blockingCount === null) {
991
+ console.warn(`[review-status] reconcile: cannot count findings for ${issueId}, skipping cycle recording`);
992
+ hooks.deliverReviewVerdictFeedbackHostSide(issueId, reconciled);
993
+ } else {
994
+ const runId = reviewRunDir.split("/").pop() ?? "";
995
+ if (!reconciled.reviewCycleHistory) reconciled.reviewCycleHistory = [];
996
+ const cycleNumber = reconciled.reviewCycleHistory.length + 1;
997
+ if (!reconciled.reviewCycleHistory.some((e) => e.runId === runId)) {
998
+ const entry = {
999
+ cycle: cycleNumber,
1000
+ runId,
1001
+ atCommit: reconciled.reviewedAtCommit,
1002
+ blockingCount,
1003
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString()
1004
+ };
1005
+ reconciled.reviewCycleHistory.push(entry);
1006
+ try {
1007
+ upsertReviewStatusSync(reconciled);
1008
+ } catch {}
1009
+ }
1010
+ const counts = reconciled.reviewCycleHistory.map((e) => e.blockingCount);
1011
+ if (evaluateReviewConvergence(counts) === "not-converging") {
1012
+ markWorkspaceStuck$1(issueId, "review-not-converging", { counts });
1013
+ reconciled.stuck = true;
1014
+ reconciled.stuckReason = "review-not-converging";
1015
+ reconciled.stuckAt = (/* @__PURE__ */ new Date()).toISOString();
1016
+ reconciled.stuckDetails = JSON.stringify({ counts });
1017
+ try {
1018
+ upsertReviewStatusSync(reconciled);
1019
+ } catch {}
1020
+ const countSeries = counts.join(" → ");
1021
+ console.error(`[review-status] reconcile: review loop not converging for ${issueId}: ${countSeries}. Consider decomposition (split the remaining work), or unstick to continue rework.`);
1022
+ } else hooks.deliverReviewVerdictFeedbackHostSide(issueId, reconciled);
1023
+ }
1024
+ }
1025
+ }
1026
+ } catch (error) {
1027
+ console.error(`[review-status] reconcile: cycle recording error for ${issueId}:`, error);
1028
+ hooks.deliverReviewVerdictFeedbackHostSide(issueId, reconciled);
1029
+ }
831
1030
  const wasReviewPassed = dbStatus?.reviewStatus === "passed";
832
1031
  if (reconciled.reviewStatus === "passed" && !wasReviewPassed && reconciled.testStatus === "pending") {
833
1032
  console.log(`[review-status] reconcile: review.approved for ${issueId} (host-owned handoff — sandboxed agent verdict from journal)`);
@@ -845,32 +1044,24 @@ function reconcileJournalIntoCacheSync(issueId, dbStatus, journal, hooks) {
845
1044
  var init_review_status_reconcile = __esmMin((() => {
846
1045
  init_review_status_normalize();
847
1046
  init_review_status_sync();
1047
+ init_review_convergence();
1048
+ init_projects();
848
1049
  }));
849
1050
  //#endregion
850
1051
  //#region ../../lib/review-dispatch-decision.ts
851
- /**
852
- * PAN-1988 auto-heal — decide whether a review needs to be (re-)dispatched from the durable
853
- * journal intent, as a PURE function so it is locked by tests.
854
- *
855
- * The work agent's `pan done` writes a durable `reviewRequestedAt` into the journal/record (always
856
- * writable, even sandboxed) BEFORE it tries to reach the dashboard. If that reactive trigger is
857
- * dropped — the dashboard was mid-reload, the network blipped, the deacon is frozen — the intent
858
- * survives in the journal. The host reconciles on read: when a request is newer than the last
859
- * dispatch and nothing is currently reviewing, it dispatches review. This heals with NO deacon and
860
- * NO live dashboard event, on the next status read.
861
- *
862
- * Returns true when a review dispatch is owed:
863
- * - a request exists (`reviewRequestedAt` set), AND
864
- * - it is newer than the last spawn (or there was never a spawn) — i.e. a genuinely un-serviced
865
- * request, not the request that produced the current review, AND
866
- * - review is pending rather than already reviewing or terminal, AND
867
- * - the issue is not already ready to merge or merged.
868
- *
869
- * Genuine re-review paths reset `reviewStatus` to `pending` before recording a fresh request: `pan
870
- * done` does this for a new commit, and the operator force-review route does it explicitly.
871
- */
1052
+ function isReviewRequestStale(params) {
1053
+ if (!params.reviewRequestedAt) return false;
1054
+ const now = params.now ?? Date.now();
1055
+ const maxAgeMs = params.maxAgeMs ?? 6048e5;
1056
+ return now - Date.parse(params.reviewRequestedAt) > maxAgeMs;
1057
+ }
872
1058
  function needsReviewDispatch(params) {
873
1059
  if (!params.reviewRequestedAt) return false;
1060
+ if (isReviewRequestStale({
1061
+ reviewRequestedAt: params.reviewRequestedAt,
1062
+ now: params.now,
1063
+ maxAgeMs: params.maxRequestAgeMs
1064
+ })) return false;
874
1065
  if (params.reviewStatus === "reviewing") return false;
875
1066
  if (params.reviewStatus === "passed" || params.reviewStatus === "skipped") return false;
876
1067
  if (params.readyForMerge) return false;
@@ -3663,7 +3854,7 @@ async function addSourceContext(frames) {
3663
3854
  }
3664
3855
  function getContextLinesFromFile(path, ranges, output) {
3665
3856
  return new Promise((resolve) => {
3666
- const stream = createReadStream(path);
3857
+ const stream = createReadStream$1(path);
3667
3858
  const lineReaded = createInterface({ input: stream });
3668
3859
  function destroyStreamAndResolve() {
3669
3860
  stream.destroy();
@@ -6346,7 +6537,7 @@ var init_config = __esmMin((() => {
6346
6537
  //#endregion
6347
6538
  //#region ../../lib/telemetry/install-id.ts
6348
6539
  function readValidInstallId(path) {
6349
- const installId = readFileSync(path, "utf8").trim();
6540
+ const installId = readFileSync$1(path, "utf8").trim();
6350
6541
  return UUID_V4_PATTERN.test(installId) ? installId : null;
6351
6542
  }
6352
6543
  function errorCode(error) {
@@ -6354,7 +6545,7 @@ function errorCode(error) {
6354
6545
  }
6355
6546
  function repairOwnerIsAlive(lockPath) {
6356
6547
  try {
6357
- const rawOwner = readFileSync(lockPath, "utf8").trim();
6548
+ const rawOwner = readFileSync$1(lockPath, "utf8").trim();
6358
6549
  let ownerPid;
6359
6550
  let createdAt;
6360
6551
  try {
@@ -6363,7 +6554,7 @@ function repairOwnerIsAlive(lockPath) {
6363
6554
  createdAt = Number(owner.createdAt);
6364
6555
  } catch {
6365
6556
  ownerPid = Number(rawOwner);
6366
- createdAt = statSync(lockPath).mtimeMs;
6557
+ createdAt = statSync$1(lockPath).mtimeMs;
6367
6558
  }
6368
6559
  if (!Number.isInteger(ownerPid) || ownerPid <= 0 || !Number.isFinite(createdAt) || Date.now() - createdAt >= REPAIR_LOCK_LEASE_MS) return false;
6369
6560
  process.kill(ownerPid, 0);
@@ -6376,22 +6567,22 @@ function replaceInvalidInstallId(path) {
6376
6567
  const installId = randomUUID();
6377
6568
  const temporaryPath = `${path}.${process.pid}.${randomUUID()}.tmp`;
6378
6569
  try {
6379
- writeFileSync(temporaryPath, `${installId}\n`, {
6570
+ writeFileSync$1(temporaryPath, `${installId}\n`, {
6380
6571
  encoding: "utf8",
6381
6572
  mode: 384,
6382
6573
  flag: "wx"
6383
6574
  });
6384
- renameSync(temporaryPath, path);
6385
- chmodSync(path, 384);
6575
+ renameSync$1(temporaryPath, path);
6576
+ chmodSync$1(path, 384);
6386
6577
  } finally {
6387
- rmSync(temporaryPath, { force: true });
6578
+ rmSync$1(temporaryPath, { force: true });
6388
6579
  }
6389
6580
  }
6390
6581
  function repairInvalidInstallId(path, overdeckHome) {
6391
6582
  const lockPath = join(overdeckHome, INSTALL_ID_REPAIR_LOCK);
6392
6583
  for (let attempt = 0; attempt < REPAIR_MAX_ATTEMPTS; attempt += 1) {
6393
6584
  try {
6394
- writeFileSync(lockPath, `${JSON.stringify({
6585
+ writeFileSync$1(lockPath, `${JSON.stringify({
6395
6586
  pid: process.pid,
6396
6587
  createdAt: Date.now()
6397
6588
  })}\n`, {
@@ -6404,7 +6595,7 @@ function repairInvalidInstallId(path, overdeckHome) {
6404
6595
  const winner = readValidInstallId(path);
6405
6596
  if (winner) return winner;
6406
6597
  if (!repairOwnerIsAlive(lockPath)) {
6407
- rmSync(lockPath, { force: true });
6598
+ rmSync$1(lockPath, { force: true });
6408
6599
  continue;
6409
6600
  }
6410
6601
  Atomics.wait(REPAIR_WAIT_ARRAY, 0, 0, REPAIR_WAIT_MS);
@@ -6418,7 +6609,7 @@ function repairInvalidInstallId(path, overdeckHome) {
6418
6609
  if (!repaired) throw new Error(`Failed to repair ${path}`);
6419
6610
  return repaired;
6420
6611
  } finally {
6421
- rmSync(lockPath, { force: true });
6612
+ rmSync$1(lockPath, { force: true });
6422
6613
  }
6423
6614
  }
6424
6615
  throw new Error(`Timed out waiting to repair ${path}`);
@@ -6431,10 +6622,10 @@ function getOrCreateInstallId() {
6431
6622
  } catch (error) {
6432
6623
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") throw error;
6433
6624
  }
6434
- mkdirSync(overdeckHome, { recursive: true });
6625
+ mkdirSync$1(overdeckHome, { recursive: true });
6435
6626
  const installId = randomUUID();
6436
6627
  try {
6437
- writeFileSync(installIdPath, `${installId}\n`, {
6628
+ writeFileSync$1(installIdPath, `${installId}\n`, {
6438
6629
  encoding: "utf8",
6439
6630
  mode: 384,
6440
6631
  flag: "wx"
@@ -6461,7 +6652,7 @@ var init_install_id = __esmMin((() => {
6461
6652
  function getOverdeckVersion() {
6462
6653
  if (cachedOverdeckVersion) return cachedOverdeckVersion;
6463
6654
  try {
6464
- const manifest = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
6655
+ const manifest = JSON.parse(readFileSync$1(join(packageRoot, "package.json"), "utf8"));
6465
6656
  cachedOverdeckVersion = typeof manifest.version === "string" ? manifest.version : "unknown";
6466
6657
  } catch {
6467
6658
  cachedOverdeckVersion = "unknown";
@@ -6665,9 +6856,9 @@ var init_service = __esmMin((() => {
6665
6856
  //#region ../../lib/telemetry/pipeline.ts
6666
6857
  async function readCanonicalPipelineMembership(issueId) {
6667
6858
  const [membershipModule, gatherModule, recordModule] = await Promise.all([
6668
- import("./pipeline-membership-BGSvkT2M.js"),
6669
- import("./pipeline-membership-gather-DTfcgxLl.js"),
6670
- import("./record-CtroO946.js")
6859
+ import("./pipeline-membership-C88VBnhJ.js"),
6860
+ import("./pipeline-membership-gather-4eR-7Tqy.js"),
6861
+ import("./record-BTwWhtBb.js")
6671
6862
  ]);
6672
6863
  const project = recordModule.resolveProjectForIssue(issueId);
6673
6864
  if (!project) return false;
@@ -6893,7 +7084,7 @@ function setReviewStatusSync(issueId, update, existing) {
6893
7084
  });
6894
7085
  if (readyForMerge && !status.readyForMerge && updated.prUrl) (async () => {
6895
7086
  try {
6896
- const { isGitHubAppConfigured, reportCommitStatus } = await import("./github-app-DtAsvwzK.js");
7087
+ const { isGitHubAppConfigured, reportCommitStatus } = await import("./github-app-Bmg4R9mv.js");
6897
7088
  if (!isGitHubAppConfigured()) return;
6898
7089
  const prMatch = updated.prUrl.match(/github\.com\/([^/]+)\/([^/]+)\/pull/);
6899
7090
  if (!prMatch) return;
@@ -7147,8 +7338,8 @@ function emitReactiveLifecycleEvent(type, issueId) {
7147
7338
  }
7148
7339
  async function deliverReviewVerdictFeedbackHostSide(issueId, status) {
7149
7340
  try {
7150
- const { deliverReviewVerdictFeedback } = await import("./review-verdict-feedback-BPDn4li_.js");
7151
- const { getAgentStateSync } = await import("./agents-BKKkxKgK.js");
7341
+ const { deliverReviewVerdictFeedback } = await import("./review-verdict-feedback-HwF6ODFy.js");
7342
+ const { getAgentStateSync } = await import("./agents-ePFVoZbu.js");
7152
7343
  const runId = getAgentStateSync(`agent-${issueId.toLowerCase()}-review`)?.reviewRunId;
7153
7344
  if ((await Effect.runPromise(deliverReviewVerdictFeedback({
7154
7345
  issueId,
@@ -7168,7 +7359,22 @@ function maybeAutoDispatchReviewHostSide(issueId, status) {
7168
7359
  reviewStatus: status.reviewStatus,
7169
7360
  mergeStatus: status.mergeStatus,
7170
7361
  readyForMerge: status.readyForMerge
7171
- })) return;
7362
+ })) {
7363
+ if (!isReviewRequestStale({ reviewRequestedAt: status.reviewRequestedAt }) || staleReviewRequestClearAttemptedAt.has(issueId)) return;
7364
+ staleReviewRequestClearAttemptedAt.set(issueId, Date.now());
7365
+ try {
7366
+ setReviewStatusSync(issueId, { reviewRequestedAt: void 0 }, status);
7367
+ const message = `${issueId} — cleared stale review request older than 7 days`;
7368
+ console.warn(`[review-status] ${message}`);
7369
+ emitActivityEntrySync({
7370
+ source: "cloister",
7371
+ level: "warn",
7372
+ issueId,
7373
+ message
7374
+ });
7375
+ } catch {}
7376
+ return;
7377
+ }
7172
7378
  const last = reviewDispatchAttemptAt.get(issueId) ?? 0;
7173
7379
  if (Date.now() - last < REVIEW_AUTO_DISPATCH_THROTTLE_MS) return;
7174
7380
  reviewDispatchAttemptAt.set(issueId, Date.now());
@@ -7176,7 +7382,15 @@ function maybeAutoDispatchReviewHostSide(issueId, status) {
7176
7382
  }
7177
7383
  async function dispatchReviewHostSide(issueId, prUrl) {
7178
7384
  try {
7179
- const [{ startDurableReviewPipelineHostSide }, { spawnReviewRoleForIssue }] = await Promise.all([import("./durable-review-pipeline-jpgCJZFp.js"), import("./review-agent-CD4RCI0Y.js")]);
7385
+ const { hasDurableReviewPipelineHandler, startDurableReviewPipelineHostSide } = await import("./durable-review-pipeline-DP6bIcOY.js");
7386
+ if (!hasDurableReviewPipelineHandler()) {
7387
+ if (!loggedMissingPipelineHandler) {
7388
+ loggedMissingPipelineHandler = true;
7389
+ console.debug("[review-status] durable review pipeline handler is not registered; skipping host-side review auto-dispatch");
7390
+ }
7391
+ return;
7392
+ }
7393
+ const { spawnReviewRoleForIssue } = await import("./review-agent-BTCNkq2h.js");
7180
7394
  if (!await startDurableReviewPipelineHostSide({
7181
7395
  issueId,
7182
7396
  ...prUrl ? { prUrl } : {},
@@ -7198,13 +7412,13 @@ function maybeRecoverTestVerdictHostSide(issueId, status) {
7198
7412
  }
7199
7413
  async function recoverTestVerdictHostSide(issueId) {
7200
7414
  try {
7201
- const { resolveProjectFromIssueSync } = await import("./projects-B03Wr-xc.js");
7415
+ const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
7202
7416
  const resolved = resolveProjectFromIssueSync(issueId);
7203
7417
  if (!resolved) return;
7204
7418
  const { existsSync } = await import("fs");
7205
7419
  const workspace = join$1(resolved.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
7206
7420
  if (!existsSync(workspace)) return;
7207
- const { readTestVerdictArtifact } = await import("./test-verdict-Gw-btEfb.js");
7421
+ const { readTestVerdictArtifact } = await import("./test-verdict-BHgTAwIG.js");
7208
7422
  const artifact = readTestVerdictArtifact(workspace);
7209
7423
  if (!artifact) return;
7210
7424
  setReviewStatusSync(issueId, {
@@ -7251,13 +7465,13 @@ function resetPipelineVerdictsForWorkStartSync(issueId, options = {}) {
7251
7465
  }
7252
7466
  async function deliverTestFailureToWorkAgentHostSide(issueId, status) {
7253
7467
  try {
7254
- const { resolveProjectFromIssueSync } = await import("./projects-B03Wr-xc.js");
7468
+ const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
7255
7469
  const resolved = resolveProjectFromIssueSync(issueId);
7256
7470
  const workspace = resolved ? join$1(resolved.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`) : void 0;
7257
7471
  const notes = status.testNotes;
7258
7472
  let feedbackPath;
7259
7473
  try {
7260
- const { writeFeedbackFile } = await import("./feedback-writer-D1fm-5Z8.js");
7474
+ const { writeFeedbackFile } = await import("./feedback-writer-CoB9Z6aU.js");
7261
7475
  const r = await Effect.runPromise(writeFeedbackFile({
7262
7476
  issueId,
7263
7477
  workspacePath: workspace,
@@ -7269,10 +7483,10 @@ async function deliverTestFailureToWorkAgentHostSide(issueId, status) {
7269
7483
  if (r.success) feedbackPath = r.filePath;
7270
7484
  } catch {}
7271
7485
  const message = `SPECIALIST FEEDBACK: test-agent reported FAILED for ${issueId}.\n\n${feedbackPath ? `MUST READ: ${feedbackPath}\n\n` : ""}${notes ? `${notes.slice(0, 400)}\n\n` : ""}Fix the failing tests, commit and push, then re-run pan done ${issueId}. Do NOT stop at the prompt.`;
7272
- const { resolveIssueFeedbackTarget, surfaceIssueFeedbackNeedsYou } = await import("./feedback-target-C0ZzyHvU.js");
7486
+ const { resolveIssueFeedbackTarget, surfaceIssueFeedbackNeedsYou } = await import("./feedback-target-BJ5ZADsu.js");
7273
7487
  const target = await resolveIssueFeedbackTarget(issueId);
7274
7488
  if ("agentId" in target) {
7275
- const { messageAgent } = await import("./agents-BKKkxKgK.js");
7489
+ const { messageAgent } = await import("./agents-ePFVoZbu.js");
7276
7490
  await messageAgent(target.agentId, message, "internal", { owesRework: true });
7277
7491
  console.log(`[review-status] delivered test failure to ${target.agentId} for ${issueId} (host-side)`);
7278
7492
  } else await surfaceIssueFeedbackNeedsYou(issueId, target.reason, {
@@ -7467,7 +7681,7 @@ function setAutoMerge(issueId, autoMerge) {
7467
7681
  console.error(`[review-status] Failed to set autoMerge for ${issueId}:`, err);
7468
7682
  }
7469
7683
  }
7470
- var DEFAULT_STATUS_FILE, reviewDispatchAttemptAt, REVIEW_AUTO_DISPATCH_THROTTLE_MS, testVerdictRecoveryAt, TEST_VERDICT_RECOVERY_THROTTLE_MS, FEEDBACK_DELIVERY_STUCK_REASON, ReviewStatusError, setReviewStatus, getReviewStatus;
7684
+ var DEFAULT_STATUS_FILE, reviewDispatchAttemptAt, staleReviewRequestClearAttemptedAt, REVIEW_AUTO_DISPATCH_THROTTLE_MS, loggedMissingPipelineHandler, testVerdictRecoveryAt, TEST_VERDICT_RECOVERY_THROTTLE_MS, FEEDBACK_DELIVERY_STUCK_REASON, ReviewStatusError, setReviewStatus, getReviewStatus;
7471
7685
  var init_review_status = __esmMin((() => {
7472
7686
  init_pipeline_notifier();
7473
7687
  init_activity_logger();
@@ -7483,7 +7697,9 @@ var init_review_status = __esmMin((() => {
7483
7697
  registerCanonicalReviewStatusResolver((issueId) => getReviewStatusSync(issueId));
7484
7698
  DEFAULT_STATUS_FILE = join$1(homedir(), ".overdeck", "review-status.json");
7485
7699
  reviewDispatchAttemptAt = /* @__PURE__ */ new Map();
7700
+ staleReviewRequestClearAttemptedAt = /* @__PURE__ */ new Map();
7486
7701
  REVIEW_AUTO_DISPATCH_THROTTLE_MS = 3e4;
7702
+ loggedMissingPipelineHandler = false;
7487
7703
  testVerdictRecoveryAt = /* @__PURE__ */ new Map();
7488
7704
  TEST_VERDICT_RECOVERY_THROTTLE_MS = 6e4;
7489
7705
  FEEDBACK_DELIVERY_STUCK_REASON = "feedback_delivery_needs_you";
@@ -7516,6 +7732,6 @@ var init_review_status = __esmMin((() => {
7516
7732
  });
7517
7733
  }));
7518
7734
  //#endregion
7519
- export { getOrCreateInstallId as A, verificationSatisfied as B, capturePipelineStage as C, getAnalyticsService as D, resolvePipelineTelemetryContext as E, init_pipeline_agent_reader as F, saveOverdeckAgentStateSync as G, getOverdeckAgentStateSync as H, registerPipelineTelemetryAgentReader as I, stateToOverdeckParamsForDb as K, init_review_dispatch_decision as L, init_config as M, resolveTelemetryEnabled as N, init_service as O, telemetryEnvironmentForcesOff as P, needsReviewDispatch as R, setReviewStatusSync as S, init_pipeline as T, init_agent_state_sync as U, AGENT_COLUMNS_FOR_DB as V, listOverdeckAgentStatesSync as W, mergeGateEligibility as _, clearStuckMergeStatuses as a, setDeaconIgnored as b, fixStuckReadyForMerge as c, getReviewStatusesSync as d, init_review_status as f, markWorkspaceStuck as g, loadReviewStatusesForIssues as h, clearReviewStatus as i, init_install_id as j, synchronizeAnalyticsServices as k, getReviewStatus as l, loadReviewStatuses as m, ReviewStatusError as n, clearWorkspaceStuck as o, loadReadyForMergeFlags as p, clearFeedbackDeliveryStuck as r, fixStuckCommentedReviews as s, FEEDBACK_DELIVERY_STUCK_REASON as t, getReviewStatusSync as u, resetPipelineVerdictsForWorkStartSync as v, capturePipelineStageForIssue as w, setReviewStatus as x, setAutoMerge as y, reviewGatesPassedSync as z };
7735
+ export { synchronizeAnalyticsServices as A, reviewGatesPassedSync as B, setReviewStatusSync as C, resolvePipelineTelemetryContext as D, init_pipeline as E, telemetryEnvironmentForcesOff as F, readJournalStatus as G, findBlockingFindings as H, init_pipeline_agent_reader as I, getOverdeckAgentStateSync as J, readJournalStatusSync as K, registerPipelineTelemetryAgentReader as L, init_install_id as M, init_config as N, getAnalyticsService as O, resolveTelemetryEnabled as P, stateToOverdeckParamsForDb as Q, init_review_dispatch_decision as R, setReviewStatus as S, capturePipelineStageForIssue as T, init_review_findings as U, verificationSatisfied as V, init_review_status_record_sync as W, listOverdeckAgentStatesSync as X, init_agent_state_sync as Y, saveOverdeckAgentStateSync as Z, markWorkspaceStuck as _, clearStuckMergeStatuses as a, setAutoMerge as b, fixStuckCommentedReviews as c, getReviewStatusSync as d, getReviewStatusesSync as f, loadReviewStatusesForIssues as g, loadReviewStatuses as h, clearReviewStatus as i, getOrCreateInstallId as j, init_service as k, fixStuckReadyForMerge as l, loadReadyForMergeFlags as m, ReviewStatusError as n, clearWorkspaceStuck as o, init_review_status as p, AGENT_COLUMNS_FOR_DB as q, clearFeedbackDeliveryStuck as r, dispatchReviewHostSide as s, FEEDBACK_DELIVERY_STUCK_REASON as t, getReviewStatus as u, mergeGateEligibility as v, capturePipelineStage as w, setDeaconIgnored as x, resetPipelineVerdictsForWorkStartSync as y, needsReviewDispatch as z };
7520
7736
 
7521
- //# sourceMappingURL=review-status-yljtTd-q.js.map
7737
+ //# sourceMappingURL=review-status-CGvlA4o_.js.map