@overdeck/desktop 0.45.24 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (511) hide show
  1. package/drizzle/overdeck/0000_overdeck_init.sql +32 -0
  2. package/package.json +1 -1
  3. package/server/{acceptance-criteria-DDCnXF58.js → acceptance-criteria-CCwFGICj.js} +2 -2
  4. package/server/activity-logger-CMthG6Vd.js +3 -0
  5. package/server/{activity-logger-DDlOIAML.js → activity-logger-CyteR4JO.js} +24 -13
  6. package/server/{advancing-selfheal-BVwW4qRn.js → advancing-selfheal-De1L-Sb4.js} +6 -6
  7. package/server/{agent-gc-CHcnvonI.js → agent-gc-CBULruzm.js} +5 -5
  8. package/server/agent-state-VQk8fY9F.js +3 -0
  9. package/server/{agent-state-service-BsgWxZuB.js → agent-state-service-BlnSkRFA.js} +5 -5
  10. package/server/{agent-state-service-D5UGKIJL.js → agent-state-service-hZpxIw1E.js} +1 -1
  11. package/server/agents-BKKkxKgK.js +3 -0
  12. package/server/{agents-EbI0zCJl.js → agents-C5rWYhb6.js} +4 -4
  13. package/server/archive-planning-0FJ6Xd3b.js +2 -0
  14. package/server/{archive-planning-Du25Jtst.js → archive-planning-C0lAbNB_.js} +16 -24
  15. package/server/{artifact-index-jobs-CbEDfCDu.js → artifact-index-jobs-ug6ZxIP5.js} +2 -2
  16. package/server/{assemble-J2ZZ2C15.js → assemble-DnffNpOo.js} +2 -2
  17. package/server/{backlog-auto-trigger-2R2jog7n.js → backlog-auto-trigger-Dh-i9PQf.js} +3 -3
  18. package/server/{behavior-B3exJ42O.js → behavior-CfIg6pKp.js} +2 -2
  19. package/server/bridge-pool-patrol-CUFmjVDN.js +136 -0
  20. package/server/{briefing-freshness-D1wzUIWv.js → briefing-freshness-DHmCSLar.js} +2 -2
  21. package/server/{build-info-CZk_TITh.js → build-info-BP160gU7.js} +1 -1
  22. package/server/{build-info-Ie_D0_BT.js → build-info-CuFfxZxp.js} +5 -3
  23. package/server/{checkpoint-manager-BI1Wxoku.js → checkpoint-manager-DEWD82qK.js} +2 -2
  24. package/server/{checkpoint-manager-DwbQoqrC.js → checkpoint-manager-Dxh0FYsv.js} +1 -1
  25. package/server/checkpoint-worker.js +1 -1
  26. package/server/{checkpoints-CQB1h765.js → checkpoints-CZvbtLnr.js} +2 -2
  27. package/server/{checkpoints-BJIs5QIA.js → checkpoints-DMTgXuLG.js} +1 -1
  28. package/server/{claude-hooks-provision-8Ngo8TpT.js → claude-hooks-provision-CN-xo-do.js} +1 -1
  29. package/server/{claude-hooks-provision-D8GXF3_s.js → claude-hooks-provision-fvy4RD2b.js} +13 -2
  30. package/server/{claude-permissions-DNWEVV6z.js → claude-permissions-CN0cSCPp.js} +2 -2
  31. package/server/{claude-settings-overlay-CEdaqpWI.js → claude-settings-overlay-CJn35FHQ.js} +2 -2
  32. package/server/{claude-settings-overlay-DWy-Bb4Y.js → claude-settings-overlay-Dabi9slj.js} +1 -1
  33. package/server/cli-DmXETsw-.js +3 -0
  34. package/server/{cli-RoOx5DUf.js → cli-oCWYA1pE.js} +9 -9
  35. package/server/{cliproxy-C8a1vtTU.js → cliproxy-C8mB3KuB.js} +2 -2
  36. package/server/{cliproxy-fHfIeiGd.js → cliproxy-PGwTX_o8.js} +1 -1
  37. package/server/{close-issue-DoOifFIK.js → close-issue-D5MF5GqF.js} +5 -5
  38. package/server/{closed-issue-reaper-CktPXo8m.js → closed-issue-reaper-CJ24u0Zt.js} +1 -1
  39. package/server/{closed-issue-reaper-Bk3SU4RC.js → closed-issue-reaper-Cltx86x5.js} +37 -16
  40. package/server/{codex-GcHuUF-k.js → codex-BdEsUFWh.js} +1 -1
  41. package/server/{codex-BZXGhUVB.js → codex-Drlf5Xhf.js} +36 -7
  42. package/server/{codex-parser-CFZ1_1Jl.js → codex-parser-DpB89Vqa.js} +2 -2
  43. package/server/compaction-continuation-K2AxQX4H.js +200 -0
  44. package/server/{config-CKxYiCmX.js → config-B2IMcBxx.js} +4 -3
  45. package/server/{config-DzV30TOm.js → config-DV-grfQc.js} +1 -1
  46. package/server/{config-BZ0sHTju.js → config-Dr3pW6w6.js} +2 -2
  47. package/server/{config-yaml-DySPNmKN.js → config-yaml-CmOPzmBb.js} +268 -14
  48. package/server/{conflict-gate-BaCVrH-N.js → conflict-gate-B9cN3SBi.js} +4 -4
  49. package/server/{conflict-gate-BhAY7TUd.js → conflict-gate-Dh754uyA.js} +1 -1
  50. package/server/{context-layers-BrPmE__h.js → context-layers-D6LZo3l1.js} +2 -2
  51. package/server/{context-layers-igZ4FI4_.js → context-layers-dR5YxHYB.js} +3 -3
  52. package/server/{control-settings-BQp7_4uD.js → control-settings-C7DUehE1.js} +49 -19
  53. package/server/{conversation-compaction-CgrR8YYp.js → conversation-compaction-BoqdDXWF.js} +8 -8
  54. package/server/{conversation-compaction-eQB5CkOe.js → conversation-compaction-Dj4FAKoZ.js} +1 -1
  55. package/server/{conversation-service-DPJ71F33.js → conversation-service-5aCnq1zR.js} +8 -7
  56. package/server/conversation-service-BCxl4f8Z.js +3 -0
  57. package/server/{conversations-6AfUfbwc.js → conversations-BUpYsOZg.js} +4 -4
  58. package/server/{conversations-CAsJF9kh.js → conversations-C34dyIb9.js} +1 -1
  59. package/server/{cost-B2ddP6wq.js → cost-Bgcub5kW.js} +12 -2
  60. package/server/{cost-R-m6Yi-W.js → cost-CvxRrucd.js} +3 -3
  61. package/server/{cost-sync-BsN6ER0n.js → cost-sync-Dv3LUaNW.js} +3 -3
  62. package/server/{dag-B1ucnjDU.js → dag-ombYYt4s.js} +2 -2
  63. package/server/{dangerous-git-ops-BXqeWVSf.js → dangerous-git-ops-BcJPC5Rr.js} +1 -1
  64. package/server/dashboard-db-worker.js +7 -7
  65. package/server/deacon-DrXqT9LQ.js +4 -0
  66. package/server/{deacon-CU_cAYSR.js → deacon-hi9KLPLT.js} +2933 -2704
  67. package/server/{deacon-nudge-log-6wVqAaqz.js → deacon-nudge-log-BNBebzeL.js} +3 -3
  68. package/server/deacon-pending-lifecycle-Cpk0k7Hi.js +33 -0
  69. package/server/{deacon-swarm-BXZZ1Z2-.js → deacon-swarm-DBxUaO-A.js} +13 -13
  70. package/server/deacon-swarm-I2JfX5Tg.js +2 -0
  71. package/server/deacon.js +14 -19
  72. package/server/dead-end-trip-CQcP70ND.js +13 -0
  73. package/server/delivery-Da0zEMY4.js +3 -0
  74. package/server/{deploy-patrol-AiFoP8dw.js → deploy-patrol-Df-Tmaq0.js} +69 -18
  75. package/server/deploy-queue-9SrhZR63.js +3 -0
  76. package/server/deploy-queue-UjKGYsDe.js +169 -0
  77. package/server/deploy-window-jOiPRHL0.js +3 -0
  78. package/server/{deploy-window-C3F-tihF.js → deploy-window-rpqpWqHA.js} +40 -16
  79. package/server/{dev-supervisor-bcOWqdQE.js → dev-supervisor-CC46Ig8q.js} +2 -2
  80. package/server/{devcontainer-renderer-_d6XhyND.js → devcontainer-renderer-68CSCRnu.js} +3 -3
  81. package/server/{dist-Cb_0uvpS.js → dist-CJy72uEg.js} +1 -1
  82. package/server/dist-DSlxIU1H.js +3 -0
  83. package/server/{dist-src-BSoS7mkd.js → dist-src-Bik83hFi.js} +1 -1
  84. package/server/docker-BMVTSFL5.js +3 -0
  85. package/server/{docker-DcMTFTUC.js → docker-Dam7mbIB.js} +2 -2
  86. package/server/{dod-C6n9RV3G.js → dod-Dar-yheg.js} +8 -4
  87. package/server/durable-review-pipeline-CGZ5QBxh.js +17 -0
  88. package/server/durable-review-pipeline-jpgCJZFp.js +3 -0
  89. package/server/{ensure-devcontainer-DNi-ono3.js → ensure-devcontainer-B057YA81.js} +4 -4
  90. package/server/{ensure-devcontainer-BZgOhRo7.js → ensure-devcontainer-C98V8yW-.js} +1 -1
  91. package/server/{esm-shims-OSHAYaS1.js → esm-shims-Br9BPdkR.js} +1 -1
  92. package/server/{event-store-EV2cMiXj.js → event-store-ELqkVOn0.js} +1 -1
  93. package/server/{event-store-CQL6NeqB.js → event-store-zY5MJHgF.js} +23 -4
  94. package/server/{events-BTdrdEq8.js → events-D6pyqhzM.js} +1 -1
  95. package/server/{events-DTfAe4My.js → events-D9PR1IC0.js} +3 -3
  96. package/server/{factory-CFibJuaw.js → factory-CRoOpGsF.js} +5 -5
  97. package/server/{feature-registry-population-DKZFMbFt.js → feature-registry-population--YUXU999.js} +4 -4
  98. package/server/{feature-registry-storage-BdPuLcBX.js → feature-registry-storage-BORBTo0y.js} +2 -2
  99. package/server/{features-ez2271oH.js → features--nFkJY8v.js} +2 -2
  100. package/server/{feedback-target-CoFDHiM8.js → feedback-target-C0ZzyHvU.js} +1 -1
  101. package/server/{feedback-target-7mqqwrX6.js → feedback-target-Dt9BsapX.js} +8 -8
  102. package/server/{feedback-writer-CY5L1lB7.js → feedback-writer-BG0RUZiu.js} +5 -5
  103. package/server/{feedback-writer-D3a22RCd.js → feedback-writer-D1fm-5Z8.js} +1 -1
  104. package/server/{flywheel-SVF02Jpq.js → flywheel-BekukH4i.js} +1 -1
  105. package/server/{flywheel-DHrgCphM.js → flywheel-BiT3odRb.js} +23 -15
  106. package/server/{flywheel-DzGtWnJ1.js → flywheel-CLVB55Be.js} +16 -15
  107. package/server/flywheel-merge-order-BJv1DZz1.js +462 -0
  108. package/server/flywheel-merge-order-BKw9o6ku.js +2 -0
  109. package/server/forge-CZbSg6Ds.js +383 -0
  110. package/server/forge-DK3blQb_.js +3 -0
  111. package/server/{from-kNxT0bZC.js → from-D_4_dk7i.js} +1 -1
  112. package/server/{fts-db-CE46vDkZ.js → fts-db-BeOomFa-.js} +2 -2
  113. package/server/{fts-operations-CqY6zl-i.js → fts-operations-BdewJ_g9.js} +2 -2
  114. package/server/git-utils-CI6cwyyC.js +3 -0
  115. package/server/{git-utils-CRw2zLPC.js → git-utils-ameCgDdy.js} +30 -5
  116. package/server/{github-app-C3QrAUd0.js → github-app-CQ1Lo6LA.js} +3 -3
  117. package/server/{github-app-ClZ2lk8D.js → github-app-DtAsvwzK.js} +1 -1
  118. package/server/{github-client-BnIsSrEN.js → github-client-BfyDxuRN.js} +2 -2
  119. package/server/{github-client-DfQYVUaw.js → github-client-Cj0yl_07.js} +1 -1
  120. package/server/github-pr-lookup-BDq6Wznz.js +58 -0
  121. package/server/{harness-binary-DPUi-Pv8.js → harness-binary-DqkftwTb.js} +2 -2
  122. package/server/{harness-resolve-3lNZkyT4.js → harness-resolve-CqMqM1Mb.js} +4 -4
  123. package/server/{health-events-BBcTYQKU.js → health-events-CazRxJUS.js} +2 -2
  124. package/server/{health-events-BDOHby5Q.js → health-events-_xfTaOUs.js} +1 -1
  125. package/server/{hooks-CKZgXlJb.js → hooks-BO3QT1sn.js} +2 -2
  126. package/server/{hooks-DPVX1rwQ.js → hooks-BnJsxlSq.js} +1 -1
  127. package/server/{hume-Cz8igP9E.js → hume-CDYJxqx-.js} +2 -2
  128. package/server/hume-Dq--7rOQ.js +3 -0
  129. package/server/{idle-stack-reaper-CuLF0j2H.js → idle-stack-reaper-BYqERdkE.js} +1 -1
  130. package/server/{idle-stack-reaper-DDIRwxUY.js → idle-stack-reaper-CnGx_PO_.js} +99 -6
  131. package/server/in-flight-guard-Bq3epG58.js +45 -0
  132. package/server/{infra-BEqFxlJc.js → infra-BjuxvjdS.js} +70 -5
  133. package/server/{injection-CPUIqNhI.js → injection-DZxlV2al.js} +1 -1
  134. package/server/{injection-C8aiVJrF.js → injection-UCf8EsjX.js} +7 -7
  135. package/server/{inspect-agent-BLuJ1AkT.js → inspect-agent-6kylZnrm.js} +26 -25
  136. package/server/inspect-agent-BVwDrVrz.js +2 -0
  137. package/server/{internal-token-s0-oKybJ.js → internal-token-DvMTQSOS.js} +2 -2
  138. package/server/{internal-token-BrcU6qfe.js → internal-token-M9omeXM1.js} +1 -1
  139. package/server/{io-C9kF1wtJ.js → io-VHvc0Ssp.js} +43 -26
  140. package/server/{issue-closed-CDJk4pIp.js → issue-closed-B6KJkmHZ.js} +7 -7
  141. package/server/{issue-lifecycle-B8sZHVHh.js → issue-lifecycle-9gk3fnXN.js} +1 -1
  142. package/server/{issue-lifecycle-ojZAzDBP.js → issue-lifecycle-C4Zj0WmE.js} +34 -28
  143. package/server/{issue-service-singleton-Yx5DdmVJ.js → issue-service-singleton-DmCh7EHj.js} +10 -10
  144. package/server/{issue-service-singleton-BvJ09SaR.js → issue-service-singleton-PMx8F1jr.js} +1 -1
  145. package/server/{issues-BMmP_77e.js → issues-CgnQ1OGQ.js} +2 -2
  146. package/server/{jsonl-parser-BXSlHwEh.js → jsonl-parser-DJOH_O-w.js} +5 -4
  147. package/server/{label-cleanup-B0UJwnv5.js → label-cleanup-Dv7AV_R1.js} +3 -3
  148. package/server/{label-reconciler-B4iOAjlC.js → label-reconciler--F85rufp.js} +4 -4
  149. package/server/{lifecycle-yPd___5E.js → lifecycle-CTdOWYMi.js} +2 -2
  150. package/server/{lifecycle-xmBfK2GJ.js → lifecycle-DDN8ApVY.js} +6 -7
  151. package/server/{lifecycle-io-BREGpnLk.js → lifecycle-io-D-lGdzK3.js} +5 -5
  152. package/server/{lifecycle-io-DPo7x11I.js → lifecycle-io-D_zTLvP1.js} +1 -1
  153. package/server/{linear-client-BsuUvkdA.js → linear-client-BQU36QqE.js} +2 -2
  154. package/server/{linear-client-CTskEeT_.js → linear-client-CY4O_Tu3.js} +1 -1
  155. package/server/linear-mcp-auth-BnU4TYfY.js +280 -0
  156. package/server/linear-mcp-auth-NYBq_oHZ.js +2 -0
  157. package/server/memory-fts-worker.js +1 -1
  158. package/server/{merge-CefQNAnq.js → merge-Bpx4jjht.js} +13 -11
  159. package/server/{merge-agent-4WOWlSYA.js → merge-agent-DdMVSV2Y.js} +233 -83
  160. package/server/{merge-agent-CKkgIBPB.js → merge-agent-DrXa1CpW.js} +1 -1
  161. package/server/{merge-batch-ClFn2T-y.js → merge-batch-C5q1c1GX.js} +1 -1
  162. package/server/merge-completeness-BMm8tMyZ.js +277 -0
  163. package/server/merge-completeness-D0ljXbk3.js +3 -0
  164. package/server/{merge-B1DiziGU.js → merge-idOG--29.js} +1 -1
  165. package/server/merge-ops-DdpTiEMt.js +2 -0
  166. package/server/merge-rebase-DGQpYJU3.js +2 -0
  167. package/server/{merge-rebase-BfaTyXsw.js → merge-rebase-xLnMlw5h.js} +3 -3
  168. package/server/{merge-set-DJ8-UErs.js → merge-set-DH7ot3yz.js} +11 -5
  169. package/server/merge-set-DzsOTBg5.js +3 -0
  170. package/server/{merge-sync-VPV28g0g.js → merge-sync-CQ-LgZ1_.js} +406 -153
  171. package/server/merge-sync-Ca7F5JnQ.js +3 -0
  172. package/server/{merge-train-CHopycP0.js → merge-train-DTEMyIu4.js} +18 -8
  173. package/server/{merge-train-deps-D1cOZzy2.js → merge-train-deps-CNPJzepw.js} +4 -4
  174. package/server/merge-verification-x3JO8Dtz.js +220 -0
  175. package/server/merged-docker-cleanup-worker-CTpC27Bs.js +107 -0
  176. package/server/merged-docker-cleanup-worker-Cdi9apm-.js +3 -0
  177. package/server/{multipart-parser-duPAfSBw.js → multipart-parser-IMSBfePV.js} +2 -2
  178. package/server/{no-resume-mode-Nw29vaFb.js → no-resume-mode-C5ULAXwO.js} +1 -1
  179. package/server/node_modules/.package-lock.json +27 -27
  180. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/package.json +3 -3
  181. package/server/node_modules/@google-cloud/common/package.json +2 -2
  182. package/server/node_modules/gaxios/build/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  183. package/server/node_modules/gaxios/build/esm/tsconfig.tsbuildinfo +1 -1
  184. package/server/node_modules/gaxios/package.json +1 -1
  185. package/server/node_modules/google-auth-library/build/src/auth/googleauth.js +24 -19
  186. package/server/node_modules/google-auth-library/package.json +1 -1
  187. package/server/node_modules/google-gax/build/protos/google/api/auth.proto +2 -1
  188. package/server/node_modules/google-gax/build/protos/google/api/backend.proto +12 -1
  189. package/server/node_modules/google-gax/build/protos/google/api/billing.proto +1 -1
  190. package/server/node_modules/google-gax/build/protos/google/api/client.proto +165 -53
  191. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1/resources.proto +1 -1
  192. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1beta/quota_adjuster_settings.proto +7 -3
  193. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1beta/resources.proto +1 -1
  194. package/server/node_modules/google-gax/build/protos/google/api/config_change.proto +1 -1
  195. package/server/node_modules/google-gax/build/protos/google/api/context.proto +1 -1
  196. package/server/node_modules/google-gax/build/protos/google/api/control.proto +3 -3
  197. package/server/node_modules/google-gax/build/protos/google/api/distribution.proto +1 -1
  198. package/server/node_modules/google-gax/build/protos/google/api/documentation.proto +1 -1
  199. package/server/node_modules/google-gax/build/protos/google/api/endpoint.proto +1 -1
  200. package/server/node_modules/google-gax/build/protos/google/api/error_reason.proto +186 -1
  201. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/checked.proto +31 -3
  202. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/eval.proto +8 -9
  203. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/explain.proto +1 -2
  204. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/syntax.proto +20 -22
  205. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/value.proto +2 -3
  206. package/server/node_modules/google-gax/build/protos/google/api/field_behavior.proto +1 -1
  207. package/server/node_modules/google-gax/build/protos/google/api/field_info.proto +1 -1
  208. package/server/node_modules/google-gax/build/protos/google/api/http.proto +1 -1
  209. package/server/node_modules/google-gax/build/protos/google/api/httpbody.proto +1 -1
  210. package/server/node_modules/google-gax/build/protos/google/api/label.proto +1 -1
  211. package/server/node_modules/google-gax/build/protos/google/api/launch_stage.proto +1 -1
  212. package/server/node_modules/google-gax/build/protos/google/api/log.proto +1 -1
  213. package/server/node_modules/google-gax/build/protos/google/api/logging.proto +1 -1
  214. package/server/node_modules/google-gax/build/protos/google/api/metric.proto +1 -1
  215. package/server/node_modules/google-gax/build/protos/google/api/monitored_resource.proto +1 -1
  216. package/server/node_modules/google-gax/build/protos/google/api/monitoring.proto +1 -1
  217. package/server/node_modules/google-gax/build/protos/google/api/policy.proto +1 -1
  218. package/server/node_modules/google-gax/build/protos/google/api/quota.proto +1 -1
  219. package/server/node_modules/google-gax/build/protos/google/api/resource.proto +1 -1
  220. package/server/node_modules/google-gax/build/protos/google/api/routing.proto +8 -4
  221. package/server/node_modules/google-gax/build/protos/google/api/service.proto +2 -3
  222. package/server/node_modules/google-gax/build/protos/google/api/source_info.proto +1 -1
  223. package/server/node_modules/google-gax/build/protos/google/api/system_parameter.proto +1 -1
  224. package/server/node_modules/google-gax/build/protos/google/api/usage.proto +7 -27
  225. package/server/node_modules/google-gax/build/protos/google/api/visibility.proto +1 -1
  226. package/server/node_modules/google-gax/build/protos/google/longrunning/operations.proto +20 -1
  227. package/server/node_modules/google-gax/build/protos/google/protobuf/any.proto +52 -108
  228. package/server/node_modules/google-gax/build/protos/google/protobuf/compiler/ruby/ruby_generated_code.proto +2 -0
  229. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_features.proto +21 -1
  230. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_file_options.proto +24 -0
  231. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_options.proto +15 -0
  232. package/server/node_modules/google-gax/build/protos/google/protobuf/descriptor.proto +118 -30
  233. package/server/node_modules/google-gax/build/protos/google/protobuf/field_mask.proto +16 -18
  234. package/server/node_modules/google-gax/build/protos/google/protobuf/internal_options.proto +8 -1
  235. package/server/node_modules/google-gax/build/protos/google/protobuf/json/json_enumval_custom_string.proto +26 -0
  236. package/server/node_modules/google-gax/build/protos/google/protobuf/json_enumvalue_options.proto +29 -0
  237. package/server/node_modules/google-gax/build/protos/google/protobuf/json_options.proto +14 -0
  238. package/server/node_modules/google-gax/build/protos/google/protobuf/struct.proto +38 -22
  239. package/server/node_modules/google-gax/build/protos/google/protobuf/test_protos/forced_micro_string.proto +3 -0
  240. package/server/node_modules/google-gax/build/protos/google/protobuf/test_protos/repeated_field_proxy_import_message.proto +14 -0
  241. package/server/node_modules/google-gax/build/protos/google/protobuf/timestamp.proto +9 -8
  242. package/server/node_modules/google-gax/build/protos/google/protobuf/util/json_format_proto3.proto +18 -0
  243. package/server/node_modules/google-gax/build/protos/google/rpc/code.proto +1 -1
  244. package/server/node_modules/google-gax/build/protos/google/rpc/context/attribute_context.proto +7 -2
  245. package/server/node_modules/google-gax/build/protos/google/rpc/context/audit_context.proto +1 -1
  246. package/server/node_modules/google-gax/build/protos/google/rpc/error_details.proto +5 -5
  247. package/server/node_modules/google-gax/build/protos/google/rpc/http.proto +1 -1
  248. package/server/node_modules/google-gax/build/protos/google/rpc/status.proto +1 -2
  249. package/server/node_modules/google-gax/build/protos/google/type/calendar_period.proto +1 -1
  250. package/server/node_modules/google-gax/build/protos/google/type/color.proto +9 -10
  251. package/server/node_modules/google-gax/build/protos/google/type/date.proto +11 -9
  252. package/server/node_modules/google-gax/build/protos/google/type/datetime.proto +17 -17
  253. package/server/node_modules/google-gax/build/protos/google/type/dayofweek.proto +1 -1
  254. package/server/node_modules/google-gax/build/protos/google/type/decimal.proto +11 -13
  255. package/server/node_modules/google-gax/build/protos/google/type/expr.proto +1 -1
  256. package/server/node_modules/google-gax/build/protos/google/type/fraction.proto +1 -1
  257. package/server/node_modules/google-gax/build/protos/google/type/interval.proto +1 -2
  258. package/server/node_modules/google-gax/build/protos/google/type/latlng.proto +4 -5
  259. package/server/node_modules/google-gax/build/protos/google/type/localized_text.proto +3 -3
  260. package/server/node_modules/google-gax/build/protos/google/type/money.proto +1 -2
  261. package/server/node_modules/google-gax/build/protos/google/type/month.proto +1 -1
  262. package/server/node_modules/google-gax/build/protos/google/type/phone_number.proto +20 -15
  263. package/server/node_modules/google-gax/build/protos/google/type/postal_address.proto +39 -39
  264. package/server/node_modules/google-gax/build/protos/google/type/quaternion.proto +4 -4
  265. package/server/node_modules/google-gax/build/protos/google/type/timeofday.proto +11 -8
  266. package/server/node_modules/google-gax/package.json +5 -5
  267. package/server/node_modules/retry-request/package.json +4 -4
  268. package/server/node_modules/teeny-request/package.json +5 -5
  269. package/server/node_modules/undici/lib/cache/memory-cache-store.js +54 -9
  270. package/server/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
  271. package/server/node_modules/undici/lib/core/request.js +12 -1
  272. package/server/node_modules/undici/lib/dispatcher/client-h1.js +11 -2
  273. package/server/node_modules/undici/lib/global.js +36 -16
  274. package/server/node_modules/undici/lib/handler/cache-handler.js +236 -116
  275. package/server/node_modules/undici/lib/handler/cache-revalidation-handler.js +3 -3
  276. package/server/node_modules/undici/lib/handler/retry-handler.js +24 -0
  277. package/server/node_modules/undici/lib/interceptor/cache.js +152 -62
  278. package/server/node_modules/undici/lib/interceptor/decompress.js +5 -2
  279. package/server/node_modules/undici/lib/util/cache.js +328 -66
  280. package/server/node_modules/undici/lib/util/date.js +23 -6
  281. package/server/node_modules/undici/lib/web/cookies/util.js +78 -8
  282. package/server/node_modules/undici/package.json +1 -1
  283. package/server/{orphan-proposed-reconciler-CTSGcK8p.js → orphan-proposed-reconciler-CWmOdM9-.js} +1 -1
  284. package/server/{orphan-proposed-reconciler-BvKkWMJQ.js → orphan-proposed-reconciler-Dg6U4ADZ.js} +24 -15
  285. package/server/package-lock.json +28 -28
  286. package/server/package.json +1 -1
  287. package/server/{pan-dir-B0c3w0Ya.js → pan-dir-ubraCiUg.js} +24 -10
  288. package/server/{paths-D-xWGHdh.js → paths-cXmOwSbh.js} +2 -2
  289. package/server/pending-lifecycle-claim-DEteYdS9.js +110 -0
  290. package/server/{pickup-DUCLWrJY.js → pickup-D8xtG1J2.js} +1 -1
  291. package/server/pipeline-membership-BGSvkT2M.js +3 -0
  292. package/server/pipeline-membership-CrAPLYtf.js +57 -0
  293. package/server/{pipeline-membership-mY3GprlK.js → pipeline-membership-gather-CET40frr.js} +177 -109
  294. package/server/pipeline-membership-gather-DTfcgxLl.js +3 -0
  295. package/server/{pipeline-notifier-BXkJzDC4.js → pipeline-notifier-BuQ0e4hF.js} +2 -2
  296. package/server/{pipeline-notifier-BJr8gQX6.js → pipeline-notifier-ImNXknf0.js} +1 -1
  297. package/server/post-merge-lifecycle-worker-DbO10pum.js +50 -0
  298. package/server/{project-pipelines-C0MWUeCU.js → project-pipelines-Bim6bThI.js} +2 -2
  299. package/server/{project-repos-B6GycDh9.js → project-repos-C0nuoBGv.js} +7 -3
  300. package/server/project-repos-CRE6Ykow.js +3 -0
  301. package/server/projects-B03Wr-xc.js +3 -0
  302. package/server/{prompts-DxzFXuLl.js → prompts-BEx08AIu.js} +2 -2
  303. package/server/{providers-u4Ga0jOr.js → providers-D7IluJe0.js} +1 -1
  304. package/server/{providers-qQAwGQDW.js → providers-evXhiQeg.js} +7 -7
  305. package/server/public/assets/{chunk-BO2N2NFS-BamJdinX.js → chunk-BO2N2NFS-D1s4-Sqp.js} +4 -4
  306. package/server/public/assets/{diagram-OG6HWLK6-DfOB8-w4.js → diagram-OG6HWLK6-1gdMoSF7.js} +1 -1
  307. package/server/public/assets/{dist-D7zYSEA6.js → dist-CxAOHbil.js} +1 -1
  308. package/server/public/assets/{dist-ByIuzMQW.js → dist-DqDRYW6P.js} +3 -3
  309. package/server/public/assets/{ganttDiagram-6RSMTGT7-EdmRyXL3.js → ganttDiagram-6RSMTGT7-BYex-Ec7.js} +1 -1
  310. package/server/public/assets/{highlighted-body-OFNGDK62-MerOfTX8.js → highlighted-body-OFNGDK62-DlVkiG0S.js} +1 -1
  311. package/server/public/assets/index-Cc7cnFC4.css +1 -0
  312. package/server/public/assets/index-K0hAYCgV.js +807 -0
  313. package/server/public/assets/{linear-BBbArIcK.js → linear-B4cuEFmO.js} +1 -1
  314. package/server/public/assets/mermaid-GHXKKRXX-DyDHFXHV.js +1 -0
  315. package/server/public/assets/{pieDiagram-4H26LBE5-BKIddiJN.js → pieDiagram-4H26LBE5-CBHNBIJQ.js} +1 -1
  316. package/server/public/assets/{prod-B8vYiu52.js → prod-CN2nHBvX.js} +4 -4
  317. package/server/public/assets/{quadrantDiagram-W4KKPZXB-D6RtoULk.js → quadrantDiagram-W4KKPZXB-Bom87VOQ.js} +1 -1
  318. package/server/public/assets/{sankeyDiagram-5OEKKPKP-CLrCedZX.js → sankeyDiagram-5OEKKPKP-UrBeyLxk.js} +1 -1
  319. package/server/public/assets/{xychartDiagram-2RQKCTM6-hznR8DYl.js → xychartDiagram-2RQKCTM6-DhkbrIxR.js} +1 -1
  320. package/server/public/index.html +2 -2
  321. package/server/{pull-requests-7N8WKseP.js → pull-requests-Cv7LxzUN.js} +1 -1
  322. package/server/{pull-requests-_lHueOHW.js → pull-requests-DHWiKxo7.js} +19 -10
  323. package/server/{queries-CjNIf-Ub.js → queries-DHJm7bTd.js} +631 -110
  324. package/server/{rally-CyWT_lNO.js → rally-B71M9f4o.js} +3 -3
  325. package/server/rally-YDjU513q.js +3 -0
  326. package/server/{rally-api-ClOSd-Tt.js → rally-api-D5uXN08-.js} +1 -1
  327. package/server/{rally-api-C8e_1JRi.js → rally-api-Dkqmok65.js} +2 -2
  328. package/server/{rally-client-lc-nokqr.js → rally-client-Bfqm6XI4.js} +4 -4
  329. package/server/{rally-client-sgtVqzNU.js → rally-client-CxsA6ExK.js} +1 -1
  330. package/server/{reap-terminal-sessions-7KeHv1R1.js → reap-terminal-sessions-BQ23nriz.js} +2 -2
  331. package/server/{reap-terminal-sessions-BtHPo6Xc.js → reap-terminal-sessions-CvmwaqKv.js} +2 -2
  332. package/server/{rebuild-stack-lwtsW0GO.js → rebuild-stack-0EEYReVZ.js} +16 -7
  333. package/server/{rebuild-stack-CFvcBHsS.js → rebuild-stack-qeRqHZxH.js} +2 -2
  334. package/server/{reconstruct-cache-C3Ui7ojV.js → reconstruct-cache-BbYFsqLa.js} +7 -6
  335. package/server/record-CtroO946.js +3 -0
  336. package/server/record-update-DH6dLJID.js +3 -0
  337. package/server/{record-update-dE1Aw83j.js → record-update-Z0QCxmMp.js} +124 -34
  338. package/server/{recovery-trip-BvRWfUXM.js → recovery-trip-eJe26h-f.js} +2 -2
  339. package/server/{release-engine-Cx48W7z8.js → release-engine-lPUp-MTd.js} +5 -5
  340. package/server/{release-set-CQfuN9-v.js → release-set-BwGeyZKX.js} +3 -3
  341. package/server/{remote-C_2hasl7.js → remote-BCd02Es1.js} +3 -3
  342. package/server/{remote-ChgimyYa.js → remote-CVGUhXMV.js} +3 -3
  343. package/server/{remote-agents-CA3Ihlxj.js → remote-agents-C1bssi41.js} +2 -2
  344. package/server/{remote-agents-By1ige5O.js → remote-agents-C_VxssLU.js} +300 -46
  345. package/server/{remote-completion-fVe9e_3u.js → remote-completion-DAB0P706.js} +12 -12
  346. package/server/resume-u9byntrq.js +3 -0
  347. package/server/{review-agent-DNboMyW4.js → review-agent-CD4RCI0Y.js} +1 -1
  348. package/server/{review-agent-CIGOQYBD.js → review-agent-CHhI66UP.js} +60 -47
  349. package/server/{review-artifacts-nRDPuMxd.js → review-artifacts-DSMRIfuJ.js} +7 -6
  350. package/server/{review-context-2uj-YQ8J.js → review-context-oFuBbiEE.js} +8 -8
  351. package/server/{in-flight-guard-CAAkqPLu.js → review-convoy-liveness-CpzrcJ5F.js} +3 -44
  352. package/server/review-status-BZH8h-6W.js +3 -0
  353. package/server/review-status-emit-CUExtHd5.js +50 -0
  354. package/server/{review-status-enrichment-Dci-ZwEt.js → review-status-enrichment-QV_hQkgS.js} +4 -4
  355. package/server/{review-status-source-CxuEjLGg.js → review-status-source-CpvJnvnQ.js} +24 -3
  356. package/server/review-status-source-ylw5QZUR.js +3 -0
  357. package/server/{review-status-sync-BTOpxtTC.js → review-status-sync-483sujRo.js} +2 -2
  358. package/server/{review-status-sync-DSDK3OMy.js → review-status-sync-NaWvI9Xf.js} +1 -1
  359. package/server/review-status-yljtTd-q.js +7521 -0
  360. package/server/{review-verdict-feedback-CTd4QMBu.js → review-verdict-feedback-BPDn4li_.js} +1 -1
  361. package/server/{review-verdict-feedback-CCjVA7Uk.js → review-verdict-feedback-CELeUinh.js} +48 -8
  362. package/server/{rollup-FGsKki9R.js → rollup-DTNvelz9.js} +8 -8
  363. package/server/{rollup-BKQC7jp4.js → rollup-DYZfq1c4.js} +1 -1
  364. package/server/{scanner-CnqEZeDy.js → scanner-CV35oSn4.js} +8 -7
  365. package/server/{sequence-io-D909zgeH.js → sequence-io-DF_8iuhV.js} +4 -4
  366. package/server/{sequencer-agent-CzkcK6P5.js → sequencer-agent-B2WeCtGi.js} +5 -5
  367. package/server/server.js +1952 -578
  368. package/server/{service-CLeAoU6G.js → service-Br9rpBNA.js} +81 -64
  369. package/server/{session-fork-CHI1XvL9.js → session-fork-D0LY152N.js} +2 -2
  370. package/server/{session-history-BT3IvqhC.js → session-history-BUyK29eq.js} +4 -4
  371. package/server/{settings-BTMvpNFU.js → settings-Bse1Pdcj.js} +3 -3
  372. package/server/settings-CdvIF84R.js +2 -0
  373. package/server/{settings-C0zgxOGf.js → settings-CvVGqNEs.js} +3 -2
  374. package/server/{shadow-engineering-BJfgm-hX.js → shadow-engineering-BWLa8ODz.js} +2 -2
  375. package/server/{shadow-state-7a-524T8.js → shadow-state-B4fpKxOO.js} +2 -2
  376. package/server/{shadow-state-DnDyjujH.js → shadow-state-FV6PHfEW.js} +1 -1
  377. package/server/{shadow-utils-Db3oroFG.js → shadow-utils-D7asqxOZ.js} +2 -2
  378. package/server/{ship-log-D9MlVzYU.js → ship-log-xplJ8t75.js} +1 -1
  379. package/server/{smart-compaction-CV2ukKND.js → smart-compaction-CPp2Ykf6.js} +1 -1
  380. package/server/{smart-compaction-KCYScAU1.js → smart-compaction-D3U_79f-.js} +8 -7
  381. package/server/{spawn-planning-session-qUC2VWu3.js → spawn-planning-session-1nFi3gfk.js} +1 -1
  382. package/server/{spawn-planning-session-DKpdFyOC.js → spawn-planning-session-DGfZ5B8D.js} +17 -17
  383. package/server/{specialist-completion-Ky9wCDpb.js → specialist-completion-Br48eiDP.js} +1 -1
  384. package/server/{specialist-context-Bn3dCGS2.js → specialist-context-cVbGnTa3.js} +5 -5
  385. package/server/{specialist-handoff-logger-CMEwYxa2.js → specialist-handoff-logger-DK-GTz4s.js} +2 -2
  386. package/server/{specialist-logs-C5p8G7tx.js → specialist-logs-Cl5-hqT8.js} +3 -3
  387. package/server/{specialists-CC4r-c2s.js → specialists-CNfYO3G2.js} +975 -227
  388. package/server/{specialists-jiuuyVkp.js → specialists-Cicieuzu.js} +18 -18
  389. package/server/{specialists-CShuVGWT.js → specialists-JHsdU3pA.js} +1 -1
  390. package/server/{specialists-DM6bWjsi.js → specialists-Tdezg_6N.js} +1 -1
  391. package/server/specs-Bt7WJDoC.js +3 -0
  392. package/server/src-CRmCHlma.js +11408 -0
  393. package/server/{src-CXmtj0im.js → src-Ck028hjO.js} +6 -6
  394. package/server/{src-CdmnTM2m.js → src-UWcGe0Ix.js} +3 -3
  395. package/server/{stack-health-Bn3o8FBX.js → stack-health-CJLMrLBl.js} +1 -1
  396. package/server/{stack-health-DxSdG9cW.js → stack-health-DqSqx0zv.js} +7 -5
  397. package/server/{stale-task-claims-KJKxxiiQ.js → stale-task-claims-CYFOUNlT.js} +4 -4
  398. package/server/{staleness-CT34nwr9.js → staleness-BQ-0gMYK.js} +1 -1
  399. package/server/{staleness-DPm7ClwA.js → staleness-D47CUJok.js} +1 -1
  400. package/server/{state-home-Cn_Qu8IX.js → state-home-BYV7qZTW.js} +2 -2
  401. package/server/{state-mapping-BL_-3Yt8.js → state-mapping-BVldLhBf.js} +1 -1
  402. package/server/{state-migrate-BGg2ZaOt.js → state-migrate-CvvBtS0Y.js} +4 -4
  403. package/server/{stuck-remediation-s9_2qfi6.js → stuck-remediation-Wt0UVvu1.js} +1 -1
  404. package/server/{stuck-remediation-DYuPRYYw.js → stuck-remediation-mkLC6G_t.js} +79 -22
  405. package/server/{substrate-bug-weights-service-B-FwCs5V.js → substrate-bug-weights-service-XfLAKnmK.js} +3 -3
  406. package/server/{summary-fork-DpcxN9tf.js → summary-fork-CD7GOts0.js} +2 -2
  407. package/server/{summary-fork-D1RAk9rJ.js → summary-fork-xiXBnWG9.js} +8 -8
  408. package/server/supervisor/{injection-budget-Csw5tqfJ.js → injection-budget-B5SbvDx2.js} +1 -1
  409. package/server/supervisor/{paths-DehGY2Fj.js → paths-K3noE4N_.js} +1 -1
  410. package/server/supervisor/pty-supervisor.js +49 -3
  411. package/server/supervisor/{pty-token-x-ea28Us.js → pty-token-B7lp0ElT.js} +2 -2
  412. package/server/{supervisor-wM4ooB5O.js → supervisor-DL788vos.js} +3 -3
  413. package/server/supervisor-UWiQNK-y.js +2 -0
  414. package/server/{swarm-readiness-DlP_UjHq.js → swarm-readiness-BV14DF5N.js} +3 -3
  415. package/server/{system-prerequisites-DUDj1YHf.js → system-prerequisites-pdWG6ZQs.js} +2 -2
  416. package/server/{teardown-workspace-DeTTImn-.js → teardown-workspace-l2F4_zim.js} +15 -16
  417. package/server/{test-agent-queue-MbxX5vqq.js → test-agent-queue-qakFIIGz.js} +6 -6
  418. package/server/{test-verdict-bWYBtqBg.js → test-verdict-BJYDggMm.js} +1 -1
  419. package/server/{test-verdict-gscuksPv.js → test-verdict-Gw-btEfb.js} +1 -1
  420. package/server/{tldr-daemon-BYFkts95.js → tldr-daemon-BKOYB616.js} +1 -1
  421. package/server/{tldr-daemon-C-69c3OI.js → tldr-daemon-CBaWkV9k.js} +2 -2
  422. package/server/{tmux-R7N7y-Mh.js → tmux-B1Wbxz5o.js} +3 -3
  423. package/server/{tmux-B6z7h_vZ.js → tmux-DQ6jB76i.js} +1 -1
  424. package/server/{launcher-generator-BBWG_SiS.js → tmux-dedup-DbN6MGzM.js} +428 -9
  425. package/server/{token-BK6t8BIT.js → token-Cxbk023d.js} +2 -2
  426. package/server/{token-util-DxXu-vd1.js → token-util-CLq2MmQt.js} +1 -1
  427. package/server/token-util-zlz9U0ki.js +3 -0
  428. package/server/{tracker-config-G6latr8C.js → tracker-config-DZ8Zn2nQ.js} +2 -2
  429. package/server/{tracker-utils-DHv5pSDT.js → tracker-utils-L0FKtjq2.js} +3 -3
  430. package/server/{traefik-connect-Df2uXPsQ.js → traefik-connect-bNX6jKkb.js} +1 -1
  431. package/server/{tunnel-CDVKJpRv.js → tunnel-BAm1XgjG.js} +3 -3
  432. package/server/{tunnel-DGdUkGoZ.js → tunnel-CjSnHdTc.js} +1 -1
  433. package/server/{types-5M0lupud.js → types-q67TYYg5.js} +1 -1
  434. package/server/uat-promote-verification-CKB9ZrKC.js +92 -0
  435. package/server/uat-train-Cu-4nvbf.js +2 -0
  436. package/server/uat-train-D5UjcyAa.js +0 -0
  437. package/server/{validate-IfDGkaVR.js → validate-Cxsx5Uz1.js} +8 -6
  438. package/server/{validation-CC9OPqJZ.js → validation-DEaTZafj.js} +1 -1
  439. package/server/{validation-Dw1pzDzr.js → validation-VZgJxmqc.js} +4 -4
  440. package/server/{verification-artifact-B3itKTxu.js → verification-artifact-C85cRTc_.js} +1 -1
  441. package/server/{verification-artifact-TVFSz_q1.js → verification-artifact-g3yuxQDL.js} +1 -1
  442. package/server/{verification-runner-BW4HOKAz.js → verification-runner-DlZI8yhw.js} +1 -1
  443. package/server/{verification-runner-CkgX6EtI.js → verification-runner-KDZIsBj4.js} +40 -18
  444. package/server/{vtt-parser-DYPbKcIJ.js → vtt-parser-Jr94BF3Y.js} +1 -1
  445. package/server/{work-agent-prompt-Du8Vh2aJ.js → work-agent-prompt-C-vuP3_J.js} +20 -9
  446. package/server/workflows-CHrx_hcW.js +2 -0
  447. package/server/{workflows-mbQzh6mQ.js → workflows-D0oip4eV.js} +161 -78
  448. package/server/{workspace--8tnhDI0.js → workspace-BqFg__wH.js} +1 -1
  449. package/server/{workspace-BPUws1-_.js → workspace-C0fH3aek.js} +3 -3
  450. package/server/workspace-anchor-drift-B4gMRHl4.js +3 -0
  451. package/server/workspace-anchor-drift-CZKofakh.js +224 -0
  452. package/server/{workspace-config-CIVWZOQr.js → workspace-config-B123aZl-.js} +1 -1
  453. package/server/workspace-manager-CDTKjjdU.js +3 -0
  454. package/server/{workspace-manager-CBhNdzE4.js → workspace-manager-CwO-Hek7.js} +156 -117
  455. package/server/{workspace-metadata-_WygnyoX.js → workspace-metadata-CQv00QwK.js} +2 -2
  456. package/server/{workspace-metadata-BzHnwwX4.js → workspace-metadata-D4M8BM4W.js} +1 -1
  457. package/server/{workspaces-Do_9J0LQ.js → workspaces-j1e_6aAT.js} +719 -292
  458. package/sync-sources/dev-skills/pan-dashboard-restart/SKILL.md +34 -10
  459. package/sync-sources/hooks/linear-mcp-auth-hook +97 -0
  460. package/sync-sources/rules/ask-user-question-self-contained.md +9 -0
  461. package/sync-sources/skills/pan-close/SKILL.md +5 -3
  462. package/sync-sources/skills/pan-peer-review/SKILL.md +195 -0
  463. package/sync-sources/skills/pan-reload/SKILL.md +3 -3
  464. package/sync-sources/skills/pan-restart/SKILL.md +5 -4
  465. package/sync-sources/skills/pan-review/SKILL.md +7 -1
  466. package/sync-sources/skills/pan-sync-main/SKILL.md +9 -8
  467. package/sync-sources/skills/pipeline-status/SKILL.md +10 -1
  468. package/sync-sources/skills/workspace-add-repo/SKILL.md +16 -1
  469. package/server/activity-logger-OEUBdfZ8.js +0 -3
  470. package/server/agent-state-Bc3tzUC8.js +0 -3
  471. package/server/agents-wi9NWzs2.js +0 -3
  472. package/server/archive-planning-BZDgzoEj.js +0 -3
  473. package/server/cli-B86rejVV.js +0 -3
  474. package/server/conversation-service-BLd3MYsG.js +0 -3
  475. package/server/deacon-kiQrb4ZT.js +0 -4
  476. package/server/deacon-swarm-C-GwfjJy.js +0 -2
  477. package/server/deploy-window-DkZraDyj.js +0 -3
  478. package/server/dist-Bzy0y69j.js +0 -3
  479. package/server/flywheel-merge-order-UU0tiUld.js +0 -245
  480. package/server/flywheel-merge-order-UUcsCDb6.js +0 -2
  481. package/server/forge-CNFnyqps.js +0 -270
  482. package/server/forge-DXnS_YFH.js +0 -2
  483. package/server/git-utils-D0_yhCgF.js +0 -3
  484. package/server/github-pr-lookup-D16NGsSO.js +0 -44
  485. package/server/hume-ccTf4wTX.js +0 -3
  486. package/server/inspect-agent-Brtz0URj.js +0 -2
  487. package/server/merge-ops-CR44oU9-.js +0 -2
  488. package/server/merge-set-bUqbm3yc.js +0 -3
  489. package/server/merge-sync-BJYeOODr.js +0 -3
  490. package/server/merge-verification-BkaOqPsw.js +0 -124
  491. package/server/project-repos-DXKQsc_m.js +0 -3
  492. package/server/projects-vjjcmiN8.js +0 -3
  493. package/server/public/assets/index-CWeMerGO.js +0 -804
  494. package/server/public/assets/index-CenuJ3Cw.css +0 -1
  495. package/server/public/assets/mermaid-GHXKKRXX-CpPWAFwE.js +0 -1
  496. package/server/rally-zhhtXuDP.js +0 -3
  497. package/server/record-CN0pj4_5.js +0 -3
  498. package/server/record-update-bLJxAXH4.js +0 -3
  499. package/server/resume-BFv1PGpA.js +0 -3
  500. package/server/review-status-btEYlaxA.js +0 -3
  501. package/server/review-status-kZj_KyCk.js +0 -1470
  502. package/server/settings-66A6uvIA.js +0 -2
  503. package/server/specs-C8Wsn2XO.js +0 -3
  504. package/server/src-DtcUOZCq.js +0 -4826
  505. package/server/supervisor-FTJAIsAK.js +0 -2
  506. package/server/token-util-DuPuNriz.js +0 -3
  507. package/server/tracker-utils-B4ylXZQK.js +0 -3
  508. package/server/uat-train-B05BWkp-.js +0 -2
  509. package/server/uat-train-DDSrSoV1.js +0 -2152
  510. package/server/workflows-BQu4RFQ-.js +0 -2
  511. package/server/workspace-manager-CWT55qeI.js +0 -3
@@ -1,46 +1,47 @@
1
1
  import { a as __toCommonJS } from "./rolldown-runtime-DNCzzKnI.js";
2
- import { A as canUseHarnessSync, Br as getOverdeckHome, D as resolveTieredExecutionEnabled, H as init_providers, I as UnknownModelError, Jn as extractPrefixSync, M as init_harness_policy, Nr as encodeClaudeProjectDir, O as resolveTieredExecutionEnabledForIssue, Qt as parsePorcelainStatusPaths, T as init_tier_table, Tn as init_projects, U as piProviderForModel, Ur as packageRoot, V as getProviderForModelSync, Vr as init_paths, Wr as resolveOhmypiExtensionPath, Yn as init_issue_id, Yt as init_state_plane, Zn as parseIssueIdSync, c as isClaudeCodeChannelsEnabled, f as loadConfigSync, fn as findProjectByPathSync, in as shouldCommitLegacyWorkspaceArtifacts, ir as FsError, kn as listProjectsSync, mr as init_errors, nn as init_state_read_home, rn as resolveStateReadHomeSync, t as init_config_yaml, tt as resolveModel, yn as getProjectSync, zn as resolveProjectFromIssueSync } from "./config-yaml-DySPNmKN.js";
3
- import { a as init_activity_logger, n as emitActivityEntrySync } from "./activity-logger-DDlOIAML.js";
4
- import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-BEqFxlJc.js";
5
- import { $ as init_child_env, B as sendKeysAsync, D as killSession, H as sessionExists, M as listSessionNames, N as listSessions, Q as buildChildEnvWithoutTmuxSync, T as isHarnessProcessAlive, U as sessionExistsSync, V as sendRawKeystroke, W as setOption, X as BLANKED_PROVIDER_ENV, g as findManagedServerPidSync, i as capturePane, m as exactPaneTarget, s as createSession, w as init_tmux } from "./tmux-R7N7y-Mh.js";
6
- import { a as init_event_store, n as getEventStore } from "./event-store-CQL6NeqB.js";
7
- import { M as normalizeChannelReplyPayload, o as getHarnessBehavior, t as init_src, w as DomainEvent } from "./src-DtcUOZCq.js";
8
- import { E as init_agent_state_sync, b as setReviewStatusSync, c as getReviewStatusSync, d as loadReviewStatuses, i as clearWorkspaceStuck, k as stateToOverdeckParamsForDb, l as init_review_status, w as AGENT_COLUMNS_FOR_DB } from "./review-status-kZj_KyCk.js";
9
- import { a as EventStoreService, c as ReadModelService, d as init_read_model, i as init_issue_lifecycle, s as init_domain_services, t as IssueLifecycle, u as getClosedIssueIdsForReadSource } from "./issue-lifecycle-ojZAzDBP.js";
10
- import { d as isTerminalIssueStage, o as init_agents, u as getIssueStageSync } from "./agents-EbI0zCJl.js";
11
- import { n as ensureSessionContextBriefingFile, r as init_briefing_freshness } from "./briefing-freshness-D1wzUIWv.js";
12
- import { o as getPricingSync, s as init_cost, t as calculateCostSync } from "./cost-B2ddP6wq.js";
13
- import { Ar as saveAgentRuntimeState, At as deliverAgentPermissionDecision, Bt as assertWorkspaceStackHealthyForSpawn, Cr as normalizeAgentId, Dn as validateProviderHealth, Dr as getAgentRuntimeState, En as init_provider_health, Er as waitForReadySignal, F as init_tier_escalation, Fn as writeChannelsBridgeMcpConfig, Fr as init_codex_auth, G as resumeAgent, Gn as getAgentDir, Gt as transitionIssueToInProgress, H as restartAgent, Lt as BRIDGE_TOKEN_HEADER, Nt as setAgentDeliveryMethod, Or as getAgentRuntimeStateSync, P as decideEscalation, Pn as dismissDevChannelsDialog, Pr as checkCodexAuthStatus, Q as operatorInterventionEvent, Rt as init_bridge_token, Sn as determineModel, Ut as init_spawn_prep, V as recoverAgent, Vn as clearAgentTroubled, X as messageAgent, Xt as resolveStaffing, Yn as getAgentStateSync, Z as init_operator_interventions, _r as init_pty_token, an as getProviderAuthMode, at as saveSessionId, b as init_agents$1, br as resolvePtySupervisorScriptPath, cr as saveAgentState, et as getActivity, fn as init_pi_fifo, ft as stopAgent, hn as ohmypiFifoPaths, i as listRunningAgents, kt as deliverAgentMessage, lr as saveAgentStateSync, mn as init_ohmypi_fifo, mr as writeAgentStateJsonSync, nn as getAgentRuntimeBaseCommand, nr as markAgentStoppedState, nt as getLatestSessionIdSync, pn as piFifoPaths, pr as wipeAgentStateDirs, qn as getAgentState, qt as init_staffing, r as listAgentStates, rt as getSessionId, sn as init_runtime_command, tn as getAcpLauncherFields, tt as getLatestSessionId, un as waitForAcpHostReady, ur as setAgentPaused, vr as writePtyToken, wn as getProviderExportsForModel, xr as clearReadySignal, yr as init_pty_supervisor_locate, zn as clearAgentPaused, zt as writeBridgeTokenSync } from "./queries-CjNIf-Ub.js";
14
- import { a as performHandoff, i as checkAllTriggers, s as getAgentHealth, t as getCloisterService } from "./service-CLeAoU6G.js";
15
- import { o as init_persistent_logger, s as logAgentLifecycleSync } from "./session-history-BT3IvqhC.js";
16
- import { t as init_behavior } from "./behavior-B3exJ42O.js";
17
- import { a as init_tracker_config, t as getGitHubConfig } from "./tracker-config-G6latr8C.js";
18
- import { n as init_issue_service_singleton, r as issue_service_singleton_exports } from "./issue-service-singleton-Yx5DdmVJ.js";
19
- import { o as getInternalTokenSync, s as init_internal_token } from "./internal-token-s0-oKybJ.js";
2
+ import { A as canUseHarnessSync, Cn as resolveStateReadHomeSync, D as resolveTieredExecutionEnabled, Fr as init_errors, Gn as init_projects, H as init_providers, I as UnknownModelError, M as init_harness_policy, Mn as findProjectByPathSync, O as resolveTieredExecutionEnabledForIssue, Sn as init_state_read_home, T as init_tier_table, Tr as FsError, U as piProviderForModel, V as getProviderForModelSync, Yn as listProjectsSync, ar as resolveProjectFromIssueSync, c as isClaudeCodeChannelsEnabled, ci as init_paths, di as resolveOhmypiExtensionPath, ei as encodeClaudeProjectDir, f as loadConfigSync, gr as init_issue_id, h as jsYaml, hn as init_state_plane, hr as extractPrefixSync, m as init_js_yaml, si as getOverdeckHome, t as init_config_yaml, tt as resolveModel, ui as packageRoot, vn as parsePorcelainStatusPaths, vr as parseIssueIdSync, wn as shouldCommitLegacyWorkspaceArtifacts, zn as getProjectSync } from "./config-yaml-CmOPzmBb.js";
3
+ import { n as emitActivityEntryDurable, o as init_activity_logger, r as emitActivityEntrySync } from "./activity-logger-CyteR4JO.js";
4
+ import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-BjuxvjdS.js";
5
+ import { B as sendKeysAsync, D as killSession, H as sessionExists, M as listSessionNames, N as listSessions, Q as BLANKED_PROVIDER_ENV, T as isHarnessProcessAlive, U as sessionExistsSync, V as sendRawKeystroke, W as setOption, et as buildChildEnvWithoutTmuxSync, g as findManagedServerPidSync, i as capturePane, m as exactPaneTarget, o as capturePaneText, s as createSession, tt as init_child_env, w as init_tmux } from "./tmux-B1Wbxz5o.js";
6
+ import { a as init_event_store, n as getEventStore } from "./event-store-zY5MJHgF.js";
7
+ import { N as normalizeChannelReplyPayload, T as DomainEvent, n as COMPOSER_COMMAND_MANIFEST, s as getHarnessBehavior, t as init_src } from "./src-CRmCHlma.js";
8
+ import { K as stateToOverdeckParamsForDb, S as setReviewStatusSync, U as init_agent_state_sync, V as AGENT_COLUMNS_FOR_DB, f as init_review_status, m as loadReviewStatuses, o as clearWorkspaceStuck, u as getReviewStatusSync } from "./review-status-yljtTd-q.js";
9
+ import { a as EventStoreService, c as ReadModelService, d as getClosedIssueIdsForReadSource, f as init_read_model, i as init_issue_lifecycle, s as init_domain_services, t as IssueLifecycle } from "./issue-lifecycle-C4Zj0WmE.js";
10
+ import { d as isTerminalIssueStage, o as init_agents, u as getIssueStageSync } from "./agents-C5rWYhb6.js";
11
+ import { n as ensureSessionContextBriefingFile, r as init_briefing_freshness } from "./briefing-freshness-DHmCSLar.js";
12
+ import { o as getPricingSync, s as init_cost, t as calculateCostSync } from "./cost-Bgcub5kW.js";
13
+ import { $ as operatorInterventionEvent, $n as getAgentDir, An as getProviderExportsForModel, Bn as dismissDevChannelsDialog, Dr as init_pty_supervisor_locate, Er as writePtyToken, F as init_tier_escalation, Fr as getAgentRuntimeState, G as resumeAgent, Gt as assertWorkspaceStackHealthyForSpawn, H as restartAgent, Hr as checkCodexAuthStatus, Ht as BRIDGE_TOKEN_HEADER, Ir as getAgentRuntimeStateSync, Jt as init_spawn_prep, Mn as init_provider_health, Mt as deliverAgentMessage, Nn as validateProviderHealth, Nt as deliverAgentPermissionDecision, On as determineModel, Or as resolvePtySupervisorScriptPath, P as decideEscalation, Pr as waitForReadySignal, Q as init_operator_interventions, Qt as init_staffing, Rr as saveAgentRuntimeState, Rt as setAgentDeliveryMethod, Sr as writeAgentStateJsonSync, Tr as init_pty_token, Un as writeChannelsBridgeMcpConfig, Ur as init_codex_auth, Ut as init_bridge_token, V as recoverAgent, Wt as writeBridgeTokenSync, X as messageAgent, Xt as transitionIssueToInProgress, Yn as clearAgentTroubled, _r as saveAgentStateSync, b as init_agents$1, bn as init_ohmypi_fifo, cn as getAgentRuntimeBaseCommand, dn as getProviderAuthMode, gn as waitForAcpHostReady, gr as saveAgentState, i as listRunningAgents, it as getSessionId, jr as normalizeAgentId, kr as clearReadySignal, nn as resolveStaffing, nt as getLatestSessionId, ot as saveSessionId, pn as init_runtime_command, pt as stopAgent, qn as clearAgentPaused, r as listAgentStates, rr as getAgentStateSync, rt as getLatestSessionIdSync, sn as getAcpLauncherFields, tn as resolveIssueWorkModel, tr as getAgentState, tt as getActivity, ur as markAgentStoppedState, vn as init_pi_fifo, vr as setAgentPaused, xn as ohmypiFifoPaths, xr as wipeAgentStateDirs, yn as piFifoPaths } from "./queries-DHJm7bTd.js";
14
+ import { a as performHandoff, i as checkAllTriggers, s as getAgentHealth, t as getCloisterService } from "./service-Br9rpBNA.js";
15
+ import { o as init_persistent_logger, s as logAgentLifecycleSync } from "./session-history-BUyK29eq.js";
16
+ import { t as init_behavior } from "./behavior-CfIg6pKp.js";
17
+ import { a as init_tracker_config, t as getGitHubConfig } from "./tracker-config-DZ8Zn2nQ.js";
18
+ import { n as init_issue_service_singleton, r as issue_service_singleton_exports } from "./issue-service-singleton-DmCh7EHj.js";
19
+ import { o as getInternalTokenSync, s as init_internal_token } from "./internal-token-DvMTQSOS.js";
20
20
  import { a as PAN_DIRNAME, i as PAN_CONTINUE_FILENAME, p as init_types } from "./types-hraoaQIp.js";
21
- import { a as generateXBriefFilename, o as init_lifecycle } from "./lifecycle-yPd___5E.js";
22
- import { f as readTierOverrides, g as serializeXBriefDocument, h as recordTierPromotion, m as readWorkspacePlanSync, o as init_io, r as findPlan, u as readPlan } from "./io-C9kF1wtJ.js";
23
- import { B as removeFavorite, E as hasOtherActiveConversationOnTmuxSession, F as markConversationEnded, G as setConversationHarness, K as setConversationModel, M as listConversations, P as markConversationActive, Q as updateConversationDeliveryMethod, S as getConversationByName, W as setConversationEffort, g as backfillConversationModel, h as archiveConversation, k as init_conversations, nt as updateLastAttached, rt as updateSpawnError, x as getConversationById, y as createConversation } from "./conversations-6AfUfbwc.js";
24
- import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population-DKZFMbFt.js";
25
- import { a as normalizeModelOverrideSync, i as init_model_validation, n as init_launcher_generator, o as requireModelOverrideSync, r as MODEL_ID_PATTERN, t as generateLauncherScriptSync } from "./launcher-generator-BBWG_SiS.js";
26
- import { a as init_claude_permissions, o as resolvePermissionModeSync, r as getClaudePermissionFlagsStringSync, t as BYPASS_PERMISSION_MODE } from "./claude-permissions-DNWEVV6z.js";
27
- import { E as init_layers, I as workspaceContextFile, k as piGlobalContextFile } from "./assemble-J2ZZ2C15.js";
28
- import { i as prepareHarnessLaunch, r as init_harness_binary } from "./harness-binary-DPUi-Pv8.js";
29
- import { a as getWorkspaceStackHealth, s as init_stack_health } from "./stack-health-DxSdG9cW.js";
30
- import { l as init_dag, o as getDispatchableItems } from "./dag-B1ucnjDU.js";
31
- import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-3lNZkyT4.js";
32
- import { a as loadCloisterConfigSync, r as init_config } from "./config-CKxYiCmX.js";
33
- import { c as isStateMigrated, o as init_state_home } from "./state-home-Cn_Qu8IX.js";
34
- import { a as init_lifecycle_io, c as updatePlanStatus, s as transitionXBriefOnMain } from "./lifecycle-io-BREGpnLk.js";
35
- import { _ as init_codex_conversation_parser, b as parseAcpConversationMessages, c as parseEntireConversation, d as init_pi_conversation_parser, g as parseOhmypiConversationMessages, m as init_ohmypi_conversation_parser, p as parsePiConversationMessages, t as init_conversation_service, v as parseCodexConversationMessages, y as init_acp_conversation_parser } from "./conversation-service-DPJ71F33.js";
36
- import { _ as parseCodexApprovalPrompt, d as getAgentPendingQuestions$1, f as getAgentWorkspace$1, g as normalizeAwaitingInputPrompt, m as detectAwaitingInputForAgent, o as getRuntimeForAgent, p as scanPendingInputsPromise, s as computeAgentEnrichment, u as getAgentJsonlPath$1 } from "./stuck-remediation-DYuPRYYw.js";
37
- import { B as getBook, H as liveOrderIssueLookup, T as resolveLiveFlywheelRunId, w as readFlywheelLaunchMetadata, y as getFlywheelRunDir, z as computeBookProgress } from "./flywheel-DHrgCphM.js";
38
- import { Dt as classifyMemoryPressure, It as getSystemHealthSnapshot, Pt as getResourceConfig } from "./deacon-CU_cAYSR.js";
39
- import { o as stopWorkspaceDocker, r as init_workspace_manager } from "./workspace-manager-CBhNdzE4.js";
40
- import { a as init_jsonl_parser, o as normalizeModelName } from "./jsonl-parser-BXSlHwEh.js";
41
- import { r as init_in_flight_guard, t as createInFlightGuard } from "./in-flight-guard-CAAkqPLu.js";
42
- import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-_WygnyoX.js";
43
- import { basename, delimiter, dirname, join, resolve } from "node:path";
21
+ import { l as resolveWorkspaceRepoRootsSync, o as resolvePrimaryWorkspaceRepoDirSync, r as init_project_repos } from "./project-repos-C0nuoBGv.js";
22
+ import { a as generateXBriefFilename, o as init_lifecycle } from "./lifecycle-CTdOWYMi.js";
23
+ import { f as readTierOverrides, g as serializeXBriefDocument, h as recordTierPromotion, m as readWorkspacePlanSync, o as init_io, r as findPlan, u as readPlan } from "./io-VHvc0Ssp.js";
24
+ import { B as removeFavorite, E as hasOtherActiveConversationOnTmuxSession, F as markConversationEnded, G as setConversationHarness, K as setConversationModel, M as listConversations, P as markConversationActive, Q as updateConversationDeliveryMethod, S as getConversationByName, W as setConversationEffort, g as backfillConversationModel, h as archiveConversation, k as init_conversations, nt as updateLastAttached, rt as updateSpawnError, x as getConversationById, y as createConversation } from "./conversations-BUpYsOZg.js";
25
+ import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population--YUXU999.js";
26
+ import { d as generateLauncherScriptSync, f as init_launcher_generator, g as requireModelOverrideSync, h as normalizeModelOverrideSync, m as init_model_validation, p as MODEL_ID_PATTERN } from "./tmux-dedup-DbN6MGzM.js";
27
+ import { a as init_claude_permissions, o as resolvePermissionModeSync, r as getClaudePermissionFlagsStringSync, t as BYPASS_PERMISSION_MODE } from "./claude-permissions-CN0cSCPp.js";
28
+ import { E as init_layers, I as workspaceContextFile, k as piGlobalContextFile } from "./assemble-DnffNpOo.js";
29
+ import { i as prepareHarnessLaunch, r as init_harness_binary } from "./harness-binary-DqkftwTb.js";
30
+ import { a as getWorkspaceStackHealth, s as init_stack_health } from "./stack-health-DqSqx0zv.js";
31
+ import { l as init_dag, o as getDispatchableItems } from "./dag-ombYYt4s.js";
32
+ import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-CqMqM1Mb.js";
33
+ import { a as loadCloisterConfigSync, r as init_config } from "./config-B2IMcBxx.js";
34
+ import { c as isStateMigrated, o as init_state_home } from "./state-home-BYV7qZTW.js";
35
+ import { a as init_lifecycle_io, c as updatePlanStatus, s as transitionXBriefOnMain } from "./lifecycle-io-D-lGdzK3.js";
36
+ import { _ as init_codex_conversation_parser, b as parseAcpConversationMessages, c as parseEntireConversation, d as init_pi_conversation_parser, g as parseOhmypiConversationMessages, m as init_ohmypi_conversation_parser, p as parsePiConversationMessages, t as init_conversation_service, v as parseCodexConversationMessages, y as init_acp_conversation_parser } from "./conversation-service-5aCnq1zR.js";
37
+ import { _ as normalizeAwaitingInputPrompt, d as getAgentPendingQuestions$1, f as getAgentWorkspace$1, h as detectAwaitingInputForAgent, m as scanPendingInputsPromise, o as getRuntimeForAgent, p as isBlockedOnPendingInput, s as computeAgentEnrichment, u as getAgentJsonlPath$1, v as parseCodexApprovalPrompt } from "./stuck-remediation-mkLC6G_t.js";
38
+ import { B as getBook, H as liveOrderIssueLookup, T as resolveLiveFlywheelRunId, w as readFlywheelLaunchMetadata, y as getFlywheelRunDir, z as computeBookProgress } from "./flywheel-BiT3odRb.js";
39
+ import { Ft as getResourceConfig, Lt as getSystemHealthSnapshot, Ot as classifyMemoryPressure } from "./deacon-hi9KLPLT.js";
40
+ import { o as stopWorkspaceDocker, r as init_workspace_manager } from "./workspace-manager-CwO-Hek7.js";
41
+ import { a as init_jsonl_parser, o as normalizeModelName } from "./jsonl-parser-DJOH_O-w.js";
42
+ import { r as init_in_flight_guard, t as createInFlightGuard } from "./in-flight-guard-Bq3epG58.js";
43
+ import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-CQv00QwK.js";
44
+ import { basename, delimiter, dirname, isAbsolute, join, resolve } from "node:path";
44
45
  import { Cause, Data, Effect, Layer, Option, Schema, Stream } from "effect";
45
46
  import { join as join$1 } from "path";
46
47
  import { homedir, networkInterfaces } from "node:os";
@@ -52,9 +53,9 @@ import { mkdir as mkdir$1, writeFile as writeFile$1 } from "fs/promises";
52
53
  import { exec, execFile, spawn } from "node:child_process";
53
54
  import { promisify } from "node:util";
54
55
  import { createHash as createHash$1, createHmac, randomBytes, randomUUID as randomUUID$1, timingSafeEqual } from "node:crypto";
56
+ import { createInterface } from "node:readline";
55
57
  import { pathToFileURL } from "node:url";
56
58
  import { request } from "node:http";
57
- import { createInterface } from "node:readline";
58
59
  import * as Result$1 from "effect/Result";
59
60
  //#region http-helpers.ts
60
61
  init_paths();
@@ -86,6 +87,7 @@ init_projects();
86
87
  init_providers();
87
88
  init_harness_policy();
88
89
  init_tier_table();
90
+ init_js_yaml();
89
91
  init_config_yaml();
90
92
  init_child_env();
91
93
  init_tmux();
@@ -101,6 +103,7 @@ init_cost();
101
103
  init_behavior();
102
104
  init_persistent_logger();
103
105
  init_tracker_config();
106
+ init_project_repos();
104
107
  init_lifecycle();
105
108
  init_review_status();
106
109
  init_io();
@@ -218,6 +221,27 @@ function addTrustedOrigin(origins, raw) {
218
221
  const normalized = normalizeOrigin(raw.trim());
219
222
  if (normalized) origins.add(normalized);
220
223
  }
224
+ /**
225
+ * Last-resort origin config for launches that carry no origin env at all
226
+ * (manual `node dist/...`, ad-hoc re-exec). `pan up` builds its launch env from
227
+ * this same config.yaml, so reading it here keeps every launch path trusting the
228
+ * same Traefik domain instead of 403ing /ws/* into a "Reconnecting" loop.
229
+ */
230
+ function readTraefikConfigFromYaml() {
231
+ try {
232
+ const configPath = join(process.env["OVERDECK_HOME"] || join(homedir(), ".overdeck"), "config.yaml");
233
+ if (!existsSync(configPath)) return null;
234
+ const traefik = jsYaml.load(readFileSync(configPath, "utf8"))?.traefik;
235
+ if (!traefik || typeof traefik !== "object") return null;
236
+ if (typeof traefik.domain !== "string" || traefik.domain.trim() === "") return null;
237
+ return {
238
+ enabled: traefik.enabled === true,
239
+ domain: traefik.domain.trim()
240
+ };
241
+ } catch {
242
+ return null;
243
+ }
244
+ }
221
245
  function getTrustedOrigins() {
222
246
  if (cachedTrustedOrigins !== void 0) return cachedTrustedOrigins;
223
247
  const port = parseInt(process.env["API_PORT"] ?? process.env["PORT"] ?? "3011", 10);
@@ -232,6 +256,10 @@ function getTrustedOrigins() {
232
256
  for (const origin of trustedOrigins?.split(",") ?? []) addTrustedOrigin(origins, origin);
233
257
  const traefikDomain = process.env["OVERDECK_TRAEFIK_DOMAIN"] ?? process.env["TRAEFIK_DOMAIN"];
234
258
  if (process.env["OVERDECK_TRAEFIK_ENABLED"] === "1" && traefikDomain) addTrustedOrigin(origins, `https://${traefikDomain}`);
259
+ if (!(process.env["OVERDECK_TRAEFIK_ENABLED"] !== void 0 || traefikDomain !== void 0 || process.env["OVERDECK_TRUSTED_ORIGINS"] !== void 0)) {
260
+ const fromYaml = readTraefikConfigFromYaml();
261
+ if (fromYaml?.enabled) addTrustedOrigin(origins, `https://${fromYaml.domain}`);
262
+ }
235
263
  if (process.env["NODE_ENV"] === "development") {
236
264
  addTrustedOrigin(origins, "http://localhost:3000");
237
265
  addTrustedOrigin(origins, "http://127.0.0.1:3000");
@@ -799,7 +827,7 @@ async function resolveCodexRolloutPath(agentId, opts = {}) {
799
827
  const agentDir = join(opts.agentsDirOverride ?? join(getOverdeckHome(), "agents"), agentId);
800
828
  const codexHome = join(agentDir, "codex-home");
801
829
  if (!await pathExists$1(codexHome)) return null;
802
- const { findRolloutPath, findLatestRollout } = await import("./codex-GcHuUF-k.js");
830
+ const { findRolloutPath, findLatestRollout } = await import("./codex-BdEsUFWh.js");
803
831
  const threadId = (await readOptional(join(agentDir, "codex-thread-id")))?.trim();
804
832
  if (threadId) {
805
833
  const rollout = findRolloutPath(codexHome, threadId);
@@ -1185,42 +1213,130 @@ async function resolveAgentGitInfo(workspacePath, expectedBranch) {
1185
1213
  };
1186
1214
  }
1187
1215
  //#endregion
1188
- //#region routes/agents/shared.ts
1216
+ //#region ../../lib/composer-commands/executors.ts
1217
+ const CAPTURED_COMMAND_MAX_OUTPUT_BYTES = 64 * 1024;
1218
+ const TRUNCATION_MESSAGE = "\n\nOutput was truncated after 65,536 bytes.";
1219
+ function runCapturedCommand(argv, dependencies = {}) {
1220
+ const command = `/pan ${argv.join(" ")}`;
1221
+ const spawnCommand = dependencies.spawnPanCli ?? spawnPanCli;
1222
+ const timeoutMs = dependencies.timeoutMs ?? 3e4;
1223
+ const child = spawnCommand(argv, { stdio: [
1224
+ "ignore",
1225
+ "pipe",
1226
+ "pipe"
1227
+ ] });
1228
+ return new Promise((resolve) => {
1229
+ const chunks = [];
1230
+ let bufferedBytes = 0;
1231
+ let settled = false;
1232
+ let timeout;
1233
+ let truncated = false;
1234
+ const appendOutput = (data) => {
1235
+ if (truncated) return;
1236
+ const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
1237
+ const remaining = CAPTURED_COMMAND_MAX_OUTPUT_BYTES - Buffer.byteLength(TRUNCATION_MESSAGE) - bufferedBytes;
1238
+ if (buffer.length <= remaining) {
1239
+ chunks.push(buffer);
1240
+ bufferedBytes += buffer.length;
1241
+ return;
1242
+ }
1243
+ if (remaining > 0) {
1244
+ chunks.push(buffer.subarray(0, remaining));
1245
+ bufferedBytes += remaining;
1246
+ }
1247
+ truncated = true;
1248
+ };
1249
+ const output = () => {
1250
+ const captured = Buffer.concat(chunks, bufferedBytes).toString("utf8");
1251
+ return truncated ? `${captured}${TRUNCATION_MESSAGE}` : captured;
1252
+ };
1253
+ const finish = (result) => {
1254
+ if (settled) return;
1255
+ settled = true;
1256
+ if (timeout !== void 0) clearTimeout(timeout);
1257
+ resolve(result);
1258
+ };
1259
+ child.stdout?.on("data", appendOutput);
1260
+ child.stderr?.on("data", appendOutput);
1261
+ child.once("error", (error) => {
1262
+ finish({
1263
+ kind: "captured",
1264
+ status: "failed",
1265
+ command,
1266
+ output: `Command ${command} could not start: ${error.message}`,
1267
+ truncated: false
1268
+ });
1269
+ });
1270
+ child.once("close", (code) => {
1271
+ const captured = output();
1272
+ finish({
1273
+ kind: "captured",
1274
+ status: code === 0 ? "completed" : "failed",
1275
+ command,
1276
+ output: captured || `Command ${command} ${code === 0 ? "completed without output." : `failed with exit code ${code ?? "unknown"}.`}`,
1277
+ truncated
1278
+ });
1279
+ });
1280
+ timeout = setTimeout(() => {
1281
+ stopChild(child);
1282
+ finish({
1283
+ kind: "captured",
1284
+ status: "failed",
1285
+ command,
1286
+ output: `Command ${command} timed out after ${Math.round(timeoutMs / 1e3)} seconds and was stopped.`,
1287
+ truncated: false
1288
+ });
1289
+ }, timeoutMs);
1290
+ });
1291
+ }
1292
+ function stopChild(child) {
1293
+ child.kill("SIGTERM");
1294
+ }
1295
+ //#endregion
1296
+ //#region ../../lib/composer-commands/detached.ts
1189
1297
  init_paths();
1190
- init_agents$1();
1191
- init_tmux();
1192
- const execAsync$2 = promisify(exec);
1193
- const execFileAsync$2 = promisify(execFile);
1194
- function buildPanStartArgs(input) {
1195
- return [
1196
- "start",
1197
- input.issueId,
1198
- "--local",
1199
- "--model",
1200
- input.model,
1201
- ...input.harness ? ["--harness", input.harness] : [],
1202
- ...input.allowHost ? ["--host", "--yes"] : [],
1203
- ...input.offBook ? ["--off-book"] : []
1204
- ];
1298
+ const DETACHED_TRUNCATION_MESSAGE = "\n\nOutput was truncated after 65,536 bytes.";
1299
+ function resolveAgentDirectory(overdeckHome, agentId) {
1300
+ if (agentId.length === 0 || agentId === "." || agentId === ".." || agentId.includes("/") || agentId.includes("\\") || isAbsolute(agentId)) throw new Error("Agent ID must be a single filesystem-safe path segment.");
1301
+ return join(resolve(overdeckHome, "agents"), agentId);
1302
+ }
1303
+ async function readBoundedSpawnOutput(spawnLogPath, startOffset) {
1304
+ const maximumPrefixBytes = CAPTURED_COMMAND_MAX_OUTPUT_BYTES - Buffer.byteLength(DETACHED_TRUNCATION_MESSAGE);
1305
+ const handle = await open(spawnLogPath, "r");
1306
+ try {
1307
+ const stats = await handle.stat();
1308
+ const outputBytes = Math.max(0, stats.size - startOffset);
1309
+ if (outputBytes === 0) return "";
1310
+ const bytesToRead = Math.min(outputBytes, maximumPrefixBytes);
1311
+ const buffer = Buffer.alloc(bytesToRead);
1312
+ const { bytesRead } = await handle.read(buffer, 0, bytesToRead, startOffset);
1313
+ const output = buffer.subarray(0, bytesRead).toString("utf8");
1314
+ return outputBytes > maximumPrefixBytes ? `${output}${DETACHED_TRUNCATION_MESSAGE}` : output;
1315
+ } finally {
1316
+ await handle.close().catch(() => void 0);
1317
+ }
1205
1318
  }
1206
- /**
1207
- * PAN-1985: detached-spawn helper for `pan <args>`, shared between the
1208
- * standard work-spawn route and the restart-fresh route. Opens a spawn.log
1209
- * inside the agent dir (creating the dir if missing — the dir may have been
1210
- * just wiped), spawns `pan` detached with stdio to that log, and resolves
1211
- * with an activity id once the child closes with code 0. Throws an Error
1212
- * with the log contents attached on non-zero exit.
1213
- */
1214
- async function spawnPanCommandDetached(input) {
1319
+ async function appendAgentLifecycleLog(agentId, event, details = {}, overdeckHome = getOverdeckHome()) {
1320
+ const agentDir = resolveAgentDirectory(overdeckHome, agentId);
1321
+ await mkdir(agentDir, { recursive: true });
1322
+ const logLine = JSON.stringify({
1323
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
1324
+ event,
1325
+ ...details
1326
+ });
1327
+ await appendFile(join(agentDir, "lifecycle.log"), `${logLine}\n`);
1328
+ }
1329
+ async function launchPanCommandDetached(input, dependencies = {}) {
1215
1330
  const { agentSessionName, issueId, role, workspacePath, args } = input;
1216
1331
  const cwd = input.cwd ?? workspacePath;
1217
- const activityId = `activity-${Date.now()}`;
1218
- const agentDir = join(homedir(), ".overdeck", "agents", agentSessionName);
1332
+ const overdeckHome = dependencies.overdeckHome ?? getOverdeckHome();
1333
+ const activityId = input.activityId ?? `activity-${(dependencies.now ?? Date.now)()}`;
1334
+ const agentDir = resolveAgentDirectory(overdeckHome, agentSessionName);
1219
1335
  await mkdir(agentDir, { recursive: true });
1220
1336
  const spawnLogPath = join(agentDir, "spawn.log");
1221
1337
  const spawnLogHandle = await open(spawnLogPath, "a");
1222
- const invocation = panCliInvocation(args);
1223
- const child = spawn(invocation.command, invocation.args, {
1338
+ const spawnLogStart = (await spawnLogHandle.stat()).size;
1339
+ const child = (dependencies.spawnPanCli ?? spawnPanCli)(args, {
1224
1340
  cwd,
1225
1341
  detached: true,
1226
1342
  stdio: [
@@ -1229,67 +1345,200 @@ async function spawnPanCommandDetached(input) {
1229
1345
  spawnLogHandle.fd
1230
1346
  ]
1231
1347
  });
1348
+ let spawned = false;
1349
+ let settleSpawn;
1350
+ let rejectSpawn;
1351
+ const spawnPromise = new Promise((resolve, reject) => {
1352
+ settleSpawn = resolve;
1353
+ rejectSpawn = reject;
1354
+ });
1355
+ const completion = commandCompletion(child, {
1356
+ agentSessionName,
1357
+ issueId,
1358
+ role,
1359
+ workspacePath,
1360
+ activityId,
1361
+ args,
1362
+ cwd,
1363
+ spawnLogPath,
1364
+ spawnLogStart,
1365
+ spawnLogHandle,
1366
+ overdeckHome,
1367
+ onSpawn: () => {
1368
+ spawned = true;
1369
+ settleSpawn?.();
1370
+ },
1371
+ onError: (error) => {
1372
+ if (!spawned) rejectSpawn?.(error);
1373
+ }
1374
+ });
1375
+ completion.catch(() => void 0);
1376
+ await spawnPromise;
1377
+ child.unref();
1378
+ return {
1379
+ activityId,
1380
+ spawnLogPath,
1381
+ spawnLogStart,
1382
+ completion
1383
+ };
1384
+ }
1385
+ function commandCompletion(child, context) {
1232
1386
  child.once("spawn", () => {
1233
- appendAgentLifecycleLog(agentSessionName, "agent.work_spawn_process_spawned", {
1234
- issueId,
1235
- role,
1236
- workspacePath,
1237
- activityId,
1387
+ appendAgentLifecycleLog(context.agentSessionName, "agent.work_spawn_process_spawned", {
1388
+ issueId: context.issueId,
1389
+ role: context.role,
1390
+ workspacePath: context.workspacePath,
1391
+ activityId: context.activityId,
1238
1392
  pid: child.pid,
1239
- args,
1240
- cwd,
1241
- spawnLogPath
1242
- }).catch(() => void 0);
1393
+ args: context.args,
1394
+ cwd: context.cwd,
1395
+ spawnLogPath: context.spawnLogPath
1396
+ }, context.overdeckHome).catch(() => void 0).finally(context.onSpawn);
1243
1397
  });
1244
- try {
1245
- const result = await new Promise((resolve, reject) => {
1246
- child.once("error", (error) => {
1247
- appendAgentLifecycleLog(agentSessionName, "agent.work_spawn_process_error", {
1248
- issueId,
1249
- role,
1250
- workspacePath,
1251
- activityId,
1398
+ return new Promise((resolve, reject) => {
1399
+ let settled = false;
1400
+ const finish = async (error) => {
1401
+ if (settled) return;
1402
+ settled = true;
1403
+ await context.spawnLogHandle.close().catch(() => void 0);
1404
+ if (error) reject(error);
1405
+ else resolve();
1406
+ };
1407
+ child.once("error", (error) => {
1408
+ (async () => {
1409
+ await appendAgentLifecycleLog(context.agentSessionName, "agent.work_spawn_process_error", {
1410
+ issueId: context.issueId,
1411
+ role: context.role,
1412
+ workspacePath: context.workspacePath,
1413
+ activityId: context.activityId,
1252
1414
  error: error.message,
1253
- args,
1254
- cwd,
1255
- spawnLogPath
1256
- }).catch(() => void 0);
1257
- reject(error);
1258
- });
1259
- child.once("close", (code, signal) => {
1260
- appendAgentLifecycleLog(agentSessionName, "agent.work_spawn_process_closed", {
1261
- issueId,
1262
- role,
1263
- workspacePath,
1264
- activityId,
1415
+ args: context.args,
1416
+ cwd: context.cwd,
1417
+ spawnLogPath: context.spawnLogPath
1418
+ }, context.overdeckHome).catch(() => void 0);
1419
+ context.onError(error);
1420
+ await finish(error);
1421
+ })();
1422
+ });
1423
+ child.once("close", (code, signal) => {
1424
+ (async () => {
1425
+ await appendAgentLifecycleLog(context.agentSessionName, "agent.work_spawn_process_closed", {
1426
+ issueId: context.issueId,
1427
+ role: context.role,
1428
+ workspacePath: context.workspacePath,
1429
+ activityId: context.activityId,
1265
1430
  code,
1266
1431
  signal,
1267
- args,
1268
- cwd,
1269
- spawnLogPath
1270
- }).catch(() => void 0);
1271
- resolve({
1432
+ args: context.args,
1433
+ cwd: context.cwd,
1434
+ spawnLogPath: context.spawnLogPath
1435
+ }, context.overdeckHome).catch(() => void 0);
1436
+ if (code === 0) {
1437
+ await finish();
1438
+ return;
1439
+ }
1440
+ const output = await readBoundedSpawnOutput(context.spawnLogPath, context.spawnLogStart).catch(() => "");
1441
+ const error = new Error(output.trim() || `pan ${context.args.join(" ")} exited with code ${code ?? "null"}`);
1442
+ Object.assign(error, {
1443
+ activityId: context.activityId,
1444
+ spawnLogPath: context.spawnLogPath,
1272
1445
  code,
1273
- signal
1446
+ signal,
1447
+ output
1274
1448
  });
1275
- });
1449
+ await finish(error);
1450
+ })();
1276
1451
  });
1277
- if (result.code !== 0) {
1278
- const output = await readFile(spawnLogPath, "utf-8").catch(() => "");
1279
- const error = new Error(output.trim() || `pan ${args.join(" ")} exited with code ${result.code ?? "null"}`);
1280
- Object.assign(error, {
1281
- activityId,
1282
- spawnLogPath,
1283
- code: result.code,
1284
- signal: result.signal,
1285
- output
1286
- });
1287
- throw error;
1288
- }
1289
- return activityId;
1290
- } finally {
1291
- await spawnLogHandle.close();
1452
+ });
1453
+ }
1454
+ async function runDetachedCommand(argv, dependencies = {}) {
1455
+ const issueId = argv[1] ?? "";
1456
+ const parsedIssueId = parseIssueIdSync(issueId);
1457
+ if (!parsedIssueId) return {
1458
+ kind: "terminal-only",
1459
+ status: "rejected",
1460
+ message: `/pan ${argv[0] ?? "command"} requires a canonical issue ID such as PAN-1525.`
1461
+ };
1462
+ const role = argv[0] === "plan" ? "plan" : "work";
1463
+ const agentSessionName = `${role === "plan" ? "planning" : "agent"}-${parsedIssueId.normalized}`;
1464
+ const command = `/pan ${argv.join(" ")}`;
1465
+ const activityId = `activity-${(dependencies.now ?? Date.now)()}`;
1466
+ const emitActivity = dependencies.emitActivity ?? emitActivityEntryDurable;
1467
+ const source = role === "plan" ? "planning-agent" : "work-agent";
1468
+ const emitTransition = (status, level, message, output) => emitActivity({
1469
+ id: activityId,
1470
+ source,
1471
+ level,
1472
+ status,
1473
+ command,
1474
+ message,
1475
+ details: output,
1476
+ output,
1477
+ issueId
1478
+ });
1479
+ await emitTransition("accepted", "info", `Accepted ${command} for ${issueId} as activity ${activityId}.`);
1480
+ let launch;
1481
+ try {
1482
+ launch = await launchPanCommandDetached({
1483
+ agentSessionName,
1484
+ issueId,
1485
+ role,
1486
+ workspacePath: process.cwd(),
1487
+ args: argv,
1488
+ activityId
1489
+ }, dependencies);
1490
+ } catch (error) {
1491
+ const output = error instanceof Error ? error.message : String(error);
1492
+ await emitTransition("failed", "error", `Activity ${activityId} failed to start ${command} for ${issueId}.`, output).catch(() => void 0);
1493
+ throw error;
1292
1494
  }
1495
+ await emitTransition("running", "info", `Activity ${activityId} is running ${command} for ${issueId}.`).catch(() => void 0);
1496
+ launch.completion.then(async () => {
1497
+ const output = await readBoundedSpawnOutput(launch.spawnLogPath, launch.spawnLogStart).catch(() => "");
1498
+ await emitTransition("completed", "success", `Activity ${activityId} completed ${command} for ${issueId}.`, output || `Command ${command} completed without output.`);
1499
+ }, async (error) => {
1500
+ const activityError = error;
1501
+ const output = activityError.output?.trim() || activityError.message;
1502
+ await emitTransition("failed", "error", `Activity ${activityId} failed ${command} for ${issueId}.`, output);
1503
+ }).catch(() => void 0);
1504
+ return {
1505
+ kind: "activity",
1506
+ status: "accepted",
1507
+ command,
1508
+ activityId: launch.activityId,
1509
+ message: `Started ${command} for ${issueId}. Watch activity ${launch.activityId} or the ${issueId} issue view for progress.`
1510
+ };
1511
+ }
1512
+ //#endregion
1513
+ //#region routes/agents/shared.ts
1514
+ init_paths();
1515
+ init_agents$1();
1516
+ init_activity_logger();
1517
+ init_tmux();
1518
+ const execAsync$2 = promisify(exec);
1519
+ const execFileAsync$2 = promisify(execFile);
1520
+ function buildPanStartArgs(input) {
1521
+ return [
1522
+ "start",
1523
+ input.issueId,
1524
+ "--local",
1525
+ "--model",
1526
+ input.model,
1527
+ ...input.harness ? ["--harness", input.harness] : [],
1528
+ ...input.allowHost ? ["--host", "--yes"] : [],
1529
+ ...input.offBook ? ["--off-book"] : []
1530
+ ];
1531
+ }
1532
+ /**
1533
+ * PAN-1985: detached-spawn helper for `pan <args>`, shared between the
1534
+ * standard work-spawn route and the restart-fresh route. The neutral launcher
1535
+ * owns process/log lifecycle; this route-compatible wrapper preserves the
1536
+ * original behavior by waiting for a successful child exit.
1537
+ */
1538
+ async function spawnPanCommandDetached(input, dependencies = {}) {
1539
+ const launch = await launchPanCommandDetached(input, dependencies);
1540
+ await launch.completion;
1541
+ return launch.activityId;
1293
1542
  }
1294
1543
  function emitStartAgentPhase(issueId, phase, status, reason, details = {}) {
1295
1544
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -1344,16 +1593,6 @@ async function validateAgentRuntimeEventAuth(request) {
1344
1593
  }, { status: 403 })
1345
1594
  };
1346
1595
  }
1347
- async function appendAgentLifecycleLog(agentId, event, details = {}) {
1348
- const agentDir = join(homedir(), ".overdeck", "agents", agentId);
1349
- await mkdir(agentDir, { recursive: true });
1350
- const logLine = JSON.stringify({
1351
- ts: (/* @__PURE__ */ new Date()).toISOString(),
1352
- event,
1353
- ...details
1354
- });
1355
- await appendFile(join(agentDir, "lifecycle.log"), logLine + "\n");
1356
- }
1357
1596
  function updateRegistryForAgentStart(issueId, workspacePath, agentId) {
1358
1597
  recordFeatureRegistryLifecycle({
1359
1598
  issueId,
@@ -1537,13 +1776,14 @@ async function getWorkspaceLocation(issueId) {
1537
1776
  }
1538
1777
  } catch {}
1539
1778
  }
1540
- async function getGitStatusAsync(workspacePath) {
1779
+ async function getGitStatusAsync(issueId, workspacePath) {
1541
1780
  try {
1542
1781
  if (!existsSync(workspacePath)) return null;
1782
+ const repoDir = resolvePrimaryWorkspaceRepoDirSync(issueId, workspacePath);
1543
1783
  const [branchResult, uncommittedResult, commitResult] = await Promise.all([
1544
- execAsync$2("git rev-parse --abbrev-ref HEAD 2>/dev/null || echo \"\"", { cwd: workspacePath }),
1545
- execAsync$2("git status --porcelain 2>/dev/null | wc -l", { cwd: workspacePath }),
1546
- execAsync$2("git log -1 --pretty=format:\"%s\" 2>/dev/null || echo \"\"", { cwd: workspacePath })
1784
+ execAsync$2("git rev-parse --abbrev-ref HEAD 2>/dev/null || echo \"\"", { cwd: repoDir }),
1785
+ execAsync$2("git status --porcelain 2>/dev/null | wc -l", { cwd: repoDir }),
1786
+ execAsync$2("git log -1 --pretty=format:\"%s\" 2>/dev/null || echo \"\"", { cwd: repoDir })
1547
1787
  ]);
1548
1788
  const branch = branchResult.stdout.trim();
1549
1789
  const uncommitted = uncommittedResult.stdout.trim();
@@ -1700,6 +1940,22 @@ const getAgentPendingQuestions = getAgentPendingQuestions$1;
1700
1940
  //#region routes/agents/listing.ts
1701
1941
  init_agents$1();
1702
1942
  init_tmux();
1943
+ /**
1944
+ * PAN-3070 — the health status a live agent row reports.
1945
+ *
1946
+ * A live tmux session used to mean `healthy` unconditionally, so an agent frozen
1947
+ * for hours on an unanswered tool-permission prompt was reported
1948
+ * `status: healthy` / `resolution: working` while the Decisions surface
1949
+ * simultaneously showed it as needing the operator. Two surfaces answering "is
1950
+ * this agent stuck?" from different evidence, and this one stale.
1951
+ *
1952
+ * `warning` is the value `src/lib/health.ts` already reports for an agent
1953
+ * waiting on a human, and it stays inside the fleet-view status set, so a
1954
+ * blocked agent is flagged without disappearing from any existing list.
1955
+ */
1956
+ function liveAgentHealthStatus(enrichment) {
1957
+ return isBlockedOnPendingInput(enrichment) ? "warning" : "healthy";
1958
+ }
1703
1959
  const getAgentsRoute = HttpRouter.add("GET", "/api/agents", httpHandler(Effect.gen(function* () {
1704
1960
  const now = Date.now();
1705
1961
  if (agentsCache.data && now - agentsCache.timestamp < 5e3) return jsonResponse(agentsCache.data);
@@ -1833,7 +2089,7 @@ const getAgentsRoute = HttpRouter.add("GET", "/api/agents", httpHandler(Effect.g
1833
2089
  const enrichment = await Effect.runPromise(computeAgentEnrichment(name, startedAt, hasActiveSpecialist));
1834
2090
  const workspaceLocation = isRemote ? "remote" : await getWorkspaceLocation(issueId);
1835
2091
  const workspace = isRemote && remoteState.vmName ? `/workspace (${String(remoteState.vmName)})` : state.workspace || null;
1836
- const gitStatus = workspace && !isRemote ? await getGitStatusAsync(workspace) : null;
2092
+ const gitStatus = workspace && !isRemote ? await getGitStatusAsync(issueId, workspace) : null;
1837
2093
  let contextPercent = null;
1838
2094
  let initialContextPercent = null;
1839
2095
  const agentCtxDir = join(homedir(), ".overdeck", "agents", name);
@@ -1843,12 +2099,13 @@ const getAgentsRoute = HttpRouter.add("GET", "/api/agents", httpHandler(Effect.g
1843
2099
  const initCtxFile = join(agentCtxDir, "initial-context-pct");
1844
2100
  initialContextPercent = parseInt((await readFile(initCtxFile, "utf-8").catch(() => "")).trim(), 10) || null;
1845
2101
  } catch {}
2102
+ const blockedOnPendingInput = isBlockedOnPendingInput(enrichment);
1846
2103
  return {
1847
2104
  id: name,
1848
2105
  issueId,
1849
2106
  runtime: state.harness ?? "claude-code",
1850
2107
  model: state.model || (isPlanning ? "opus" : "sonnet"),
1851
- status: "healthy",
2108
+ status: liveAgentHealthStatus(enrichment),
1852
2109
  startedAt,
1853
2110
  ...buildAgentGateFailureSnapshot(state),
1854
2111
  killCount: health.killCount || 0,
@@ -1865,7 +2122,7 @@ const getAgentsRoute = HttpRouter.add("GET", "/api/agents", httpHandler(Effect.g
1865
2122
  pendingInputCount: enrichment.pendingInputCount,
1866
2123
  pendingInputKinds: enrichment.pendingInputKinds,
1867
2124
  pendingAskUserQuestion: enrichment.pendingAskUserQuestion,
1868
- resolution: runtimeData?.resolution || enrichment.resolution || "working",
2125
+ resolution: blockedOnPendingInput ? "needs_input" : runtimeData?.resolution || enrichment.resolution || "working",
1869
2126
  resolutionCount: runtimeData?.resolutionCount || enrichment.resolutionCount || 0,
1870
2127
  contextPercent,
1871
2128
  initialContextPercent,
@@ -1951,7 +2208,7 @@ const getAgentOutputRoute = HttpRouter.add("GET", "/api/agents/:id/output", http
1951
2208
  } catch {}
1952
2209
  let stdout;
1953
2210
  if (isRemote && vmName) {
1954
- const { getRemoteAgentOutput } = await import("./remote-agents-CA3Ihlxj.js");
2211
+ const { getRemoteAgentOutput } = await import("./remote-agents-C1bssi41.js");
1955
2212
  stdout = await getRemoteAgentOutput(id, vmName, parseInt(String(lines), 10) || 100);
1956
2213
  } else stdout = await Effect.runPromise(capturePane(id, parseInt(String(lines), 10) || 100));
1957
2214
  if (!stdout || stdout.trim() === "" || stdout.trim() === "Session not found") {
@@ -2104,6 +2361,352 @@ const getAgentTimelineRoute = HttpRouter.add("GET", "/api/agents/:id/timeline",
2104
2361
  return jsonResponse({ timeline: events.slice(0, limit) });
2105
2362
  })));
2106
2363
  //#endregion
2364
+ //#region ../../lib/composer-commands/confirmations.ts
2365
+ const COMPOSER_CONFIRMATION_TTL_MS = 300 * 1e3;
2366
+ function composerCommandConfirmationFromBody(body) {
2367
+ if (!("confirmationNonce" in body) && !("confirmationText" in body)) return void 0;
2368
+ return {
2369
+ nonce: body["confirmationNonce"],
2370
+ typedText: body["confirmationText"]
2371
+ };
2372
+ }
2373
+ var ComposerCommandConfirmationError = class extends Error {
2374
+ code = "invalid-confirmation";
2375
+ constructor(message) {
2376
+ super(message);
2377
+ this.name = "ComposerCommandConfirmationError";
2378
+ }
2379
+ };
2380
+ function createComposerConfirmationStore(dependencies = {}) {
2381
+ const entries = /* @__PURE__ */ new Map();
2382
+ const now = dependencies.now ?? Date.now;
2383
+ const createNonce = dependencies.createNonce ?? (() => randomBytes(24).toString("base64url"));
2384
+ function pruneExpired() {
2385
+ const currentTime = now();
2386
+ for (const [nonce, entry] of entries) if (entry.expiresAt <= currentTime) entries.delete(nonce);
2387
+ }
2388
+ return {
2389
+ issue({ target, argv, policy, display }) {
2390
+ if (policy.safety === "destructive" && !policy.typedConfirmation) throw new Error(`Destructive composer policy for ${display} must define typedConfirmation.`);
2391
+ pruneExpired();
2392
+ const nonce = createNonce();
2393
+ entries.set(nonce, {
2394
+ targetKind: target.kind,
2395
+ targetId: target.id,
2396
+ argv: [...argv],
2397
+ safety: policy.safety,
2398
+ typedText: policy.typedConfirmation,
2399
+ expiresAt: now() + COMPOSER_CONFIRMATION_TTL_MS
2400
+ });
2401
+ return {
2402
+ kind: "confirmation",
2403
+ status: "confirmation_required",
2404
+ nonce,
2405
+ consequence: policy.confirmationText ?? `Running ${display} requires confirmation before Overdeck continues.`,
2406
+ ...policy.typedConfirmation ? { typedText: policy.typedConfirmation } : {}
2407
+ };
2408
+ },
2409
+ consume({ target, argv, policy, confirmation }) {
2410
+ if (typeof confirmation.nonce !== "string") throw new ComposerCommandConfirmationError("A valid confirmation nonce is required before this command can run.");
2411
+ const entry = entries.get(confirmation.nonce);
2412
+ entries.delete(confirmation.nonce);
2413
+ if (!entry) throw new ComposerCommandConfirmationError("This command confirmation is missing, invalid, or has already been used. Request a new confirmation and try again.");
2414
+ if (entry.expiresAt <= now()) throw new ComposerCommandConfirmationError("This command confirmation has expired. Request a new confirmation and try again.");
2415
+ if (entry.targetKind !== target.kind || entry.targetId !== target.id || entry.safety !== policy.safety || !sameArgv(entry.argv, argv)) throw new ComposerCommandConfirmationError("This command confirmation does not match the current target or command. Request a new confirmation and try again.");
2416
+ if (policy.safety === "destructive" && (typeof confirmation.typedText !== "string" || confirmation.typedText !== entry.typedText)) throw new ComposerCommandConfirmationError(`Type "${entry.typedText ?? ""}" exactly to confirm this destructive command.`);
2417
+ }
2418
+ };
2419
+ }
2420
+ function sameArgv(left, right) {
2421
+ return left.length === right.length && left.every((value, index) => value === right[index]);
2422
+ }
2423
+ const composerConfirmationStore = createComposerConfirmationStore();
2424
+ //#endregion
2425
+ //#region ../../lib/composer-commands/parser.ts
2426
+ var ComposerCommandParseError = class extends Error {
2427
+ constructor(code, message, token, expected) {
2428
+ super(message);
2429
+ this.code = code;
2430
+ this.token = token;
2431
+ this.expected = expected;
2432
+ this.name = "ComposerCommandParseError";
2433
+ }
2434
+ };
2435
+ const FORBIDDEN_TOKEN = /\$\(|[;|&<>`]/;
2436
+ function expectedSyntax(entry) {
2437
+ const args = entry.args.map((argument) => {
2438
+ const name = argument.variadic ? `${argument.name}...` : argument.name;
2439
+ return argument.required ? `<${name}>` : `[${name}]`;
2440
+ });
2441
+ const options = entry.options.length > 0 ? ["[options]"] : [];
2442
+ return [
2443
+ entry.display,
2444
+ ...args,
2445
+ ...options
2446
+ ].join(" ");
2447
+ }
2448
+ function tokenize(input) {
2449
+ const tokens = [];
2450
+ let current = "";
2451
+ let quote = null;
2452
+ let escaped = false;
2453
+ const pushCurrent = () => {
2454
+ if (current.length === 0) return;
2455
+ tokens.push(current);
2456
+ current = "";
2457
+ };
2458
+ for (const character of input) {
2459
+ if (escaped) {
2460
+ current += character;
2461
+ escaped = false;
2462
+ continue;
2463
+ }
2464
+ if (character === "\\") {
2465
+ escaped = true;
2466
+ continue;
2467
+ }
2468
+ if (quote !== null) {
2469
+ if (character === quote) quote = null;
2470
+ else current += character;
2471
+ continue;
2472
+ }
2473
+ if (character === "\"" || character === "'") {
2474
+ quote = character;
2475
+ continue;
2476
+ }
2477
+ if (/\s/.test(character)) {
2478
+ pushCurrent();
2479
+ continue;
2480
+ }
2481
+ current += character;
2482
+ }
2483
+ if (escaped) current += "\\";
2484
+ if (quote !== null) throw new ComposerCommandParseError("missing-argument", `Unclosed ${quote} quote. Close the quoted value before submitting the command.`, quote, `a closing ${quote}`);
2485
+ pushCurrent();
2486
+ return tokens;
2487
+ }
2488
+ function aliasesForPath(entry) {
2489
+ let candidates = [[]];
2490
+ for (let index = 0; index < entry.path.length; index += 1) {
2491
+ const prefix = entry.path.slice(0, index + 1);
2492
+ const prefixEntry = COMPOSER_COMMAND_MANIFEST.find((candidate) => candidate.path.length === prefix.length && candidate.path.every((part, partIndex) => part === prefix[partIndex]));
2493
+ const names = [entry.path[index], ...prefixEntry?.aliases ?? []];
2494
+ candidates = candidates.flatMap((candidate) => names.map((name) => [...candidate, name]));
2495
+ }
2496
+ return candidates;
2497
+ }
2498
+ function resolveEntry(tokens) {
2499
+ const match = COMPOSER_COMMAND_MANIFEST.flatMap((entry) => aliasesForPath(entry).filter((path) => path.every((part, index) => tokens[index] === part)).map((path) => ({
2500
+ entry,
2501
+ pathLength: path.length
2502
+ }))).sort((left, right) => right.pathLength - left.pathLength)[0];
2503
+ if (match) return match;
2504
+ const token = tokens[0] ?? "";
2505
+ throw new ComposerCommandParseError("unknown-command", token ? `Unknown Overdeck command "${token}". Type /pan to list available commands.` : "Missing an Overdeck command after /pan. Type /pan to list available commands.", token, "/pan <command>");
2506
+ }
2507
+ function optionDefinitions(entry) {
2508
+ const definitions = /* @__PURE__ */ new Map();
2509
+ for (const option of entry.options) {
2510
+ const flags = option.flags.split(/[ ,|]+/).filter((part) => part.startsWith("-"));
2511
+ const canonicalFlag = flags.find((flag) => flag.startsWith("--")) ?? flags[0];
2512
+ for (const flag of flags) definitions.set(flag, {
2513
+ option,
2514
+ canonicalFlag
2515
+ });
2516
+ }
2517
+ return definitions;
2518
+ }
2519
+ function splitFlag(token) {
2520
+ const separator = token.indexOf("=");
2521
+ if (separator === -1) return { flag: token };
2522
+ return {
2523
+ flag: token.slice(0, separator),
2524
+ inlineValue: token.slice(separator + 1)
2525
+ };
2526
+ }
2527
+ function parseOverdeckComposerCommand(message) {
2528
+ if (!/^\/pan(?:\s|$)/.test(message)) return null;
2529
+ const forbidden = message.match(FORBIDDEN_TOKEN)?.[0];
2530
+ if (forbidden !== void 0) throw new ComposerCommandParseError("forbidden-token", `The token "${forbidden}" is not allowed in /pan commands. Run compound shell syntax in a terminal instead.`, forbidden, "plain arguments without shell operators");
2531
+ const tokens = tokenize(message.slice(4).trim());
2532
+ const { entry, pathLength } = resolveEntry(tokens);
2533
+ const remaining = tokens.slice(pathLength);
2534
+ const definitions = optionDefinitions(entry);
2535
+ const positionals = [];
2536
+ const flags = [];
2537
+ for (let index = 0; index < remaining.length; index += 1) {
2538
+ const token = remaining[index];
2539
+ if (!token.startsWith("-")) {
2540
+ positionals.push(token);
2541
+ continue;
2542
+ }
2543
+ const { flag, inlineValue } = splitFlag(token);
2544
+ const definition = definitions.get(flag);
2545
+ if (definition === void 0) throw new ComposerCommandParseError("unknown-flag", `Unknown flag "${flag}" for ${entry.display}. Expected syntax: ${expectedSyntax(entry)}.`, flag, expectedSyntax(entry));
2546
+ flags.push(definition.canonicalFlag);
2547
+ if (definition.option.valueHint === null) {
2548
+ if (inlineValue !== void 0) throw new ComposerCommandParseError("unknown-flag", `Flag "${flag}" does not accept a value. Expected syntax: ${expectedSyntax(entry)}.`, token, expectedSyntax(entry));
2549
+ continue;
2550
+ }
2551
+ if (inlineValue !== void 0) {
2552
+ if (inlineValue.length === 0 && definition.option.required) throw new ComposerCommandParseError("missing-argument", `Flag "${flag}" requires <${definition.option.valueHint}>. Expected syntax: ${expectedSyntax(entry)}.`, flag, expectedSyntax(entry));
2553
+ if (inlineValue.length > 0) flags.push(inlineValue);
2554
+ continue;
2555
+ }
2556
+ const next = remaining[index + 1];
2557
+ const nextIsFlag = next?.startsWith("-") === true;
2558
+ if (definition.option.required && (next === void 0 || nextIsFlag)) throw new ComposerCommandParseError("missing-argument", `Flag "${flag}" requires <${definition.option.valueHint}>. Expected syntax: ${expectedSyntax(entry)}.`, flag, expectedSyntax(entry));
2559
+ if (next !== void 0 && !nextIsFlag) {
2560
+ flags.push(next);
2561
+ index += 1;
2562
+ }
2563
+ }
2564
+ if (!(entry.args.at(-1)?.variadic === true) && positionals.length > entry.args.length) {
2565
+ const token = positionals[entry.args.length];
2566
+ throw new ComposerCommandParseError("unknown-command", `Unexpected token "${token}" for ${entry.display}. Expected syntax: ${expectedSyntax(entry)}.`, token, expectedSyntax(entry));
2567
+ }
2568
+ const missing = entry.args.find((argument, index) => argument.required && positionals[index] === void 0);
2569
+ if (missing !== void 0) throw new ComposerCommandParseError("missing-argument", `Missing required argument <${missing.name}> for ${entry.display}. Expected syntax: ${expectedSyntax(entry)}.`, missing.name, expectedSyntax(entry));
2570
+ return {
2571
+ entry,
2572
+ argv: [
2573
+ ...entry.path,
2574
+ ...positionals,
2575
+ ...flags
2576
+ ]
2577
+ };
2578
+ }
2579
+ //#endregion
2580
+ //#region ../../lib/composer-commands/policy.ts
2581
+ init_src();
2582
+ const COMPOSER_COMMAND_POLICIES = {
2583
+ start: {
2584
+ mode: "detached",
2585
+ safety: "safe"
2586
+ },
2587
+ plan: {
2588
+ mode: "detached",
2589
+ safety: "safe"
2590
+ },
2591
+ show: {
2592
+ mode: "captured",
2593
+ safety: "safe"
2594
+ },
2595
+ status: {
2596
+ mode: "captured",
2597
+ safety: "safe"
2598
+ },
2599
+ tell: {
2600
+ mode: "captured",
2601
+ safety: "safe"
2602
+ },
2603
+ handoff: {
2604
+ mode: "ui",
2605
+ safety: "dialog",
2606
+ uiAction: "handoff",
2607
+ confirmationText: "This opens the handoff dialog for the selected conversation. Review the destination and focus before continuing."
2608
+ },
2609
+ fork: {
2610
+ mode: "ui",
2611
+ safety: "dialog",
2612
+ uiAction: "fork",
2613
+ confirmationText: "This opens the fork dialog for the selected conversation. Review the fork mode and destination before continuing."
2614
+ }
2615
+ };
2616
+ const DEFAULT_POLICY = {
2617
+ mode: "terminal-only",
2618
+ safety: "safe"
2619
+ };
2620
+ function assertPolicyOverlayIntegrity(policies = COMPOSER_COMMAND_POLICIES, manifest = COMPOSER_COMMAND_MANIFEST) {
2621
+ for (const path of Object.keys(policies)) {
2622
+ const matches = manifest.filter((entry) => entry.path.join(" ") === path);
2623
+ if (matches.length !== 1) throw new Error(`Composer command policy path "${path}" must match exactly one manifest entry; found ${matches.length}.`);
2624
+ }
2625
+ }
2626
+ function resolvePolicy(path) {
2627
+ return COMPOSER_COMMAND_POLICIES[path.join(" ")] ?? DEFAULT_POLICY;
2628
+ }
2629
+ assertPolicyOverlayIntegrity();
2630
+ //#endregion
2631
+ //#region ../../lib/composer-commands/router.ts
2632
+ const UI_COMMAND_PATTERNS = [{
2633
+ action: "handoff",
2634
+ pattern: /^\/(?:handoff|pan-handoff|pan\s+handoff)(?:\s+([\s\S]+))?$/i
2635
+ }, {
2636
+ action: "fork",
2637
+ pattern: /^\/pan\s+fork(?:\s+([\s\S]+))?$/i
2638
+ }];
2639
+ function isComposerCommandMessage(message) {
2640
+ return UI_COMMAND_PATTERNS.some(({ pattern }) => pattern.test(message)) || /^\/pan(?:\s|$)/.test(message);
2641
+ }
2642
+ async function handleComposerCommandMessage({ message, target, confirmation }, dependencies = {}) {
2643
+ for (const { action, pattern } of UI_COMMAND_PATTERNS) {
2644
+ const match = message.match(pattern);
2645
+ if (match) {
2646
+ const parsed = parseOverdeckComposerCommand(`/pan ${action}`);
2647
+ const focus = match[1]?.trim();
2648
+ if (focus) parsed.argv.push(focus);
2649
+ return handleComposerCommand({
2650
+ parsed,
2651
+ target,
2652
+ confirmation
2653
+ }, dependencies);
2654
+ }
2655
+ }
2656
+ const parsed = parseOverdeckComposerCommand(message);
2657
+ if (parsed === null) return null;
2658
+ return handleComposerCommand({
2659
+ parsed,
2660
+ target,
2661
+ confirmation
2662
+ }, dependencies);
2663
+ }
2664
+ async function handleComposerCommand({ parsed, target, confirmation }, dependencies = {}) {
2665
+ const policy = (dependencies.resolvePolicy ?? resolvePolicy)(parsed.entry.path);
2666
+ if (policy.safety !== "safe") {
2667
+ const confirmationStore = dependencies.confirmationStore ?? composerConfirmationStore;
2668
+ if (confirmation === void 0) return confirmationStore.issue({
2669
+ target,
2670
+ argv: parsed.argv,
2671
+ policy,
2672
+ display: parsed.entry.display
2673
+ });
2674
+ confirmationStore.consume({
2675
+ target,
2676
+ argv: parsed.argv,
2677
+ policy,
2678
+ confirmation
2679
+ });
2680
+ }
2681
+ if (policy.mode === "captured") return runCapturedCommand(parsed.argv);
2682
+ if (policy.mode === "detached") return runDetachedCommand(parsed.argv);
2683
+ if (policy.mode === "ui" && policy.uiAction) return uiCommandResult(policy.uiAction, parsed.argv.slice(parsed.entry.path.length).join(" ") || void 0);
2684
+ if (policy.mode === "terminal-only") return {
2685
+ kind: "terminal-only",
2686
+ status: "rejected",
2687
+ message: `${parsed.entry.display} must run in a terminal. Composer execution has not been enabled for this command.`
2688
+ };
2689
+ return missingExecutorResult(parsed.entry.display, policy);
2690
+ }
2691
+ function uiCommandResult(action, focus) {
2692
+ return {
2693
+ kind: "ui",
2694
+ status: "requires_ui",
2695
+ action,
2696
+ args: focus ? { focus } : {}
2697
+ };
2698
+ }
2699
+ function missingExecutorResult(display, policy) {
2700
+ return {
2701
+ kind: "terminal-only",
2702
+ status: "rejected",
2703
+ message: `${display} is recognized as a ${policy.mode} command, but its composer executor is not registered yet. Run it in a terminal for now.`
2704
+ };
2705
+ }
2706
+ function composerCommandResultHttpStatus(result) {
2707
+ return result.kind === "terminal-only" ? 422 : 200;
2708
+ }
2709
+ //#endregion
2107
2710
  //#region routes/agents/messaging.ts
2108
2711
  init_agents$1();
2109
2712
  async function sendAgentMessage(id, message) {
@@ -2119,6 +2722,55 @@ async function sendAgentMessage(id, message) {
2119
2722
  remote: true
2120
2723
  } : { success: true };
2121
2724
  }
2725
+ async function handleAgentMessage(id, message, confirmation) {
2726
+ try {
2727
+ if (isComposerCommandMessage(message)) {
2728
+ let agentState;
2729
+ try {
2730
+ agentState = await Effect.runPromise(getAgentState(id));
2731
+ } catch {
2732
+ return jsonResponse({
2733
+ error: `Failed to resolve agent target: ${id}`,
2734
+ code: "agent-resolution-failed"
2735
+ }, { status: 503 });
2736
+ }
2737
+ if (!agentState) return jsonResponse({
2738
+ error: `Agent not found: ${id}`,
2739
+ code: "agent-not-found"
2740
+ }, { status: 404 });
2741
+ if (!agentState.harness) return jsonResponse({
2742
+ error: `Agent harness could not be resolved: ${id}`,
2743
+ code: "agent-harness-unresolved"
2744
+ }, { status: 503 });
2745
+ const result = await handleComposerCommandMessage({
2746
+ message,
2747
+ confirmation,
2748
+ target: {
2749
+ kind: "agent",
2750
+ id,
2751
+ harness: agentState.harness,
2752
+ cwd: agentState.workspace,
2753
+ issueId: agentState.issueId
2754
+ }
2755
+ });
2756
+ if (result !== null) return jsonResponse(result, { status: composerCommandResultHttpStatus(result) });
2757
+ }
2758
+ } catch (error) {
2759
+ if (error instanceof ComposerCommandConfirmationError) return jsonResponse({
2760
+ error: error.message,
2761
+ code: error.code
2762
+ }, { status: 422 });
2763
+ if (!(error instanceof ComposerCommandParseError)) throw error;
2764
+ const status = error.code === "unknown-command" ? 404 : error.code === "unknown-flag" ? 422 : 400;
2765
+ return jsonResponse({
2766
+ error: error.message,
2767
+ code: error.code,
2768
+ token: error.token,
2769
+ expected: error.expected
2770
+ }, { status });
2771
+ }
2772
+ return jsonResponse(await sendAgentMessage(id, message));
2773
+ }
2122
2774
  function validateAgentMessageOrigin(request) {
2123
2775
  const originCheck = validateOrigin(request);
2124
2776
  if (!originCheck.ok) return {
@@ -2135,9 +2787,10 @@ function postAgentMessageLikeRoute(path) {
2135
2787
  const originCheck = validateAgentMessageOrigin(yield* HttpServerRequest.HttpServerRequest);
2136
2788
  if (!originCheck.ok) return originCheck.response;
2137
2789
  const id = (yield* HttpRouter.params)["id"] ?? "";
2138
- const { message } = yield* readJsonBody$1;
2790
+ const body = yield* readJsonBody$1;
2791
+ const { message } = body;
2139
2792
  if (!message) return jsonResponse({ error: "Message required" }, { status: 400 });
2140
- return yield* Effect.promise(() => sendAgentMessage(id, message)).pipe(Effect.map((result) => jsonResponse(result)));
2793
+ return yield* Effect.promise(() => handleAgentMessage(id, message, composerCommandConfirmationFromBody(body)));
2141
2794
  })));
2142
2795
  }
2143
2796
  const postAgentMessageRoute = postAgentMessageLikeRoute("/api/agents/:id/message");
@@ -2386,7 +3039,7 @@ async function cleanupConversationAttachments(name) {
2386
3039
  * sessions that the lifecycle poller missed. */
2387
3040
  async function cleanupOrphanedConversationAttachments() {
2388
3041
  try {
2389
- const { listConversations } = await import("./conversations-CAsJF9kh.js");
3042
+ const { listConversations } = await import("./conversations-C34dyIb9.js");
2390
3043
  const convNames = new Set(listConversations().map((c) => c.name));
2391
3044
  const root = getConversationAttachmentsRoot();
2392
3045
  await runInBatches((await readdir(root, { withFileTypes: true })).filter((entry) => entry.isDirectory() && !convNames.has(entry.name)).map((entry) => join(root, entry.name)), 10, (path) => rm(path, {
@@ -2811,6 +3464,21 @@ async function handleConversationSwitchModel(name, body) {
2811
3464
  function getPtySupervisorSocketPath(agentId) {
2812
3465
  return join(getOverdeckHome(), "sockets", `pty-${agentId}.sock`);
2813
3466
  }
3467
+ /**
3468
+ * Pull the supervisor's own failure out of the tmux pane it died in.
3469
+ *
3470
+ * A supervisor that cannot load its native node-pty exits instantly with an
3471
+ * ERR_MODULE_NOT_FOUND on stderr; all the spawn path sees is the socket that
3472
+ * never appeared. Reporting only the timeout hides the actual cause and sent
3473
+ * an operator hunting the memory governor instead (PAN-3172).
3474
+ */
3475
+ function extractSupervisorFailure(paneText) {
3476
+ const lines = paneText.split("\n").map((line) => line.trim()).filter(Boolean);
3477
+ const errors = lines.filter((line) => /error|cannot find|ERR_[A-Z_]+|pty-supervisor:/i.test(line));
3478
+ const chosen = (errors.length > 0 ? errors : lines).slice(-3);
3479
+ if (chosen.length === 0) return null;
3480
+ return chosen.join(" | ").slice(0, 500);
3481
+ }
2814
3482
  async function waitForPtySupervisorSocket(agentId, timeoutMs = PTY_SUPERVISOR_SOCKET_WAIT_MS) {
2815
3483
  const socketPath = getPtySupervisorSocketPath(agentId);
2816
3484
  const start = Date.now();
@@ -2820,7 +3488,8 @@ async function waitForPtySupervisorSocket(agentId, timeoutMs = PTY_SUPERVISOR_SO
2820
3488
  } catch {}
2821
3489
  await new Promise((r) => setTimeout(r, 250));
2822
3490
  }
2823
- throw new Error(`Timed out waiting for PTY supervisor socket ${socketPath}`);
3491
+ const failure = extractSupervisorFailure(await capturePaneText(agentId, 40));
3492
+ throw new Error(`Timed out waiting for PTY supervisor socket ${socketPath}` + (failure ? ` — supervisor output: ${failure}` : ""));
2824
3493
  }
2825
3494
  async function extractModelFromSessionFile(sessionFile) {
2826
3495
  try {
@@ -2980,7 +3649,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
2980
3649
  const codexApprovalPolicy = codexPermMode === "full-access" ? "never" : "on-request";
2981
3650
  const codexSandboxMode = codexPermMode === "full-access" ? "danger-full-access" : codexPermMode === "read-only" ? "read-only" : "workspace-write";
2982
3651
  const codexApprovalsReviewer = codexPermMode === "auto-review" ? "auto_review" : void 0;
2983
- const { initCodexHome, extractThreadIdFromRollout } = await import("./codex-GcHuUF-k.js");
3652
+ const { initCodexHome, extractThreadIdFromRollout } = await import("./codex-BdEsUFWh.js");
2984
3653
  initCodexHome(codexHome, {
2985
3654
  trustedDir: cwd,
2986
3655
  approvalPolicy: codexApprovalPolicy,
@@ -3049,7 +3718,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
3049
3718
  } catch {}
3050
3719
  console.log(`[claude-invoke] purpose=conversation-session | model=${model || "default"} | source=conversations.ts:spawnConversationSession | session=${tmuxSession} | resume=${resume} | command="${runtimeCommand}"`);
3051
3720
  try {
3052
- const { preTrustDirectory } = await import("./workspace-manager-CWT55qeI.js");
3721
+ const { preTrustDirectory } = await import("./workspace-manager-CDTKjjdU.js");
3053
3722
  preTrustDirectory(cwd);
3054
3723
  } catch {}
3055
3724
  try {
@@ -3066,7 +3735,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
3066
3735
  const codexHomeDir = codexFields.codexHome;
3067
3736
  (async () => {
3068
3737
  try {
3069
- const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-GcHuUF-k.js");
3738
+ const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-BdEsUFWh.js");
3070
3739
  const rollout = await waitForCodexRollout(codexHomeDir, 12e4);
3071
3740
  if (rollout) {
3072
3741
  const threadId = extractThreadIdFromRollout(rollout);
@@ -3957,7 +4626,7 @@ const postInternalAgentPermissionRequestRoute = HttpRouter.add("POST", "/api/int
3957
4626
  error: "missing agent id"
3958
4627
  }, { status: 400 });
3959
4628
  const request = yield* HttpServerRequest.HttpServerRequest;
3960
- const { INTERNAL_TOKEN_HEADER, getInternalTokenSync } = yield* Effect.promise(() => import("./internal-token-BrcU6qfe.js"));
4629
+ const { INTERNAL_TOKEN_HEADER, getInternalTokenSync } = yield* Effect.promise(() => import("./internal-token-M9omeXM1.js"));
3961
4630
  const expected = getInternalTokenSync();
3962
4631
  if (!expected) return jsonResponse({
3963
4632
  ok: false,
@@ -4093,6 +4762,7 @@ const postAgentPermissionResponseRoute = HttpRouter.add("POST", "/api/agents/:id
4093
4762
  * pollers (PAN-1134). Extracted from routes/agents.ts so Pi event polling
4094
4763
  * can reuse bodyToEvent without importing a heavy route module.
4095
4764
  */
4765
+ init_src();
4096
4766
  /**
4097
4767
  * Translate a decoded body into an unsigned DomainEvent (no sequence yet).
4098
4768
  * Returns null if the body doesn't map to a runtime event.
@@ -4213,6 +4883,25 @@ const bodyToEvent = (agentId, body, timestamp) => {
4213
4883
  contextSaturatedAt: source["contextSaturatedAt"]
4214
4884
  }
4215
4885
  };
4886
+ case "linear_mcp_auth_required": return {
4887
+ type: "linear_mcp_auth.required",
4888
+ timestamp,
4889
+ payload: {
4890
+ agentId,
4891
+ issueId: source["issueId"] ?? null,
4892
+ authUrl: source["authUrl"] ?? null,
4893
+ expiresAt: source["expiresAt"] ?? null
4894
+ }
4895
+ };
4896
+ case "linear_mcp_auth_healthy": return {
4897
+ type: "linear_mcp_auth.healthy",
4898
+ timestamp,
4899
+ payload: {
4900
+ agentId,
4901
+ issueId: source["issueId"] ?? null,
4902
+ source: "hook"
4903
+ }
4904
+ };
4216
4905
  default: return null;
4217
4906
  }
4218
4907
  };
@@ -4224,7 +4913,7 @@ const getAgentHealthHistoryRoute = HttpRouter.add("GET", "/api/agents/:id/health
4224
4913
  const request = yield* HttpServerRequest.HttpServerRequest;
4225
4914
  const urlOpt = HttpServerRequest.toURL(request);
4226
4915
  const hours = Option.isSome(urlOpt) ? urlOpt.value.searchParams.get("hours") ?? "24" : "24";
4227
- const { getHealthHistory } = yield* Effect.promise(() => import("./health-events-BDOHby5Q.js"));
4916
+ const { getHealthHistory } = yield* Effect.promise(() => import("./health-events-_xfTaOUs.js"));
4228
4917
  const endTime = /* @__PURE__ */ new Date();
4229
4918
  const startTime = /* @__PURE__ */ new Date(endTime.getTime() - parseInt(hours) * 60 * 60 * 1e3);
4230
4919
  const events = getHealthHistory(id, startTime.toISOString(), endTime.toISOString());
@@ -4237,9 +4926,18 @@ const getAgentHealthHistoryRoute = HttpRouter.add("GET", "/api/agents/:id/health
4237
4926
  })));
4238
4927
  function emitAgentRuntimeEvent(id, body, timestamp) {
4239
4928
  return Effect.gen(function* () {
4929
+ let eventBody = body;
4930
+ if (body["kind"] === "linear_mcp_auth_required" || body["kind"] === "linear_mcp_auth_healthy") {
4931
+ const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-hZpxIw1E.js"));
4932
+ const snapshot = yield* (yield* AgentStateService).get(id);
4933
+ eventBody = {
4934
+ ...body,
4935
+ issueId: snapshot?.currentIssue ?? null
4936
+ };
4937
+ }
4240
4938
  let raw;
4241
4939
  try {
4242
- raw = bodyToEvent(id, body, timestamp);
4940
+ raw = bodyToEvent(id, eventBody, timestamp);
4243
4941
  } catch (error) {
4244
4942
  return {
4245
4943
  ok: false,
@@ -4265,7 +4963,7 @@ function emitAgentRuntimeEvent(id, body, timestamp) {
4265
4963
  detail: String(decoded.failure)
4266
4964
  }, { status: 400 })
4267
4965
  };
4268
- const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-D5UGKIJL.js"));
4966
+ const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-hZpxIw1E.js"));
4269
4967
  yield* (yield* AgentStateService).emit(decoded.success);
4270
4968
  return {
4271
4969
  ok: true,
@@ -4347,7 +5045,7 @@ const getAgentRuntimeRoute = HttpRouter.add("GET", "/api/agents/:id/runtime", ht
4347
5045
  success: false,
4348
5046
  error: "missing agent id"
4349
5047
  }, { status: 400 });
4350
- const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-D5UGKIJL.js"));
5048
+ const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-hZpxIw1E.js"));
4351
5049
  const snapshot = yield* (yield* AgentStateService).get(id);
4352
5050
  if (!snapshot) return jsonResponse({
4353
5051
  success: false,
@@ -4532,8 +5230,8 @@ function createAgentStopHandler(lifecycleEvent) {
4532
5230
  yield* stopAgent(id);
4533
5231
  if (stateBeforeStop?.issueId) yield* Effect.promise(async () => {
4534
5232
  try {
4535
- const { resolveProjectFromIssueSync } = await import("./projects-vjjcmiN8.js");
4536
- const { findWorkspacePath } = await import("./archive-planning-BZDgzoEj.js");
5233
+ const { resolveProjectFromIssueSync } = await import("./projects-B03Wr-xc.js");
5234
+ const { findWorkspacePath } = await import("./archive-planning-0FJ6Xd3b.js");
4537
5235
  const issueLower = stateBeforeStop.issueId.toLowerCase();
4538
5236
  const workspacePath = findWorkspacePath(resolveProjectFromIssueSync(stateBeforeStop.issueId)?.projectPath ?? process.cwd(), issueLower);
4539
5237
  if (workspacePath) {
@@ -4673,7 +5371,7 @@ const postAgentUnpauseRoute = HttpRouter.add("POST", "/api/agents/:id/unpause",
4673
5371
  if ((yield* getWorkAgentLifecycleState(id)).canResumeSession && updatedState.troubled !== true) {
4674
5372
  resumeTriggered = true;
4675
5373
  yield* Effect.promise(() => appendAgentLifecycleLog(id, "agent.unpause_immediate_resume_triggered"));
4676
- import("./resume-BFv1PGpA.js").then(({ resumeAgent }) => resumeAgent(id)).then((result) => {
5374
+ import("./resume-u9byntrq.js").then(({ resumeAgent }) => resumeAgent(id)).then((result) => {
4677
5375
  if (!result.success) console.warn(`[agents] immediate resume after unpause failed for ${id}: ${result.error}`);
4678
5376
  }).catch((err) => console.warn(`[agents] immediate resume after unpause errored for ${id}:`, err));
4679
5377
  }
@@ -5963,15 +6661,15 @@ init_agents$1();
5963
6661
  function handleRemoteAgentSpawn(input) {
5964
6662
  return Effect.gen(function* () {
5965
6663
  const { issueId, workspacePath, workspaceMetadata, spawnModel, projectPath, spawnGuardrails, lifecycle } = input;
5966
- const { spawnRemoteAgent, checkRemoteSpendCap } = yield* Effect.promise(() => import("./remote-agents-CA3Ihlxj.js"));
5967
- const { createFlyProviderFromConfig } = yield* Effect.promise(() => import("./remote-ChgimyYa.js"));
5968
- const { loadConfigSync: loadPanConfig } = yield* Effect.promise(() => import("./config-DzV30TOm.js"));
6664
+ const { spawnRemoteAgent, checkRemoteSpendCap } = yield* Effect.promise(() => import("./remote-agents-C1bssi41.js"));
6665
+ const { createFlyProviderFromConfig } = yield* Effect.promise(() => import("./remote-CVGUhXMV.js"));
6666
+ const { loadConfigSync: loadPanConfig } = yield* Effect.promise(() => import("./config-DV-grfQc.js"));
5969
6667
  const panConfig = loadPanConfig();
5970
6668
  const spendCap = checkRemoteSpendCap(panConfig);
5971
6669
  if (!spendCap.allowed) return jsonResponse({ error: spendCap.message }, { status: 429 });
5972
6670
  const fly = createFlyProviderFromConfig(panConfig.remote);
5973
6671
  yield* Effect.promise(() => fly.syncAllCredentials(workspaceMetadata.vmName));
5974
- const { buildWorkAgentPrompt, getTrackerContext } = yield* Effect.promise(() => import("./work-agent-prompt-Du8Vh2aJ.js"));
6672
+ const { buildWorkAgentPrompt, getTrackerContext } = yield* Effect.promise(() => import("./work-agent-prompt-C-vuP3_J.js"));
5975
6673
  const trackerContext = yield* Effect.promise(() => getTrackerContext(issueId, workspacePath));
5976
6674
  const agentPrompt = yield* Effect.promise(() => buildWorkAgentPrompt({
5977
6675
  issueId,
@@ -6287,10 +6985,12 @@ function handleContainerOrchestration(input) {
6287
6985
  //#endregion
6288
6986
  //#region routes/agents/spawn.ts
6289
6987
  init_agents$1();
6988
+ init_staffing();
6290
6989
  init_operator_interventions();
6291
6990
  init_child_env();
6292
6991
  init_harness_policy();
6293
6992
  init_activity_logger();
6993
+ init_issue_id();
6294
6994
  init_projects();
6295
6995
  init_review_status();
6296
6996
  init_state_read_home();
@@ -6328,20 +7028,17 @@ function emitDirtyWorkspaceRefusalActivity(issueId, porcelain) {
6328
7028
  });
6329
7029
  } catch {}
6330
7030
  }
6331
- const LEGACY_WORKSPACE_RUNTIME_FILES = new Set([
6332
- ".pan/continue.json",
6333
- ".pan/spec.vbrief.json",
6334
- ".pan/kickoff.md",
6335
- ".pan/sessions.jsonl",
6336
- ".pan/pipeline-verdict.json",
6337
- ".pan/verification-latest.json",
6338
- ".pan/agent-mcp.json"
6339
- ]);
7031
+ /**
7032
+ * Both workspace runtime directories are Overdeck-owned in full, so both get a
7033
+ * blanket prefix match. The legacy `.pan/` allowlist only matched the collapsed
7034
+ * `?? .pan/` porcelain form plus a closed set of files — but this gate always
7035
+ * runs with `--untracked-files=all`, which expands untracked directories into
7036
+ * individual paths. A pipeline-authored `.pan/drafts/<ISSUE>.md` therefore read
7037
+ * as operator dirt and 409'd the planning→work auto-handoff (PAN-3042).
7038
+ */
6340
7039
  function isOverdeckWorkspaceRuntimePath(path) {
6341
7040
  if (path === ".overdeck" || path.startsWith(".overdeck/")) return true;
6342
- if (path === ".pan" || path === ".pan/") return true;
6343
- if (LEGACY_WORKSPACE_RUNTIME_FILES.has(path)) return true;
6344
- return path.startsWith(".pan/feedback/") || path.startsWith(".pan/review/") || path.startsWith(".pan/test/") || path.startsWith(".pan/handoff-");
7041
+ return path === ".pan" || path === ".pan/" || path.startsWith(".pan/");
6345
7042
  }
6346
7043
  /** True when git porcelain contains only Overdeck-owned workspace runtime files. */
6347
7044
  function isOnlyOverdeckRuntimeWorkspaceChanges(porcelain) {
@@ -6534,7 +7231,7 @@ const postAgentsRoute = HttpRouter.add("POST", "/api/agents", httpHandler(Effect
6534
7231
  let spawnModel;
6535
7232
  try {
6536
7233
  spawnModel = determineModel({
6537
- model: body.model,
7234
+ model: body.model ?? resolveIssueWorkModel(issueId),
6538
7235
  role,
6539
7236
  spawnKey: `${role}:${issueId}`
6540
7237
  });
@@ -6692,7 +7389,7 @@ const postAgentsRoute = HttpRouter.add("POST", "/api/agents", httpHandler(Effect
6692
7389
  console.warn(`[start-agent] Failed to set plan.status=running (non-fatal): ${planStatusErr?.message ?? planStatusErr}`);
6693
7390
  }
6694
7391
  try {
6695
- const { appendSessionEntry, getProjectConfigFromWorkspacePath, resolveProjectForIssue } = await import("./record-CN0pj4_5.js");
7392
+ const { appendSessionEntry, getProjectConfigFromWorkspacePath, resolveProjectForIssue } = await import("./record-CtroO946.js");
6696
7393
  await appendSessionEntry(resolveProjectForIssue(issueId) ?? getProjectConfigFromWorkspacePath(workspacePath), issueId, {
6697
7394
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6698
7395
  reason: "start",
@@ -7142,16 +7839,26 @@ const readJsonBody = Effect.gen(function* () {
7142
7839
  const postMergeGuard = createInFlightGuard();
7143
7840
  const _serverManagedMerges = /* @__PURE__ */ new Set();
7144
7841
  function firePostMergeLifecycle(issueId, options) {
7145
- const started = postMergeGuard.run(issueId, async () => {
7146
- const projectPath = getProjectPathForIssue(extractPrefixSync(issueId) ?? issueId.split("-")[0]);
7147
- const { postMergeLifecycle } = await import("./merge-agent-CKkgIBPB.js");
7148
- await postMergeLifecycle(issueId, projectPath, options?.sourceBranch, options?.verifiedMergedRef ? { verifiedMergedRef: options.verifiedMergedRef } : void 0);
7149
- console.log(`[merge] post-merge lifecycle completed for ${issueId}`);
7150
- const { runMergeTrainReconcile } = await import("./merge-train-CHopycP0.js");
7151
- const outcomes = await runMergeTrainReconcile(issueId);
7152
- if (outcomes.length > 0) console.log(`[merge-train] reconciled ${outcomes.length} sibling(s) after ${issueId}: ` + outcomes.map((o) => `${o.issueId}=${o.result}`).join(", "));
7153
- }, (err) => console.error(`[merge] post-merge lifecycle failed for ${issueId}:`, err));
7154
- if (!started) console.log(`[merge] firePostMergeLifecycle: skipping ${issueId} — already in flight`);
7842
+ const parsedIssueId = parseIssueIdSync(issueId.trim());
7843
+ if (!parsedIssueId) {
7844
+ console.error(`[merge] Refusing post-merge lifecycle for invalid issue ID: ${issueId}`);
7845
+ return false;
7846
+ }
7847
+ const normalizedIssueId = parsedIssueId.normalized.toUpperCase();
7848
+ const started = postMergeGuard.run(normalizedIssueId, async () => {
7849
+ const projectPath = getProjectPathForIssue(parsedIssueId.prefix);
7850
+ const { postMergeLifecycle } = await import("./merge-agent-DrXa1CpW.js");
7851
+ const lifecycleOptions = {
7852
+ ...options?.verifiedMergedRef ? { verifiedMergedRef: options.verifiedMergedRef } : {},
7853
+ ...options?.verifiedMergedRepos?.length ? { verifiedMergedRepos: options.verifiedMergedRepos } : {}
7854
+ };
7855
+ await postMergeLifecycle(normalizedIssueId, projectPath, options?.sourceBranch, Object.keys(lifecycleOptions).length > 0 ? lifecycleOptions : void 0);
7856
+ console.log(`[merge] post-merge lifecycle completed for ${normalizedIssueId}`);
7857
+ const { runMergeTrainReconcile } = await import("./merge-train-DTEMyIu4.js");
7858
+ const outcomes = await runMergeTrainReconcile(normalizedIssueId);
7859
+ if (outcomes.length > 0) console.log(`[merge-train] reconciled ${outcomes.length} sibling(s) after ${normalizedIssueId}: ` + outcomes.map((o) => `${o.issueId}=${o.result}`).join(", "));
7860
+ }, (err) => console.error(`[merge] post-merge lifecycle failed for ${normalizedIssueId}:`, err));
7861
+ if (!started) console.log(`[merge] firePostMergeLifecycle: skipping ${normalizedIssueId} — already in flight`);
7155
7862
  return started;
7156
7863
  }
7157
7864
  function getProjectPathForIssue(issuePrefix) {
@@ -7168,15 +7875,15 @@ init_io();
7168
7875
  init_domain_services();
7169
7876
  init_tmux();
7170
7877
  const getSpecialistsRoute = HttpRouter.add("GET", "/api/specialists", httpHandler(Effect.gen(function* () {
7171
- const { getAllSpecialistStatus, getAllProjectSpecialistStatuses } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
7878
+ const { getAllSpecialistStatus, getAllProjectSpecialistStatuses } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7172
7879
  return jsonResponse({
7173
7880
  specialists: yield* Effect.promise(() => getAllSpecialistStatus()),
7174
7881
  projects: yield* Effect.promise(() => getAllProjectSpecialistStatuses())
7175
7882
  });
7176
7883
  })));
7177
7884
  const postSpecialistsResetAllRoute = HttpRouter.add("POST", "/api/specialists/reset-all", httpHandler(Effect.gen(function* () {
7178
- const { getAllSpecialists, isRunning, getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
7179
- const { clearHookSync } = yield* Effect.promise(() => import("./hooks-DPVX1rwQ.js"));
7885
+ const { getAllSpecialists, isRunning, getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7886
+ const { clearHookSync } = yield* Effect.promise(() => import("./hooks-BnJsxlSq.js"));
7180
7887
  const specialists = getAllSpecialists();
7181
7888
  const results = [];
7182
7889
  for (const specialist of specialists) {
@@ -7211,7 +7918,7 @@ const postSpecialistsResetAllRoute = HttpRouter.add("POST", "/api/specialists/re
7211
7918
  const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done", httpHandler(Effect.gen(function* () {
7212
7919
  const body = yield* readJsonBody;
7213
7920
  const eventStore = yield* EventStoreService;
7214
- const { specialist, issueId, status, notes, itemId } = body;
7921
+ const { specialist, issueId, status, notes, itemId, runId } = body;
7215
7922
  const validSpecialists = [
7216
7923
  "review",
7217
7924
  "test",
@@ -7232,7 +7939,7 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7232
7939
  }
7233
7940
  console.log(`[specialists/done] ${specialist} signaling ${status} for ${normalizedIssueId}`);
7234
7941
  if (specialist === "merge") {
7235
- const { reportSpecialistCompletion } = yield* Effect.promise(() => import("./specialist-completion-Ky9wCDpb.js"));
7942
+ const { reportSpecialistCompletion } = yield* Effect.promise(() => import("./specialist-completion-Br48eiDP.js"));
7236
7943
  if (yield* reportSpecialistCompletion(normalizedIssueId, {
7237
7944
  status,
7238
7945
  notes
@@ -7276,10 +7983,27 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7276
7983
  break;
7277
7984
  }
7278
7985
  const updatedStatus = setReviewStatusSync(normalizedIssueId, update);
7279
- if (specialist === "inspect" && status === "failed") yield* Effect.promise(() => reportTieredInspectFailureEscalation(normalizedIssueId, notes));
7986
+ if (specialist === "inspect" && status === "failed") {
7987
+ yield* Effect.promise(() => reportTieredInspectFailureEscalation(normalizedIssueId, notes));
7988
+ yield* Effect.promise(async () => {
7989
+ try {
7990
+ const failedItemId = itemId ?? getReviewStatusSync(normalizedIssueId)?.inspectBeadId ?? void 0;
7991
+ const project = resolveProjectFromIssueSync(normalizedIssueId);
7992
+ if (project && failedItemId) {
7993
+ const workspacePath = join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`);
7994
+ if (existsSync(workspacePath)) {
7995
+ const { onInspectComplete } = await import("./inspect-agent-BVwDrVrz.js");
7996
+ await Effect.runPromise(onInspectComplete(project.projectKey, normalizedIssueId, failedItemId, "failed", workspacePath, notes));
7997
+ }
7998
+ }
7999
+ } catch (err) {
8000
+ console.error(`[specialists/done] Error delivering failed inspect verdict for ${normalizedIssueId}:`, err);
8001
+ }
8002
+ });
8003
+ }
7280
8004
  yield* Effect.promise(async () => {
7281
8005
  try {
7282
- const { getTmuxSessionName, updateRunMetadata, makeSpecialistRegistryKey } = await import("./specialists-DM6bWjsi.js");
8006
+ const { getTmuxSessionName, updateRunMetadata, makeSpecialistRegistryKey } = await import("./specialists-Tdezg_6N.js");
7283
8007
  const projectKey = resolveProjectFromIssueSync(normalizedIssueId)?.projectKey;
7284
8008
  const tmuxSession = projectKey ? getTmuxSessionName(`${specialist}-agent`, projectKey, normalizedIssueId) : getTmuxSessionName(`${specialist}-agent`);
7285
8009
  saveAgentRuntimeState(tmuxSession, {
@@ -7298,7 +8022,7 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7298
8022
  });
7299
8023
  console.log(`[specialists/done] Cleared registry lock for ${registryKey} (${projectKey})`);
7300
8024
  }
7301
- const { updateSpecialistHandoffStatus } = await import("./specialist-handoff-logger-CMEwYxa2.js");
8025
+ const { updateSpecialistHandoffStatus } = await import("./specialist-handoff-logger-DK-GTz4s.js");
7302
8026
  if (await Effect.runPromise(updateSpecialistHandoffStatus(normalizedIssueId, `${specialist}-agent`, status === "passed" ? "completed" : "failed", status === "passed" ? "success" : "failure"))) console.log(`[specialists/done] Updated handoff log: ${specialist}-agent ${normalizedIssueId} → ${status}`);
7303
8027
  } catch (err) {
7304
8028
  console.error(`[specialists/done] Error managing specialist state:`, err);
@@ -7310,10 +8034,12 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7310
8034
  if (project) {
7311
8035
  const workspacePath = join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`);
7312
8036
  if (existsSync(workspacePath)) {
7313
- const { getWorkspaceGitInfo } = await import("./git-utils-D0_yhCgF.js");
7314
- const { HEAD } = await Effect.runPromise(getWorkspaceGitInfo(workspacePath));
7315
- setReviewStatusSync(normalizedIssueId, { reviewedAtCommit: HEAD });
7316
- console.log(`[specialists/done] Snapshotted reviewedAtCommit=${HEAD.substring(0, 8)} for ${normalizedIssueId}`);
8037
+ const { formatAnchorShort, snapshotWorkspaceHeadsPromise } = await import("./git-utils-CI6cwyyC.js");
8038
+ const headAnchor = await snapshotWorkspaceHeadsPromise(normalizedIssueId, workspacePath);
8039
+ if (headAnchor) {
8040
+ setReviewStatusSync(normalizedIssueId, { reviewedAtCommit: headAnchor });
8041
+ console.log(`[specialists/done] Snapshotted reviewedAtCommit=${formatAnchorShort(headAnchor)} for ${normalizedIssueId}`);
8042
+ }
7317
8043
  }
7318
8044
  }
7319
8045
  } catch (err) {
@@ -7322,11 +8048,11 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7322
8048
  });
7323
8049
  if (specialist === "inspect" && status === "passed") yield* Effect.promise(async () => {
7324
8050
  try {
7325
- const { onInspectComplete } = await import("./inspect-agent-Brtz0URj.js");
8051
+ const { onInspectComplete } = await import("./inspect-agent-BVwDrVrz.js");
7326
8052
  const project = resolveProjectFromIssueSync(normalizedIssueId);
7327
8053
  if (project) {
7328
8054
  const workspacePath = join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`);
7329
- if (existsSync(workspacePath)) await Effect.runPromise(onInspectComplete(project.projectKey, normalizedIssueId, itemId, "passed", workspacePath));
8055
+ if (existsSync(workspacePath)) await Effect.runPromise(onInspectComplete(project.projectKey, normalizedIssueId, itemId, "passed", workspacePath, notes));
7330
8056
  }
7331
8057
  } catch (err) {
7332
8058
  console.error(`[specialists/done] Error saving inspect checkpoint:`, err);
@@ -7338,7 +8064,7 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7338
8064
  if (project) {
7339
8065
  if (existsSync(join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`))) {
7340
8066
  setReviewStatusSync(normalizedIssueId, { testStatus: "passed" });
7341
- const { initEventStore } = await import("./event-store-EV2cMiXj.js");
8067
+ const { initEventStore } = await import("./event-store-ELqkVOn0.js");
7342
8068
  await (await initEventStore()).appendAsync({
7343
8069
  type: "test.passed",
7344
8070
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -7391,8 +8117,8 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7391
8117
  if (notes?.toLowerCase().includes("conflict")) yield* Effect.promise(async () => {
7392
8118
  try {
7393
8119
  const workAgentId = `agent-${normalizedIssueId.toLowerCase()}`;
7394
- const { sessionExists } = await import("./tmux-B6z7h_vZ.js");
7395
- const { messageAgent, spawnAgent, getAgentStateSync } = await import("./agents-wi9NWzs2.js");
8120
+ const { sessionExists } = await import("./tmux-DQ6jB76i.js");
8121
+ const { messageAgent, spawnAgent, getAgentStateSync } = await import("./agents-BKKkxKgK.js");
7396
8122
  if (await Effect.runPromise(sessionExists(workAgentId))) {
7397
8123
  await messageAgent(workAgentId, `MERGE CONFLICT: The merge-agent could not rebase your branch onto main due to conflicts. Please fix this now:\n\n1. git fetch origin main\n2. git rebase origin/main\n3. Resolve any conflicts (git add <file> && git rebase --continue)\n4. git push --force-with-lease\n5. Resubmit: curl -s -X POST http://localhost:3011/api/review/${normalizedIssueId}/request -H "Content-Type: application/json" -d "{}"\n\nConflict details: ${notes}`);
7398
8124
  console.log(`[specialists/done] Sent rebase instructions to ${workAgentId}`);
@@ -7406,19 +8132,38 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7406
8132
  try {
7407
8133
  const project = resolveProjectFromIssueSync(normalizedIssueId);
7408
8134
  const workspacePath = project ? join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`) : void 0;
7409
- const { deliverReviewVerdictFeedback } = await import("./review-verdict-feedback-CTd4QMBu.js");
8135
+ const { deliverReviewVerdictFeedback } = await import("./review-verdict-feedback-BPDn4li_.js");
7410
8136
  const result = await Effect.runPromise(deliverReviewVerdictFeedback({
7411
8137
  issueId: normalizedIssueId,
7412
8138
  verdict: status === "failed" ? "failed" : "blocked",
7413
8139
  notes,
7414
8140
  workspacePath,
7415
- prUrl: updatedStatus.prUrl
8141
+ prUrl: updatedStatus.prUrl,
8142
+ ...runId ? { runId } : {}
7416
8143
  }));
7417
8144
  console.log(`[specialists/done] Delivered review verdict feedback for ${normalizedIssueId} (feedback=${result.feedbackPath ?? "none"}, synthesis=${result.synthesisPath ?? "none"}, prComment=${result.prCommentPosted})`);
7418
8145
  } catch (err) {
7419
8146
  console.warn(`[specialists/done] Failed to deliver review verdict feedback: ${err.message}`);
7420
8147
  }
7421
8148
  });
8149
+ if (specialist === "review" && status === "failed") yield* Effect.promise(async () => {
8150
+ try {
8151
+ const project = resolveProjectFromIssueSync(normalizedIssueId);
8152
+ if (project) {
8153
+ const workspacePath = join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`);
8154
+ if (existsSync(workspacePath)) {
8155
+ const { formatAnchorShort, snapshotWorkspaceHeadsPromise } = await import("./git-utils-CI6cwyyC.js");
8156
+ const reviewedAtCommit = await snapshotWorkspaceHeadsPromise(normalizedIssueId, workspacePath);
8157
+ if (reviewedAtCommit) {
8158
+ setReviewStatusSync(normalizedIssueId, { reviewedAtCommit });
8159
+ console.log(`[specialists/done] Snapshotted blocked reviewedAtCommit=${formatAnchorShort(reviewedAtCommit)} for ${normalizedIssueId}`);
8160
+ }
8161
+ }
8162
+ }
8163
+ } catch (err) {
8164
+ console.error(`[specialists/done] Failed to snapshot blocked reviewedAtCommit for ${normalizedIssueId}:`, err);
8165
+ }
8166
+ });
7422
8167
  const eventRole = specialistEventRole(specialist);
7423
8168
  if (eventRole) if (status === "passed") yield* eventStore.append({
7424
8169
  type: "specialist.completed",
@@ -7447,7 +8192,7 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7447
8192
  });
7448
8193
  })));
7449
8194
  const postSpecialistsLogsCleanupAllRoute = HttpRouter.add("POST", "/api/specialists/logs/cleanup-all", httpHandler(Effect.gen(function* () {
7450
- const { cleanupAllLogsSync } = yield* Effect.promise(() => import("./specialist-logs-C5p8G7tx.js"));
8195
+ const { cleanupAllLogsSync } = yield* Effect.promise(() => import("./specialist-logs-Cl5-hqT8.js"));
7451
8196
  const results = cleanupAllLogsSync();
7452
8197
  return jsonResponse({
7453
8198
  success: true,
@@ -7457,7 +8202,7 @@ const postSpecialistsLogsCleanupAllRoute = HttpRouter.add("POST", "/api/speciali
7457
8202
  });
7458
8203
  })));
7459
8204
  const getSpecialistsProjectsRoute = HttpRouter.add("GET", "/api/specialists/projects", httpHandler(Effect.gen(function* () {
7460
- const { getAllProjectSpecialistStatuses } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8205
+ const { getAllProjectSpecialistStatuses } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7461
8206
  return jsonResponse(yield* Effect.promise(() => getAllProjectSpecialistStatuses()));
7462
8207
  })));
7463
8208
  const postSpecialistWakeRoute = HttpRouter.add("POST", "/api/specialists/:name/wake", httpHandler(Effect.gen(function* () {
@@ -7501,7 +8246,7 @@ const postSpecialistReportStatusRoute = HttpRouter.add("POST", "/api/specialists
7501
8246
  "blocked",
7502
8247
  "failed"
7503
8248
  ].includes(status)) {
7504
- const { getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8249
+ const { getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7505
8250
  saveAgentRuntimeState(getTmuxSessionName(name), {
7506
8251
  state: "idle",
7507
8252
  lastActivity: (/* @__PURE__ */ new Date()).toISOString()
@@ -7600,6 +8345,7 @@ const specialistsLegacyRouteLayer = Layer.mergeAll(getSpecialistsRoute, getSpeci
7600
8345
  //#endregion
7601
8346
  //#region routes/specialists/project-routes.ts
7602
8347
  init_config_yaml();
8348
+ init_project_repos();
7603
8349
  init_projects();
7604
8350
  init_review_status();
7605
8351
  init_tmux();
@@ -7622,7 +8368,7 @@ const postProjectSpecialistKillRoute = HttpRouter.add("POST", "/api/specialists/
7622
8368
  const issueId = params["issueId"];
7623
8369
  const type = params["type"];
7624
8370
  if (!validateSpecialistAgentName(type)) return jsonResponse({ error: "Invalid specialist type. Must be review-agent, test-agent, or merge-agent" }, { status: 400 });
7625
- const { getTmuxSessionName, makeSpecialistRegistryKey, getRunMetadata } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8371
+ const { getTmuxSessionName, makeSpecialistRegistryKey, getRunMetadata } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7626
8372
  const tmuxSession = getRunMetadata(project, makeSpecialistRegistryKey(type, issueId)).tmuxSession ?? getTmuxSessionName(type, project, issueId);
7627
8373
  yield* Effect.promise(() => Effect.runPromise(killSession(tmuxSession)).catch(() => {}));
7628
8374
  saveAgentRuntimeState(tmuxSession, {
@@ -7649,7 +8395,7 @@ const getProjectSpecialistRunsRoute = HttpRouter.add("GET", "/api/specialists/:p
7649
8395
  if (limitParam) limit = parseInt(limitParam, 10);
7650
8396
  if (offsetParam) offset = parseInt(offsetParam, 10);
7651
8397
  }
7652
- const { listRunLogsSync } = yield* Effect.promise(() => import("./specialist-logs-C5p8G7tx.js"));
8398
+ const { listRunLogsSync } = yield* Effect.promise(() => import("./specialist-logs-Cl5-hqT8.js"));
7653
8399
  return jsonResponse(listRunLogsSync(project, type, {
7654
8400
  limit,
7655
8401
  offset
@@ -7660,7 +8406,7 @@ const getProjectSpecialistRunStreamRoute = HttpRouter.add("GET", "/api/specialis
7660
8406
  const project = params["project"];
7661
8407
  const type = params["type"];
7662
8408
  const runId = params["runId"];
7663
- const { getRunLogPath, isRunLogActive } = yield* Effect.promise(() => import("./specialist-logs-C5p8G7tx.js"));
8409
+ const { getRunLogPath, isRunLogActive } = yield* Effect.promise(() => import("./specialist-logs-Cl5-hqT8.js"));
7664
8410
  const logPath = getRunLogPath(project, type, runId);
7665
8411
  if (!existsSync(logPath)) return jsonResponse({ error: "Run log not found" }, { status: 404 });
7666
8412
  const encoder = new TextEncoder();
@@ -7719,7 +8465,7 @@ const getProjectSpecialistRunRoute = HttpRouter.add("GET", "/api/specialists/:pr
7719
8465
  const project = params["project"];
7720
8466
  const type = params["type"];
7721
8467
  const runId = params["runId"];
7722
- const { getRunLogSync, parseLogMetadata } = yield* Effect.promise(() => import("./specialist-logs-C5p8G7tx.js"));
8468
+ const { getRunLogSync, parseLogMetadata } = yield* Effect.promise(() => import("./specialist-logs-Cl5-hqT8.js"));
7723
8469
  const content = getRunLogSync(project, type, runId);
7724
8470
  if (!content) return jsonResponse({ error: "Run log not found" }, { status: 404 });
7725
8471
  return jsonResponse({
@@ -7733,7 +8479,7 @@ const postProjectSpecialistRunTerminateRoute = HttpRouter.add("POST", "/api/spec
7733
8479
  const project = params["project"];
7734
8480
  const type = params["type"];
7735
8481
  if (!validateSpecialistAgentName(type)) return jsonResponse({ error: "Invalid specialist type. Must be review-agent, test-agent, or merge-agent" }, { status: 400 });
7736
- const { terminateSpecialist } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8482
+ const { terminateSpecialist } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7737
8483
  yield* Effect.promise(() => terminateSpecialist(project, type));
7738
8484
  return jsonResponse({
7739
8485
  success: true,
@@ -7745,7 +8491,7 @@ const postProjectSpecialistGracePauseRoute = HttpRouter.add("POST", "/api/specia
7745
8491
  const project = params["project"];
7746
8492
  const type = params["type"];
7747
8493
  if (!validateSpecialistAgentName(type)) return jsonResponse({ error: "Invalid specialist type. Must be review-agent, test-agent, or merge-agent" }, { status: 400 });
7748
- const { pauseGracePeriod } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8494
+ const { pauseGracePeriod } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7749
8495
  if (pauseGracePeriod(project, type)) return jsonResponse({
7750
8496
  success: true,
7751
8497
  message: "Grace period paused"
@@ -7757,7 +8503,7 @@ const postProjectSpecialistGraceResumeRoute = HttpRouter.add("POST", "/api/speci
7757
8503
  const project = params["project"];
7758
8504
  const type = params["type"];
7759
8505
  if (!validateSpecialistAgentName(type)) return jsonResponse({ error: "Invalid specialist type. Must be review-agent, test-agent, or merge-agent" }, { status: 400 });
7760
- const { resumeGracePeriod } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8506
+ const { resumeGracePeriod } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7761
8507
  if (resumeGracePeriod(project, type)) return jsonResponse({
7762
8508
  success: true,
7763
8509
  message: "Grace period resumed"
@@ -7769,7 +8515,7 @@ const postProjectSpecialistGraceExitRoute = HttpRouter.add("POST", "/api/special
7769
8515
  const project = params["project"];
7770
8516
  const type = params["type"];
7771
8517
  if (!validateSpecialistAgentName(type)) return jsonResponse({ error: "Invalid specialist type. Must be review-agent, test-agent, or merge-agent" }, { status: 400 });
7772
- const { exitGracePeriod } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8518
+ const { exitGracePeriod } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7773
8519
  exitGracePeriod(project, type);
7774
8520
  return jsonResponse({
7775
8521
  success: true,
@@ -7781,7 +8527,7 @@ const getProjectSpecialistGraceRoute = HttpRouter.add("GET", "/api/specialists/:
7781
8527
  const project = params["project"];
7782
8528
  const type = params["type"];
7783
8529
  if (!validateSpecialistAgentName(type)) return jsonResponse({ error: "Invalid specialist type. Must be review-agent, test-agent, or merge-agent" }, { status: 400 });
7784
- const { getGracePeriodState } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8530
+ const { getGracePeriodState } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7785
8531
  const state = getGracePeriodState(project, type);
7786
8532
  if (state) return jsonResponse(state);
7787
8533
  else return jsonResponse({ error: "No active grace period" }, { status: 404 });
@@ -7790,7 +8536,7 @@ const getProjectSpecialistContextRoute = HttpRouter.add("GET", "/api/specialists
7790
8536
  const params = yield* HttpRouter.params;
7791
8537
  const project = params["project"];
7792
8538
  const type = params["type"];
7793
- const { loadContextDigest } = yield* Effect.promise(() => import("./specialist-context-Bn3dCGS2.js"));
8539
+ const { loadContextDigest } = yield* Effect.promise(() => import("./specialist-context-cVbGnTa3.js"));
7794
8540
  const digest = loadContextDigest(project, type);
7795
8541
  if (digest) return jsonResponse({ digest });
7796
8542
  else return jsonResponse({ error: "No context digest found" }, { status: 404 });
@@ -7799,7 +8545,7 @@ const postProjectSpecialistContextRegenerateRoute = HttpRouter.add("POST", "/api
7799
8545
  const params = yield* HttpRouter.params;
7800
8546
  const project = params["project"];
7801
8547
  const type = params["type"];
7802
- const { regenerateContextDigest } = yield* Effect.promise(() => import("./specialist-context-Bn3dCGS2.js"));
8548
+ const { regenerateContextDigest } = yield* Effect.promise(() => import("./specialist-context-cVbGnTa3.js"));
7803
8549
  const digest = yield* Effect.promise(() => regenerateContextDigest(project, type));
7804
8550
  if (digest) return jsonResponse({
7805
8551
  digest,
@@ -7818,7 +8564,7 @@ const postProjectSpecialistCompleteRoute = HttpRouter.add("POST", "/api/speciali
7818
8564
  "blocked"
7819
8565
  ].includes(status)) return jsonResponse({ error: "Valid status (passed/failed/blocked) is required" }, { status: 400 });
7820
8566
  if (!validateSpecialistAgentName(type)) return jsonResponse({ error: "Invalid specialist type. Must be review-agent, test-agent, or merge-agent" }, { status: 400 });
7821
- const { signalSpecialistCompletion } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8567
+ const { signalSpecialistCompletion } = yield* Effect.promise(() => import("./specialists-Tdezg_6N.js"));
7822
8568
  signalSpecialistCompletion(project, type, {
7823
8569
  status,
7824
8570
  notes
@@ -7852,8 +8598,8 @@ const postProjectSpecialistLogsCleanupRoute = HttpRouter.add("POST", "/api/speci
7852
8598
  const params = yield* HttpRouter.params;
7853
8599
  const project = params["project"];
7854
8600
  const type = params["type"];
7855
- const { cleanupOldLogsSync } = yield* Effect.promise(() => import("./specialist-logs-C5p8G7tx.js"));
7856
- const { getSpecialistRetention } = yield* Effect.promise(() => import("./projects-vjjcmiN8.js"));
8601
+ const { cleanupOldLogsSync } = yield* Effect.promise(() => import("./specialist-logs-Cl5-hqT8.js"));
8602
+ const { getSpecialistRetention } = yield* Effect.promise(() => import("./projects-B03Wr-xc.js"));
7857
8603
  const retention = getSpecialistRetention(project);
7858
8604
  const deleted = cleanupOldLogsSync(project, type, {
7859
8605
  maxDays: retention.max_days,
@@ -7874,21 +8620,23 @@ const postProjectReviewRestartRoute = HttpRouter.add("POST", "/api/specialists/:
7874
8620
  const project = params["project"];
7875
8621
  const issueId = params["issueId"];
7876
8622
  const { model, harness } = yield* readJsonBody;
7877
- const { killAllReviewerSessions } = yield* Effect.promise(() => import("./review-agent-DNboMyW4.js"));
8623
+ const { killAllReviewerSessions } = yield* Effect.promise(() => import("./review-agent-CD4RCI0Y.js"));
7878
8624
  const killResult = yield* killAllReviewerSessions(project, issueId);
7879
8625
  const projectConfig = resolveProjectFromIssueSync(issueId);
7880
8626
  if (!projectConfig) return jsonResponse({ error: `Cannot resolve project for ${issueId}` }, { status: 404 });
7881
8627
  const workspacePath = join(projectConfig.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
7882
8628
  if (!existsSync(workspacePath)) return jsonResponse({ error: `Workspace not found: ${workspacePath}` }, { status: 404 });
7883
- let branch = "unknown";
8629
+ const primaryRepo = resolveWorkspaceRepoRootsSync(issueId, workspacePath)[0];
8630
+ let branch = primaryRepo.sourceBranch;
7884
8631
  try {
7885
- const { stdout } = yield* Effect.promise(() => execAsync(`cd "${workspacePath}" && git branch --show-current`, {
8632
+ const { stdout } = yield* Effect.promise(() => execAsync("git branch --show-current", {
8633
+ cwd: resolvePrimaryWorkspaceRepoDirSync(issueId, workspacePath),
7886
8634
  encoding: "utf-8",
7887
8635
  timeout: 5e3
7888
8636
  }));
7889
- branch = stdout.trim() || "unknown";
8637
+ branch = stdout.trim() || primaryRepo.sourceBranch;
7890
8638
  } catch {}
7891
- const { spawnReviewRoleForIssue } = yield* Effect.promise(() => import("./review-agent-DNboMyW4.js"));
8639
+ const { spawnReviewRoleForIssue } = yield* Effect.promise(() => import("./review-agent-CD4RCI0Y.js"));
7892
8640
  const prUrl = getReviewStatusSync(issueId)?.prUrl;
7893
8641
  const result = yield* spawnReviewRoleForIssue({
7894
8642
  issueId,
@@ -8037,6 +8785,6 @@ const specialistsProjectRouteLayer = Layer.mergeAll(getProjectSpecialistStatusRo
8037
8785
  */
8038
8786
  const specialistsRouteLayer = Layer.mergeAll(specialistsLegacyRouteLayer, specialistsProjectRouteLayer);
8039
8787
  //#endregion
8040
- export { panCliInvocation as $, resolveAllowedHarness as A, cleanupUnreferencedConversationAttachments as B, handleConversationCreate as C, jsonStringResponse as Ct, handleConversationStop as D, handleConversationResume as E, tmuxSessionExists as F, isManagedConversationAttachmentPath as G, extractConversationAttachmentPaths as H, waitForPiTuiReady as I, evaluateSpawnGuardrails as J, removeConversationAttachment as K, waitForTmuxSession as L, spawnConversationSession as M, startConversationModelBackfill as N, handleConversationSwitchModel as O, stopConversationRuntime as P, getWorkAgentLifecycleStateSync as Q, cleanupConversationAttachments as R, conversationSessionAliveFromState as S, jsonResponse as St, handleConversationRestartAll as T, getConversationAttachmentsRoot as U, ensureConversationAttachmentDir as V, hasConversationAttachment as W, resolveAgentGitInfo as X, invalidateAgentsCache as Y, resolveConversationGitInfo as Z, isPiControlChannelHarness as _, isTrustedOriginForHost as _t, agentsRouteLayer as a, resolveCodexRolloutPath as at, validateConversationControlAckOrigin as b, httpHandler as bt, codexConversationPendingInput as c, dashboardCsrfToken as ct, handleConversationCodexApproval as d, rejectUnauthorizedDashboardRequest as dt, spawnPanCli as et, handleConversationCompact as f, rejectUnauthorizedDashboardSessionMintRequest as ft, handleConversationThinkingLevel as g, getHeaderFromMap as gt, handleConversationPlanAction as h, waitForSessionRespawn as ht, validateSpecialistAutoCompleteMetadata as i, resolveClaudeSessionId as it, shouldReportUnresolvedLiveSession as j, isInsideGitWorkTree as k, deliverConversationViaControlChannel as l, dashboardSessionCookieHeader as lt, handleConversationDeliveryMethod as m, isRespawnPending as mt, _serverManagedMerges as n, resolveAcpTranscriptPath as nt, saveAgentStateAndEmitEvent as o, resolveJsonlPath as ot, handleConversationControlAck as p, rejectUnsafeDashboardMutationRequest as pt, runInBatches as q, firePostMergeLifecycle as r, resolveAgentHarness as rt, saveAgentStateAndEmitEventProgram as s, resolvePiSessionPath as st, specialistsRouteLayer as t, readLauncherPinnedSessionId as tt, handleConversationAbort as u, hasDashboardInternalToken as ut, pickDeliverAs as v, validateOrigin as vt, handleConversationDelete as w, conversationNeedsRunningRepair as x, getDefaultCwd as xt, resolveConversationDeliveryMethod as y, validateOriginHeaders as yt, cleanupOrphanedConversationAttachments as z };
8788
+ export { composerCommandConfirmationFromBody as $, resolveAllowedHarness as A, cleanupUnreferencedConversationAttachments as B, handleConversationCreate as C, isTrustedOriginForHost as Ct, handleConversationStop as D, getDefaultCwd as Dt, handleConversationResume as E, httpHandler as Et, tmuxSessionExists as F, isManagedConversationAttachmentPath as G, extractConversationAttachmentPaths as H, waitForPiTuiReady as I, composerCommandResultHttpStatus as J, removeConversationAttachment as K, waitForTmuxSession as L, spawnConversationSession as M, startConversationModelBackfill as N, handleConversationSwitchModel as O, jsonResponse as Ot, stopConversationRuntime as P, ComposerCommandConfirmationError as Q, cleanupConversationAttachments as R, conversationSessionAliveFromState as S, getHeaderFromMap as St, handleConversationRestartAll as T, validateOriginHeaders as Tt, getConversationAttachmentsRoot as U, ensureConversationAttachmentDir as V, hasConversationAttachment as W, resolvePolicy as X, handleComposerCommandMessage as Y, ComposerCommandParseError as Z, isPiControlChannelHarness as _, rejectUnauthorizedDashboardRequest as _t, agentsRouteLayer as a, panCliInvocation as at, validateConversationControlAckOrigin as b, isRespawnPending as bt, codexConversationPendingInput as c, resolveAcpTranscriptPath as ct, handleConversationCodexApproval as d, resolveCodexRolloutPath as dt, evaluateSpawnGuardrails as et, handleConversationCompact as f, resolveJsonlPath as ft, handleConversationThinkingLevel as g, hasDashboardInternalToken as gt, handleConversationPlanAction as h, dashboardSessionCookieHeader as ht, validateSpecialistAutoCompleteMetadata as i, getWorkAgentLifecycleStateSync as it, shouldReportUnresolvedLiveSession as j, isInsideGitWorkTree as k, jsonStringResponse as kt, deliverConversationViaControlChannel as l, resolveAgentHarness as lt, handleConversationDeliveryMethod as m, dashboardCsrfToken as mt, _serverManagedMerges as n, resolveAgentGitInfo as nt, saveAgentStateAndEmitEvent as o, spawnPanCli as ot, handleConversationControlAck as p, resolvePiSessionPath as pt, runInBatches as q, firePostMergeLifecycle as r, resolveConversationGitInfo as rt, saveAgentStateAndEmitEventProgram as s, readLauncherPinnedSessionId as st, specialistsRouteLayer as t, invalidateAgentsCache as tt, handleConversationAbort as u, resolveClaudeSessionId as ut, pickDeliverAs as v, rejectUnauthorizedDashboardSessionMintRequest as vt, handleConversationDelete as w, validateOrigin as wt, conversationNeedsRunningRepair as x, waitForSessionRespawn as xt, resolveConversationDeliveryMethod as y, rejectUnsafeDashboardMutationRequest as yt, cleanupOrphanedConversationAttachments as z };
8041
8789
 
8042
- //# sourceMappingURL=specialists-CC4r-c2s.js.map
8790
+ //# sourceMappingURL=specialists-CNfYO3G2.js.map