@overdeck/core 0.45.10 → 0.45.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/dist/{agent-state-KVbJEG5f.js → agent-state-RLhS7ckO.js} +1 -1
  2. package/dist/{agents-pp8FO7Uj.js → agents-By3u_fQ8.js} +1 -1
  3. package/dist/{agents-CQHK0CSA.js → agents-CgVr77Qq.js} +12 -12
  4. package/dist/{agents-CQHK0CSA.js.map → agents-CgVr77Qq.js.map} +1 -1
  5. package/dist/{backlog-auto-trigger-CyuoS0nl.js → backlog-auto-trigger-B_-1tk4e.js} +5 -5
  6. package/dist/{backlog-auto-trigger-CyuoS0nl.js.map → backlog-auto-trigger-B_-1tk4e.js.map} +1 -1
  7. package/dist/cli/index.js +45 -45
  8. package/dist/{cli-Cewlu3yU.js → cli-DGeSW85B.js} +2 -2
  9. package/dist/{cli-Cewlu3yU.js.map → cli-DGeSW85B.js.map} +1 -1
  10. package/dist/cli-MTB9IOoR.js +3 -0
  11. package/dist/{close-issue-BJGX9_z7.js → close-issue-Djajb6Sv.js} +2 -2
  12. package/dist/{close-issue-BJGX9_z7.js.map → close-issue-Djajb6Sv.js.map} +1 -1
  13. package/dist/{concurrency-Ca-fC7tA.js → concurrency-4rzjHAQA.js} +1 -1
  14. package/dist/{conversation-compaction-B_6s9EvM.js → conversation-compaction-BQvZh09I.js} +4 -4
  15. package/dist/{conversation-compaction-B_6s9EvM.js.map → conversation-compaction-BQvZh09I.js.map} +1 -1
  16. package/dist/dashboard/{advancing-selfheal-CMlGznKv.js → advancing-selfheal-BezNfM3P.js} +3 -3
  17. package/dist/dashboard/{advancing-selfheal-CMlGznKv.js.map → advancing-selfheal-BezNfM3P.js.map} +1 -1
  18. package/dist/dashboard/{agent-state-xk_G8t90.js → agent-state-BUANcaA7.js} +1 -1
  19. package/dist/dashboard/{agent-state-service-C1iUF9Ft.js → agent-state-service-DmFpIMbP.js} +1 -1
  20. package/dist/dashboard/{agent-state-service-5ge9xxhx.js → agent-state-service-tXUdp6UF.js} +2 -2
  21. package/dist/dashboard/{agent-state-service-5ge9xxhx.js.map → agent-state-service-tXUdp6UF.js.map} +1 -1
  22. package/dist/dashboard/{agents-BIggLvi_.js → agents-C-vqmKDi.js} +1 -1
  23. package/dist/dashboard/{agents-DHvsjsuP.js → agents-C7V4odQ6.js} +11 -11
  24. package/dist/dashboard/{agents-DHvsjsuP.js.map → agents-C7V4odQ6.js.map} +1 -1
  25. package/dist/dashboard/{backlog-auto-trigger-COm_R96V.js → backlog-auto-trigger-Cb8PR-5w.js} +2 -2
  26. package/dist/dashboard/{backlog-auto-trigger-COm_R96V.js.map → backlog-auto-trigger-Cb8PR-5w.js.map} +1 -1
  27. package/dist/dashboard/{cli-CvK9xuSS.js → cli-BgzbB6h3.js} +2 -2
  28. package/dist/dashboard/{cli-CvK9xuSS.js.map → cli-BgzbB6h3.js.map} +1 -1
  29. package/dist/dashboard/cli-DCqy_wFa.js +3 -0
  30. package/dist/dashboard/{close-issue-BnpErnD1.js → close-issue-BWf3pxn4.js} +2 -2
  31. package/dist/dashboard/{close-issue-BnpErnD1.js.map → close-issue-BWf3pxn4.js.map} +1 -1
  32. package/dist/dashboard/{closed-issue-reaper-DRqK5k39.js → closed-issue-reaper-D7XPq5pY.js} +4 -4
  33. package/dist/dashboard/{closed-issue-reaper-DRqK5k39.js.map → closed-issue-reaper-D7XPq5pY.js.map} +1 -1
  34. package/dist/dashboard/{closed-issue-reaper-BLCQwTpF.js → closed-issue-reaper-VSTSTROK.js} +1 -1
  35. package/dist/dashboard/{conflict-gate-JdFuhKuF.js → conflict-gate-DwOslTij.js} +1 -1
  36. package/dist/dashboard/{conflict-gate-BhKvrPxn.js → conflict-gate-FFEvTDVA.js} +3 -3
  37. package/dist/dashboard/{conflict-gate-BhKvrPxn.js.map → conflict-gate-FFEvTDVA.js.map} +1 -1
  38. package/dist/dashboard/{conversation-compaction-C5o_eKEm.js → conversation-compaction-CCqN4hWk.js} +4 -4
  39. package/dist/dashboard/{conversation-compaction-C5o_eKEm.js.map → conversation-compaction-CCqN4hWk.js.map} +1 -1
  40. package/dist/dashboard/{conversation-compaction-Ba5aZdrb.js → conversation-compaction-CL5Ti4j4.js} +1 -1
  41. package/dist/dashboard/{deacon-j3qSZ7--.js → deacon-CGHl90eC.js} +107 -50
  42. package/dist/dashboard/{deacon-j3qSZ7--.js.map → deacon-CGHl90eC.js.map} +1 -1
  43. package/dist/dashboard/{deacon-Cv2RMfHs.js → deacon-DMPh40Im.js} +2 -2
  44. package/dist/dashboard/deacon-swarm-CVTiNL0N.js +2 -0
  45. package/dist/dashboard/{deacon-swarm-DadWNi5J.js → deacon-swarm-aMMJTq6t.js} +4 -4
  46. package/dist/dashboard/{deacon-swarm-DadWNi5J.js.map → deacon-swarm-aMMJTq6t.js.map} +1 -1
  47. package/dist/dashboard/deacon.js +4 -4
  48. package/dist/dashboard/{feedback-target-oE4-Esxl.js → feedback-target-dJjFfITP.js} +4 -4
  49. package/dist/dashboard/{feedback-target-oE4-Esxl.js.map → feedback-target-dJjFfITP.js.map} +1 -1
  50. package/dist/dashboard/{feedback-target-C4DaDSZ8.js → feedback-target-nQSM6ygL.js} +1 -1
  51. package/dist/dashboard/{flywheel-ClMjGW_u.js → flywheel-BLoVNtJV.js} +6 -6
  52. package/dist/dashboard/{flywheel-ClMjGW_u.js.map → flywheel-BLoVNtJV.js.map} +1 -1
  53. package/dist/dashboard/{flywheel-DefHRzY4.js → flywheel-Cqf8vu7N.js} +6 -6
  54. package/dist/dashboard/{flywheel-DefHRzY4.js.map → flywheel-Cqf8vu7N.js.map} +1 -1
  55. package/dist/dashboard/{flywheel-BqDdGvrQ.js → flywheel-PJsbrXNY.js} +1 -1
  56. package/dist/dashboard/{flywheel-merge-order-CuDcqTRJ.js → flywheel-merge-order-B7BH8mZ3.js} +2 -2
  57. package/dist/dashboard/{flywheel-merge-order-CuDcqTRJ.js.map → flywheel-merge-order-B7BH8mZ3.js.map} +1 -1
  58. package/dist/dashboard/{flywheel-merge-order-B6YDSElh.js → flywheel-merge-order-CCwF60b-.js} +1 -1
  59. package/dist/dashboard/{harness-resolve-DKeSVsJL.js → harness-resolve-B3f9G1Kp.js} +2 -2
  60. package/dist/dashboard/{harness-resolve-DKeSVsJL.js.map → harness-resolve-B3f9G1Kp.js.map} +1 -1
  61. package/dist/dashboard/{inspect-agent-BKKc0XnB.js → inspect-agent-CKF5-SJr.js} +3 -3
  62. package/dist/dashboard/{inspect-agent-BKKc0XnB.js.map → inspect-agent-CKF5-SJr.js.map} +1 -1
  63. package/dist/dashboard/inspect-agent-CqpEWGWy.js +2 -0
  64. package/dist/dashboard/{issue-lifecycle-DnhQgddB.js → issue-lifecycle-5LbOcATP.js} +7 -7
  65. package/dist/dashboard/{issue-lifecycle-DnhQgddB.js.map → issue-lifecycle-5LbOcATP.js.map} +1 -1
  66. package/dist/dashboard/{issue-lifecycle-nY4esZn8.js → issue-lifecycle-CjYqQ669.js} +1 -1
  67. package/dist/dashboard/{issue-service-singleton-Bnqv1uaa.js → issue-service-singleton-B8iu_TKV.js} +1 -1
  68. package/dist/dashboard/{issue-service-singleton-_AquSBTl.js → issue-service-singleton-CDGt__oQ.js} +2 -2
  69. package/dist/dashboard/{issue-service-singleton-_AquSBTl.js.map → issue-service-singleton-CDGt__oQ.js.map} +1 -1
  70. package/dist/dashboard/{lifecycle-CGKm7doE.js → lifecycle-CEg4sHZH.js} +4 -4
  71. package/dist/dashboard/{lifecycle-CGKm7doE.js.map → lifecycle-CEg4sHZH.js.map} +1 -1
  72. package/dist/dashboard/{merge-agent-Dh8Y9PDO.js → merge-agent-7nBiCytp.js} +1 -1
  73. package/dist/dashboard/{merge-agent-BcgAYStl.js → merge-agent-C81xPIGd.js} +6 -6
  74. package/dist/dashboard/{merge-agent-BcgAYStl.js.map → merge-agent-C81xPIGd.js.map} +1 -1
  75. package/dist/dashboard/merge-ops-DE_6CnmZ.js +2 -0
  76. package/dist/dashboard/{merge-train-DmxlYbEo.js → merge-train-D3qzRccL.js} +2 -2
  77. package/dist/dashboard/{merge-train-DmxlYbEo.js.map → merge-train-D3qzRccL.js.map} +1 -1
  78. package/dist/dashboard/{merge-train-deps-DBHsOWt9.js → merge-train-deps-Be5ElC_P.js} +2 -2
  79. package/dist/dashboard/{merge-train-deps-DBHsOWt9.js.map → merge-train-deps-Be5ElC_P.js.map} +1 -1
  80. package/dist/dashboard/{orphan-proposed-reconciler-Db8tUhce.js → orphan-proposed-reconciler-Boq_XaRe.js} +3 -3
  81. package/dist/dashboard/{orphan-proposed-reconciler-Db8tUhce.js.map → orphan-proposed-reconciler-Boq_XaRe.js.map} +1 -1
  82. package/dist/dashboard/{orphan-proposed-reconciler-mXV--tcB.js → orphan-proposed-reconciler-C0sPnDq_.js} +1 -1
  83. package/dist/dashboard/{reconstruct-cache-_tDZ2D72.js → reconstruct-cache-C2pCltOq.js} +3 -3
  84. package/dist/dashboard/{reconstruct-cache-_tDZ2D72.js.map → reconstruct-cache-C2pCltOq.js.map} +1 -1
  85. package/dist/dashboard/{remote-completion-Bklh6loJ.js → remote-completion-BmxD5UMQ.js} +3 -3
  86. package/dist/dashboard/{remote-completion-Bklh6loJ.js.map → remote-completion-BmxD5UMQ.js.map} +1 -1
  87. package/dist/dashboard/resume-C-nxu9Y4.js +3 -0
  88. package/dist/dashboard/{review-agent-phzqNqIs.js → review-agent-D6P6d3pz.js} +26 -17
  89. package/dist/dashboard/review-agent-D6P6d3pz.js.map +1 -0
  90. package/dist/dashboard/review-agent-DTINEffB.js +3 -0
  91. package/dist/dashboard/{review-context-CCq56O_Y.js → review-context-Dyo0tsBa.js} +2 -2
  92. package/dist/dashboard/{review-context-CCq56O_Y.js.map → review-context-Dyo0tsBa.js.map} +1 -1
  93. package/dist/dashboard/{review-status-BQjqQXZG.js → review-status-B5ZASOo4.js} +18 -5
  94. package/dist/dashboard/review-status-B5ZASOo4.js.map +1 -0
  95. package/dist/dashboard/{review-status-bBkqUj5i.js → review-status-h7BXIA4z.js} +1 -1
  96. package/dist/dashboard/{review-verdict-feedback-wqnikhMK.js → review-verdict-feedback-B70VbfRL.js} +4 -4
  97. package/dist/dashboard/{review-verdict-feedback-wqnikhMK.js.map → review-verdict-feedback-B70VbfRL.js.map} +1 -1
  98. package/dist/dashboard/{review-verdict-feedback-cZh9Wi9G.js → review-verdict-feedback-CorgH49f.js} +1 -1
  99. package/dist/dashboard/{sequence-io-B2GmilSI.js → sequence-io-6YP8fVpH.js} +2 -2
  100. package/dist/dashboard/{sequence-io-B2GmilSI.js.map → sequence-io-6YP8fVpH.js.map} +1 -1
  101. package/dist/dashboard/{sequencer-agent-D8pW2aU_.js → sequencer-agent-ja-nkEc1.js} +5 -5
  102. package/dist/dashboard/{sequencer-agent-D8pW2aU_.js.map → sequencer-agent-ja-nkEc1.js.map} +1 -1
  103. package/dist/dashboard/server.js +66 -55
  104. package/dist/dashboard/server.js.map +1 -1
  105. package/dist/dashboard/{service-CILd-uOt.js → service-HKDrIy0h.js} +24 -24
  106. package/dist/dashboard/{service-CILd-uOt.js.map → service-HKDrIy0h.js.map} +1 -1
  107. package/dist/dashboard/{smart-compaction-Bgp_gwcA.js → smart-compaction-L0LSnF0_.js} +1 -1
  108. package/dist/dashboard/{smart-compaction-CrP90OFE.js → smart-compaction-uke1npUz.js} +2 -2
  109. package/dist/dashboard/{smart-compaction-CrP90OFE.js.map → smart-compaction-uke1npUz.js.map} +1 -1
  110. package/dist/dashboard/{spawn-planning-session-D15KbPOy.js → spawn-planning-session-CSMWco8B.js} +1 -1
  111. package/dist/dashboard/{spawn-planning-session-BmJWHSCu.js → spawn-planning-session-CXc0NkwV.js} +3 -3
  112. package/dist/dashboard/{spawn-planning-session-BmJWHSCu.js.map → spawn-planning-session-CXc0NkwV.js.map} +1 -1
  113. package/dist/dashboard/{specialist-context-CwKkcXL9.js → specialist-context-BGCJ24LH.js} +3 -3
  114. package/dist/dashboard/{specialist-context-CwKkcXL9.js.map → specialist-context-BGCJ24LH.js.map} +1 -1
  115. package/dist/dashboard/{specialist-logs-CvDxquV_.js → specialist-logs--Uz-r8ia.js} +2 -2
  116. package/dist/dashboard/{specialist-logs-CvDxquV_.js.map → specialist-logs--Uz-r8ia.js.map} +1 -1
  117. package/dist/dashboard/{specialists-BCjcG4uE.js → specialists-Ca9XSBCS.js} +1 -1
  118. package/dist/dashboard/{specialists-D07ybnam.js → specialists-DEfrAbWs.js} +36 -36
  119. package/dist/dashboard/{specialists-D07ybnam.js.map → specialists-DEfrAbWs.js.map} +1 -1
  120. package/dist/dashboard/{specialists-F2uMO4QS.js → specialists-DeZx9xom.js} +1 -1
  121. package/dist/dashboard/{specialists-BYi0k8CZ.js → specialists-nZ0mRwpZ.js} +12 -12
  122. package/dist/dashboard/{specialists-BYi0k8CZ.js.map → specialists-nZ0mRwpZ.js.map} +1 -1
  123. package/dist/dashboard/{summary-fork-DedqguZb.js → summary-fork-2a1L2DIU.js} +2 -2
  124. package/dist/dashboard/{summary-fork-EjvOkEPl.js → summary-fork-Xn0QUNmb.js} +3 -3
  125. package/dist/dashboard/{summary-fork-EjvOkEPl.js.map → summary-fork-Xn0QUNmb.js.map} +1 -1
  126. package/dist/dashboard/{teardown-workspace-5LCVbjfq.js → teardown-workspace-DhA6oAIK.js} +2 -2
  127. package/dist/dashboard/{teardown-workspace-5LCVbjfq.js.map → teardown-workspace-DhA6oAIK.js.map} +1 -1
  128. package/dist/dashboard/{test-agent-queue-qfsq6uaC.js → test-agent-queue-B_ukPyIK.js} +3 -3
  129. package/dist/dashboard/{test-agent-queue-qfsq6uaC.js.map → test-agent-queue-B_ukPyIK.js.map} +1 -1
  130. package/dist/dashboard/{uat-train-CtNGgXxj.js → uat-train-BLBAbJ8Y.js} +10 -10
  131. package/dist/dashboard/{uat-train-CtNGgXxj.js.map → uat-train-BLBAbJ8Y.js.map} +1 -1
  132. package/dist/dashboard/{uat-train-C3hWXtip.js → uat-train-DPfGR9_I.js} +1 -1
  133. package/dist/dashboard/{verification-runner-DuZRHjPU.js → verification-runner-KTGTNugM.js} +1 -1
  134. package/dist/dashboard/{verification-runner-BPAhPWR7.js → verification-runner-R2-4XgMO.js} +4 -4
  135. package/dist/dashboard/{verification-runner-BPAhPWR7.js.map → verification-runner-R2-4XgMO.js.map} +1 -1
  136. package/dist/dashboard/{workflows-H-COJ84X.js → workflows-CSKX5MhC.js} +7 -7
  137. package/dist/dashboard/{workflows-H-COJ84X.js.map → workflows-CSKX5MhC.js.map} +1 -1
  138. package/dist/dashboard/workflows-DVwXauef.js +2 -0
  139. package/dist/dashboard/{workspaces-CRU9_vRn.js → workspaces-DXLDgXo2.js} +32 -32
  140. package/dist/dashboard/{workspaces-CRU9_vRn.js.map → workspaces-DXLDgXo2.js.map} +1 -1
  141. package/dist/docs-index.sqlite +0 -0
  142. package/dist/{feedback-target-DTGAhFkM.js → feedback-target-BsKN4Tr_.js} +4 -4
  143. package/dist/{feedback-target-DTGAhFkM.js.map → feedback-target-BsKN4Tr_.js.map} +1 -1
  144. package/dist/{feedback-target-DutF088V.js → feedback-target-DM1WzOKy.js} +1 -1
  145. package/dist/{harness-resolve-Bz1prk6B.js → harness-resolve-B-YDNwNW.js} +2 -2
  146. package/dist/{harness-resolve-Bz1prk6B.js.map → harness-resolve-B-YDNwNW.js.map} +1 -1
  147. package/dist/{issue-lifecycle-fVqvCdKM.js → issue-lifecycle-Bc1l3U9f.js} +7 -7
  148. package/dist/{issue-lifecycle-fVqvCdKM.js.map → issue-lifecycle-Bc1l3U9f.js.map} +1 -1
  149. package/dist/{issue-service-singleton-CZm8p6Rj.js → issue-service-singleton-D-8Q6tdT.js} +1 -1
  150. package/dist/{issue-service-singleton-Cr73JAaR.js → issue-service-singleton-D1433I7n.js} +2 -2
  151. package/dist/{issue-service-singleton-Cr73JAaR.js.map → issue-service-singleton-D1433I7n.js.map} +1 -1
  152. package/dist/{lifecycle-CR6tZfl1.js → lifecycle-SmrqysDf.js} +7 -7
  153. package/dist/{lifecycle-CR6tZfl1.js.map → lifecycle-SmrqysDf.js.map} +1 -1
  154. package/dist/{lifecycle-D_EWiUjk.js → lifecycle-mRMyiIXs.js} +2 -2
  155. package/dist/{merge-agent-LM4avOtA.js → merge-agent-B9hIZ6Z0.js} +6 -6
  156. package/dist/{merge-agent-LM4avOtA.js.map → merge-agent-B9hIZ6Z0.js.map} +1 -1
  157. package/dist/{merge-agent-Bj046HE1.js → merge-agent-DUj22cXL.js} +1 -1
  158. package/dist/{merge-fulfillment-DrnC1Kmg.js → merge-fulfillment-__P4WE-T.js} +3 -3
  159. package/dist/{merge-fulfillment-DrnC1Kmg.js.map → merge-fulfillment-__P4WE-T.js.map} +1 -1
  160. package/dist/{reconstruct-cache-NPqoAUg-.js → reconstruct-cache-9SWp82SQ.js} +3 -3
  161. package/dist/{reconstruct-cache-NPqoAUg-.js.map → reconstruct-cache-9SWp82SQ.js.map} +1 -1
  162. package/dist/{records-BIkN1LQ4.js → records-CTmvuRzz.js} +14 -1
  163. package/dist/{records-BIkN1LQ4.js.map → records-CTmvuRzz.js.map} +1 -1
  164. package/dist/records-backfill-BQcmTmwF.js +2 -0
  165. package/dist/{records-backfill-HM0Pln6N.js → records-backfill-BrNsv_zT.js} +2 -2
  166. package/dist/{records-backfill-HM0Pln6N.js.map → records-backfill-BrNsv_zT.js.map} +1 -1
  167. package/dist/resume-Bn4kDk9x.js +3 -0
  168. package/dist/{review-agent-DFosQzCG.js → review-agent-PhqOhpx3.js} +24 -16
  169. package/dist/{review-agent-DFosQzCG.js.map → review-agent-PhqOhpx3.js.map} +1 -1
  170. package/dist/review-agent-hLbRRxZF.js +3 -0
  171. package/dist/{review-status-iJwfEoNX.js → review-status-B_XXomV0.js} +6 -6
  172. package/dist/{review-status-iJwfEoNX.js.map → review-status-B_XXomV0.js.map} +1 -1
  173. package/dist/{review-status-BbNVlXh1.js → review-status-Bo-EFVKh.js} +1 -1
  174. package/dist/{review-verdict-feedback-BGPw3z1X.js → review-verdict-feedback-CXHkoiKZ.js} +1 -1
  175. package/dist/{review-verdict-feedback-CCZ05atV.js → review-verdict-feedback-DGV13LDb.js} +4 -4
  176. package/dist/{review-verdict-feedback-CCZ05atV.js.map → review-verdict-feedback-DGV13LDb.js.map} +1 -1
  177. package/dist/{sequence-io-CcxZNHcD.js → sequence-io-Cg4NHAco.js} +1 -1
  178. package/dist/{sequence-io-Cx1usxG3.js → sequence-io-CyxvNHfA.js} +2 -2
  179. package/dist/{sequence-io-Cx1usxG3.js.map → sequence-io-CyxvNHfA.js.map} +1 -1
  180. package/dist/{smart-compaction-ByUEgQkF.js → smart-compaction-ByKXTQNy.js} +2 -2
  181. package/dist/{smart-compaction-ByUEgQkF.js.map → smart-compaction-ByKXTQNy.js.map} +1 -1
  182. package/dist/{smart-compaction-DfLe_CtH.js → smart-compaction-U6e_uB1E.js} +1 -1
  183. package/dist/{specialist-context-McuGkaeR.js → specialist-context-BUTadO-U.js} +3 -3
  184. package/dist/{specialist-context-McuGkaeR.js.map → specialist-context-BUTadO-U.js.map} +1 -1
  185. package/dist/{specialist-logs-CUUJ4eiB.js → specialist-logs-pEMCTtGZ.js} +2 -2
  186. package/dist/{specialist-logs-CUUJ4eiB.js.map → specialist-logs-pEMCTtGZ.js.map} +1 -1
  187. package/dist/{specialists-BSrylD1S.js → specialists-BGFnrQ8n.js} +1 -1
  188. package/dist/{specialists-B0elgInc.js → specialists-DeTkkp8b.js} +12 -12
  189. package/dist/{specialists-B0elgInc.js.map → specialists-DeTkkp8b.js.map} +1 -1
  190. package/dist/{summary-fork-DskMRnyb.js → summary-fork-CgzThE2-.js} +2 -2
  191. package/dist/{summary-fork-CPUTKcAT.js → summary-fork-Dx1RMuvU.js} +3 -3
  192. package/dist/{summary-fork-CPUTKcAT.js.map → summary-fork-Dx1RMuvU.js.map} +1 -1
  193. package/dist/{sync-BiNVQHBf.js → sync-Bsww9tuj.js} +2 -2
  194. package/dist/{sync-BiNVQHBf.js.map → sync-Bsww9tuj.js.map} +1 -1
  195. package/dist/sync-CylE_SjB.js +2 -0
  196. package/dist/{verdict-restore-DQiV7_fe.js → verdict-restore-DGpX0ZOJ.js} +5 -5
  197. package/dist/{verdict-restore-DQiV7_fe.js.map → verdict-restore-DGpX0ZOJ.js.map} +1 -1
  198. package/dist/{webhook-handlers-DHBSEDEm.js → webhook-handlers-BjsfIL7u.js} +3 -3
  199. package/dist/{webhook-handlers-DHBSEDEm.js.map → webhook-handlers-BjsfIL7u.js.map} +1 -1
  200. package/dist/{workspace-migrate-duUsWNpd.js → workspace-migrate-BBQ8nAnP.js} +2 -2
  201. package/dist/{workspace-migrate-duUsWNpd.js.map → workspace-migrate-BBQ8nAnP.js.map} +1 -1
  202. package/dist/{workspace-reap-DLCIoJmn.js → workspace-reap-12O9354k.js} +2 -2
  203. package/dist/{workspace-reap-DLCIoJmn.js.map → workspace-reap-12O9354k.js.map} +1 -1
  204. package/package.json +1 -1
  205. package/scripts/file-size-baseline.txt +1 -1
  206. package/dist/cli-DBWG12XK.js +0 -3
  207. package/dist/dashboard/cli-CJDWXE_Y.js +0 -3
  208. package/dist/dashboard/deacon-swarm-D1iAUX-P.js +0 -2
  209. package/dist/dashboard/inspect-agent-vm88mLYr.js +0 -2
  210. package/dist/dashboard/merge-ops-QdBiQ8XB.js +0 -2
  211. package/dist/dashboard/resume-DnIsmIgC.js +0 -3
  212. package/dist/dashboard/review-agent-DgySDb-G.js +0 -3
  213. package/dist/dashboard/review-agent-phzqNqIs.js.map +0 -1
  214. package/dist/dashboard/review-status-BQjqQXZG.js.map +0 -1
  215. package/dist/dashboard/workflows-Cz8OtiB4.js +0 -2
  216. package/dist/records-backfill-DEgtRyKL.js +0 -2
  217. package/dist/resume-DGymuXZM.js +0 -3
  218. package/dist/review-agent-DjVadURa.js +0 -3
  219. package/dist/sync-4jqukkxz.js +0 -2
@@ -2,15 +2,16 @@ import { n as __esmMin } from "./rolldown-runtime-DNCzzKnI.js";
2
2
  import { Ft as resolveProjectForIssue, Gr as sessionFilePath, Nt as readIssueRecordSync, Ot as init_record, Ur as packageRoot, Vr as init_paths, X as resolveModel, f as loadConfigSync, t as init_config_yaml, yr as AGENTS_DIR } from "./config-yaml-DPAieL_G.js";
3
3
  import { a as init_activity_logger, n as emitActivityEntrySync } from "./activity-logger-pcbf-e30.js";
4
4
  import { C as isPaneDead, O as listSessionNames, w as killSession, x as init_tmux } from "./tmux-ePNhMIMU.js";
5
- import { c as init_review_status, s as getReviewStatusSync, y as setReviewStatusSync } from "./review-status-BQjqQXZG.js";
5
+ import { c as init_review_status, s as getReviewStatusSync, y as setReviewStatusSync } from "./review-status-B5ZASOo4.js";
6
6
  import { d as init_agents, f as listAgentIdsByPrefixSync, m as removeAgentSync } from "./briefing-freshness-CXhZdnB8.js";
7
- import { Pn as getAgentStateSync, t as init_agents$1 } from "./agents-DHvsjsuP.js";
7
+ import { Pn as getAgentStateSync, t as init_agents$1 } from "./agents-C7V4odQ6.js";
8
8
  import { a as PAN_DIRNAME, p as init_types } from "./types-CE1m_daD.js";
9
9
  import { n as init_review_monitor, t as REVIEW_SUB_ROLES } from "./review-monitor-BKG2ubt5.js";
10
10
  import { n as shouldSkipDispatchAsMerged, t as init_merge_verification } from "./merge-verification-DA9rvqsE.js";
11
- import { n as formatTier1Summary, o as init_review_context, t as buildReviewContext } from "./review-context-CCq56O_Y.js";
12
- import { a as resolveConflictGate, i as init_conflict_gate, r as getCachedConflictGateMergeability, t as buildRealConflictGateDeps } from "./conflict-gate-BhKvrPxn.js";
11
+ import { n as formatTier1Summary, o as init_review_context, t as buildReviewContext } from "./review-context-Dyo0tsBa.js";
12
+ import { a as resolveConflictGate, i as init_conflict_gate, r as getCachedConflictGateMergeability, t as buildRealConflictGateDeps } from "./conflict-gate-FFEvTDVA.js";
13
13
  import { Effect } from "effect";
14
+ import { existsSync } from "fs";
14
15
  import { dirname, join } from "path";
15
16
  import { mkdir, readFile, rm, writeFile } from "fs/promises";
16
17
  import { exec } from "child_process";
@@ -150,7 +151,7 @@ async function buildConvoyPromptPromise(opts) {
150
151
  }
151
152
  async function spawnReviewSubRoleForIssuePromise(opts) {
152
153
  try {
153
- const { saveAgentState, spawnRun, getAgentStateSync, getLatestSessionIdSync, resumeAgent } = await import("./agents-BIggLvi_.js");
154
+ const { saveAgentState, spawnRun, getAgentStateSync, getLatestSessionIdSync, resumeAgent } = await import("./agents-C-vqmKDi.js");
154
155
  const cfg = loadConfigSync().config;
155
156
  const outputPath = opts.outputPath ?? reviewerAgentOutputPath(opts.workspace, opts.runId, opts.subRole);
156
157
  const synthesisAgentId = opts.synthesisAgentId ?? `agent-${opts.issueId.toLowerCase()}-review`;
@@ -268,7 +269,7 @@ async function computeConvoyScope(issueId, workspace) {
268
269
  let carried = [];
269
270
  let scope = "changed";
270
271
  try {
271
- const { getReviewStatusSync } = await import("./review-status-bBkqUj5i.js");
272
+ const { getReviewStatusSync } = await import("./review-status-h7BXIA4z.js");
272
273
  scope = resolveReReviewScope(issueId);
273
274
  const priorVerdicts = getReviewStatusSync(issueId)?.reviewerVerdicts;
274
275
  let changedFiles;
@@ -311,7 +312,7 @@ async function computeConvoyScope(issueId, workspace) {
311
312
  */
312
313
  async function forkParentSessionForReviewer(parentAgentId, workspace) {
313
314
  try {
314
- const { getLatestSessionIdSync } = await import("./agents-BIggLvi_.js");
315
+ const { getLatestSessionIdSync } = await import("./agents-C-vqmKDi.js");
315
316
  const parentSessionId = getLatestSessionIdSync(parentAgentId);
316
317
  if (!parentSessionId) return null;
317
318
  const src = sessionFilePath(workspace, parentSessionId);
@@ -355,13 +356,13 @@ async function launchConvoyReviewersPromise(params) {
355
356
  }
356
357
  }
357
358
  const cfg = loadConfigSync().config;
358
- const { getAgentStateSync } = await import("./agents-BIggLvi_.js");
359
+ const { getAgentStateSync } = await import("./agents-C-vqmKDi.js");
359
360
  const parentState = getAgentStateSync(params.synthesisAgentId);
360
361
  const reviewerResults = await Promise.all(params.inScope.map(async (subRole) => {
361
362
  const outputPath = reviewerAgentOutputPath(params.workspace, params.runId, subRole);
362
363
  let forkedSessionId;
363
364
  if (params.forkFromParent && parentState?.harness === "claude-code" && !params.harness) try {
364
- const { getLatestSessionIdSync } = await import("./agents-BIggLvi_.js");
365
+ const { getLatestSessionIdSync } = await import("./agents-C-vqmKDi.js");
365
366
  const reviewerModel = params.model ?? resolveModel("review", subRole, cfg);
366
367
  if (!!!getLatestSessionIdSync(reviewerAgentId(params.issueId, subRole)) && reviewerModel === parentState.model) {
367
368
  forkedSessionId = await forkParentSessionForReviewer(params.synthesisAgentId, params.workspace) ?? void 0;
@@ -382,7 +383,7 @@ async function launchConvoyReviewersPromise(params) {
382
383
  allowHost: params.allowHost ?? false
383
384
  }));
384
385
  if (!result.success) try {
385
- const { messageAgent } = await import("./agents-BIggLvi_.js");
386
+ const { messageAgent } = await import("./agents-C-vqmKDi.js");
386
387
  await messageAgent(params.synthesisAgentId, `REVIEWER_FAILED ${subRole} ${result.error ?? result.message}`);
387
388
  } catch (signalErr) {
388
389
  console.warn(`[review-agent] Failed to signal ${subRole} spawn failure to ${params.synthesisAgentId}:`, signalErr);
@@ -409,7 +410,7 @@ async function launchConvoyReviewersPromise(params) {
409
410
  async function handleReviewDiscoveryReady(issueId, opts = {}) {
410
411
  const normalized = issueId.toUpperCase();
411
412
  const parentId = `agent-${normalized.toLowerCase()}-review`;
412
- const { saveAgentState, getAgentStateSync } = await import("./agents-BIggLvi_.js");
413
+ const { saveAgentState, getAgentStateSync } = await import("./agents-C-vqmKDi.js");
413
414
  const parent = getAgentStateSync(parentId);
414
415
  if (!parent) return {
415
416
  success: false,
@@ -734,13 +735,14 @@ async function spawnReviewRoleForIssuePromise(opts) {
734
735
  if ((await Effect.runPromise(listSessionNames())).includes(reviewSessionName)) {
735
736
  const paneDead = await Effect.runPromise(isPaneDead(reviewSessionName));
736
737
  let staleRunId = false;
738
+ let currentRunId;
737
739
  if (!paneDead && !opts.force) try {
738
740
  const { stdout } = await execAsync("git rev-parse --short=8 HEAD", {
739
741
  cwd: opts.workspace,
740
742
  encoding: "utf-8",
741
743
  timeout: 1e4
742
744
  });
743
- const currentRunId = `agent-${opts.issueId.toLowerCase()}-review-${stdout.trim()}`;
745
+ currentRunId = `agent-${opts.issueId.toLowerCase()}-review-${stdout.trim()}`;
744
746
  const synthReviewRunId = getAgentStateSync(reviewSessionName)?.reviewRunId;
745
747
  if (!synthReviewRunId || synthReviewRunId !== currentRunId) {
746
748
  staleRunId = true;
@@ -754,7 +756,11 @@ async function spawnReviewRoleForIssuePromise(opts) {
754
756
  const status = getReviewStatusSync(opts.issueId);
755
757
  const terminal = status?.reviewStatus === "passed" || status?.reviewStatus === "blocked" || status?.reviewStatus === "failed";
756
758
  const newerRequest = !!status?.reviewRequestedAt && (!status.reviewSpawnedAt || status.reviewRequestedAt > status.reviewSpawnedAt);
757
- finishedIdle = terminal && newerRequest;
759
+ let reportWritten = false;
760
+ if (currentRunId) try {
761
+ reportWritten = existsSync(join(opts.workspace, PAN_DIRNAME, "review", currentRunId, "review.md"));
762
+ } catch {}
763
+ finishedIdle = (terminal || reportWritten) && newerRequest;
758
764
  if (finishedIdle) console.log(`[review-agent] ${reviewSessionName} is finished-idle (verdict ${status?.reviewStatus}, newer request pending) — warm-reusing for the new review cycle`);
759
765
  else if (terminal) console.log(`[review-agent] ${reviewSessionName} has a terminal verdict (${status?.reviewStatus}) and no newer request — treating this dispatch as a stale duplicate; leaving the verdict intact`);
760
766
  } catch (statusErr) {
@@ -830,7 +836,7 @@ async function spawnReviewRoleForIssuePromise(opts) {
830
836
  });
831
837
  } catch {}
832
838
  try {
833
- const { spawnRun, saveAgentState, getAgentState, getAgentStateSync, getLatestSessionIdSync, resumeAgent, wipeAgentStateDirs } = await import("./agents-BIggLvi_.js");
839
+ const { spawnRun, saveAgentState, getAgentState, getAgentStateSync, getLatestSessionIdSync, resumeAgent, wipeAgentStateDirs } = await import("./agents-C-vqmKDi.js");
834
840
  const workAgentState = await Effect.runPromise(getAgentState(`agent-${opts.issueId.toLowerCase()}`));
835
841
  const allowHost = opts.allowHost === true || workAgentState?.hostOverride === true;
836
842
  let headSha = "unknown";
@@ -936,6 +942,7 @@ async function spawnReviewRoleForIssuePromise(opts) {
936
942
  const resumed = getAgentStateSync(reviewAgentId);
937
943
  if (resumed) {
938
944
  resumed.reviewRunId = runId;
945
+ resumed.reviewDeadlineAt = new Date(Date.now() + PARENT_REVIEW_TIMEOUT_MS).toISOString();
939
946
  await Effect.runPromise(saveAgentState(resumed));
940
947
  }
941
948
  } catch {}
@@ -966,6 +973,7 @@ async function spawnReviewRoleForIssuePromise(opts) {
966
973
  ...allowHost ? { allowHost: true } : {}
967
974
  });
968
975
  run.reviewRunId = runId;
976
+ run.reviewDeadlineAt = new Date(Date.now() + PARENT_REVIEW_TIMEOUT_MS).toISOString();
969
977
  try {
970
978
  await Effect.runPromise(saveAgentState(run));
971
979
  } catch (saveErr) {
@@ -1152,7 +1160,7 @@ async function purgeReviewAgentsForIssue(projectKey, issueId) {
1152
1160
  removed
1153
1161
  };
1154
1162
  }
1155
- var execAsync, spawnReviewRoleForIssue, killAllReviewerSessions, killAllReviewSessions;
1163
+ var execAsync, PARENT_REVIEW_TIMEOUT_MS, spawnReviewRoleForIssue, killAllReviewerSessions, killAllReviewSessions;
1156
1164
  var init_review_agent = __esmMin((() => {
1157
1165
  init_tmux();
1158
1166
  init_activity_logger();
@@ -1169,11 +1177,12 @@ var init_review_agent = __esmMin((() => {
1169
1177
  init_types();
1170
1178
  init_agents$1();
1171
1179
  execAsync = promisify(exec);
1180
+ PARENT_REVIEW_TIMEOUT_MS = 2700 * 1e3;
1172
1181
  spawnReviewRoleForIssue = (opts) => Effect.promise(() => spawnReviewRoleForIssuePromise(opts));
1173
1182
  killAllReviewerSessions = (projectKey, issueId) => Effect.promise(() => killAllReviewerSessionsPromise(projectKey, issueId));
1174
1183
  killAllReviewSessions = () => Effect.promise(() => killAllReviewSessionsPromise());
1175
1184
  }));
1176
1185
  //#endregion
1177
- export { killAllReviewSessions as a, resolveReviewMode as c, handleReviewDiscoveryReady as d, resolveReReviewScope as f, isReviewStaleSync as i, spawnReviewRoleForIssue as l, reviewResumeDecision as m, isExtendedReviewEnabled as n, killAllReviewerSessions as o, spawnReviewSubRoleForIssue as p, isReviewSessionForIssue as r, purgeReviewAgentsForIssue as s, init_review_agent as t, buildConvoyPrompt as u };
1186
+ export { isReviewStaleSync as a, purgeReviewAgentsForIssue as c, buildConvoyPrompt as d, handleReviewDiscoveryReady as f, reviewResumeDecision as h, isReviewSessionForIssue as i, resolveReviewMode as l, spawnReviewSubRoleForIssue as m, init_review_agent as n, killAllReviewSessions as o, resolveReReviewScope as p, isExtendedReviewEnabled as r, killAllReviewerSessions as s, PARENT_REVIEW_TIMEOUT_MS as t, spawnReviewRoleForIssue as u };
1178
1187
 
1179
- //# sourceMappingURL=review-agent-phzqNqIs.js.map
1188
+ //# sourceMappingURL=review-agent-D6P6d3pz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-agent-D6P6d3pz.js","names":["loadYamlConfig","execAsync","loadYamlConfig"],"sources":["../../src/lib/cloister/review-resume-decision.ts","../../src/lib/cloister/review-rerun-scope.ts","../../src/lib/cloister/review-convoy.ts","../../src/lib/cloister/review-agent.ts"],"sourcesContent":["/**\n * PAN-1862 — the resume-vs-fresh decision for a review agent, as a PURE function so it is locked\n * by tests and shared by both quick review (the parent) and convoy (the sub-reviewers).\n *\n * RESUME (preserve the prior review's context — files read, findings raised — so a re-review\n * checks the fix instead of re-researching the whole diff) when there is a saved, resumable\n * session AND the requested harness/model is unchanged. Fresh-spawn ONLY when the harness or\n * model actually changed (it's a different agent then) or there is no resumable session. A change\n * is detected only when BOTH the requested and saved values are known and differ — an unspecified\n * request (use role default) or an unknown saved value never forces a wipe.\n */\nexport function reviewResumeDecision(params: {\n requestedModel?: string;\n requestedHarness?: string;\n savedModel?: string;\n savedHarness?: string;\n hasSavedState: boolean;\n hasSavedSession: boolean;\n}): boolean {\n const modelChanged =\n !!params.requestedModel && !!params.savedModel && params.requestedModel !== params.savedModel;\n const harnessChanged =\n !!params.requestedHarness && !!params.savedHarness && params.requestedHarness !== params.savedHarness;\n return params.hasSavedState && params.hasSavedSession && !modelChanged && !harnessChanged;\n}\n","/**\n * PAN-1862 (FR-7, NFR-1): pure selection logic for selective re-review.\n *\n * On a re-review cycle (the work agent committed fixes after a BLOCKED verdict),\n * `roles.review.reReviewScope` governs which convoy reviewers actually re-run:\n *\n * - `all` — re-run all four reviewers every cycle (pre-PAN-1862 behavior).\n * - `changed` — (default) re-run reviewers that blocked, PLUS any reviewer whose\n * domain is touched by the files changed since its recorded verdict.\n * - `blockers` — re-run only reviewers that blocked in the prior cycle.\n *\n * Reviewers NOT re-run carry their prior `passed` verdict forward; the dispatch\n * path materializes that as a stub report in the new run directory so synthesis\n * and the deacon fallback see four reports exactly as before.\n *\n * Quality-first bias (NFR-1): whenever the inputs are insufficient to prove a\n * reviewer can be skipped — no prior verdicts, a verdict without a commit anchor,\n * or an unknown changed-file set — the reviewer is INCLUDED. Skipping is only\n * ever an optimization on proven-safe ground.\n */\n\nimport { REVIEW_SUB_ROLES, type ReviewSubRole } from './review-monitor.js';\n\nexport type ReReviewScope = 'all' | 'changed' | 'blockers';\n\nexport interface ReviewerVerdictEntry {\n status: 'passed' | 'blocked';\n /** HEAD sha the verdict was recorded against (anchor for drift invalidation). */\n atCommit?: string;\n /** Path to the reviewer's findings report for that cycle. */\n findingsPath?: string;\n}\n\nexport type ReviewerVerdictsMap = Partial<Record<ReviewSubRole, ReviewerVerdictEntry>>;\n\n/**\n * Domain map for `changed` scope (PRD \"open question\", resolved conservatively):\n * `correctness` and `requirements` are in scope whenever ANY file changed;\n * `security` when a security-sensitive path changed; `performance` when a\n * hot-path-ish file changed. Patterns err toward matching (include the reviewer).\n */\nconst SECURITY_SENSITIVE = /auth|crypt|token|secret|credential|password|session|login|permission|sandbox|escape|inject|input|parse|network|http|request|fetch|socket|proxy|exec|spawn|shell|env|\\.env|package(-lock)?\\.json|bun\\.lock|yarn\\.lock|Dockerfile|docker-compose/i;\nconst PERFORMANCE_SENSITIVE = /query|sql|db|database|cache|index|loop|batch|stream|worker|pool|queue|schedul|poll|interval|timer|migration|perf|bench|concurren|parallel/i;\n\nfunction domainTouched(subRole: ReviewSubRole, changedFiles: readonly string[]): boolean {\n if (changedFiles.length === 0) return false;\n switch (subRole) {\n case 'correctness':\n case 'requirements':\n return true; // every change is in scope for correctness + requirements\n case 'security':\n return changedFiles.some(f => SECURITY_SENSITIVE.test(f));\n case 'performance':\n return changedFiles.some(f => PERFORMANCE_SENSITIVE.test(f));\n default:\n return true; // unknown sub-role → include (fail toward quality)\n }\n}\n\nexport interface ReviewersToRerunInput {\n scope: ReReviewScope;\n /** Prior cycle's per-reviewer verdicts; absent/empty = first cycle → all run. */\n priorVerdicts?: ReviewerVerdictsMap;\n /**\n * Files changed since the prior verdicts' commit anchor. `undefined` means the\n * changed set could NOT be determined — every reviewer runs (fail toward quality).\n */\n changedFiles?: readonly string[];\n}\n\nexport function reviewersToRerun(input: ReviewersToRerunInput): ReviewSubRole[] {\n const all = [...REVIEW_SUB_ROLES];\n if (input.scope === 'all') return all;\n\n const verdicts = input.priorVerdicts ?? {};\n // A reviewer with no recorded verdict, or a verdict with no commit anchor,\n // cannot be proven safe to skip — it always runs.\n const unproven = all.filter(r => !verdicts[r] || !verdicts[r]!.atCommit);\n const blocked = all.filter(r => verdicts[r]?.status === 'blocked');\n\n if (input.scope === 'blockers') {\n return dedupe([...blocked, ...unproven]);\n }\n\n // scope === 'changed'\n if (input.changedFiles === undefined) return all; // unknown drift → everyone runs\n const touched = all.filter(r => verdicts[r]?.status === 'passed' && verdicts[r]!.atCommit && domainTouched(r, input.changedFiles!));\n return dedupe([...blocked, ...unproven, ...touched]);\n}\n\nfunction dedupe(roles: ReviewSubRole[]): ReviewSubRole[] {\n // Preserve the canonical REVIEW_SUB_ROLES ordering for stable prompts/logs.\n const set = new Set(roles);\n return REVIEW_SUB_ROLES.filter(r => set.has(r));\n}\n","/**\n * PAN-1862: the review CONVOY — sub-reviewer prompts and spawning, selective\n * re-review scope, warm-parent fork, and the discovery-ready orchestration.\n *\n * Split out of review-agent.ts (which keeps the review entry point, the\n * synthesis/self-review prompts, mode resolution, and session teardown).\n * This module must NEVER import review-agent.ts — review-agent imports (and\n * re-exports) from here, and a reverse edge would close a cycle.\n *\n * The four convoy sub-roles are security, correctness, performance, and\n * requirements (REVIEW_SUB_ROLES, review-monitor.ts); the synthesis parent is\n * the fifth review role. See docs/REVIEW-AGENT-ARCHITECTURE.md.\n */\n\nimport { exec } from 'child_process';\nimport { mkdir, readFile, rm, writeFile } from 'fs/promises';\nimport { dirname, join } from 'path';\nimport { promisify } from 'util';\nimport { Effect } from 'effect';\nimport { listSessionNames } from '../tmux.js';\nimport { emitActivityEntrySync } from '../activity-logger.js';\nimport { loadConfigSync as loadYamlConfig, resolveModel } from '../config-yaml.js';\nimport { formatTier1Summary, type ReviewContextManifest } from './review-context.js';\nimport { REVIEW_SUB_ROLES, type ReviewSubRole } from './review-monitor.js';\nimport { reviewResumeDecision } from './review-resume-decision.js';\nimport { reviewersToRerun, type ReviewerVerdictsMap, type ReReviewScope } from './review-rerun-scope.js';\nimport { readIssueRecordSync, resolveProjectForIssue } from '../pan-dir/record.js';\nimport { PAN_DIRNAME } from '../pan-dir/types.js';\nimport { AGENTS_DIR, packageRoot, sessionFilePath } from '../paths.js';\nimport type { RuntimeName } from '../runtimes/types.js';\n\nconst execAsync = promisify(exec);\n\n/**\n * Read a convoy sub-role prompt template from the overdeck install.\n *\n * Sub-role prompts are harness-agnostic templates owned by Overdeck. The\n * orchestrator reads them from its own install (packageRoot/roles/) and\n * inlines the body into the spawn message — they never live in the agent's\n * workspace, and they are never loaded via the Claude-specific `--agent` flag.\n * That keeps the same prompt content driving Claude Code, Pi, Codex, or any\n * future harness, and prevents a work agent from ambiently discovering its\n * own reviewer prompts in the workspace tree.\n */\nasync function readConvoySubRoleTemplate(subRole: string): Promise<string> {\n const path = join(packageRoot, 'roles', `review-${subRole}.md`);\n return readFile(path, 'utf-8');\n}\n\n\n\nconst REVIEWER_TIMEOUT_MS = 20 * 60 * 1000;\n\nfunction reviewerAgentId(issueId: string, subRole: ReviewSubRole): string {\n return `agent-${issueId.toLowerCase()}-review-${subRole}`;\n}\n\nfunction reviewerAgentOutputPath(workspace: string, runId: string, subRole: ReviewSubRole): string {\n return join(workspace, PAN_DIRNAME, 'review', runId, `${subRole}.md`);\n}\n\n\n\nasync function buildConvoyPromptPromise(opts: {\n issueId: string;\n subRole: string;\n outputPath: string;\n synthesisAgentId: string;\n contextManifestPath?: string;\n tier1Summary?: string;\n}): Promise<string> {\n const template = await readConvoySubRoleTemplate(opts.subRole);\n const prompt = [\n `REVIEW TASK for ${opts.issueId} — ${opts.subRole.toUpperCase()} REVIEW:`,\n '',\n `Issue: ${opts.issueId}`,\n `Sub-role: ${opts.subRole}`,\n '',\n 'Output file — write your full findings here when done:',\n ` ${opts.outputPath}`,\n '',\n opts.tier1Summary\n ? [\n 'Shared review context (read this first; do not run git diff yourself):',\n '─────────────────────────────────────────────────────────────',\n opts.tier1Summary,\n '─────────────────────────────────────────────────────────────',\n '',\n opts.contextManifestPath\n ? `Full manifest (read on demand for additional detail): ${opts.contextManifestPath}`\n : '',\n ].join('\\n')\n : opts.contextManifestPath\n ? [\n 'Context manifest (read this first; do not run git diff yourself):',\n ` ${opts.contextManifestPath}`,\n 'The manifest contains per-file risk ranking and acceptance criteria.',\n ].join('\\n')\n : 'No context manifest available. Write a blocked reviewer report explaining that the shared review context is missing.',\n '',\n '─────────────────────────────────────────────────────────────',\n 'REVIEW METHODOLOGY (inlined from roles/review-' + opts.subRole + '.md):',\n '─────────────────────────────────────────────────────────────',\n '',\n template.trim(),\n '',\n '─────────────────────────────────────────────────────────────',\n '',\n 'Write exactly one final report to the output file shown above, then stop',\n 'and wait. You do NOT need to signal synthesis or run any pan command —',\n 'when you finish your turn with the report written, Overdeck detects it',\n 'and signals the synthesis agent REVIEWER_READY automatically. Your only',\n 'job is to write the report file, then stop.',\n 'Only the output file is consumed by synthesis; your chat response is not the review report.',\n ].filter(Boolean).join('\\n');\n\n const sizeBytes = Buffer.byteLength(prompt, 'utf-8');\n console.log(`[review-agent] Convoy prompt for ${opts.issueId}/${opts.subRole}: ${sizeBytes} bytes`);\n return prompt;\n}\n\n\n\nasync function spawnReviewSubRoleForIssuePromise(opts: {\n issueId: string;\n workspace: string;\n subRole: ReviewSubRole;\n runId: string;\n outputPath?: string;\n contextManifestPath?: string;\n synthesisAgentId?: string;\n model?: string;\n harness?: RuntimeName;\n allowHost?: boolean;\n /**\n * PAN-1862 Phase A: a session id FORKED from the synthesis parent's discovery\n * session. When set, the reviewer launches with `claude --resume <id>` so its\n * first request replays the parent's byte-identical prefix and reads the warm\n * prompt cache instead of re-reading the diff and files at full price.\n */\n forkedSessionId?: string;\n}): Promise<{ success: boolean; message: string; error?: string; sessionId?: string }> {\n try {\n const { saveAgentState, spawnRun, getAgentStateSync, getLatestSessionIdSync, resumeAgent } = await import('../agents.js');\n const cfg = loadYamlConfig().config;\n const outputPath = opts.outputPath ?? reviewerAgentOutputPath(opts.workspace, opts.runId, opts.subRole);\n const synthesisAgentId = opts.synthesisAgentId ?? `agent-${opts.issueId.toLowerCase()}-review`;\n const model = opts.model ?? resolveModel('review', opts.subRole, cfg, opts.subRole ? undefined : `review:${opts.issueId}`);\n const reviewerDir = join(AGENTS_DIR, reviewerAgentId(opts.issueId, opts.subRole));\n\n await mkdir(dirname(outputPath), { recursive: true });\n await rm(outputPath, { force: true });\n await rm(join(reviewerDir, 'reviewer-signaled'), { force: true });\n await rm(join(reviewerDir, 'reviewer-launcher.pid'), { force: true });\n\n // Build Tier-1 inline summary from manifest when available (PAN-1125)\n let tier1Summary: string | undefined;\n if (opts.contextManifestPath) {\n try {\n const manifestRaw = await readFile(opts.contextManifestPath, 'utf-8');\n const manifest = JSON.parse(manifestRaw) as ReviewContextManifest;\n tier1Summary = formatTier1Summary(manifest);\n } catch (manifestErr) {\n console.warn(`[review-agent] Failed to read manifest for Tier-1 summary (${opts.issueId}/${opts.subRole}):`, manifestErr);\n }\n }\n\n const prompt = await Effect.runPromise(buildConvoyPrompt({\n issueId: opts.issueId,\n subRole: opts.subRole,\n outputPath,\n synthesisAgentId,\n contextManifestPath: opts.contextManifestPath,\n tier1Summary,\n }));\n\n // PAN-1862: convoy sub-reviewers RESUME by default too — same rule as quick review. Each\n // lane keeps its prior round's context so a re-review checks the fix instead of re-reading\n // the whole diff. Fresh-spawn only on a harness/model change or when no session exists.\n // A forked first-cycle spawn (forkedSessionId) bypasses the saved-resume decision entirely:\n // there is no prior lane context, and the fork IS the context.\n const reviewerAgent = reviewerAgentId(opts.issueId, opts.subRole);\n const savedReviewer = opts.forkedSessionId ? null : getAgentStateSync(reviewerAgent);\n const canResumeReviewer = !opts.forkedSessionId && reviewResumeDecision({\n requestedModel: opts.model ?? model,\n requestedHarness: opts.harness,\n savedModel: savedReviewer?.model,\n savedHarness: savedReviewer?.harness,\n hasSavedState: !!savedReviewer,\n hasSavedSession: !!getLatestSessionIdSync(reviewerAgent),\n });\n if (canResumeReviewer) {\n console.log(`[review-agent] Resuming convoy sub-reviewer ${opts.subRole} for ${opts.issueId} — preserving context (PAN-1862)`);\n const resumeResult = await resumeAgent(reviewerAgent, prompt);\n if (resumeResult.success) {\n try {\n const resumed = getAgentStateSync(reviewerAgent);\n if (resumed) {\n resumed.reviewSubRole = opts.subRole;\n resumed.reviewRunId = opts.runId;\n resumed.reviewOutputPath = outputPath;\n resumed.reviewSynthesisAgentId = synthesisAgentId;\n resumed.reviewDeadlineAt = new Date(Date.now() + REVIEWER_TIMEOUT_MS).toISOString();\n await Effect.runPromise(saveAgentState(resumed));\n }\n } catch { /* non-fatal */ }\n return { success: true, message: `Review ${opts.subRole} resumed (session preserved): ${reviewerAgent}`, sessionId: reviewerAgent };\n }\n console.warn(`[review-agent] Convoy sub-reviewer ${opts.subRole} resume failed; falling back to a fresh session: ${resumeResult.error}`);\n }\n\n const forkedPreface = opts.forkedSessionId\n ? [\n 'SHARED DISCOVERY CONTEXT (PAN-1862): this session was forked from the review',\n 'parent AFTER it completed a shared discovery pass — the diff, the high-risk',\n 'changed files, and their surrounding code are already in your history above.',\n 'That pass exists for cost (forked reviewers reuse the warm prompt cache instead',\n 'of four full-price re-reads) and for consistency (every reviewer sees the same',\n 'curated context). BUILD ON IT: do not re-run a broad git diff and do not',\n 're-read the files already shown above; read further code only where your',\n 'sub-role needs deeper detail.',\n '',\n ].join('\\n')\n : '';\n const run = await spawnRun(opts.issueId, 'review', {\n workspace: opts.workspace,\n subRole: opts.subRole,\n prompt: forkedPreface + prompt,\n model,\n harness: opts.harness,\n ...(opts.forkedSessionId ? { resumeSessionId: opts.forkedSessionId } : {}),\n // PAN-977: thread the synthesis wiring up front so the generated launcher\n // owns the REVIEWER_READY/FAILED/TIMEOUT signal deterministically.\n reviewSynthesisAgentId: synthesisAgentId,\n reviewOutputPath: outputPath,\n allowHost: opts.allowHost ?? false,\n });\n run.reviewSubRole = opts.subRole;\n run.reviewRunId = opts.runId;\n run.reviewOutputPath = outputPath;\n run.reviewSynthesisAgentId = synthesisAgentId;\n run.reviewDeadlineAt = new Date(Date.now() + REVIEWER_TIMEOUT_MS).toISOString();\n if (opts.forkedSessionId) run.reviewForkedFromParent = true;\n await Effect.runPromise(saveAgentState(run));\n try {\n const { notifyPipelineSync } = await import('../pipeline-notifier.js');\n notifyPipelineSync({ type: 'reviewer_started', issueId: opts.issueId, role: opts.subRole, sessionName: run.id });\n } catch {\n // Non-fatal\n }\n return { success: true, message: `Review ${opts.subRole} spawned: ${run.id}`, sessionId: run.id };\n } catch (err) {\n return {\n success: false,\n message: `Failed to spawn review ${opts.subRole}`,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n\n/**\n * PAN-1862: selective re-review scope for one dispatch — which convoy reviewers\n * run this cycle and which carry their prior passed verdict forward. Shared by\n * the inline dispatch path and the discovery-ready fork handler.\n */\nexport async function computeConvoyScope(issueId: string, workspace: string): Promise<{\n inScope: ReviewSubRole[];\n carried: Array<{ subRole: ReviewSubRole; atCommit?: string }>;\n scope: ReReviewScope;\n}> {\n let inScope: ReviewSubRole[] = [...REVIEW_SUB_ROLES];\n let carried: Array<{ subRole: ReviewSubRole; atCommit?: string }> = [];\n let scope: ReReviewScope = 'changed';\n try {\n // Dynamic import: review-status.ts reaches back into cloister via review-agent,\n // so a static edge here would close a module cycle (lint:circular).\n const { getReviewStatusSync } = await import('../review-status.js');\n scope = resolveReReviewScope(issueId);\n const priorVerdicts = getReviewStatusSync(issueId)?.reviewerVerdicts as ReviewerVerdictsMap | undefined;\n let changedFiles: string[] | undefined;\n const anchors = new Set(\n Object.values(priorVerdicts ?? {}).map(v => v?.atCommit).filter((c): c is string => !!c),\n );\n if (anchors.size === 1) {\n try {\n const { stdout } = await execAsync(`git diff --name-only ${[...anchors][0]}..HEAD`, {\n cwd: workspace, encoding: 'utf-8', timeout: 15_000,\n });\n changedFiles = stdout.split('\\n').map(l => l.trim()).filter(Boolean);\n } catch { /* anchor unreachable (rebase) -> unknown drift -> all run */ }\n }\n inScope = reviewersToRerun({ scope, priorVerdicts, changedFiles });\n carried = REVIEW_SUB_ROLES\n .filter(r => !inScope.includes(r))\n .map(r => ({ subRole: r, atCommit: priorVerdicts?.[r]?.atCommit }));\n if (carried.length > 0) {\n console.log(`[review-agent] Selective re-review for ${issueId} (scope=${scope}): re-running [${inScope.join(', ')}], carrying forward [${carried.map(c => c.subRole).join(', ')}]`);\n }\n } catch (scopeErr) {\n console.warn(`[review-agent] Selective re-review scope resolution failed for ${issueId} — running the full convoy:`, scopeErr);\n inScope = [...REVIEW_SUB_ROLES];\n carried = [];\n }\n return { inScope, carried, scope };\n}\n\n/**\n * PAN-1862 Phase A: fork the synthesis parent's Claude session JSONL to a fresh\n * session id so a convoy reviewer can `--resume` it and inherit the discovery\n * context (and its warm, content-addressed prompt cache). Returns null when the\n * fork is not possible — caller degrades to a fresh independent spawn (NFR-2).\n * The source JSONL is copied, never modified.\n */\nasync function forkParentSessionForReviewer(parentAgentId: string, workspace: string): Promise<string | null> {\n try {\n const { getLatestSessionIdSync } = await import('../agents.js');\n const parentSessionId = getLatestSessionIdSync(parentAgentId);\n if (!parentSessionId) return null;\n const src = sessionFilePath(workspace, parentSessionId);\n const { existsSync } = await import('fs');\n if (!existsSync(src)) return null;\n const { reserveForkSession, copySessionForFork } = await import('../conversations/session-fork.js');\n const reserved = await reserveForkSession(workspace);\n await copySessionForFork(src, reserved.sessionFile, { fullHistory: true });\n return reserved.sessionId;\n } catch (err) {\n console.warn(`[review-agent] Fork from ${parentAgentId} failed (degrading to independent spawn): ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\nexport interface ConvoyLaunchParams {\n issueId: string;\n workspace: string;\n runId: string;\n synthesisAgentId: string;\n inScope: ReviewSubRole[];\n carried: Array<{ subRole: ReviewSubRole; atCommit?: string }>;\n scope: ReReviewScope;\n contextManifestPath?: string;\n model?: string;\n harness?: RuntimeName;\n allowHost?: boolean;\n /** PAN-1862 Phase A: fork each eligible first-cycle reviewer from the parent's session. */\n forkFromParent?: boolean;\n}\n\n/**\n * Launch the review convoy for one run: write carried-forward stub reports, then\n * spawn (or fork-resume) each in-scope sub-reviewer. Shared by the inline\n * dispatch path (no fork) and the discovery-ready handler (fork).\n */\nexport async function launchConvoyReviewersPromise(params: ConvoyLaunchParams): Promise<Array<{ success: boolean; message: string }>> {\n const reviewDir = join(params.workspace, PAN_DIRNAME, 'review', params.runId);\n // PAN-1862 (FR-8): materialize carried-forward verdicts as stub reports in the\n // NEW run directory so synthesis and the deacon fallback still see one report\n // per sub-role, exactly as when every reviewer runs. Blocking-findings\n // extraction on a stub finds none -> the sub-role reads as passed.\n if (params.carried.length > 0) {\n await mkdir(reviewDir, { recursive: true });\n for (const c of params.carried) {\n const stubPath = reviewerAgentOutputPath(params.workspace, params.runId, c.subRole);\n const anchorNote = c.atCommit ? ` at commit ${c.atCommit.slice(0, 8)}` : '';\n await writeFile(stubPath, [\n `# ${c.subRole} review — VERDICT CARRIED FORWARD`,\n '',\n '## Verdict: APPROVED (carried forward — reviewer not re-run this cycle)',\n '',\n `This reviewer passed the prior cycle${anchorNote} and no files in its domain`,\n `changed since (reReviewScope=${params.scope}, PAN-1862 selective re-review).`,\n 'Its prior findings report remains the report of record for that verdict.',\n '',\n '## Findings',\n '',\n 'None.',\n '',\n ].join('\\n'), 'utf-8');\n }\n }\n\n const cfg = loadYamlConfig().config;\n const { getAgentStateSync } = await import('../agents.js');\n const parentState = getAgentStateSync(params.synthesisAgentId);\n const reviewerResults = await Promise.all(params.inScope.map(async (subRole) => {\n const outputPath = reviewerAgentOutputPath(params.workspace, params.runId, subRole);\n\n // PAN-1862 Phase A fork decision, per reviewer: fork only when (a) fork mode is\n // on, (b) the parent runs claude-code (the fork machinery is Claude's --resume),\n // (c) the reviewer resolves to the SAME model as the parent (the cache is\n // per-model — a mismatched fork would replay the history at full price and the\n // Settings banner is the operator surface for that), and (d) the reviewer has\n // no resumable prior-cycle session of its own (its OWN context beats a re-fork —\n // PRD decision 3). Every failure degrades to today's independent spawn (NFR-2).\n let forkedSessionId: string | undefined;\n if (params.forkFromParent && parentState?.harness === 'claude-code' && !params.harness) {\n try {\n const { getLatestSessionIdSync } = await import('../agents.js');\n const reviewerModel = params.model ?? resolveModel('review', subRole, cfg);\n const hasOwnSession = !!getLatestSessionIdSync(reviewerAgentId(params.issueId, subRole));\n if (!hasOwnSession && reviewerModel === parentState.model) {\n forkedSessionId = (await forkParentSessionForReviewer(params.synthesisAgentId, params.workspace)) ?? undefined;\n if (forkedSessionId) {\n console.log(`[review-agent] Forked ${subRole} reviewer for ${params.issueId} from ${params.synthesisAgentId}'s discovery session (PAN-1862)`);\n }\n }\n } catch { /* degrade to independent spawn */ }\n }\n\n const result = await Effect.runPromise(spawnReviewSubRoleForIssue({\n issueId: params.issueId,\n workspace: params.workspace,\n subRole,\n runId: params.runId,\n outputPath,\n contextManifestPath: params.contextManifestPath,\n synthesisAgentId: params.synthesisAgentId,\n ...(params.model ? { model: params.model } : {}),\n ...(params.harness ? { harness: params.harness } : {}),\n ...(forkedSessionId ? { forkedSessionId } : {}),\n allowHost: params.allowHost ?? false,\n }));\n if (!result.success) {\n try {\n const { messageAgent } = await import('../agents.js');\n await messageAgent(params.synthesisAgentId, `REVIEWER_FAILED ${subRole} ${result.error ?? result.message}`);\n } catch (signalErr) {\n console.warn(`[review-agent] Failed to signal ${subRole} spawn failure to ${params.synthesisAgentId}:`, signalErr);\n }\n }\n return result;\n }));\n\n const failedReviewers = reviewerResults.filter(r => !r.success);\n if (failedReviewers.length > 0) {\n console.warn(`[review-agent] Convoy launched for ${params.issueId}, but ${failedReviewers.length} reviewer(s) failed to spawn`);\n }\n return reviewerResults;\n}\n\n\n\nexport const buildConvoyPrompt = (opts: {\n issueId: string;\n subRole: string;\n outputPath: string;\n synthesisAgentId: string;\n contextManifestPath?: string;\n tier1Summary?: string;\n}): Effect.Effect<string> => Effect.promise(() => buildConvoyPromptPromise(opts));\n\n/**\n * Effect variant of {@link spawnReviewSubRoleForIssue}. The Promise version\n * already aggregates errors into the structured result shape, so the Effect\n * form lifts via `Effect.promise`.\n */\nexport const spawnReviewSubRoleForIssue = (opts: {\n issueId: string;\n workspace: string;\n subRole: ReviewSubRole;\n runId: string;\n outputPath?: string;\n contextManifestPath?: string;\n synthesisAgentId?: string;\n model?: string;\n harness?: RuntimeName;\n allowHost?: boolean;\n}): Effect.Effect<{ success: boolean; message: string; error?: string; sessionId?: string }> =>\n Effect.promise(() => spawnReviewSubRoleForIssuePromise(opts));\n\n/**\n * Effect variant of {@link spawnReviewRoleForIssue}. The Promise version\n * returns a structured result instead of throwing, so the Effect form lifts\n * via `Effect.promise`.\n */\n\n\n/**\n * PAN-1862 Phase A (FR-2/FR-3/FR-4, NFR-5): handle the parent's discovery-ready\n * signal — fork the parent's session into the convoy reviewers and launch them.\n * Idempotent: a repeat signal (or a signal after the convoy already launched)\n * is a no-op. The parent survives unmodified and resumes its synthesis role;\n * the CLI (`pan admin specialists discovery-ready review <id>`) and the deacon\n * stalled-discovery backstop both land here.\n */\nexport async function handleReviewDiscoveryReady(\n issueId: string,\n opts: { source?: string } = {},\n): Promise<{ success: boolean; message: string; launched?: number }> {\n const normalized = issueId.toUpperCase();\n const parentId = `agent-${normalized.toLowerCase()}-review`;\n const { saveAgentState, getAgentStateSync } = await import('../agents.js');\n const parent = getAgentStateSync(parentId);\n if (!parent) {\n return { success: false, message: `No review parent state for ${normalized} — nothing to fork` };\n }\n const workspace = parent.workspace;\n const runId = parent.reviewRunId;\n if (!workspace || !runId) {\n return { success: false, message: `Review parent for ${normalized} is missing workspace/runId state — cannot launch the convoy` };\n }\n\n // PAN-2585: the signal is AUTHORITATIVE. `reviewDiscoveryPending` is persisted only\n // in state.json and is invisible through the DB-backed agent reader, so it must not\n // gate the launch — gating on it left parents standing by forever for reviewers that\n // were never forked. Idempotency comes from evidence instead: a live reviewer\n // session, or a reviewer output already written for the CURRENT run, means the\n // convoy launched — no-op. No evidence means launch, flag or no flag.\n try {\n const sessions = await Effect.runPromise(listSessionNames());\n const reviewerPrefix = `agent-${normalized.toLowerCase()}-review-`;\n if (sessions.some(name => name.startsWith(reviewerPrefix))) {\n parent.reviewDiscoveryPending = false;\n await Effect.runPromise(saveAgentState(parent));\n return { success: true, message: `Convoy already launched for ${normalized} — no-op` };\n }\n } catch { /* liveness probe failure — proceed; spawnRun's own guards hold */ }\n try {\n const { existsSync } = await import('node:fs');\n const hasRunOutput = REVIEW_SUB_ROLES.some(subRole =>\n existsSync(reviewerAgentOutputPath(workspace, runId, subRole)),\n );\n if (hasRunOutput) {\n parent.reviewDiscoveryPending = false;\n await Effect.runPromise(saveAgentState(parent));\n return { success: true, message: `Convoy for ${normalized} run ${runId} already produced reviewer output — no-op` };\n }\n } catch { /* output probe failure — proceed */ }\n\n // Clear the pending flag BEFORE launching so a concurrent duplicate signal\n // short-circuits on the check above / the flag here.\n parent.reviewDiscoveryPending = false;\n parent.reviewDiscoveryReadyAt = new Date().toISOString();\n await Effect.runPromise(saveAgentState(parent));\n\n const { inScope, carried, scope } = await computeConvoyScope(normalized, workspace);\n const results = await launchConvoyReviewersPromise({\n issueId: normalized,\n workspace,\n runId,\n synthesisAgentId: parentId,\n inScope,\n carried,\n scope,\n contextManifestPath: parent.reviewContextManifestPath,\n allowHost: parent.hostOverride ?? false,\n forkFromParent: true,\n });\n\n const refreshed = getAgentStateSync(parentId);\n if (refreshed) {\n refreshed.reviewConvoyForkedAt = new Date().toISOString();\n await Effect.runPromise(saveAgentState(refreshed));\n }\n\n const launched = results.filter(r => r.success).length;\n const message = `Discovery-ready for ${normalized}${opts.source ? ` (${opts.source})` : ''}: launched ${launched}/${inScope.length} convoy reviewer(s)${carried.length ? `, carried [${carried.map(c => c.subRole).join(', ')}]` : ''}`;\n console.log(`[review-agent] ${message}`);\n emitActivityEntrySync({ source: 'review', level: 'info', message, issueId: normalized });\n return { success: launched > 0 || inScope.length === 0, message, launched };\n}\n\n\n\n/** PAN-1862 (FR-7): resolved re-review scope — merged config, default 'changed'. */\nexport function resolveReReviewScope(issueId?: string): ReReviewScope {\n // PAN-1874: per-issue record override beats merged project/global config\n // (same resolution shape as resolveReviewMode in review-agent.ts).\n if (issueId) {\n try {\n const project = resolveProjectForIssue(issueId);\n const issueScope = project ? readIssueRecordSync(project, issueId)?.reReviewScope : undefined;\n if (issueScope === 'all' || issueScope === 'changed' || issueScope === 'blockers') return issueScope;\n } catch { /* fall through to config */ }\n }\n const scope = loadYamlConfig().config.roles?.review?.reReviewScope;\n return scope === 'all' || scope === 'blockers' ? scope : 'changed';\n}\n\n\n","/**\n * Review role entry point.\n *\n * PAN-1048 review feedback 007: every legacy convoy helper has been retired.\n * The bash/tmux coordinator path (dispatchParallelReview /\n * spawnReviewCoordinatorSession / runParallelReview) was deleted in R6, and\n * the round-7 cleanup additionally removed the supporting cast that the\n * coordinator used to drive — spawnSingleReviewer, waitForReviewer,\n * archiveReviewerRound, parseReviewSynthesis, parseAgentOutput,\n * selectCompletedReviewers, getReviewAgents, getFilesChangedFromPR,\n * buildReviewFeedbackBody, parseReviewerTemplate, resolvePromptTemplatePath\n * (and the resolveTemplatePath alias), resolveReviewerModel,\n * reviewResultToReviewStatus, reviewerRetryBackoffMs,\n * isRetryableReviewerFailure, the ReviewContext / ReviewResult /\n * ReviewerTemplate / ReviewerRoundArtifact / ReviewerOutcome /\n * ReviewerWaitResult / ReviewerFailureReason / ReviewHistoryEntry types,\n * and DEFAULT_REVIEW_AGENTS / REVIEW_TIMEOUT_MS / MAX_REVIEWER_TIMEOUT_RETRIES\n * / REVIEWER_TIMEOUT_RETRY_BACKOFF_MS / REVIEW_HISTORY_DIR / REVIEW_HISTORY_FILE\n * / SPECIALISTS_DIR constants. None of these had any production caller after R6;\n * their tests went with them.\n *\n * Every active review surface — POST /api/review/:issueId/trigger, the\n * reactive scheduler review branch, and the dashboard kanban \"Review again\"\n * button — flows through\n * spawnReviewRoleForIssue → spawnRun(issueId, 'review'). The review role\n * launches four isolated review sub-role sessions via `pan review spawn-reviewer`,\n * then writes the report and signals the verdict via Overdeck's CLI inside\n * the role itself (see roles/review.md).\n *\n * Surface area kept:\n * - spawnReviewRoleForIssue — the only review entry point\n * - killAllReviewerSessions — kill the canonical reviewer sessions\n * for one issue (merge-agent +\n * dashboard cancel/abort routes)\n * - killAllReviewSessions — kill ALL review sessions on shutdown\n * (pan down)\n */\n\nimport { exec } from 'child_process';\nimport { existsSync } from 'fs';\nimport { mkdir, readFile, rm, writeFile } from 'fs/promises';\nimport { dirname, join } from 'path';\nimport { promisify } from 'util';\nimport { Effect } from 'effect';\nimport { killSession, listSessionNames, isPaneDead } from '../tmux.js';\nimport { emitActivityEntrySync } from '../activity-logger.js';\nimport { removeAgentSync, listAgentIdsByPrefixSync } from '../overdeck/agents.js';\nimport { getReviewStatusSync, setReviewStatusSync } from '../review-status.js';\nimport { loadConfigSync as loadYamlConfig, resolveModel, type ReviewMode } from '../config-yaml.js';\nimport { buildReviewContext, formatTier1Summary, type ReviewContextManifest } from './review-context.js';\nimport { buildRealConflictGateDeps, getCachedConflictGateMergeability, resolveConflictGate } from './conflict-gate.js';\nimport { REVIEW_SUB_ROLES, type ReviewSubRole } from './review-monitor.js';\nimport { reviewResumeDecision } from './review-resume-decision.js';\nimport { type ReReviewScope } from './review-rerun-scope.js';\nimport {\n computeConvoyScope,\n launchConvoyReviewersPromise,\n} from './review-convoy.js';\nimport { shouldSkipDispatchAsMerged } from './merge-verification.js';\nimport { readIssueRecordSync, resolveProjectForIssue } from '../pan-dir/record.js';\nimport { PAN_DIRNAME } from '../pan-dir/types.js';\nimport { AGENTS_DIR, packageRoot, sessionFilePath } from '../paths.js';\nimport { getAgentStateSync } from '../agents.js';\nimport type { RuntimeName } from '../runtimes/types.js';\n\nconst execAsync = promisify(exec);\n// PAN-1531: review-temp stash helpers removed.\n\n// PAN-2584: liveness budget for the review PARENT (discovery + convoy + synthesis).\n// Sub-reviewers get their own 20-minute deadlines in review-convoy.ts; the parent\n// needs headroom for all three phases. Enforced by checkStalledReviewParents.\nexport const PARENT_REVIEW_TIMEOUT_MS = 45 * 60 * 1000;\n// Review now runs against the committed diff only. The dirty-worktree gate\n// at pan done time (and the same gate added to /api/review/:id/request)\n// guarantees the worktree is clean before specialists see the diff.\n\nfunction buildReviewRolePrompt(opts: {\n issueId: string;\n workspace: string;\n branch: string;\n prUrl?: string;\n runId: string;\n reviewDir: string;\n contextManifestPath?: string;\n tier1Summary?: string;\n /** PAN-1862 (FR-9): sub-roles actually running this cycle (default: all four). */\n inScopeSubRoles?: ReviewSubRole[];\n /** PAN-1862 (FR-9): sub-roles whose passed verdicts are carried forward this cycle. */\n carriedSubRoles?: Array<{ subRole: ReviewSubRole; atCommit?: string }>;\n /**\n * PAN-1862 Phase A: when true, the parent performs SHARED DISCOVERY first and\n * signals `pan admin specialists discovery-ready review <id>`; the server then\n * forks this session into the convoy so the reviewers inherit the warm cache.\n */\n discovery?: boolean;\n}): string {\n const inScope = opts.inScopeSubRoles && opts.inScopeSubRoles.length > 0 ? opts.inScopeSubRoles : [...REVIEW_SUB_ROLES];\n const carried = opts.carriedSubRoles ?? [];\n const subRoleFiles = REVIEW_SUB_ROLES.map(r => ` ${join(opts.reviewDir, `${r}.md`)}`).join('\\n');\n const expectedSignals = inScope.map(r => ` REVIEWER_READY ${r} <outputPath> or REVIEWER_FAILED ${r} <reason> or REVIEWER_TIMEOUT ${r} <reason>`).join('\\n');\n const synthesisPath = join(opts.reviewDir, 'synthesis.md');\n const runningDesc = inScope.length === REVIEW_SUB_ROLES.length\n ? 'the four convoy reviewers (security, correctness, performance, requirements)'\n : `${inScope.length} convoy reviewer(s) this cycle (${inScope.join(', ')})`;\n const carriedSection = carried.length > 0\n ? [\n '',\n `CARRIED-FORWARD VERDICTS (PAN-1862 selective re-review): ${carried.map(c => c.subRole).join(', ')}.`,\n 'These reviewers PASSED the prior cycle and none of their domain files changed',\n 'since, so they were NOT re-run. Their stub reports are already written in the',\n 'review directory — treat each as a passed verdict. Do NOT wait for signals',\n 'from them; they will never arrive.',\n ].join('\\n')\n : '';\n const discoverySection = opts.discovery\n ? [\n `DISCOVERY + SYNTHESIS — REVIEW for ${opts.issueId}`,\n '',\n 'PHASE 1 — SHARED DISCOVERY (do this FIRST):',\n 'Read the code the whole review convoy will need so it lives in THIS',\n \"session's history. WHY: after you signal readiness the server FORKS this\",\n 'session into the convoy reviewers, and because the prompt cache is',\n 'content-addressed, everything you read here becomes a ~90%-discounted',\n 'cache read for every forked reviewer instead of four independent',\n 'full-price re-reads. Reviewers also review better when they all see the',\n 'same curated context and understand the change as a whole.',\n '',\n '1. Read the context manifest (path below): risk ranking + acceptance criteria.',\n '2. Read the committed diff for the branch (git diff against the merge base).',\n '3. Read the FULL contents of the HIGH-risk changed files and the immediately',\n ' surrounding code they depend on. Stay within the manifest scope — this is',\n ' curation for the convoy, not an open-ended crawl.',\n '',\n 'Then signal readiness EXACTLY ONCE (repeat signals are a server-side no-op):',\n ` pan admin specialists discovery-ready review ${opts.issueId}`,\n '',\n 'PHASE 2 — STANDBY (after the signal):',\n `The server forks this session into ${runningDesc}.`,\n 'Your work resumes only once they finish.',\n '',\n ]\n : [\n `STANDBY — REVIEW SYNTHESIS for ${opts.issueId}`,\n '',\n `Do NOT do anything yet. The Overdeck server has already spawned ${runningDesc}`,\n 'and they are running in parallel right now. Your work begins only once they finish.',\n '',\n ];\n const prompt = [\n ...discoverySection,\n `You will receive exactly one \\`pan tell\\` signal per RUNNING sub-role as each`,\n 'reviewer finishes — these are delivered to you as user messages:',\n expectedSignals,\n carriedSection,\n '',\n `Until all ${inScope.length} terminal signal(s) have arrived: do nothing. Do not read the`,\n 'reviewer output files, do not run git, do not inspect tmux sessions, do not',\n 'poll anything. Just wait — the reviewers notify you when they finish, and',\n 'Deacon is the failsafe if one never starts or never completes. Acting early',\n 'wastes tokens reviewing nothing.',\n '',\n `Once you have all ${inScope.length} terminal signal(s), follow roles/review.md exactly to`,\n 'read the reports (including any carried-forward stubs), synthesize the verdict,',\n 'write the synthesis report, and signal the status.',\n '',\n '── Review context ──',\n `Issue: ${opts.issueId}`,\n `Branch: ${opts.branch}`,\n `Workspace: ${opts.workspace}`,\n opts.prUrl ? `PR: ${opts.prUrl}` : `PR: (resolve via: gh pr view ${opts.branch})`,\n `Run ID: ${opts.runId}`,\n `Review directory: ${opts.reviewDir}`,\n `Synthesis output file: ${synthesisPath}`,\n '',\n opts.tier1Summary\n ? [\n 'Shared review context:',\n '─────────────────────────────────────────────────────────────',\n opts.tier1Summary,\n '─────────────────────────────────────────────────────────────',\n '',\n opts.contextManifestPath ? `Full manifest: ${opts.contextManifestPath}` : '',\n ].join('\\n')\n : opts.contextManifestPath\n ? `Context manifest: ${opts.contextManifestPath}`\n : 'Context manifest: (missing — block review per roles/review.md)',\n '',\n 'Convoy reviewer output files (read each one ONLY after its REVIEWER_READY signal):',\n subRoleFiles,\n '',\n 'After writing the synthesis report, signal the verdict with Overdeck CLI,',\n 'including a per-reviewer verdict for each sub-role that RAN this cycle',\n '(PAN-1862 — this is what lets the next re-review skip provably-clean reviewers;',\n 'do NOT list carried-forward sub-roles, their verdicts are already recorded):',\n ` pan admin specialists done review ${opts.issueId} --status passed --notes \"<one-line summary>\" --reviewers \"${inScope.map(r => `${r}=passed`).join(',')}\"`,\n ` pan admin specialists done review ${opts.issueId} --status blocked --notes \"<one-line top blocker>\" --reviewers \"<subRole>=passed|blocked for each of: ${inScope.join(', ')}>\"`,\n '',\n // PAN-2007: do NOT tell the agent to `exit`. The session is kept alive through\n // the pipeline (KEEP_SPECIALIST_SESSIONS_ALIVE) so it can be reused for the next\n // review cycle without a cold re-spawn. Exiting before the signal command is\n // what stranded reviews at reviewStatus=reviewing.\n 'After running the signal command above, STOP and wait — do not exit, do not run',\n 'any further commands. The session stays open for the next review cycle.',\n '',\n 'Reactive Cloister dispatches the test role after review passes. Never queue tests yourself and never edit code.',\n ].filter(Boolean).join('\\n');\n\n const sizeBytes = Buffer.byteLength(prompt, 'utf-8');\n console.log(`[review-agent] Synthesis prompt for ${opts.issueId}: ${sizeBytes} bytes`);\n return prompt;\n}\n\n// PAN-1981 (quick path to production): the review role agent reviews the diff\n// ITSELF — no convoy, no synthesis. `buildReviewRolePrompt` above (the synthesis\n// \"stand by, wait for the convoy\" prompt) is kept for when we restore the convoy\n// as an opt-in (#1982 fast-follow); for now the review agent gets this self-review\n// prompt instead. We will decide convoy-vs-self-review (and better per-harness\n// message transmission) in the fast-follow.\nfunction buildSelfReviewPrompt(opts: {\n issueId: string;\n workspace: string;\n branch: string;\n prUrl?: string;\n runId: string;\n reviewDir: string;\n contextManifestPath?: string;\n tier1Summary?: string;\n}): string {\n const reviewReportPath = join(opts.reviewDir, 'review.md');\n const prompt = [\n `CODE REVIEW for ${opts.issueId} — you are the sole reviewer; review the change yourself.`,\n '',\n 'Review the diff for this branch yourself, across ALL dimensions in one pass:',\n 'correctness/logic, security, requirements/acceptance-criteria, and performance.',\n 'Do NOT spawn or wait for any sub-reviewers — there is no convoy; you do the',\n 'whole review yourself and emit the verdict.',\n '',\n '── Review context ──',\n `Issue: ${opts.issueId}`,\n `Branch: ${opts.branch}`,\n `Workspace: ${opts.workspace}`,\n opts.prUrl ? `PR: ${opts.prUrl}` : `PR: (resolve via: gh pr view ${opts.branch})`,\n `Run ID: ${opts.runId}`,\n `Review directory: ${opts.reviewDir}`,\n `Review output file: ${reviewReportPath}`,\n '',\n opts.tier1Summary\n ? [\n 'Shared review context (risk-ranked changed files + acceptance criteria):',\n '─────────────────────────────────────────────────────────────',\n opts.tier1Summary,\n '─────────────────────────────────────────────────────────────',\n '',\n opts.contextManifestPath ? `Full manifest: ${opts.contextManifestPath}` : '',\n ].join('\\n')\n : opts.contextManifestPath\n ? `Context manifest: ${opts.contextManifestPath}`\n : 'Context manifest: (missing — inspect the diff directly: git diff origin/main...HEAD)',\n '',\n 'How to review:',\n '1. Read the diff — use the manifest risk ranking, `git diff` the high-risk files,',\n ' and read the surrounding code as needed.',\n '2. Evaluate correctness, security, requirements/AC, and performance. Use the',\n ' severity + verdict vocabulary in roles/review.md.',\n `3. Write your findings to ${reviewReportPath}.`,\n '',\n 'Then signal the verdict with the Overdeck CLI (exactly one):',\n ` pan admin specialists done review ${opts.issueId} --status passed --notes \"<one-line summary>\"`,\n ` pan admin specialists done review ${opts.issueId} --status blocked --notes \"<one-line top blocker>\"`,\n '',\n // PAN-2007: do NOT tell the agent to `exit`. The session is kept alive through\n // the pipeline (KEEP_SPECIALIST_SESSIONS_ALIVE) so it can be reused for the next\n // review cycle without a cold re-spawn. Exiting before the signal command is\n // what stranded reviews at reviewStatus=reviewing.\n 'After running the signal command above, STOP and wait — do not exit, do not run',\n 'any further commands. The session stays open for the next review cycle.',\n '',\n 'Reactive Cloister dispatches the test role after review passes. Never queue tests yourself and never edit code.',\n ].filter(Boolean).join('\\n');\n\n const sizeBytes = Buffer.byteLength(prompt, 'utf-8');\n console.log(`[review-agent] Self-review prompt for ${opts.issueId}: ${sizeBytes} bytes`);\n return prompt;\n}\nasync function spawnReviewRoleForIssuePromise(\n opts: { issueId: string; workspace: string; branch: string; prUrl?: string; model?: string; harness?: RuntimeName; force?: boolean; allowHost?: boolean },\n): Promise<{ success: boolean; message: string; error?: string; gated?: boolean }> {\n const reviewSessionName = `agent-${opts.issueId.toLowerCase()}-review`;\n\n // PAN-2420: GitHub-authoritative guard. Do not waste time on conflict-gate\n // checks or context builds for a PR that GitHub already reports merged.\n const mergedGuard = await shouldSkipDispatchAsMerged(opts.issueId);\n if (mergedGuard.skip) {\n const message = `[review-agent] Skipping review dispatch for ${opts.issueId} — ${mergedGuard.reason}`;\n console.log(message);\n emitActivityEntrySync({ source: 'cloister', level: 'info', message, issueId: opts.issueId });\n return { success: false, message };\n }\n\n // PAN-1862 (FR-14): review mode 'none' — skip the AI review entirely. This sits at\n // the single review entry point so the trigger route, host auto-dispatch, and every\n // Deacon re-dispatch site all honor it without per-call-site logic. The pre-review\n // verification gate (typecheck/lint/test floor) has already run by the time any\n // caller reaches here — 'none' skips only the AI review, never the quality floor.\n // reviewSpawnedAt is stamped so the durable reviewRequestedAt intent counts as\n // serviced (otherwise needsReviewDispatch would re-fire this skip every read).\n // Setting reviewStatus 'skipped' advances the lifecycle exactly like an approved\n // review (the setReviewStatusSync write path emits review.approved for it).\n if (resolveReviewMode(opts.issueId) === 'none') {\n setReviewStatusSync(opts.issueId, {\n reviewStatus: 'skipped',\n reviewNotes: 'Review mode: none — AI review skipped by configuration; verification gate still enforced',\n reviewSpawnedAt: new Date().toISOString(),\n });\n const message = `Review skipped for ${opts.issueId} (mode=none) — advancing to test`;\n console.log(`[review-agent] ${message}`);\n emitActivityEntrySync({ source: 'review', level: 'info', message, issueId: opts.issueId });\n return { success: true, message };\n }\n\n // Idempotency: if a review role agent for this issue already has an alive\n // tmux pane, treat the current dispatch as a no-op. spawnRun has its own\n // session-exists check but it throws — we want soft \"already running\"\n // semantics so callers can keep their existing success-path messaging.\n //\n // Force mode (human override from dashboard) kills the old session and\n // respawns so the review runs against current HEAD, not stale state.\n try {\n const sessions = await Effect.runPromise(listSessionNames());\n if (sessions.includes(reviewSessionName)) {\n const paneDead = await Effect.runPromise(isPaneDead(reviewSessionName));\n\n // A synthesis agent that has finished its verdict does NOT terminate:\n // its role prompt tells it to \"exit\", but it runs `Bash(exit)` which\n // only exits a subshell — the Claude process stays idle-alive with a\n // live pane. So \"pane alive\" does NOT mean \"actively reviewing\", and the\n // old guard would skip re-dispatch forever, jamming the issue at\n // review=reviewing with no convoy actually running (PAN-1131).\n //\n // Disambiguate via the run id: every review run is keyed to a HEAD sha\n // (runId = agent-<issue>-review-<head8>). If the existing synthesis\n // session was started for a different HEAD than the one we are about to\n // review, it is a stale leftover — kill the convoy and respawn. Only a\n // session whose runId matches the *current* HEAD is genuinely the\n // review-in-progress we should defer to.\n let staleRunId = false;\n let currentRunId: string | undefined;\n if (!paneDead && !opts.force) {\n try {\n const { stdout } = await execAsync('git rev-parse --short=8 HEAD', {\n cwd: opts.workspace,\n encoding: 'utf-8',\n timeout: 10_000,\n });\n currentRunId = `agent-${opts.issueId.toLowerCase()}-review-${stdout.trim()}`;\n const synthReviewRunId = getAgentStateSync(reviewSessionName)?.reviewRunId;\n // A missing identity cannot prove that the live pane covers the\n // current obligation, so legacy/unknown sessions are stale too.\n if (!synthReviewRunId || synthReviewRunId !== currentRunId) {\n staleRunId = true;\n console.log(\n `[review-agent] ${reviewSessionName} is stale — runId ${synthReviewRunId ?? 'missing'} != current ${currentRunId}; killing convoy and respawning`,\n );\n }\n } catch (probeErr) {\n console.warn(\n `[review-agent] Could not probe ${reviewSessionName} runId, falling back to pane-alive idempotency:`,\n probeErr,\n );\n }\n }\n\n // PAN-1131 residual + PAN-2579: a runId-matching live pane is only \"actively\n // reviewing\" while this cycle's verdict is UNRECORDED. Once the verdict is\n // terminal, the session is warm-idle (kept alive by the warm-by-default\n // lifecycle) — a re-dispatch request must NOT be swallowed by the guard, or\n // the issue jams at a stale verdict with a live-but-finished reviewer. Fall\n // through to the respawn path below: it kills the convoy tmux and the spawn\n // machinery resumes the saved session with its context intact (warm reuse).\n let finishedIdle = false;\n if (!paneDead && !opts.force && !staleRunId) {\n try {\n const status = getReviewStatusSync(opts.issueId);\n const terminal = status?.reviewStatus === 'passed'\n || status?.reviewStatus === 'blocked'\n || status?.reviewStatus === 'failed';\n // Warm-reuse ONLY for a genuinely un-serviced newer request (same\n // ISO-string comparison as needsReviewDispatch). A terminal verdict\n // with NO newer request means this call is a stale duplicate dispatch\n // racing the verdict (the PAN-399 shape) — skip below and leave the\n // verdict alone rather than re-entering 'reviewing'.\n const newerRequest = !!status?.reviewRequestedAt\n && (!status.reviewSpawnedAt || status.reviewRequestedAt > status.reviewSpawnedAt);\n // PAN-2584: a lost verdict leaves the status non-terminal while the\n // reviewer already wrote its report for this exact HEAD — that session\n // is finished, not reviewing. Report-on-disk for the current runId is\n // terminal evidence too; without it a newer request deadlocks behind\n // the guard forever.\n let reportWritten = false;\n if (currentRunId) {\n try {\n reportWritten = existsSync(join(opts.workspace, PAN_DIRNAME, 'review', currentRunId, 'review.md'));\n } catch { /* probe failure — fall back to verdict-only evidence */ }\n }\n finishedIdle = (terminal || reportWritten) && newerRequest;\n if (finishedIdle) {\n console.log(\n `[review-agent] ${reviewSessionName} is finished-idle (verdict ${status?.reviewStatus}, newer request pending) — warm-reusing for the new review cycle`,\n );\n } else if (terminal) {\n console.log(\n `[review-agent] ${reviewSessionName} has a terminal verdict (${status?.reviewStatus}) and no newer request — treating this dispatch as a stale duplicate; leaving the verdict intact`,\n );\n }\n } catch (statusErr) {\n console.warn(`[review-agent] Could not probe review status for finished-idle check on ${opts.issueId}:`, statusErr);\n }\n }\n\n if (!paneDead && !opts.force && !staleRunId && !finishedIdle) {\n console.log(`[review-agent] Idempotency guard: ${reviewSessionName} already running for ${opts.issueId} — skipping spawn`);\n return { success: true, message: `Review already in progress: ${reviewSessionName}` };\n }\n // Session pane is dead, force mode, stale runId, or finished-idle — kill the\n // convoy tmux and respawn (the spawn path resumes the saved session, so a\n // warm reviewer keeps its context).\n const reason = opts.force ? 'force-killed for re-review'\n : paneDead ? 'pane is dead'\n : staleRunId ? 'stale runId'\n : 'finished-idle (warm reuse for new cycle)';\n console.log(`[review-agent] ${reviewSessionName} ${reason} — respawning convoy`);\n await Effect.runPromise(\n killAllReviewerSessions(undefined, opts.issueId).pipe(\n Effect.catch(() => Effect.succeed({ killed: [], failed: [] })),\n ),\n );\n }\n } catch (err) {\n console.warn(`[review-agent] Idempotency check failed for ${opts.issueId}, proceeding:`, err);\n }\n\n // Fast synchronous cache check for the gated case. If the probe cache says\n // the branch has conflicts (or we cannot verify mergeability), fail fast\n // without shelling out to git on the awaited request path.\n const cachedMergeability = getCachedConflictGateMergeability(opts.issueId);\n if (cachedMergeability === 'conflicts' || cachedMergeability === 'unknown') {\n const targetBranch = 'main';\n const reason = cachedMergeability === 'conflicts'\n ? `merge conflict with ${targetBranch} must be resolved before review dispatch`\n : `mergeability against ${targetBranch} could not be verified; deferring review conservatively`;\n const message = `Review dispatch deferred: ${reason}`;\n setReviewStatusSync(opts.issueId, {\n reviewStatus: 'pending',\n reviewNotes: message,\n });\n return { success: false, gated: true, message };\n }\n\n const gate = await resolveConflictGate(\n opts.issueId,\n opts.workspace,\n 'main',\n buildRealConflictGateDeps(),\n );\n if (gate.gated) {\n const message = `Review dispatch deferred: ${gate.reason ?? 'merge conflict must be resolved first'}`;\n setReviewStatusSync(opts.issueId, {\n reviewStatus: 'pending',\n reviewNotes: message,\n });\n return { success: false, gated: true, message };\n }\n\n // Clear feedback from any previous review cycle so the work agent only\n // sees current-cycle feedback when it reads .pan/feedback/.\n try {\n const { archiveFeedbackFiles } = await import('./feedback-writer.js');\n await Effect.runPromise(archiveFeedbackFiles(opts.workspace));\n } catch {\n // Non-fatal: archiving is best-effort\n }\n\n // PAN-1531: review-temp stash machinery removed. Reviewers see only the\n // committed diff because the dirty-worktree gate refuses pan done /\n // pan review request before reaching here. If callers somehow bypass the\n // gate, uncommitted scratch becomes visible in the review — that's the\n // correct fail-loud behavior, not a reason to silently stash.\n try {\n setReviewStatusSync(opts.issueId, {\n reviewStatus: 'reviewing',\n reviewSpawnedAt: new Date().toISOString(),\n });\n } catch (err) {\n console.error(`[review-agent] Failed to set reviewing status for ${opts.issueId}:`, err);\n return {\n success: false,\n message: 'Failed to initialize review status',\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n try {\n const { notifyPipelineSync } = await import('../pipeline-notifier.js');\n notifyPipelineSync({ type: 'task_queued', specialist: 'review-agent', issueId: opts.issueId });\n } catch {\n // Non-fatal\n }\n\n try {\n const { spawnRun, saveAgentState, getAgentState, getAgentStateSync, getLatestSessionIdSync, resumeAgent, wipeAgentStateDirs } = await import('../agents.js');\n const workAgentState = await Effect.runPromise(getAgentState(`agent-${opts.issueId.toLowerCase()}`));\n const allowHost = opts.allowHost === true || workAgentState?.hostOverride === true;\n\n // Build the shared context manifest before spawning so all reviewers\n // read one pre-built diff+AC object instead of each running git diff\n // independently (PAN-1059).\n //\n // Include HEAD SHA in runId so re-reviews of the same issue get their own\n // directory and don't overwrite round-1 files (collision prevention).\n let headSha = 'unknown';\n try {\n const { stdout } = await execAsync('git rev-parse --short=8 HEAD', { cwd: opts.workspace, encoding: 'utf-8', timeout: 10_000 });\n headSha = stdout.trim();\n } catch { /* non-fatal — fall back to static runId */ }\n const runId = headSha !== 'unknown'\n ? `agent-${opts.issueId.toLowerCase()}-review-${headSha}`\n : `agent-${opts.issueId.toLowerCase()}-review`;\n const reviewDir = join(opts.workspace, PAN_DIRNAME, 'review', runId);\n let contextManifestPath: string | undefined;\n let tier1Summary: string | undefined;\n try {\n const manifest = await Effect.runPromise(buildReviewContext({\n runId,\n issueId: opts.issueId,\n workspace: opts.workspace,\n branch: opts.branch,\n }));\n contextManifestPath = manifest.manifestPath;\n tier1Summary = formatTier1Summary(manifest);\n console.log(`[review-agent] Context manifest built: ${contextManifestPath} (${manifest.changedFiles.length} files)`);\n } catch (ctxErr) {\n console.warn(`[review-agent] Context manifest build failed for ${opts.issueId} — reviewers will block on missing shared context:`, ctxErr);\n }\n\n const fullReview = isExtendedReviewEnabled(opts.issueId);\n\n // PAN-1862 (FR-7/FR-8/NFR-1): selective re-review — which convoy reviewers run\n // this cycle vs carry their prior passed verdict forward (computeConvoyScope).\n const { inScope: inScopeSubRoles, carried: carriedSubRoles, scope: reReviewScope } = fullReview\n ? await computeConvoyScope(opts.issueId, opts.workspace)\n : { inScope: [...REVIEW_SUB_ROLES], carried: [], scope: 'changed' as ReReviewScope };\n\n // PAN-1862 Phase A: discovery-then-fork mode. When the full-convoy review will\n // run on claude-code, the parent does the shared discovery reads FIRST, signals\n // `pan admin specialists discovery-ready review <id>`, and the server forks its\n // session into the convoy — the reviewers replay the discovery prefix as warm\n // cache reads instead of four independent full-price re-reads. Any other\n // harness keeps the inline convoy spawn (the fork machinery is Claude Code's\n // --resume; NFR-2 explicitly degrades to independent reads there). Per-reviewer\n // model mismatches are handled at fork time, not here — a mismatched reviewer\n // simply spawns fresh while the rest fork.\n const cfgReviewHarness = loadYamlConfig().config.roles?.review?.harness;\n // PAN-2585: decide from the harness that will ACTUALLY run — the saved review\n // agent is the resume target, and model routing (not config) usually picks the\n // harness. Falling through to the 'claude-code' literal put codex parents into\n // discovery mode, where they stand by forever for a fork that can never happen.\n const savedReviewHarness = getAgentStateSync(`agent-${opts.issueId.toLowerCase()}-review`)?.harness;\n const discoveryForkMode = fullReview\n && (opts.harness ?? savedReviewHarness ?? cfgReviewHarness ?? 'claude-code') === 'claude-code';\n\n const prompt = fullReview\n ? buildReviewRolePrompt({ ...opts, runId, reviewDir, contextManifestPath, tier1Summary, inScopeSubRoles, carriedSubRoles, discovery: discoveryForkMode })\n : buildSelfReviewPrompt({ ...opts, runId, reviewDir, contextManifestPath, tier1Summary });\n\n // PAN-1862: in discovery-fork mode the convoy is NOT spawned here — the parent\n // signals discovery-ready and handleReviewDiscoveryReady launches (and forks)\n // the convoy. markDiscoveryPending records what the handler needs on the\n // parent's state; the deacon's stalled-discovery backstop covers a parent that\n // never signals.\n const markDiscoveryPending = async (synthesisAgentId: string) => {\n try {\n const parent = getAgentStateSync(synthesisAgentId);\n if (parent) {\n parent.reviewDiscoveryPending = true;\n parent.reviewContextManifestPath = contextManifestPath;\n parent.reviewDiscoveryReadyAt = undefined;\n parent.reviewConvoyForkedAt = undefined;\n parent.reviewForkCacheChecked = undefined;\n await Effect.runPromise(saveAgentState(parent));\n }\n } catch (stateErr) {\n console.warn(`[review-agent] Could not mark discovery pending on ${synthesisAgentId}:`, stateErr);\n }\n };\n const spawnConvoyReviewers = async (synthesisAgentId: string) => {\n if (discoveryForkMode) {\n await markDiscoveryPending(synthesisAgentId);\n console.log(`[review-agent] ${opts.issueId}: parent spawned in discovery mode — convoy defers to the discovery-ready signal (PAN-1862)`);\n return [];\n }\n return launchConvoyReviewersPromise({\n issueId: opts.issueId,\n workspace: opts.workspace,\n runId,\n synthesisAgentId,\n inScope: inScopeSubRoles,\n carried: carriedSubRoles,\n scope: reReviewScope,\n contextManifestPath,\n ...(opts.model ? { model: opts.model } : {}),\n ...(opts.harness ? { harness: opts.harness } : {}),\n allowHost,\n });\n };\n\n // PAN-1862: RESUME the saved review session by default. The review agent keeps the prior\n // review's context (the files it read, the findings it raised), so a re-review checks the\n // fix instead of re-researching the entire diff from scratch — the token-cost problem this\n // was set out to fix. Fresh-spawn ONLY when the harness/model actually changed (it's a\n // different agent then) or there is no resumable saved session. The resume delivery is\n // resilient (supervisor → tmux fallback, PAN-1988).\n const reviewAgentId = `agent-${opts.issueId.toLowerCase()}-review`;\n const savedReview = getAgentStateSync(reviewAgentId);\n const canResumeReview = reviewResumeDecision({\n requestedModel: opts.model,\n requestedHarness: opts.harness,\n savedModel: savedReview?.model,\n savedHarness: savedReview?.harness,\n hasSavedState: !!savedReview,\n hasSavedSession: !!getLatestSessionIdSync(reviewAgentId),\n });\n if (canResumeReview) {\n console.log(`[review-agent] Resuming saved review session for ${opts.issueId} — model/harness unchanged, preserving context (PAN-1862)`);\n const resumeResult = await resumeAgent(reviewAgentId, prompt);\n if (resumeResult.success) {\n try {\n // Keep the idempotency guard's HEAD-staleness detection honest for the resumed run.\n const resumed = getAgentStateSync(reviewAgentId);\n if (resumed) {\n resumed.reviewRunId = runId;\n // PAN-2584: arm the parent's liveness deadline for this cycle.\n resumed.reviewDeadlineAt = new Date(Date.now() + PARENT_REVIEW_TIMEOUT_MS).toISOString();\n await Effect.runPromise(saveAgentState(resumed));\n }\n } catch { /* non-fatal */ }\n if (fullReview) {\n await spawnConvoyReviewers(reviewAgentId);\n return { success: true, message: `Convoy review resumed (session preserved): ${reviewAgentId}` };\n }\n return { success: true, message: `Review resumed (session preserved): ${reviewAgentId}` };\n }\n console.warn(`[review-agent] Review resume failed for ${reviewAgentId}; falling back to a fresh session: ${resumeResult.error}`);\n }\n // Fresh review: wipe any stale review state (harness/model changed, or the resume above\n // failed) so the new session does not inherit a mismatched saved session id.\n if (savedReview || getLatestSessionIdSync(reviewAgentId)) {\n try { await wipeAgentStateDirs(opts.issueId, { rolePrefix: 'review' }); }\n catch (wipeErr) { console.warn(`[review-agent] review state wipe before fresh spawn failed (non-fatal): ${wipeErr instanceof Error ? wipeErr.message : String(wipeErr)}`); }\n }\n const run = await spawnRun(opts.issueId, 'review', {\n workspace: opts.workspace,\n prompt,\n ...(opts.model ? { model: opts.model } : {}),\n ...(opts.harness ? { harness: opts.harness } : {}),\n ...(allowHost ? { allowHost: true } : {}),\n });\n // Persist the runId on the synthesis agent's own state so the idempotency\n // guard above can tell a genuinely-running review (runId matches current\n // HEAD) from a finished-but-idle leftover (runId from an older HEAD) — see\n // PAN-1131. Sub-reviewers already persist this; the synthesis agent did not.\n run.reviewRunId = runId;\n // PAN-2584: arm the parent's liveness deadline for this cycle.\n run.reviewDeadlineAt = new Date(Date.now() + PARENT_REVIEW_TIMEOUT_MS).toISOString();\n try {\n await Effect.runPromise(saveAgentState(run));\n } catch (saveErr) {\n console.warn(`[review-agent] Could not persist reviewRunId on ${run.id}:`, saveErr);\n }\n if (fullReview) {\n await spawnConvoyReviewers(run.id);\n console.log(`[review-agent] Review role (convoy synthesis) spawned for ${opts.issueId}: ${run.id}`);\n emitActivityEntrySync({ source: 'review', level: 'info', message: `Convoy review spawned for ${opts.issueId}: ${run.id}`, issueId: opts.issueId });\n return {\n success: true,\n message: `Convoy review spawned: ${run.id}`,\n };\n }\n\n console.log(`[review-agent] Review role (self-review) spawned for ${opts.issueId}: ${run.id}`);\n emitActivityEntrySync({ source: 'review', level: 'info', message: `Self-review spawned for ${opts.issueId}: ${run.id}`, issueId: opts.issueId });\n\n return {\n success: true,\n message: `Self-review spawned: ${run.id}`,\n };\n } catch (err) {\n console.error(`[review-agent] Failed to spawn review role for ${opts.issueId}:`, err);\n setReviewStatusSync(opts.issueId, {\n reviewStatus: 'failed',\n reviewNotes: `Review role spawn failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n return {\n success: false,\n message: 'Failed to spawn review role',\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/**\n * Kill all canonical reviewer sessions for one issue.\n *\n * PAN-915: this is no longer called per-round. Canonical reviewer sessions\n * persist across review rounds via PAN-830's `remain-on-exit on` so each\n * round resumes the same Claude process via `sendKeysAsync` — preserving\n * the reviewer's accumulated context (codebase patterns, prior findings,\n * decisions made during earlier rounds). This function is now invoked from\n * terminal lifecycle events: merge complete, reset, cancel, deep-wipe, and\n * explicit `pan review abort`.\n *\n * Matches the parent review role, convoy children, and legacy coordinator\n * sessions so callers do not need to know which review phase has started.\n */\nexport function isReviewSessionForIssue(sessionName: string, projectKey: string | undefined, issueId: string): boolean {\n const session = sessionName.toLowerCase();\n const issue = issueId.toLowerCase();\n const project = projectKey?.toLowerCase();\n\n // Belt-and-suspenders: a user conversation session (`conv-*`) must never be\n // classified as a reviewer session and swept into reviewer cleanup/kill.\n if (session.startsWith('conv-')) return false;\n\n if (session === `agent-${issue}-review` || session.startsWith(`agent-${issue}-review-`)) return true;\n if (session.startsWith(`review-${issue}-`) || session.startsWith(`review-coordinator-${issue}-`)) return true;\n if (!project) return false;\n if (session === `specialist-${project}-${issue}-review-agent`) return true;\n return session.startsWith(`specialist-${project}-${issue}-review-`);\n}async function killAllReviewerSessionsPromise(\n projectKey: string | undefined,\n issueId: string,\n): Promise<{ killed: string[]; failed: string[] }> {\n const killed: string[] = [];\n const failed: string[] = [];\n let allSessions: readonly string[];\n\n try {\n allSessions = await Effect.runPromise(listSessionNames());\n } catch (err) {\n console.warn('[review-agent] Failed to list tmux sessions during reviewer cleanup:', err instanceof Error ? err.message : String(err));\n return { killed, failed };\n }\n\n const sessionsToKill = allSessions.filter(s => isReviewSessionForIssue(s, projectKey, issueId));\n await Promise.all(\n sessionsToKill.map(async (sessionName) => {\n try {\n await Effect.runPromise(killSession(sessionName));\n console.log(`[review-agent] Killed reviewer session ${sessionName}`);\n killed.push(sessionName);\n } catch (err) {\n console.log(`[review-agent] Session ${sessionName} already gone or failed to kill: ${err instanceof Error ? err.message : String(err)}`);\n failed.push(sessionName);\n }\n }),\n );\n return { killed, failed };\n}async function killAllReviewSessionsPromise(): Promise<{ killed: string[]; failed: string[] }> {\n const killed: string[] = [];\n const failed: string[] = [];\n\n let allSessions: readonly string[];\n try {\n allSessions = await Effect.runPromise(listSessionNames());\n } catch (err) {\n console.warn('[review-agent] Failed to list tmux sessions during review cleanup:', err instanceof Error ? err.message : String(err));\n return { killed, failed };\n }\n\n const reviewPatterns = [\n /^agent-[a-z0-9-]+-review(?:-(?:security|correctness|performance|requirements))?$/i,\n /^review-coordinator-/,\n /^specialist-.+-review-/,\n /^review-[A-Z0-9]+-\\d+-\\d+/, // legacy: review-PAN-999-1713456789000-correctness\n ];\n\n const sessionsToKill = allSessions.filter(s => reviewPatterns.some(p => p.test(s)));\n if (sessionsToKill.length === 0) {\n return { killed, failed };\n }\n\n console.log(`[review-agent] Killing ${sessionsToKill.length} review session(s) during shutdown`);\n\n await Promise.all(\n sessionsToKill.map(async (sessionName) => {\n try {\n await Effect.runPromise(killSession(sessionName));\n console.log(`[review-agent] Killed review session ${sessionName}`);\n killed.push(sessionName);\n } catch (err) {\n console.log(`[review-agent] Session ${sessionName} already gone or failed to kill: ${err instanceof Error ? err.message : String(err)}`);\n failed.push(sessionName);\n }\n }),\n );\n\n return { killed, failed };\n}\n\n// ─── Effect variants (PAN-1249) ──────────────────────────────────────────────\n\n/**\n * Effect variant of {@link buildConvoyPrompt}. Template reads are the only\n * fallible step; any failure here is fatal and propagates via Effect's defect\n * channel through `Effect.promise`.\n */\nexport const spawnReviewRoleForIssue = (\n opts: { issueId: string; workspace: string; branch: string; prUrl?: string; model?: string; harness?: RuntimeName; force?: boolean; allowHost?: boolean },\n): Effect.Effect<{ success: boolean; message: string; error?: string; gated?: boolean }> =>\n Effect.promise(() => spawnReviewRoleForIssuePromise(opts));\n\n/**\n * Effect variant of {@link killAllReviewerSessions}. Session-kill failures are\n * already aggregated into the `failed` array — this wrapper preserves that\n * contract.\n */\nexport const killAllReviewerSessions = (\n projectKey: string | undefined,\n issueId: string,\n): Effect.Effect<{ killed: string[]; failed: string[] }> =>\n Effect.promise(() => killAllReviewerSessionsPromise(projectKey, issueId));\n\n/**\n * Effect variant of {@link killAllReviewSessions}. Same aggregation semantics\n * as the Promise version.\n */\nexport const killAllReviewSessions = (): Effect.Effect<{ killed: string[]; failed: string[] }> =>\n Effect.promise(() => killAllReviewSessionsPromise());\n\n// PAN-1862 resume-vs-fresh decision lives in its own pure module (review-resume-decision.ts) so\n// it is unit-testable without importing this heavy file. Re-exported for external callers.\nexport { reviewResumeDecision } from './review-resume-decision.js';\n// PAN-1862: convoy machinery lives in review-convoy.ts; re-exported here so the\n// deacon modules, tests, and the CLI keep one stable import surface.\nexport {\n buildConvoyPrompt,\n spawnReviewSubRoleForIssue,\n handleReviewDiscoveryReady,\n resolveReReviewScope,\n} from './review-convoy.js';\n\n/**\n * Is the issue carrying leftover EXTENDED-review (convoy) sub-reviewer agents from a\n * prior cycle? Quick-review — the current hardcoded mode — only ever creates the single\n * `agent-<id>-review` parent, so any `agent-<id>-review-<subRole>` is a stale ghost\n * (e.g. PAN-1866's `-correctness/-security/-performance/-requirements` from an old run).\n *\n * Seam for when extended review returns: this becomes a reviewRunId-mismatch check — a\n * sub-reviewer is stale only when its run differs from the active review run.\n */\nexport function isReviewStaleSync(issueId: string): boolean {\n return listAgentIdsByPrefixSync(`agent-${issueId.toLowerCase()}-review-`).length > 0;\n}\n\nexport function resolveReviewMode(issueId?: string): ReviewMode {\n if (issueId) {\n const project = resolveProjectForIssue(issueId);\n const issueMode = project ? readIssueRecordSync(project, issueId)?.reviewMode : undefined;\n if (issueMode === 'quick' || issueMode === 'full' || issueMode === 'none') {\n return issueMode;\n }\n }\n\n const configMode = loadYamlConfig().config.roles?.review?.mode;\n return configMode === 'full' || configMode === 'none' ? configMode : 'quick';\n}\n\n/**\n * Is EXTENDED (convoy) review enabled for this issue?\n *\n * `resolveReviewMode` is the single source of truth: per-issue record override\n * beats merged project/global config, and quick remains the default.\n */\nexport function isExtendedReviewEnabled(issueId?: string): boolean {\n return resolveReviewMode(issueId) === 'full';\n}\n\n/**\n * Tear down an issue's entire review fleet — the `agent-<id>-review` parent plus any\n * extended-mode sub-reviewers. Kills every review tmux session, then removes each agent\n * via the canonical removeAgentSync (overdeck.db row + state dir, never the JSONL\n * transcript). Does NOT reset review_status — the caller composes that (see the\n * POST /api/review/:id/purge route). Returns what was killed and removed.\n */\nexport async function purgeReviewAgentsForIssue(\n projectKey: string | undefined,\n issueId: string,\n): Promise<{ killed: string[]; removed: string[] }> {\n const killResult = await killAllReviewerSessionsPromise(projectKey, issueId);\n const removed: string[] = [];\n for (const agentId of listAgentIdsByPrefixSync(`agent-${issueId.toLowerCase()}-review`)) {\n removeAgentSync(agentId);\n removed.push(agentId);\n }\n return { killed: killResult.killed, removed };\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { a as isReviewStaleSync, c as purgeReviewAgentsForIssue, d as buildConvoyPrompt, f as handleReviewDiscoveryReady, h as reviewResumeDecision, i as isReviewSessionForIssue, l as resolveReviewMode, m as spawnReviewSubRoleForIssue, n as init_review_agent, o as killAllReviewSessions, p as resolveReReviewScope, r as isExtendedReviewEnabled, s as killAllReviewerSessions, t as PARENT_REVIEW_TIMEOUT_MS, u as spawnReviewRoleForIssue } from "./review-agent-D6P6d3pz.js";
2
+ init_review_agent();
3
+ export { PARENT_REVIEW_TIMEOUT_MS, buildConvoyPrompt, handleReviewDiscoveryReady, isExtendedReviewEnabled, isReviewSessionForIssue, isReviewStaleSync, killAllReviewSessions, killAllReviewerSessions, purgeReviewAgentsForIssue, resolveReReviewScope, resolveReviewMode, reviewResumeDecision, spawnReviewRoleForIssue, spawnReviewSubRoleForIssue };
@@ -4,7 +4,7 @@ import { a as PAN_DIRNAME, p as init_types } from "./types-CE1m_daD.js";
4
4
  import { i as findPlanSync, o as init_io, u as readPlan } from "./io-Wy8YpFeP.js";
5
5
  import { d as getDevrootPathSync, f as init_config } from "./config-oWoKf5jO.js";
6
6
  import { a as init_lifecycle_io, i as findVBriefByIssueSync } from "./lifecycle-io-DSrv9xGh.js";
7
- import { n as init_review_verdict_feedback } from "./review-verdict-feedback-wqnikhMK.js";
7
+ import { n as init_review_verdict_feedback } from "./review-verdict-feedback-B70VbfRL.js";
8
8
  import { n as init_github_pr_lookup, r as lookupPullRequestNumberForBranch } from "./github-pr-lookup-t8X8R0c0.js";
9
9
  import { Effect } from "effect";
10
10
  import { existsSync } from "fs";
@@ -700,4 +700,4 @@ var init_review_context = __esmMin((() => {
700
700
  //#endregion
701
701
  export { getDiffStat as a, getDiffBase as i, formatTier1Summary as n, init_review_context as o, getChangedFiles as r, buildReviewContext as t };
702
702
 
703
- //# sourceMappingURL=review-context-CCq56O_Y.js.map
703
+ //# sourceMappingURL=review-context-Dyo0tsBa.js.map