@overdeck/desktop 0.45.24 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/drizzle/overdeck/0000_overdeck_init.sql +36 -1
  2. package/package.json +1 -1
  3. package/server/{acceptance-criteria-DDCnXF58.js → acceptance-criteria-10Ur5Dne.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-BNwqxseD.js} +6 -6
  7. package/server/{agent-gc-CHcnvonI.js → agent-gc-C3h9Or3a.js} +5 -5
  8. package/server/agent-state-CYXJVG72.js +3 -0
  9. package/server/agent-state-service-C63p_ftq.js +2 -0
  10. package/server/{agent-state-service-BsgWxZuB.js → agent-state-service-Ds6OeFvo.js} +15 -9
  11. package/server/{agents-EbI0zCJl.js → agents-J5mEnekq.js} +23 -16
  12. package/server/agents-ePFVoZbu.js +3 -0
  13. package/server/archive-planning-B2XplFzT.js +2 -0
  14. package/server/{archive-planning-Du25Jtst.js → archive-planning-BwhxeP7C.js} +22 -26
  15. package/server/{artifact-index-jobs-CbEDfCDu.js → artifact-index-jobs-D1q_vR3V.js} +2 -2
  16. package/server/{assemble-J2ZZ2C15.js → assemble-Bgwqv-Ro.js} +2 -2
  17. package/server/auto-spawn-consent-CQ9Bi9q6.js +1141 -0
  18. package/server/{backlog-auto-trigger-2R2jog7n.js → backlog-auto-trigger-n1lzPgN4.js} +3 -3
  19. package/server/{behavior-B3exJ42O.js → behavior-td6-xhQk.js} +2 -2
  20. package/server/boot-reconciled-stop-events-C7gGe3oB.js +44 -0
  21. package/server/bridge-pool-patrol-CYH2OLb5.js +136 -0
  22. package/server/{briefing-freshness-D1wzUIWv.js → briefing-freshness-DRqZ8lAz.js} +2 -2
  23. package/server/{build-info-Ie_D0_BT.js → build-info-7yiEpl6u.js} +5 -3
  24. package/server/{build-info-CZk_TITh.js → build-info-CpG__c63.js} +1 -1
  25. package/server/{checkpoint-manager-DwbQoqrC.js → checkpoint-manager-CkKmB0wZ.js} +1 -1
  26. package/server/{checkpoint-manager-BI1Wxoku.js → checkpoint-manager-DBcyNR8w.js} +2 -2
  27. package/server/checkpoint-worker.js +1 -1
  28. package/server/{checkpoints-CQB1h765.js → checkpoints-D95apurL.js} +2 -2
  29. package/server/{checkpoints-BJIs5QIA.js → checkpoints-Wm963lm8.js} +1 -1
  30. package/server/{claude-hooks-provision-8Ngo8TpT.js → claude-hooks-provision-4RPxNkE8.js} +1 -1
  31. package/server/{claude-hooks-provision-D8GXF3_s.js → claude-hooks-provision-Bjitl9aI.js} +13 -2
  32. package/server/{claude-permissions-DNWEVV6z.js → claude-permissions-CpbpvUQ2.js} +2 -2
  33. package/server/{claude-settings-overlay-DWy-Bb4Y.js → claude-settings-overlay-BzkHYDwR.js} +1 -1
  34. package/server/{claude-settings-overlay-CEdaqpWI.js → claude-settings-overlay-_H9Yrzab.js} +2 -2
  35. package/server/cli-CjOCSnfj.js +3 -0
  36. package/server/{cli-RoOx5DUf.js → cli-Cte9ZFGn.js} +9 -9
  37. package/server/{cliproxy-C8a1vtTU.js → cliproxy-C5fMJ7rY.js} +2 -2
  38. package/server/{cliproxy-fHfIeiGd.js → cliproxy-DaAbWMjC.js} +1 -1
  39. package/server/{close-issue-DoOifFIK.js → close-issue-BPh1ARCF.js} +5 -5
  40. package/server/{closed-issue-reaper-CktPXo8m.js → closed-issue-reaper-DHRfRMrp.js} +1 -1
  41. package/server/{closed-issue-reaper-Bk3SU4RC.js → closed-issue-reaper-DoOZqGFK.js} +88 -17
  42. package/server/{codex-BZXGhUVB.js → codex-BzGDW_d3.js} +36 -7
  43. package/server/{codex-GcHuUF-k.js → codex-o8FJwzmy.js} +1 -1
  44. package/server/{codex-parser-CFZ1_1Jl.js → codex-parser-Dt-ycU8L.js} +2 -2
  45. package/server/compaction-continuation-CvXpbZ4w.js +200 -0
  46. package/server/{config-CKxYiCmX.js → config-Bi3u1VK7.js} +4 -3
  47. package/server/{config-BZ0sHTju.js → config-BvLe652W.js} +2 -2
  48. package/server/{config-DzV30TOm.js → config-CL3Gyvja.js} +1 -1
  49. package/server/{config-yaml-DySPNmKN.js → config-yaml-CxdwhAIA.js} +276 -14
  50. package/server/conflict-gate-CX80JYYS.js +3 -0
  51. package/server/{conflict-gate-BaCVrH-N.js → conflict-gate-E4nt7ZeS.js} +60 -14
  52. package/server/{context-layers-igZ4FI4_.js → context-layers-C_IIysnm.js} +3 -3
  53. package/server/{context-layers-BrPmE__h.js → context-layers-DAG83UZt.js} +2 -2
  54. package/server/{control-settings-BQp7_4uD.js → control-settings-CiqGxXnc.js} +56 -19
  55. package/server/{conversation-compaction-eQB5CkOe.js → conversation-compaction-BE3CNtHF.js} +1 -1
  56. package/server/{conversation-compaction-CgrR8YYp.js → conversation-compaction-D6-yLtqt.js} +8 -8
  57. package/server/{conversation-service-DPJ71F33.js → conversation-service-DBxoYMDl.js} +10 -8
  58. package/server/conversation-service-D_TS2b1r.js +3 -0
  59. package/server/{conversations-CAsJF9kh.js → conversations-BKDVpB-3.js} +1 -1
  60. package/server/{conversations-6AfUfbwc.js → conversations-D0UEdLtk.js} +4 -4
  61. package/server/{cost-R-m6Yi-W.js → cost-DS1s0DbG.js} +3 -3
  62. package/server/{cost-B2ddP6wq.js → cost-DpgYmYqR.js} +12 -2
  63. package/server/{cost-sync-BsN6ER0n.js → cost-sync-tOCCGnEt.js} +3 -3
  64. package/server/{dag-B1ucnjDU.js → dag-BtkgLeqY.js} +2 -2
  65. package/server/{dangerous-git-ops-BXqeWVSf.js → dangerous-git-ops-CFLykHWt.js} +1 -1
  66. package/server/dashboard-db-worker.js +7 -7
  67. package/server/deacon-BIblC-WX.js +4 -0
  68. package/server/{deacon-nudge-log-6wVqAaqz.js → deacon-nudge-log-B08gF0mh.js} +3 -3
  69. package/server/{deacon-CU_cAYSR.js → deacon-pLRLbPvR.js} +3308 -2707
  70. package/server/deacon-pending-lifecycle-B-Io84AP.js +33 -0
  71. package/server/deacon-swarm-B1XkIvfr.js +2 -0
  72. package/server/{deacon-swarm-BXZZ1Z2-.js → deacon-swarm-v5PMun-m.js} +15 -14
  73. package/server/deacon.js +14 -19
  74. package/server/dead-end-trip-D8A3msX9.js +13 -0
  75. package/server/delivery-BX9HR4wQ.js +3 -0
  76. package/server/{deploy-patrol-AiFoP8dw.js → deploy-patrol-sYgOxLeb.js} +69 -18
  77. package/server/deploy-queue-VfohaPN_.js +169 -0
  78. package/server/deploy-queue-gHJBycaF.js +3 -0
  79. package/server/deploy-window-CFRZ0-kt.js +3 -0
  80. package/server/{deploy-window-C3F-tihF.js → deploy-window-D4DQb8VP.js} +40 -16
  81. package/server/{dev-supervisor-bcOWqdQE.js → dev-supervisor-DiOBDM1c.js} +2 -2
  82. package/server/{devcontainer-renderer-_d6XhyND.js → devcontainer-renderer-BUOIlfgD.js} +3 -3
  83. package/server/dist-B3YPQa5A.js +3 -0
  84. package/server/{dist-Cb_0uvpS.js → dist-C3A8B8wM.js} +1 -1
  85. package/server/{dist-src-BSoS7mkd.js → dist-src-C0adpegX.js} +1 -1
  86. package/server/{docker-DcMTFTUC.js → docker-BJzlkqYB.js} +2 -2
  87. package/server/docker-Y3PElJb0.js +3 -0
  88. package/server/dod-DlNtcH6n.js +91 -0
  89. package/server/durable-review-pipeline-Cibps-Rg.js +20 -0
  90. package/server/durable-review-pipeline-DP6bIcOY.js +3 -0
  91. package/server/{ensure-devcontainer-DNi-ono3.js → ensure-devcontainer-BAofzBPv.js} +4 -4
  92. package/server/{ensure-devcontainer-BZgOhRo7.js → ensure-devcontainer-DMAbWqtQ.js} +1 -1
  93. package/server/{esm-shims-OSHAYaS1.js → esm-shims-BeObUkaw.js} +1 -1
  94. package/server/{event-store-EV2cMiXj.js → event-store-5UKzh9Jf.js} +1 -1
  95. package/server/{event-store-CQL6NeqB.js → event-store-CrHcVC5_.js} +23 -4
  96. package/server/{events-DTfAe4My.js → events-BNrvchBg.js} +3 -3
  97. package/server/{events-BTdrdEq8.js → events-CF8QDbuV.js} +1 -1
  98. package/server/{factory-CFibJuaw.js → factory-Cmm9Hsho.js} +5 -5
  99. package/server/{feature-registry-population-DKZFMbFt.js → feature-registry-population-B6HpNWRy.js} +4 -4
  100. package/server/{feature-registry-storage-BdPuLcBX.js → feature-registry-storage-DJEFx1Pf.js} +2 -2
  101. package/server/{features-ez2271oH.js → features-D5km80UI.js} +2 -2
  102. package/server/{feedback-target-CoFDHiM8.js → feedback-target-BJ5ZADsu.js} +1 -1
  103. package/server/{feedback-target-7mqqwrX6.js → feedback-target-DSxEL6lP.js} +8 -8
  104. package/server/{feedback-writer-CY5L1lB7.js → feedback-writer-C27Hak8a.js} +5 -5
  105. package/server/{feedback-writer-D3a22RCd.js → feedback-writer-CoB9Z6aU.js} +1 -1
  106. package/server/{flywheel-DHrgCphM.js → flywheel-BHx8XuMr.js} +47 -20
  107. package/server/{flywheel-SVF02Jpq.js → flywheel-DZZdtiOL.js} +1 -1
  108. package/server/{flywheel-DzGtWnJ1.js → flywheel-f662Q-y2.js} +16 -15
  109. package/server/flywheel-merge-order-D_xLMbJU.js +462 -0
  110. package/server/flywheel-merge-order-Dil0LmdN.js +2 -0
  111. package/server/forge-B5o319qI.js +3 -0
  112. package/server/forge-BaKGCya6.js +383 -0
  113. package/server/{from-kNxT0bZC.js → from-B3tZbB55.js} +1 -1
  114. package/server/fs-lock-Bre3sGoz.js +130 -0
  115. package/server/{fts-db-CE46vDkZ.js → fts-db-IVc4_M3f.js} +2 -2
  116. package/server/{fts-operations-CqY6zl-i.js → fts-operations-B9jG8wa3.js} +2 -2
  117. package/server/{git-utils-CRw2zLPC.js → git-utils-CsvYfJU3.js} +30 -5
  118. package/server/git-utils-Xg4PFN45.js +3 -0
  119. package/server/{github-app-ClZ2lk8D.js → github-app-Bmg4R9mv.js} +1 -1
  120. package/server/{github-app-C3QrAUd0.js → github-app-CmNk0zLU.js} +3 -3
  121. package/server/{github-client-DfQYVUaw.js → github-client-B6KM9_wA.js} +1 -1
  122. package/server/{github-client-BnIsSrEN.js → github-client-qazkPrg0.js} +3 -3
  123. package/server/github-pr-lookup-DAcVeRLK.js +58 -0
  124. package/server/{harness-binary-DPUi-Pv8.js → harness-binary-BSpiXaLw.js} +2 -2
  125. package/server/{harness-resolve-3lNZkyT4.js → harness-resolve-BAJu5MX8.js} +4 -4
  126. package/server/{health-events-BDOHby5Q.js → health-events-2Z6Wa9SM.js} +1 -1
  127. package/server/{health-events-BBcTYQKU.js → health-events-BwX32k8d.js} +2 -2
  128. package/server/{hooks-DPVX1rwQ.js → hooks-D1g1jKLI.js} +1 -1
  129. package/server/{hooks-CKZgXlJb.js → hooks-DbtbimEf.js} +2 -2
  130. package/server/{hume-Cz8igP9E.js → hume-DXNiu6nQ.js} +2 -2
  131. package/server/hume-VUCNbTgn.js +3 -0
  132. package/server/{idle-stack-reaper-CuLF0j2H.js → idle-stack-reaper-CRA1e0jr.js} +1 -1
  133. package/server/{idle-stack-reaper-DDIRwxUY.js → idle-stack-reaper-Cy-dQzW4.js} +99 -6
  134. package/server/in-flight-guard-D-sSkADM.js +45 -0
  135. package/server/{infra-BEqFxlJc.js → infra-BDQDRopn.js} +81 -5
  136. package/server/{injection-C8aiVJrF.js → injection-6AGnXxlj.js} +7 -7
  137. package/server/{injection-CPUIqNhI.js → injection-Bl8d_jHZ.js} +1 -1
  138. package/server/inspect-agent-CUwVmr2h.js +2 -0
  139. package/server/{inspect-agent-BLuJ1AkT.js → inspect-agent-nXdIptyh.js} +26 -25
  140. package/server/{internal-token-s0-oKybJ.js → internal-token-DzK385vD.js} +2 -2
  141. package/server/{internal-token-BrcU6qfe.js → internal-token-Ias7N8Kg.js} +1 -1
  142. package/server/{io-C9kF1wtJ.js → io-B00PBNku.js} +44 -27
  143. package/server/{issue-closed-CDJk4pIp.js → issue-closed-BehTG1be.js} +8 -8
  144. package/server/{issue-lifecycle-ojZAzDBP.js → issue-lifecycle-Birk-ifu.js} +42 -30
  145. package/server/{issue-lifecycle-B8sZHVHh.js → issue-lifecycle-BqSuQvbn.js} +1 -1
  146. package/server/{issue-service-singleton-BvJ09SaR.js → issue-service-singleton-B2wXiIlw.js} +1 -1
  147. package/server/{issue-service-singleton-Yx5DdmVJ.js → issue-service-singleton-C6ZduvuY.js} +10 -10
  148. package/server/{issues-BMmP_77e.js → issues-DQ5-LatB.js} +2 -2
  149. package/server/{jsonl-parser-BXSlHwEh.js → jsonl-parser-BDpnGFCl.js} +5 -4
  150. package/server/{label-cleanup-B0UJwnv5.js → label-cleanup-Dwnky8FG.js} +3 -3
  151. package/server/{lifecycle-xmBfK2GJ.js → lifecycle-B3s4sM1G.js} +6 -7
  152. package/server/{lifecycle-yPd___5E.js → lifecycle-B4Xdb4cY.js} +2 -2
  153. package/server/{lifecycle-io-DPo7x11I.js → lifecycle-io-CzTHEooc.js} +1 -1
  154. package/server/{lifecycle-io-BREGpnLk.js → lifecycle-io-DCo6s6ks.js} +5 -5
  155. package/server/{linear-client-BsuUvkdA.js → linear-client-9uq7fhiV.js} +3 -3
  156. package/server/{linear-client-CTskEeT_.js → linear-client-CnbtHiic.js} +1 -1
  157. package/server/linear-mcp-auth-BxUOzswy.js +280 -0
  158. package/server/linear-mcp-auth-D46fBCLf.js +2 -0
  159. package/server/memory-fts-worker.js +1 -1
  160. package/server/{merge-CefQNAnq.js → merge-DiW9RdSB.js} +13 -11
  161. package/server/{merge-agent-4WOWlSYA.js → merge-agent-BLUgRsz3.js} +234 -84
  162. package/server/{merge-agent-CKkgIBPB.js → merge-agent-DQTXZk8z.js} +1 -1
  163. package/server/{merge-batch-ClFn2T-y.js → merge-batch-Cp_j9BGk.js} +1 -1
  164. package/server/merge-completeness-B46KqhtY.js +277 -0
  165. package/server/merge-completeness-BLbB5-6n.js +3 -0
  166. package/server/merge-ops-1abz6O_P.js +2 -0
  167. package/server/merge-rebase-CJJVAJuz.js +2 -0
  168. package/server/{merge-rebase-BfaTyXsw.js → merge-rebase-DIkBjgwq.js} +3 -3
  169. package/server/{merge-set-DJ8-UErs.js → merge-set-CBgHfwM0.js} +11 -5
  170. package/server/merge-set-DeUxFsC3.js +3 -0
  171. package/server/{merge-B1DiziGU.js → merge-sr8Nrnmi.js} +1 -1
  172. package/server/merge-sync-CpGmk6Ch.js +3 -0
  173. package/server/{merge-sync-VPV28g0g.js → merge-sync-kr4vqyjM.js} +409 -153
  174. package/server/{merge-train-CHopycP0.js → merge-train-Dmrcus12.js} +18 -8
  175. package/server/{merge-train-deps-D1cOZzy2.js → merge-train-deps-D_uGX91G.js} +21 -15
  176. package/server/merge-verification-NvaAd8CZ.js +220 -0
  177. package/server/merged-docker-cleanup-worker-DH_hrGPI.js +3 -0
  178. package/server/merged-docker-cleanup-worker-Y1R06TEl.js +107 -0
  179. package/server/{multipart-parser-duPAfSBw.js → multipart-parser-R-oC8dQg.js} +2 -2
  180. package/server/{no-resume-mode-Nw29vaFb.js → no-resume-mode-BgD0JUmM.js} +1 -1
  181. package/server/node_modules/.package-lock.json +30 -30
  182. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/package.json +3 -3
  183. package/server/node_modules/@google-cloud/common/package.json +2 -2
  184. package/server/node_modules/@types/node/README.md +1 -1
  185. package/server/node_modules/@types/node/crypto.d.ts +1 -1
  186. package/server/node_modules/@types/node/package.json +2 -2
  187. package/server/node_modules/gaxios/build/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  188. package/server/node_modules/gaxios/build/esm/tsconfig.tsbuildinfo +1 -1
  189. package/server/node_modules/gaxios/package.json +1 -1
  190. package/server/node_modules/google-auth-library/build/src/auth/googleauth.js +24 -19
  191. package/server/node_modules/google-auth-library/package.json +1 -1
  192. package/server/node_modules/google-gax/build/protos/google/api/auth.proto +2 -1
  193. package/server/node_modules/google-gax/build/protos/google/api/backend.proto +12 -1
  194. package/server/node_modules/google-gax/build/protos/google/api/billing.proto +1 -1
  195. package/server/node_modules/google-gax/build/protos/google/api/client.proto +165 -53
  196. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1/resources.proto +1 -1
  197. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1beta/quota_adjuster_settings.proto +7 -3
  198. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1beta/resources.proto +1 -1
  199. package/server/node_modules/google-gax/build/protos/google/api/config_change.proto +1 -1
  200. package/server/node_modules/google-gax/build/protos/google/api/context.proto +1 -1
  201. package/server/node_modules/google-gax/build/protos/google/api/control.proto +3 -3
  202. package/server/node_modules/google-gax/build/protos/google/api/distribution.proto +1 -1
  203. package/server/node_modules/google-gax/build/protos/google/api/documentation.proto +1 -1
  204. package/server/node_modules/google-gax/build/protos/google/api/endpoint.proto +1 -1
  205. package/server/node_modules/google-gax/build/protos/google/api/error_reason.proto +186 -1
  206. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/checked.proto +31 -3
  207. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/eval.proto +8 -9
  208. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/explain.proto +1 -2
  209. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/syntax.proto +20 -22
  210. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/value.proto +2 -3
  211. package/server/node_modules/google-gax/build/protos/google/api/field_behavior.proto +1 -1
  212. package/server/node_modules/google-gax/build/protos/google/api/field_info.proto +1 -1
  213. package/server/node_modules/google-gax/build/protos/google/api/http.proto +1 -1
  214. package/server/node_modules/google-gax/build/protos/google/api/httpbody.proto +1 -1
  215. package/server/node_modules/google-gax/build/protos/google/api/label.proto +1 -1
  216. package/server/node_modules/google-gax/build/protos/google/api/launch_stage.proto +1 -1
  217. package/server/node_modules/google-gax/build/protos/google/api/log.proto +1 -1
  218. package/server/node_modules/google-gax/build/protos/google/api/logging.proto +1 -1
  219. package/server/node_modules/google-gax/build/protos/google/api/metric.proto +1 -1
  220. package/server/node_modules/google-gax/build/protos/google/api/monitored_resource.proto +1 -1
  221. package/server/node_modules/google-gax/build/protos/google/api/monitoring.proto +1 -1
  222. package/server/node_modules/google-gax/build/protos/google/api/policy.proto +1 -1
  223. package/server/node_modules/google-gax/build/protos/google/api/quota.proto +1 -1
  224. package/server/node_modules/google-gax/build/protos/google/api/resource.proto +1 -1
  225. package/server/node_modules/google-gax/build/protos/google/api/routing.proto +8 -4
  226. package/server/node_modules/google-gax/build/protos/google/api/service.proto +2 -3
  227. package/server/node_modules/google-gax/build/protos/google/api/source_info.proto +1 -1
  228. package/server/node_modules/google-gax/build/protos/google/api/system_parameter.proto +1 -1
  229. package/server/node_modules/google-gax/build/protos/google/api/usage.proto +7 -27
  230. package/server/node_modules/google-gax/build/protos/google/api/visibility.proto +1 -1
  231. package/server/node_modules/google-gax/build/protos/google/longrunning/operations.proto +20 -1
  232. package/server/node_modules/google-gax/build/protos/google/protobuf/any.proto +52 -108
  233. package/server/node_modules/google-gax/build/protos/google/protobuf/compiler/ruby/ruby_generated_code.proto +2 -0
  234. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_features.proto +21 -1
  235. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_file_options.proto +24 -0
  236. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_options.proto +15 -0
  237. package/server/node_modules/google-gax/build/protos/google/protobuf/descriptor.proto +118 -30
  238. package/server/node_modules/google-gax/build/protos/google/protobuf/field_mask.proto +16 -18
  239. package/server/node_modules/google-gax/build/protos/google/protobuf/internal_options.proto +8 -1
  240. package/server/node_modules/google-gax/build/protos/google/protobuf/json/json_enumval_custom_string.proto +26 -0
  241. package/server/node_modules/google-gax/build/protos/google/protobuf/json_enumvalue_options.proto +29 -0
  242. package/server/node_modules/google-gax/build/protos/google/protobuf/json_options.proto +14 -0
  243. package/server/node_modules/google-gax/build/protos/google/protobuf/struct.proto +38 -22
  244. package/server/node_modules/google-gax/build/protos/google/protobuf/test_protos/forced_micro_string.proto +3 -0
  245. package/server/node_modules/google-gax/build/protos/google/protobuf/test_protos/repeated_field_proxy_import_message.proto +14 -0
  246. package/server/node_modules/google-gax/build/protos/google/protobuf/timestamp.proto +9 -8
  247. package/server/node_modules/google-gax/build/protos/google/protobuf/util/json_format_proto3.proto +18 -0
  248. package/server/node_modules/google-gax/build/protos/google/rpc/code.proto +1 -1
  249. package/server/node_modules/google-gax/build/protos/google/rpc/context/attribute_context.proto +7 -2
  250. package/server/node_modules/google-gax/build/protos/google/rpc/context/audit_context.proto +1 -1
  251. package/server/node_modules/google-gax/build/protos/google/rpc/error_details.proto +5 -5
  252. package/server/node_modules/google-gax/build/protos/google/rpc/http.proto +1 -1
  253. package/server/node_modules/google-gax/build/protos/google/rpc/status.proto +1 -2
  254. package/server/node_modules/google-gax/build/protos/google/type/calendar_period.proto +1 -1
  255. package/server/node_modules/google-gax/build/protos/google/type/color.proto +9 -10
  256. package/server/node_modules/google-gax/build/protos/google/type/date.proto +11 -9
  257. package/server/node_modules/google-gax/build/protos/google/type/datetime.proto +17 -17
  258. package/server/node_modules/google-gax/build/protos/google/type/dayofweek.proto +1 -1
  259. package/server/node_modules/google-gax/build/protos/google/type/decimal.proto +11 -13
  260. package/server/node_modules/google-gax/build/protos/google/type/expr.proto +1 -1
  261. package/server/node_modules/google-gax/build/protos/google/type/fraction.proto +1 -1
  262. package/server/node_modules/google-gax/build/protos/google/type/interval.proto +1 -2
  263. package/server/node_modules/google-gax/build/protos/google/type/latlng.proto +4 -5
  264. package/server/node_modules/google-gax/build/protos/google/type/localized_text.proto +3 -3
  265. package/server/node_modules/google-gax/build/protos/google/type/money.proto +1 -2
  266. package/server/node_modules/google-gax/build/protos/google/type/month.proto +1 -1
  267. package/server/node_modules/google-gax/build/protos/google/type/phone_number.proto +20 -15
  268. package/server/node_modules/google-gax/build/protos/google/type/postal_address.proto +39 -39
  269. package/server/node_modules/google-gax/build/protos/google/type/quaternion.proto +4 -4
  270. package/server/node_modules/google-gax/build/protos/google/type/timeofday.proto +11 -8
  271. package/server/node_modules/google-gax/package.json +5 -5
  272. package/server/node_modules/retry-request/package.json +4 -4
  273. package/server/node_modules/teeny-request/package.json +5 -5
  274. package/server/node_modules/undici/lib/cache/memory-cache-store.js +54 -9
  275. package/server/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
  276. package/server/node_modules/undici/lib/core/request.js +12 -1
  277. package/server/node_modules/undici/lib/dispatcher/client-h1.js +11 -2
  278. package/server/node_modules/undici/lib/global.js +36 -16
  279. package/server/node_modules/undici/lib/handler/cache-handler.js +236 -116
  280. package/server/node_modules/undici/lib/handler/cache-revalidation-handler.js +3 -3
  281. package/server/node_modules/undici/lib/handler/retry-handler.js +24 -0
  282. package/server/node_modules/undici/lib/interceptor/cache.js +152 -62
  283. package/server/node_modules/undici/lib/interceptor/decompress.js +5 -2
  284. package/server/node_modules/undici/lib/util/cache.js +328 -66
  285. package/server/node_modules/undici/lib/util/date.js +23 -6
  286. package/server/node_modules/undici/lib/web/cookies/util.js +78 -8
  287. package/server/node_modules/undici/package.json +1 -1
  288. package/server/{orphan-proposed-reconciler-BvKkWMJQ.js → orphan-proposed-reconciler-B6vJHxtX.js} +242 -34
  289. package/server/{orphan-proposed-reconciler-CTSGcK8p.js → orphan-proposed-reconciler-DcgTPPFY.js} +1 -1
  290. package/server/package-lock.json +31 -31
  291. package/server/package.json +1 -1
  292. package/server/{pan-dir-B0c3w0Ya.js → pan-dir-DMzF5wne.js} +25 -11
  293. package/server/{paths-D-xWGHdh.js → paths-sJBSb7Ul.js} +2 -2
  294. package/server/pending-lifecycle-claim-DilzGfgk.js +110 -0
  295. package/server/persistent-logger-H_VjuOu7.js +57 -0
  296. package/server/{pickup-DUCLWrJY.js → pickup-DWhqzliO.js} +4 -3
  297. package/server/pipeline-membership-C88VBnhJ.js +3 -0
  298. package/server/pipeline-membership-D9SBvItj.js +57 -0
  299. package/server/pipeline-membership-gather-4eR-7Tqy.js +3 -0
  300. package/server/pipeline-membership-gather-CeVGnNJ2.js +593 -0
  301. package/server/{pipeline-notifier-BXkJzDC4.js → pipeline-notifier-D0ALV6Nw.js} +2 -2
  302. package/server/{pipeline-notifier-BJr8gQX6.js → pipeline-notifier-DT6xLFao.js} +1 -1
  303. package/server/post-merge-lifecycle-worker-8HIeS_J6.js +50 -0
  304. package/server/{project-pipelines-C0MWUeCU.js → project-pipelines-9SKt2bEc.js} +2 -2
  305. package/server/{project-repos-B6GycDh9.js → project-repos-B5pIphKg.js} +7 -3
  306. package/server/project-repos-DPjOdfPa.js +3 -0
  307. package/server/projects-_n3Zui6K.js +3 -0
  308. package/server/{prompts-DxzFXuLl.js → prompts-CgzMBvQF.js} +2 -2
  309. package/server/{providers-u4Ga0jOr.js → providers-BI1mOBQ4.js} +1 -1
  310. package/server/{providers-qQAwGQDW.js → providers-BJQSnAAp.js} +7 -7
  311. package/server/public/assets/{chunk-BO2N2NFS-BamJdinX.js → chunk-BO2N2NFS-D_pGACYN.js} +4 -4
  312. package/server/public/assets/{diagram-OG6HWLK6-DfOB8-w4.js → diagram-OG6HWLK6-BO6fe3hH.js} +1 -1
  313. package/server/public/assets/{dist-ByIuzMQW.js → dist-5zingMiA.js} +3 -3
  314. package/server/public/assets/{dist-D7zYSEA6.js → dist-CVxhbI2E.js} +1 -1
  315. package/server/public/assets/{ganttDiagram-6RSMTGT7-EdmRyXL3.js → ganttDiagram-6RSMTGT7-Bgj4A7kp.js} +1 -1
  316. package/server/public/assets/{highlighted-body-OFNGDK62-MerOfTX8.js → highlighted-body-OFNGDK62-DNPK7_cm.js} +1 -1
  317. package/server/public/assets/index-DEpY-D1O.js +807 -0
  318. package/server/public/assets/index-Ddkcz3WT.css +1 -0
  319. package/server/public/assets/{linear-BBbArIcK.js → linear-BB0jQT16.js} +1 -1
  320. package/server/public/assets/mermaid-GHXKKRXX-BzPfaQJ1.js +1 -0
  321. package/server/public/assets/{pieDiagram-4H26LBE5-BKIddiJN.js → pieDiagram-4H26LBE5-DeGIzzpZ.js} +1 -1
  322. package/server/public/assets/{prod-B8vYiu52.js → prod-XBLvikex.js} +4 -4
  323. package/server/public/assets/{quadrantDiagram-W4KKPZXB-D6RtoULk.js → quadrantDiagram-W4KKPZXB-BV9SLeWz.js} +1 -1
  324. package/server/public/assets/{sankeyDiagram-5OEKKPKP-CLrCedZX.js → sankeyDiagram-5OEKKPKP-Dwja0gj8.js} +1 -1
  325. package/server/public/assets/{xychartDiagram-2RQKCTM6-hznR8DYl.js → xychartDiagram-2RQKCTM6-DCB4qvfw.js} +1 -1
  326. package/server/public/index.html +2 -2
  327. package/server/{pull-requests-_lHueOHW.js → pull-requests-7BgLDsIo.js} +19 -10
  328. package/server/{pull-requests-7N8WKseP.js → pull-requests-Dq0y6IxE.js} +1 -1
  329. package/server/{queries-CjNIf-Ub.js → queries-C-MUZaIy.js} +824 -192
  330. package/server/{rally-CyWT_lNO.js → rally-CPysR4T_.js} +3 -3
  331. package/server/rally-D_VW4bJv.js +3 -0
  332. package/server/{rally-api-C8e_1JRi.js → rally-api-8Ptlp2os.js} +2 -2
  333. package/server/{rally-api-ClOSd-Tt.js → rally-api-CgosKdKL.js} +1 -1
  334. package/server/{rally-client-sgtVqzNU.js → rally-client-CCX0hADj.js} +1 -1
  335. package/server/{rally-client-lc-nokqr.js → rally-client-iYMHWQD7.js} +5 -5
  336. package/server/{reap-terminal-sessions-7KeHv1R1.js → reap-terminal-sessions-4Xg9NGA8.js} +2 -2
  337. package/server/{reap-terminal-sessions-BtHPo6Xc.js → reap-terminal-sessions-Qf-9LVQc.js} +2 -2
  338. package/server/{rebuild-stack-lwtsW0GO.js → rebuild-stack-CMdgaylx.js} +16 -7
  339. package/server/{rebuild-stack-CFvcBHsS.js → rebuild-stack-DqcOVmJO.js} +2 -2
  340. package/server/{reconstruct-cache-C3Ui7ojV.js → reconstruct-cache-CMZJ_Vjq.js} +9 -7
  341. package/server/record-BTwWhtBb.js +3 -0
  342. package/server/{record-update-dE1Aw83j.js → record-update-DaOKS7Wb.js} +124 -157
  343. package/server/record-update-DhI7eySG.js +3 -0
  344. package/server/{recovery-trip-BvRWfUXM.js → recovery-trip-DDH-02ng.js} +2 -2
  345. package/server/{release-engine-Cx48W7z8.js → release-engine-B2X9AfFC.js} +5 -5
  346. package/server/{release-set-CQfuN9-v.js → release-set-G4XKyQ8K.js} +3 -3
  347. package/server/{remote-C_2hasl7.js → remote-BXarMvqf.js} +3 -3
  348. package/server/{remote-ChgimyYa.js → remote-CUhyqjXk.js} +3 -3
  349. package/server/{remote-agents-By1ige5O.js → remote-agents-Bba-MgSA.js} +311 -48
  350. package/server/{remote-agents-CA3Ihlxj.js → remote-agents-CLZB3Coc.js} +2 -2
  351. package/server/{remote-completion-fVe9e_3u.js → remote-completion-CwAp79EC.js} +13 -13
  352. package/server/resume-mOREjlYu.js +3 -0
  353. package/server/{review-agent-CIGOQYBD.js → review-agent--pOptAEV.js} +65 -50
  354. package/server/{review-agent-DNboMyW4.js → review-agent-BTCNkq2h.js} +1 -1
  355. package/server/{review-artifacts-nRDPuMxd.js → review-artifacts-BNmw8dWE.js} +7 -6
  356. package/server/{review-context-2uj-YQ8J.js → review-context-DFxYOOJW.js} +9 -9
  357. package/server/{in-flight-guard-CAAkqPLu.js → review-convoy-liveness-BgU_1jJf.js} +3 -44
  358. package/server/review-status-CGvlA4o_.js +7737 -0
  359. package/server/review-status-Dma9SFaN.js +3 -0
  360. package/server/review-status-emit-DURrmGYX.js +50 -0
  361. package/server/{review-status-enrichment-Dci-ZwEt.js → review-status-enrichment-8NiNXi5W.js} +4 -4
  362. package/server/review-status-source-BLx_1siH.js +3 -0
  363. package/server/{review-status-source-CxuEjLGg.js → review-status-source-DIk1JSow.js} +24 -3
  364. package/server/{review-status-sync-BTOpxtTC.js → review-status-sync-0GxOqeqF.js} +11 -6
  365. package/server/{review-status-sync-DSDK3OMy.js → review-status-sync-muT-EBp2.js} +1 -1
  366. package/server/{review-verdict-feedback-CTd4QMBu.js → review-verdict-feedback-HwF6ODFy.js} +1 -1
  367. package/server/{review-verdict-feedback-CCjVA7Uk.js → review-verdict-feedback-xJNdqBnX.js} +65 -11
  368. package/server/{rollup-FGsKki9R.js → rollup-BQaol5TX.js} +8 -8
  369. package/server/{rollup-BKQC7jp4.js → rollup-BR4t_wck.js} +1 -1
  370. package/server/{scanner-CnqEZeDy.js → scanner-C-D2cFdX.js} +8 -7
  371. package/server/{sequence-io-D909zgeH.js → sequence-io-Bmf1EZM5.js} +4 -4
  372. package/server/{sequencer-agent-CzkcK6P5.js → sequencer-agent-CigMyKh2.js} +7 -6
  373. package/server/server.js +2005 -614
  374. package/server/{service-CLeAoU6G.js → service-CD0DvFvD.js} +114 -68
  375. package/server/{session-fork-CHI1XvL9.js → session-fork-B6cQ5eya.js} +2 -2
  376. package/server/{session-history-BT3IvqhC.js → session-history-3ON_IJjm.js} +7 -55
  377. package/server/settings-CVmWiJ-r.js +2 -0
  378. package/server/{settings-C0zgxOGf.js → settings-PilbFZAM.js} +3 -2
  379. package/server/{settings-BTMvpNFU.js → settings-VN0qOh4U.js} +3 -3
  380. package/server/{shadow-engineering-BJfgm-hX.js → shadow-engineering-DXvx77oE.js} +3 -3
  381. package/server/{shadow-state-7a-524T8.js → shadow-state-BBk_zacw.js} +2 -2
  382. package/server/{shadow-state-DnDyjujH.js → shadow-state-CZBp7pwq.js} +1 -1
  383. package/server/{shadow-utils-Db3oroFG.js → shadow-utils-DdZ05AJS.js} +2 -2
  384. package/server/{ship-log-D9MlVzYU.js → ship-log-7kJfjUX2.js} +1 -1
  385. package/server/{smart-compaction-CV2ukKND.js → smart-compaction-8fA5k5XN.js} +1 -1
  386. package/server/{smart-compaction-KCYScAU1.js → smart-compaction-ByhL9cRS.js} +8 -7
  387. package/server/{spawn-planning-session-DKpdFyOC.js → spawn-planning-session-pcF-YeFE.js} +38 -50
  388. package/server/spawn-planning-session-vLUJoFjy.js +3 -0
  389. package/server/{specialist-completion-Ky9wCDpb.js → specialist-completion-B07XjWD2.js} +1 -1
  390. package/server/{specialist-context-Bn3dCGS2.js → specialist-context-DJ-zFyL3.js} +5 -5
  391. package/server/{specialist-handoff-logger-CMEwYxa2.js → specialist-handoff-logger-aKSxbIgD.js} +2 -2
  392. package/server/{specialist-logs-C5p8G7tx.js → specialist-logs-Dae-n52_.js} +3 -3
  393. package/server/{specialists-CC4r-c2s.js → specialists-6PWdtWcg.js} +1177 -311
  394. package/server/{specialists-DM6bWjsi.js → specialists-Bz-wFT7R.js} +1 -1
  395. package/server/{specialists-jiuuyVkp.js → specialists-DUiExaxb.js} +18 -18
  396. package/server/{specialists-CShuVGWT.js → specialists-KR3pKulN.js} +1 -1
  397. package/server/specs--enInima.js +3 -0
  398. package/server/src-B948bGVR.js +11452 -0
  399. package/server/{src-CXmtj0im.js → src-rac0Mepv.js} +6 -6
  400. package/server/{src-CdmnTM2m.js → src-vHy2-oCv.js} +3 -3
  401. package/server/{stack-health-Bn3o8FBX.js → stack-health-BikqHSjn.js} +1 -1
  402. package/server/{stack-health-DxSdG9cW.js → stack-health-DqLTiEu4.js} +7 -5
  403. package/server/{stale-task-claims-KJKxxiiQ.js → stale-task-claims-Cab_Fo_Z.js} +5 -4
  404. package/server/{staleness-DPm7ClwA.js → staleness-C-a5rBxF.js} +1 -1
  405. package/server/{staleness-CT34nwr9.js → staleness-CGTZyp6V.js} +1 -1
  406. package/server/{state-home-Cn_Qu8IX.js → state-home-722Dkx92.js} +2 -2
  407. package/server/{state-mapping-BL_-3Yt8.js → state-mapping-CybR81Uf.js} +1 -1
  408. package/server/{state-migrate-BGg2ZaOt.js → state-migrate-2u8wIpoL.js} +4 -4
  409. package/server/{stuck-remediation-DYuPRYYw.js → stuck-remediation-CC6q3eqQ.js} +84 -26
  410. package/server/{stuck-remediation-s9_2qfi6.js → stuck-remediation-r1TJu68G.js} +1 -1
  411. package/server/{substrate-bug-weights-service-B-FwCs5V.js → substrate-bug-weights-service-CzIyyWFT.js} +3 -3
  412. package/server/{summary-fork-DpcxN9tf.js → summary-fork-BqgmgPDt.js} +2 -2
  413. package/server/{summary-fork-D1RAk9rJ.js → summary-fork-Df2WFijM.js} +8 -8
  414. package/server/supervisor/{injection-budget-Csw5tqfJ.js → injection-budget-Cg_KIb3o.js} +1 -1
  415. package/server/supervisor/{paths-DehGY2Fj.js → paths-BBOnCYlO.js} +10 -2
  416. package/server/supervisor/pty-supervisor.js +50 -4
  417. package/server/supervisor/{pty-token-x-ea28Us.js → pty-token-BbjwEUUM.js} +3 -3
  418. package/server/supervisor-B4anCCSm.js +2 -0
  419. package/server/{supervisor-wM4ooB5O.js → supervisor-BxqSpjcN.js} +3 -3
  420. package/server/{swarm-readiness-DlP_UjHq.js → swarm-readiness-DfFxa9-n.js} +3 -3
  421. package/server/{system-prerequisites-DUDj1YHf.js → system-prerequisites-ICLSkhhZ.js} +2 -2
  422. package/server/{teardown-workspace-DeTTImn-.js → teardown-workspace-DRdi_CPa.js} +15 -16
  423. package/server/{test-agent-queue-MbxX5vqq.js → test-agent-queue-A_-p-i0I.js} +8 -7
  424. package/server/{test-verdict-gscuksPv.js → test-verdict-BHgTAwIG.js} +1 -1
  425. package/server/{test-verdict-bWYBtqBg.js → test-verdict-C4i9aqEP.js} +1 -1
  426. package/server/{tldr-daemon-BYFkts95.js → tldr-daemon-CvWXBhX1.js} +1 -1
  427. package/server/{tldr-daemon-C-69c3OI.js → tldr-daemon-wvsU6bKv.js} +2 -2
  428. package/server/{tmux-R7N7y-Mh.js → tmux-CfDHob9M.js} +174 -4
  429. package/server/{tmux-B6z7h_vZ.js → tmux-Ctk6RV5l.js} +1 -1
  430. package/server/{token-BK6t8BIT.js → token-DrxwytsZ.js} +2 -2
  431. package/server/{token-util-DxXu-vd1.js → token-util-B48BlCba.js} +1 -1
  432. package/server/token-util-D411CAq9.js +3 -0
  433. package/server/{tracker-config-G6latr8C.js → tracker-config-BcPMElRB.js} +2 -2
  434. package/server/{tracker-utils-DHv5pSDT.js → tracker-utils-CJ6BHjcD.js} +3 -3
  435. package/server/{traefik-connect-Df2uXPsQ.js → traefik-connect-DZ6nMYMj.js} +1 -1
  436. package/server/{tunnel-DGdUkGoZ.js → tunnel-Bp-dRHZz.js} +1 -1
  437. package/server/{tunnel-CDVKJpRv.js → tunnel-DUbUPElU.js} +3 -3
  438. package/server/{typed-errors-BHhE85Ul.js → typed-errors-CKeoDdU3.js} +1 -1
  439. package/server/{typed-errors-2BTMxkZq.js → typed-errors-DyjseiB6.js} +1 -1
  440. package/server/{types-hraoaQIp.js → types-Cm5ASJbq.js} +1 -1
  441. package/server/{types-5M0lupud.js → types-Di8wdakq.js} +1 -1
  442. package/server/uat-promote-verification-CoJuh7XO.js +92 -0
  443. package/server/uat-train-4Q0k06CQ.js +0 -0
  444. package/server/uat-train-Dewoatps.js +2 -0
  445. package/server/{validate-IfDGkaVR.js → validate-B0C8p66t.js} +8 -6
  446. package/server/{validation-Dw1pzDzr.js → validation-B_kIRfNe.js} +4 -4
  447. package/server/{validation-CC9OPqJZ.js → validation-hVOwQk8T.js} +1 -1
  448. package/server/{verification-artifact-B3itKTxu.js → verification-artifact-BxlxTiYK.js} +1 -1
  449. package/server/{verification-artifact-TVFSz_q1.js → verification-artifact-D70AtckY.js} +1 -1
  450. package/server/{verification-runner-BW4HOKAz.js → verification-runner-Bc3cJvpC.js} +1 -1
  451. package/server/{verification-runner-CkgX6EtI.js → verification-runner-KZTz6u72.js} +40 -18
  452. package/server/{vtt-parser-DYPbKcIJ.js → vtt-parser-CE_i3Bcw.js} +1 -1
  453. package/server/{work-agent-prompt-Du8Vh2aJ.js → work-agent-prompt-ByrPAzOy.js} +20 -9
  454. package/server/{workflows-mbQzh6mQ.js → workflows-D0vP1WrK.js} +252 -99
  455. package/server/workflows-DtDX08ed.js +2 -0
  456. package/server/{workspace--8tnhDI0.js → workspace-COWvdibH.js} +1 -1
  457. package/server/{workspace-BPUws1-_.js → workspace-DQkRPLlQ.js} +3 -3
  458. package/server/workspace-anchor-drift-DXYIAHzr.js +224 -0
  459. package/server/workspace-anchor-drift-pwz23TI1.js +3 -0
  460. package/server/{workspace-config-CIVWZOQr.js → workspace-config-BdZM4PvZ.js} +1 -1
  461. package/server/{workspace-manager-CBhNdzE4.js → workspace-manager-BPgTrG66.js} +157 -118
  462. package/server/workspace-manager-C1F3XsnS.js +3 -0
  463. package/server/{workspace-metadata-BzHnwwX4.js → workspace-metadata-CdjzAP8x.js} +1 -1
  464. package/server/{workspace-metadata-_WygnyoX.js → workspace-metadata-DkO_iTLo.js} +2 -2
  465. package/server/{workspaces-Do_9J0LQ.js → workspaces-CRBJikLp.js} +749 -299
  466. package/sync-sources/dev-skills/pan-dashboard-restart/SKILL.md +34 -10
  467. package/sync-sources/hooks/linear-mcp-auth-hook +97 -0
  468. package/sync-sources/rules/ask-user-question-self-contained.md +9 -0
  469. package/sync-sources/skills/pan-close/SKILL.md +5 -3
  470. package/sync-sources/skills/pan-merge/SKILL.md +7 -5
  471. package/sync-sources/skills/pan-peer-review/SKILL.md +195 -0
  472. package/sync-sources/skills/pan-release/SKILL.md +57 -0
  473. package/sync-sources/skills/pan-reload/SKILL.md +3 -3
  474. package/sync-sources/skills/pan-restart/SKILL.md +5 -4
  475. package/sync-sources/skills/pan-review/SKILL.md +7 -1
  476. package/sync-sources/skills/pan-sync-main/SKILL.md +9 -8
  477. package/sync-sources/skills/pipeline-status/SKILL.md +10 -1
  478. package/sync-sources/skills/workspace-add-repo/SKILL.md +16 -1
  479. package/server/activity-logger-OEUBdfZ8.js +0 -3
  480. package/server/agent-state-Bc3tzUC8.js +0 -3
  481. package/server/agent-state-service-D5UGKIJL.js +0 -2
  482. package/server/agents-wi9NWzs2.js +0 -3
  483. package/server/archive-planning-BZDgzoEj.js +0 -3
  484. package/server/cli-B86rejVV.js +0 -3
  485. package/server/conflict-gate-BhAY7TUd.js +0 -3
  486. package/server/conversation-service-BLd3MYsG.js +0 -3
  487. package/server/deacon-kiQrb4ZT.js +0 -4
  488. package/server/deacon-swarm-C-GwfjJy.js +0 -2
  489. package/server/deploy-window-DkZraDyj.js +0 -3
  490. package/server/dist-Bzy0y69j.js +0 -3
  491. package/server/dod-C6n9RV3G.js +0 -66
  492. package/server/flywheel-merge-order-UU0tiUld.js +0 -245
  493. package/server/flywheel-merge-order-UUcsCDb6.js +0 -2
  494. package/server/forge-CNFnyqps.js +0 -270
  495. package/server/forge-DXnS_YFH.js +0 -2
  496. package/server/git-utils-D0_yhCgF.js +0 -3
  497. package/server/github-pr-lookup-D16NGsSO.js +0 -44
  498. package/server/hume-ccTf4wTX.js +0 -3
  499. package/server/inspect-agent-Brtz0URj.js +0 -2
  500. package/server/label-reconciler-B4iOAjlC.js +0 -113
  501. package/server/launcher-generator-BBWG_SiS.js +0 -473
  502. package/server/merge-ops-CR44oU9-.js +0 -2
  503. package/server/merge-set-bUqbm3yc.js +0 -3
  504. package/server/merge-sync-BJYeOODr.js +0 -3
  505. package/server/merge-verification-BkaOqPsw.js +0 -124
  506. package/server/pipeline-membership-mY3GprlK.js +0 -420
  507. package/server/project-repos-DXKQsc_m.js +0 -3
  508. package/server/projects-vjjcmiN8.js +0 -3
  509. package/server/public/assets/index-CWeMerGO.js +0 -804
  510. package/server/public/assets/index-CenuJ3Cw.css +0 -1
  511. package/server/public/assets/mermaid-GHXKKRXX-CpPWAFwE.js +0 -1
  512. package/server/rally-zhhtXuDP.js +0 -3
  513. package/server/record-CN0pj4_5.js +0 -3
  514. package/server/record-update-bLJxAXH4.js +0 -3
  515. package/server/resume-BFv1PGpA.js +0 -3
  516. package/server/review-status-btEYlaxA.js +0 -3
  517. package/server/review-status-kZj_KyCk.js +0 -1470
  518. package/server/settings-66A6uvIA.js +0 -2
  519. package/server/spawn-planning-session-qUC2VWu3.js +0 -2
  520. package/server/specs-C8Wsn2XO.js +0 -3
  521. package/server/src-DtcUOZCq.js +0 -4826
  522. package/server/supervisor-FTJAIsAK.js +0 -2
  523. package/server/token-util-DuPuNriz.js +0 -3
  524. package/server/tracker-utils-B4ylXZQK.js +0 -3
  525. package/server/uat-train-B05BWkp-.js +0 -2
  526. package/server/uat-train-DDSrSoV1.js +0 -2152
  527. package/server/workflows-BQu4RFQ-.js +0 -2
  528. 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";
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";
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 getOverdeckHome, di as packageRoot, ei as claudeSessionTranscriptExists, f as loadConfigSync, fi as resolveOhmypiExtensionPath, gr as init_issue_id, h as jsYaml, hn as init_state_plane, hr as extractPrefixSync, li as init_paths, m as init_js_yaml, t as init_config_yaml, ti as encodeClaudeProjectDir, tt as resolveModel, vn as parsePorcelainStatusPaths, vr as parseIssueIdSync, wn as shouldCommitLegacyWorkspaceArtifacts, zn as getProjectSync } from "./config-yaml-CxdwhAIA.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-BDQDRopn.js";
5
+ import { B as sendKeysAsync, D as killSession, H as sessionExists, J as init_pane_choice_menu, M as listSessionNames, N as listSessions, T as isHarnessProcessAlive, U as sessionExistsSync, V as sendRawKeystroke, W as setOption, X as paneHasBlockingChoiceMenu, at as buildChildEnvWithoutTmuxSync, g as findManagedServerPidSync, i as capturePane, m as exactPaneTarget, o as capturePaneText, ot as init_child_env, rt as BLANKED_PROVIDER_ENV, s as createSession, w as init_tmux } from "./tmux-CfDHob9M.js";
6
+ import { a as init_event_store, n as getEventStore } from "./event-store-CrHcVC5_.js";
7
+ import { N as normalizeChannelReplyPayload, T as DomainEvent, n as COMPOSER_COMMAND_MANIFEST, s as getHarnessBehavior, t as init_src } from "./src-B948bGVR.js";
8
+ import { C as setReviewStatusSync, Q as stateToOverdeckParamsForDb, Y as init_agent_state_sync, d as getReviewStatusSync, h as loadReviewStatuses, o as clearWorkspaceStuck, p as init_review_status, q as AGENT_COLUMNS_FOR_DB } from "./review-status-CGvlA4o_.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-Birk-ifu.js";
10
+ import { n as logAgentLifecycleSync, t as init_persistent_logger } from "./persistent-logger-H_VjuOu7.js";
11
+ import { d as isTerminalIssueStage, o as init_agents, u as getIssueStageSync } from "./agents-J5mEnekq.js";
12
+ import { n as ensureSessionContextBriefingFile, r as init_briefing_freshness } from "./briefing-freshness-DRqZ8lAz.js";
13
+ import { o as getPricingSync, s as init_cost, t as calculateCostSync } from "./cost-DpgYmYqR.js";
14
+ import { $ as operatorInterventionEvent, $n as getAgentDir, An as getProviderExportsForModel, Ar as resolvePtySupervisorScriptPath, Bn as dismissDevChannelsDialog, Br as saveAgentRuntimeState, Dr as init_pty_token, Er as init_resume_contract, F as init_tier_escalation, G as resumeAgent, Gr as init_codex_auth, Gt as assertWorkspaceStackHealthyForSpawn, H as restartAgent, Ht as BRIDGE_TOKEN_HEADER, Ir as waitForReadySignal, Jt as init_spawn_prep, Lr as getAgentRuntimeState, Mn as init_provider_health, Mt as deliverAgentMessage, Nn as validateProviderHealth, Nr as normalizeAgentId, Nt as deliverAgentPermissionDecision, On as determineModel, Or as writePtyToken, P as decideEscalation, Q as init_operator_interventions, Qt as init_staffing, Rr as getAgentRuntimeStateSync, Rt as setAgentDeliveryMethod, Sr as writeAgentStateJsonSync, Tr as buildResumeContract, Un as writeChannelsBridgeMcpConfig, Ut as init_bridge_token, V as recoverAgent, Wr as checkCodexAuthStatus, 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 clearReadySignal, kr as init_pty_supervisor_locate, 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-C-MUZaIy.js";
15
+ import { a as performHandoff, i as checkAllTriggers, s as getAgentHealth, t as getCloisterService } from "./service-CD0DvFvD.js";
16
+ import { t as init_behavior } from "./behavior-td6-xhQk.js";
17
+ import { a as init_tracker_config, t as getGitHubConfig } from "./tracker-config-BcPMElRB.js";
18
+ import { n as init_issue_service_singleton, r as issue_service_singleton_exports } from "./issue-service-singleton-C6ZduvuY.js";
19
+ import { o as getInternalTokenSync, s as init_internal_token } from "./internal-token-DzK385vD.js";
20
+ import { a as PAN_DIRNAME, i as PAN_CONTINUE_FILENAME, p as init_types } from "./types-Cm5ASJbq.js";
21
+ import { l as resolveWorkspaceRepoRootsSync, o as resolvePrimaryWorkspaceRepoDirSync, r as init_project_repos } from "./project-repos-B5pIphKg.js";
22
+ import { a as generateXBriefFilename, o as init_lifecycle } from "./lifecycle-B4Xdb4cY.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-B00PBNku.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-D0UEdLtk.js";
25
+ import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population-B6HpNWRy.js";
26
+ import { C as init_launcher_generator, D as requireModelOverrideSync, E as normalizeModelOverrideSync, S as generateLauncherScriptSync, T as init_model_validation, w as MODEL_ID_PATTERN, x as normalizeFlywheelRunId, y as init_provenance } from "./auto-spawn-consent-CQ9Bi9q6.js";
27
+ import { a as init_claude_permissions, o as resolvePermissionModeSync, r as getClaudePermissionFlagsStringSync, t as BYPASS_PERMISSION_MODE } from "./claude-permissions-CpbpvUQ2.js";
28
+ import { E as init_layers, I as workspaceContextFile, k as piGlobalContextFile } from "./assemble-Bgwqv-Ro.js";
29
+ import { i as prepareHarnessLaunch, r as init_harness_binary } from "./harness-binary-BSpiXaLw.js";
30
+ import { a as getWorkspaceStackHealth, s as init_stack_health } from "./stack-health-DqLTiEu4.js";
31
+ import { l as init_dag, o as getDispatchableItems } from "./dag-BtkgLeqY.js";
32
+ import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-BAJu5MX8.js";
33
+ import { a as loadCloisterConfigSync, r as init_config } from "./config-Bi3u1VK7.js";
34
+ import { c as isStateMigrated, o as init_state_home } from "./state-home-722Dkx92.js";
35
+ import { a as init_lifecycle_io, c as updatePlanStatus, s as transitionXBriefOnMain } from "./lifecycle-io-DCo6s6ks.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-DBxoYMDl.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-CC6q3eqQ.js";
38
+ import { B as getBook, H as liveOrderIssueLookup, T as resolveLiveFlywheelRunId, w as readFlywheelLaunchMetadata, y as getFlywheelRunDir, z as computeBookProgress } from "./flywheel-BHx8XuMr.js";
39
+ import { At as classifyMemoryPressure, Lt as getResourceConfig, zt as getSystemHealthSnapshot } from "./deacon-pLRLbPvR.js";
40
+ import { o as stopWorkspaceDocker, r as init_workspace_manager } from "./workspace-manager-BPgTrG66.js";
41
+ import { a as init_jsonl_parser, o as normalizeModelName } from "./jsonl-parser-BDpnGFCl.js";
42
+ import { r as init_in_flight_guard, t as createInFlightGuard } from "./in-flight-guard-D-sSkADM.js";
43
+ import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-DkO_iTLo.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,21 +87,24 @@ 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();
93
+ init_pane_choice_menu();
91
94
  init_tmux();
92
95
  init_infra();
93
96
  init_event_store();
94
97
  init_src();
95
98
  init_agent_state_sync();
99
+ init_persistent_logger();
96
100
  init_agents();
97
101
  init_read_model();
98
102
  init_briefing_freshness();
99
103
  init_domain_services();
100
104
  init_cost();
101
105
  init_behavior();
102
- init_persistent_logger();
103
106
  init_tracker_config();
107
+ init_project_repos();
104
108
  init_lifecycle();
105
109
  init_review_status();
106
110
  init_io();
@@ -193,6 +197,7 @@ function httpHandler(effect) {
193
197
  init_conversations();
194
198
  init_pty_supervisor_locate();
195
199
  init_pty_token();
200
+ init_resume_contract();
196
201
  init_feature_registry_population();
197
202
  init_model_validation();
198
203
  init_provider_health();
@@ -205,6 +210,7 @@ init_runtime_command();
205
210
  init_stack_health();
206
211
  init_launcher_generator();
207
212
  init_dag();
213
+ init_provenance();
208
214
  init_staffing();
209
215
  init_spawn_prep();
210
216
  init_harness_resolve();
@@ -218,6 +224,27 @@ function addTrustedOrigin(origins, raw) {
218
224
  const normalized = normalizeOrigin(raw.trim());
219
225
  if (normalized) origins.add(normalized);
220
226
  }
227
+ /**
228
+ * Last-resort origin config for launches that carry no origin env at all
229
+ * (manual `node dist/...`, ad-hoc re-exec). `pan up` builds its launch env from
230
+ * this same config.yaml, so reading it here keeps every launch path trusting the
231
+ * same Traefik domain instead of 403ing /ws/* into a "Reconnecting" loop.
232
+ */
233
+ function readTraefikConfigFromYaml() {
234
+ try {
235
+ const configPath = join(process.env["OVERDECK_HOME"] || join(homedir(), ".overdeck"), "config.yaml");
236
+ if (!existsSync(configPath)) return null;
237
+ const traefik = jsYaml.load(readFileSync(configPath, "utf8"))?.traefik;
238
+ if (!traefik || typeof traefik !== "object") return null;
239
+ if (typeof traefik.domain !== "string" || traefik.domain.trim() === "") return null;
240
+ return {
241
+ enabled: traefik.enabled === true,
242
+ domain: traefik.domain.trim()
243
+ };
244
+ } catch {
245
+ return null;
246
+ }
247
+ }
221
248
  function getTrustedOrigins() {
222
249
  if (cachedTrustedOrigins !== void 0) return cachedTrustedOrigins;
223
250
  const port = parseInt(process.env["API_PORT"] ?? process.env["PORT"] ?? "3011", 10);
@@ -232,6 +259,10 @@ function getTrustedOrigins() {
232
259
  for (const origin of trustedOrigins?.split(",") ?? []) addTrustedOrigin(origins, origin);
233
260
  const traefikDomain = process.env["OVERDECK_TRAEFIK_DOMAIN"] ?? process.env["TRAEFIK_DOMAIN"];
234
261
  if (process.env["OVERDECK_TRAEFIK_ENABLED"] === "1" && traefikDomain) addTrustedOrigin(origins, `https://${traefikDomain}`);
262
+ if (!(process.env["OVERDECK_TRAEFIK_ENABLED"] !== void 0 || traefikDomain !== void 0 || process.env["OVERDECK_TRUSTED_ORIGINS"] !== void 0)) {
263
+ const fromYaml = readTraefikConfigFromYaml();
264
+ if (fromYaml?.enabled) addTrustedOrigin(origins, `https://${fromYaml.domain}`);
265
+ }
235
266
  if (process.env["NODE_ENV"] === "development") {
236
267
  addTrustedOrigin(origins, "http://localhost:3000");
237
268
  addTrustedOrigin(origins, "http://127.0.0.1:3000");
@@ -799,7 +830,7 @@ async function resolveCodexRolloutPath(agentId, opts = {}) {
799
830
  const agentDir = join(opts.agentsDirOverride ?? join(getOverdeckHome(), "agents"), agentId);
800
831
  const codexHome = join(agentDir, "codex-home");
801
832
  if (!await pathExists$1(codexHome)) return null;
802
- const { findRolloutPath, findLatestRollout } = await import("./codex-GcHuUF-k.js");
833
+ const { findRolloutPath, findLatestRollout } = await import("./codex-o8FJwzmy.js");
803
834
  const threadId = (await readOptional(join(agentDir, "codex-thread-id")))?.trim();
804
835
  if (threadId) {
805
836
  const rollout = findRolloutPath(codexHome, threadId);
@@ -898,6 +929,7 @@ function spawnPanCli(args, options = {}) {
898
929
  //#endregion
899
930
  //#region ../../lib/work-agent-lifecycle.ts
900
931
  init_agents$1();
932
+ init_paths();
901
933
  init_tmux();
902
934
  async function pathExists(path) {
903
935
  try {
@@ -912,9 +944,11 @@ function getWorkAgentLifecycleStateSync(agentOrIssueId) {
912
944
  const agentState = getAgentStateSync(agentId);
913
945
  const runtimeState = getAgentRuntimeStateSync(agentId);
914
946
  const hasAgentState = !!agentState;
915
- const hasSavedSession = !!getLatestSessionIdSync(agentId);
947
+ const sessionId = getLatestSessionIdSync(agentId) ?? null;
948
+ const hasSavedSession = !!sessionId;
916
949
  const hasLiveTmuxSession = sessionExistsSync(agentId);
917
950
  const hasWorkspace = !!agentState?.workspace && existsSync(agentState.workspace);
951
+ const hasResumableTranscript = !sessionId || !!agentState?.harness && agentState.harness !== "claude-code" || !agentState?.workspace || claudeSessionTranscriptExists(agentState.workspace, sessionId);
918
952
  const agentStatus = agentState?.status || "unknown";
919
953
  const runtime = runtimeState?.state || "uninitialized";
920
954
  const isCompleted = runtimeState?.resolution === "completed";
@@ -925,7 +959,7 @@ function getWorkAgentLifecycleStateSync(agentOrIssueId) {
925
959
  const isRunningButStuck = isRunning && (runtime === "idle" || runtime === "suspended");
926
960
  const hasResumableBackingState = hasAgentState && hasWorkspace && !isPlaceholder;
927
961
  const isOrphaned = !hasLiveTmuxSession && (hasSavedSession && !hasResumableBackingState || hasAgentState && (!hasWorkspace || isPlaceholder));
928
- const requiresSessionResetBeforeFreshStart = hasSavedSession && !hasLiveTmuxSession && hasResumableBackingState && (isStopped || isCrashed);
962
+ const requiresSessionResetBeforeFreshStart = hasSavedSession && hasResumableTranscript && !hasLiveTmuxSession && hasResumableBackingState && (isStopped || isCrashed);
929
963
  let recommendedAction = "start";
930
964
  let reason;
931
965
  if (isRunningButStuck) {
@@ -943,6 +977,9 @@ function getWorkAgentLifecycleStateSync(agentOrIssueId) {
943
977
  } else if (requiresSessionResetBeforeFreshStart) {
944
978
  recommendedAction = "resume";
945
979
  reason = `Agent ${agentId} has a resumable Claude session. Use 'pan resume ${agentOrIssueId}' to continue it, or 'pan start ${agentOrIssueId} --fresh' to start a new session (e.g. to switch model).`;
980
+ } else if (hasSavedSession && !hasResumableTranscript && hasResumableBackingState && (isStopped || isCrashed)) {
981
+ recommendedAction = "start";
982
+ reason = `Agent ${agentId} has a saved Claude session id but its transcript is missing on disk (jsonl-missing). Start Agent will create a fresh session in the existing workspace.`;
946
983
  } else if (hasAgentState && !hasSavedSession && isStopped) {
947
984
  recommendedAction = "start";
948
985
  reason = `Agent ${agentId} is stopped and has no saved Claude session. Start Agent will create a fresh session in the existing workspace.`;
@@ -955,6 +992,7 @@ function getWorkAgentLifecycleStateSync(agentOrIssueId) {
955
992
  hasAgentState,
956
993
  hasLiveTmuxSession,
957
994
  hasSavedSession,
995
+ hasResumableTranscript,
958
996
  hasWorkspace,
959
997
  isPlaceholder,
960
998
  isOrphaned,
@@ -966,9 +1004,9 @@ function getWorkAgentLifecycleStateSync(agentOrIssueId) {
966
1004
  runtimeState: runtime,
967
1005
  agentStatus,
968
1006
  canStartFresh: (!hasLiveTmuxSession || hasLiveTmuxSession && isStopped) && (!requiresSessionResetBeforeFreshStart || isOrphaned),
969
- canResumeSession: !isRunning && hasSavedSession && hasResumableBackingState && (isStopped || isCrashed),
1007
+ canResumeSession: !isRunning && hasSavedSession && hasResumableTranscript && hasResumableBackingState && (isStopped || isCrashed),
970
1008
  canRestartWithContext: hasAgentState && hasWorkspace,
971
- canResetSession: hasSavedSession && hasResumableBackingState,
1009
+ canResetSession: hasSavedSession && hasResumableTranscript && hasResumableBackingState,
972
1010
  requiresSessionResetBeforeFreshStart,
973
1011
  recommendedAction,
974
1012
  reason
@@ -979,9 +1017,11 @@ async function getWorkAgentLifecycleStateSnapshot(agentOrIssueId) {
979
1017
  const agentState = await Effect.runPromise(getAgentState(agentId));
980
1018
  const runtimeState = await Effect.runPromise(getAgentRuntimeState(agentId));
981
1019
  const hasAgentState = !!agentState;
982
- const hasSavedSession = !!await Effect.runPromise(getLatestSessionId(agentId));
1020
+ const sessionId = await Effect.runPromise(getLatestSessionId(agentId)) ?? null;
1021
+ const hasSavedSession = !!sessionId;
983
1022
  const hasLiveTmuxSession = await Effect.runPromise(sessionExists(agentId));
984
1023
  const hasWorkspace = !!agentState?.workspace && await pathExists(agentState.workspace);
1024
+ const hasResumableTranscript = !sessionId || !!agentState?.harness && agentState.harness !== "claude-code" || !agentState?.workspace || claudeSessionTranscriptExists(agentState.workspace, sessionId);
985
1025
  const agentStatus = agentState?.status || "unknown";
986
1026
  const runtime = runtimeState?.state || "uninitialized";
987
1027
  const isCompleted = runtimeState?.resolution === "completed";
@@ -992,7 +1032,7 @@ async function getWorkAgentLifecycleStateSnapshot(agentOrIssueId) {
992
1032
  const isRunningButStuck = isRunning && (runtime === "idle" || runtime === "suspended");
993
1033
  const hasResumableBackingState = hasAgentState && hasWorkspace && !isPlaceholder;
994
1034
  const isOrphaned = !hasLiveTmuxSession && (hasSavedSession && !hasResumableBackingState || hasAgentState && (!hasWorkspace || isPlaceholder));
995
- const requiresSessionResetBeforeFreshStart = hasSavedSession && !hasLiveTmuxSession && hasResumableBackingState && (isStopped || isCrashed);
1035
+ const requiresSessionResetBeforeFreshStart = hasSavedSession && hasResumableTranscript && !hasLiveTmuxSession && hasResumableBackingState && (isStopped || isCrashed);
996
1036
  let recommendedAction = "start";
997
1037
  let reason;
998
1038
  if (isRunningButStuck) {
@@ -1010,6 +1050,9 @@ async function getWorkAgentLifecycleStateSnapshot(agentOrIssueId) {
1010
1050
  } else if (requiresSessionResetBeforeFreshStart) {
1011
1051
  recommendedAction = "resume";
1012
1052
  reason = `Agent ${agentId} has a resumable Claude session. Use 'pan resume ${agentOrIssueId}' to continue it, or 'pan start ${agentOrIssueId} --fresh' to start a new session (e.g. to switch model).`;
1053
+ } else if (hasSavedSession && !hasResumableTranscript && hasResumableBackingState && (isStopped || isCrashed)) {
1054
+ recommendedAction = "start";
1055
+ reason = `Agent ${agentId} has a saved Claude session id but its transcript is missing on disk (jsonl-missing). Start Agent will create a fresh session in the existing workspace.`;
1013
1056
  } else if (hasAgentState && !hasSavedSession && isStopped) {
1014
1057
  recommendedAction = "start";
1015
1058
  reason = `Agent ${agentId} is stopped and has no saved Claude session. Start Agent will create a fresh session in the existing workspace.`;
@@ -1022,6 +1065,7 @@ async function getWorkAgentLifecycleStateSnapshot(agentOrIssueId) {
1022
1065
  hasAgentState,
1023
1066
  hasLiveTmuxSession,
1024
1067
  hasSavedSession,
1068
+ hasResumableTranscript,
1025
1069
  hasWorkspace,
1026
1070
  isPlaceholder,
1027
1071
  isOrphaned,
@@ -1033,9 +1077,9 @@ async function getWorkAgentLifecycleStateSnapshot(agentOrIssueId) {
1033
1077
  runtimeState: runtime,
1034
1078
  agentStatus,
1035
1079
  canStartFresh: (!hasLiveTmuxSession || hasLiveTmuxSession && isStopped) && (!requiresSessionResetBeforeFreshStart || isOrphaned),
1036
- canResumeSession: !isRunning && hasSavedSession && hasResumableBackingState && (isStopped || isCrashed),
1080
+ canResumeSession: !isRunning && hasSavedSession && hasResumableTranscript && hasResumableBackingState && (isStopped || isCrashed),
1037
1081
  canRestartWithContext: hasAgentState && hasWorkspace,
1038
- canResetSession: hasSavedSession && hasResumableBackingState,
1082
+ canResetSession: hasSavedSession && hasResumableTranscript && hasResumableBackingState,
1039
1083
  requiresSessionResetBeforeFreshStart,
1040
1084
  recommendedAction,
1041
1085
  reason
@@ -1185,111 +1229,357 @@ async function resolveAgentGitInfo(workspacePath, expectedBranch) {
1185
1229
  };
1186
1230
  }
1187
1231
  //#endregion
1188
- //#region routes/agents/shared.ts
1232
+ //#region ../../lib/composer-commands/executors.ts
1233
+ const CAPTURED_COMMAND_MAX_OUTPUT_BYTES = 64 * 1024;
1234
+ const TRUNCATION_MESSAGE = "\n\nOutput was truncated after 65,536 bytes.";
1235
+ function runCapturedCommand(argv, dependencies = {}) {
1236
+ const command = `/pan ${argv.join(" ")}`;
1237
+ const spawnCommand = dependencies.spawnPanCli ?? spawnPanCli;
1238
+ const timeoutMs = dependencies.timeoutMs ?? 3e4;
1239
+ const child = spawnCommand(argv, { stdio: [
1240
+ "ignore",
1241
+ "pipe",
1242
+ "pipe"
1243
+ ] });
1244
+ return new Promise((resolve) => {
1245
+ const chunks = [];
1246
+ let bufferedBytes = 0;
1247
+ let settled = false;
1248
+ let timeout;
1249
+ let truncated = false;
1250
+ const appendOutput = (data) => {
1251
+ if (truncated) return;
1252
+ const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
1253
+ const remaining = CAPTURED_COMMAND_MAX_OUTPUT_BYTES - Buffer.byteLength(TRUNCATION_MESSAGE) - bufferedBytes;
1254
+ if (buffer.length <= remaining) {
1255
+ chunks.push(buffer);
1256
+ bufferedBytes += buffer.length;
1257
+ return;
1258
+ }
1259
+ if (remaining > 0) {
1260
+ chunks.push(buffer.subarray(0, remaining));
1261
+ bufferedBytes += remaining;
1262
+ }
1263
+ truncated = true;
1264
+ };
1265
+ const output = () => {
1266
+ const captured = Buffer.concat(chunks, bufferedBytes).toString("utf8");
1267
+ return truncated ? `${captured}${TRUNCATION_MESSAGE}` : captured;
1268
+ };
1269
+ const finish = (result) => {
1270
+ if (settled) return;
1271
+ settled = true;
1272
+ if (timeout !== void 0) clearTimeout(timeout);
1273
+ resolve(result);
1274
+ };
1275
+ child.stdout?.on("data", appendOutput);
1276
+ child.stderr?.on("data", appendOutput);
1277
+ child.once("error", (error) => {
1278
+ finish({
1279
+ kind: "captured",
1280
+ status: "failed",
1281
+ command,
1282
+ output: `Command ${command} could not start: ${error.message}`,
1283
+ truncated: false
1284
+ });
1285
+ });
1286
+ child.once("close", (code) => {
1287
+ const captured = output();
1288
+ finish({
1289
+ kind: "captured",
1290
+ status: code === 0 ? "completed" : "failed",
1291
+ command,
1292
+ output: captured || `Command ${command} ${code === 0 ? "completed without output." : `failed with exit code ${code ?? "unknown"}.`}`,
1293
+ truncated
1294
+ });
1295
+ });
1296
+ timeout = setTimeout(() => {
1297
+ stopChild(child);
1298
+ finish({
1299
+ kind: "captured",
1300
+ status: "failed",
1301
+ command,
1302
+ output: `Command ${command} timed out after ${Math.round(timeoutMs / 1e3)} seconds and was stopped.`,
1303
+ truncated: false
1304
+ });
1305
+ }, timeoutMs);
1306
+ });
1307
+ }
1308
+ function stopChild(child) {
1309
+ child.kill("SIGTERM");
1310
+ }
1311
+ //#endregion
1312
+ //#region ../../lib/composer-commands/detached.ts
1189
1313
  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
- ];
1314
+ const DETACHED_TRUNCATION_MESSAGE = "\n\nOutput was truncated after 65,536 bytes.";
1315
+ function resolveAgentDirectory(overdeckHome, agentId) {
1316
+ 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.");
1317
+ return join(resolve(overdeckHome, "agents"), agentId);
1318
+ }
1319
+ async function readBoundedSpawnOutput(spawnLogPath, startOffset) {
1320
+ const maximumPrefixBytes = CAPTURED_COMMAND_MAX_OUTPUT_BYTES - Buffer.byteLength(DETACHED_TRUNCATION_MESSAGE);
1321
+ const handle = await open(spawnLogPath, "r");
1322
+ try {
1323
+ const stats = await handle.stat();
1324
+ const outputBytes = Math.max(0, stats.size - startOffset);
1325
+ if (outputBytes === 0) return "";
1326
+ const bytesToRead = Math.min(outputBytes, maximumPrefixBytes);
1327
+ const buffer = Buffer.alloc(bytesToRead);
1328
+ const { bytesRead } = await handle.read(buffer, 0, bytesToRead, startOffset);
1329
+ const output = buffer.subarray(0, bytesRead).toString("utf8");
1330
+ return outputBytes > maximumPrefixBytes ? `${output}${DETACHED_TRUNCATION_MESSAGE}` : output;
1331
+ } finally {
1332
+ await handle.close().catch(() => void 0);
1333
+ }
1205
1334
  }
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) {
1335
+ async function appendAgentLifecycleLog(agentId, event, details = {}, overdeckHome = getOverdeckHome()) {
1336
+ const agentDir = resolveAgentDirectory(overdeckHome, agentId);
1337
+ await mkdir(agentDir, { recursive: true });
1338
+ const logLine = JSON.stringify({
1339
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
1340
+ event,
1341
+ ...details
1342
+ });
1343
+ await appendFile(join(agentDir, "lifecycle.log"), `${logLine}\n`);
1344
+ }
1345
+ async function launchPanCommandDetached(input, dependencies = {}) {
1215
1346
  const { agentSessionName, issueId, role, workspacePath, args } = input;
1216
1347
  const cwd = input.cwd ?? workspacePath;
1217
- const activityId = `activity-${Date.now()}`;
1218
- const agentDir = join(homedir(), ".overdeck", "agents", agentSessionName);
1348
+ const overdeckHome = dependencies.overdeckHome ?? getOverdeckHome();
1349
+ const activityId = input.activityId ?? `activity-${(dependencies.now ?? Date.now)()}`;
1350
+ const agentDir = resolveAgentDirectory(overdeckHome, agentSessionName);
1219
1351
  await mkdir(agentDir, { recursive: true });
1220
1352
  const spawnLogPath = join(agentDir, "spawn.log");
1221
1353
  const spawnLogHandle = await open(spawnLogPath, "a");
1222
- const invocation = panCliInvocation(args);
1223
- const child = spawn(invocation.command, invocation.args, {
1354
+ const spawnLogStart = (await spawnLogHandle.stat()).size;
1355
+ const child = (dependencies.spawnPanCli ?? spawnPanCli)(args, {
1224
1356
  cwd,
1225
1357
  detached: true,
1226
1358
  stdio: [
1227
1359
  "ignore",
1228
1360
  spawnLogHandle.fd,
1229
1361
  spawnLogHandle.fd
1230
- ]
1362
+ ],
1363
+ env: {
1364
+ ...process.env,
1365
+ ...input.env
1366
+ }
1367
+ });
1368
+ let spawned = false;
1369
+ let settleSpawn;
1370
+ let rejectSpawn;
1371
+ const spawnPromise = new Promise((resolve, reject) => {
1372
+ settleSpawn = resolve;
1373
+ rejectSpawn = reject;
1231
1374
  });
1375
+ const completion = commandCompletion(child, {
1376
+ agentSessionName,
1377
+ issueId,
1378
+ role,
1379
+ workspacePath,
1380
+ activityId,
1381
+ args,
1382
+ cwd,
1383
+ spawnLogPath,
1384
+ spawnLogStart,
1385
+ spawnLogHandle,
1386
+ overdeckHome,
1387
+ onSpawn: () => {
1388
+ spawned = true;
1389
+ settleSpawn?.();
1390
+ },
1391
+ onError: (error) => {
1392
+ if (!spawned) rejectSpawn?.(error);
1393
+ }
1394
+ });
1395
+ completion.catch(() => void 0);
1396
+ await spawnPromise;
1397
+ child.unref();
1398
+ return {
1399
+ activityId,
1400
+ spawnLogPath,
1401
+ spawnLogStart,
1402
+ completion
1403
+ };
1404
+ }
1405
+ function commandCompletion(child, context) {
1232
1406
  child.once("spawn", () => {
1233
- appendAgentLifecycleLog(agentSessionName, "agent.work_spawn_process_spawned", {
1234
- issueId,
1235
- role,
1236
- workspacePath,
1237
- activityId,
1407
+ appendAgentLifecycleLog(context.agentSessionName, "agent.work_spawn_process_spawned", {
1408
+ issueId: context.issueId,
1409
+ role: context.role,
1410
+ workspacePath: context.workspacePath,
1411
+ activityId: context.activityId,
1238
1412
  pid: child.pid,
1239
- args,
1240
- cwd,
1241
- spawnLogPath
1242
- }).catch(() => void 0);
1413
+ args: context.args,
1414
+ cwd: context.cwd,
1415
+ spawnLogPath: context.spawnLogPath
1416
+ }, context.overdeckHome).catch(() => void 0).finally(context.onSpawn);
1243
1417
  });
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,
1418
+ return new Promise((resolve, reject) => {
1419
+ let settled = false;
1420
+ const finish = async (error) => {
1421
+ if (settled) return;
1422
+ settled = true;
1423
+ await context.spawnLogHandle.close().catch(() => void 0);
1424
+ if (error) reject(error);
1425
+ else resolve();
1426
+ };
1427
+ child.once("error", (error) => {
1428
+ (async () => {
1429
+ await appendAgentLifecycleLog(context.agentSessionName, "agent.work_spawn_process_error", {
1430
+ issueId: context.issueId,
1431
+ role: context.role,
1432
+ workspacePath: context.workspacePath,
1433
+ activityId: context.activityId,
1252
1434
  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,
1435
+ args: context.args,
1436
+ cwd: context.cwd,
1437
+ spawnLogPath: context.spawnLogPath
1438
+ }, context.overdeckHome).catch(() => void 0);
1439
+ context.onError(error);
1440
+ await finish(error);
1441
+ })();
1442
+ });
1443
+ child.once("close", (code, signal) => {
1444
+ (async () => {
1445
+ await appendAgentLifecycleLog(context.agentSessionName, "agent.work_spawn_process_closed", {
1446
+ issueId: context.issueId,
1447
+ role: context.role,
1448
+ workspacePath: context.workspacePath,
1449
+ activityId: context.activityId,
1265
1450
  code,
1266
1451
  signal,
1267
- args,
1268
- cwd,
1269
- spawnLogPath
1270
- }).catch(() => void 0);
1271
- resolve({
1452
+ args: context.args,
1453
+ cwd: context.cwd,
1454
+ spawnLogPath: context.spawnLogPath
1455
+ }, context.overdeckHome).catch(() => void 0);
1456
+ if (code === 0) {
1457
+ await finish();
1458
+ return;
1459
+ }
1460
+ const output = await readBoundedSpawnOutput(context.spawnLogPath, context.spawnLogStart).catch(() => "");
1461
+ const error = new Error(output.trim() || `pan ${context.args.join(" ")} exited with code ${code ?? "null"}`);
1462
+ Object.assign(error, {
1463
+ activityId: context.activityId,
1464
+ spawnLogPath: context.spawnLogPath,
1272
1465
  code,
1273
- signal
1466
+ signal,
1467
+ output
1274
1468
  });
1275
- });
1469
+ await finish(error);
1470
+ })();
1276
1471
  });
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();
1472
+ });
1473
+ }
1474
+ async function runDetachedCommand(argv, dependencies = {}) {
1475
+ const issueId = argv[1] ?? "";
1476
+ const parsedIssueId = parseIssueIdSync(issueId);
1477
+ if (!parsedIssueId) return {
1478
+ kind: "terminal-only",
1479
+ status: "rejected",
1480
+ message: `/pan ${argv[0] ?? "command"} requires a canonical issue ID such as PAN-1525.`
1481
+ };
1482
+ const role = argv[0] === "plan" ? "plan" : "work";
1483
+ const agentSessionName = `${role === "plan" ? "planning" : "agent"}-${parsedIssueId.normalized}`;
1484
+ const command = `/pan ${argv.join(" ")}`;
1485
+ const activityId = `activity-${(dependencies.now ?? Date.now)()}`;
1486
+ const emitActivity = dependencies.emitActivity ?? emitActivityEntryDurable;
1487
+ const source = role === "plan" ? "planning-agent" : "work-agent";
1488
+ const emitTransition = (status, level, message, output) => emitActivity({
1489
+ id: activityId,
1490
+ source,
1491
+ level,
1492
+ status,
1493
+ command,
1494
+ message,
1495
+ details: output,
1496
+ output,
1497
+ issueId
1498
+ });
1499
+ await emitTransition("accepted", "info", `Accepted ${command} for ${issueId} as activity ${activityId}.`);
1500
+ let launch;
1501
+ try {
1502
+ launch = await launchPanCommandDetached({
1503
+ agentSessionName,
1504
+ issueId,
1505
+ role,
1506
+ workspacePath: process.cwd(),
1507
+ args: argv,
1508
+ activityId
1509
+ }, dependencies);
1510
+ } catch (error) {
1511
+ const output = error instanceof Error ? error.message : String(error);
1512
+ await emitTransition("failed", "error", `Activity ${activityId} failed to start ${command} for ${issueId}.`, output).catch(() => void 0);
1513
+ throw error;
1292
1514
  }
1515
+ await emitTransition("running", "info", `Activity ${activityId} is running ${command} for ${issueId}.`).catch(() => void 0);
1516
+ launch.completion.then(async () => {
1517
+ const output = await readBoundedSpawnOutput(launch.spawnLogPath, launch.spawnLogStart).catch(() => "");
1518
+ await emitTransition("completed", "success", `Activity ${activityId} completed ${command} for ${issueId}.`, output || `Command ${command} completed without output.`);
1519
+ }, async (error) => {
1520
+ const activityError = error;
1521
+ const output = activityError.output?.trim() || activityError.message;
1522
+ await emitTransition("failed", "error", `Activity ${activityId} failed ${command} for ${issueId}.`, output);
1523
+ }).catch(() => void 0);
1524
+ return {
1525
+ kind: "activity",
1526
+ status: "accepted",
1527
+ command,
1528
+ activityId: launch.activityId,
1529
+ message: `Started ${command} for ${issueId}. Watch activity ${launch.activityId} or the ${issueId} issue view for progress.`
1530
+ };
1531
+ }
1532
+ //#endregion
1533
+ //#region routes/agents/shared.ts
1534
+ init_paths();
1535
+ init_agents$1();
1536
+ init_activity_logger();
1537
+ init_tmux();
1538
+ const execAsync$2 = promisify(exec);
1539
+ const execFileAsync$2 = promisify(execFile);
1540
+ function buildPanStartArgs(input) {
1541
+ return [
1542
+ "start",
1543
+ input.issueId,
1544
+ "--local",
1545
+ "--model",
1546
+ input.model,
1547
+ ...input.harness ? ["--harness", input.harness] : [],
1548
+ ...input.allowHost ? ["--host", "--yes"] : [],
1549
+ ...input.offBook ? ["--off-book"] : []
1550
+ ];
1551
+ }
1552
+ /**
1553
+ * PAN-1985: detached-spawn helper for `pan <args>`, shared between the
1554
+ * standard work-spawn route and the restart-fresh route. The neutral launcher
1555
+ * owns process/log lifecycle; this route-compatible wrapper preserves the
1556
+ * original behavior by waiting for a successful child exit.
1557
+ */
1558
+ const INTERNAL_STARTED_BY_TOKENS = new Set([
1559
+ "operator:cli:pan-start",
1560
+ "operator:cli:pan-plan",
1561
+ "planning-auto-handoff",
1562
+ "orphan-proposed-reconciler",
1563
+ "workspace-rebuild-recovery",
1564
+ "resume-agent"
1565
+ ]);
1566
+ function resolveRequestedStartedBy(value, internalRequest = false) {
1567
+ if (!internalRequest) return "operator:dashboard";
1568
+ const token = typeof value === "string" ? value.trim() : "";
1569
+ const flywheelRunId = token.startsWith("flywheel:") ? normalizeFlywheelRunId(token.slice(9)) : void 0;
1570
+ if (flywheelRunId) return `flywheel:${flywheelRunId}`;
1571
+ if (!INTERNAL_STARTED_BY_TOKENS.has(token)) throw new Error("Invalid internal startedBy provenance token.");
1572
+ return token;
1573
+ }
1574
+ async function isInternalAgentRequest(request) {
1575
+ const expected = await readInternalTokenForRequest();
1576
+ if (!expected) return false;
1577
+ return constantTimeTokenEqual(getHeaderFromMap(request.headers, INTERNAL_TOKEN_HEADER), expected);
1578
+ }
1579
+ async function spawnPanCommandDetached(input, dependencies = {}) {
1580
+ const launch = await launchPanCommandDetached(input, dependencies);
1581
+ await launch.completion;
1582
+ return launch.activityId;
1293
1583
  }
1294
1584
  function emitStartAgentPhase(issueId, phase, status, reason, details = {}) {
1295
1585
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -1344,16 +1634,6 @@ async function validateAgentRuntimeEventAuth(request) {
1344
1634
  }, { status: 403 })
1345
1635
  };
1346
1636
  }
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
1637
  function updateRegistryForAgentStart(issueId, workspacePath, agentId) {
1358
1638
  recordFeatureRegistryLifecycle({
1359
1639
  issueId,
@@ -1434,8 +1714,10 @@ function buildStoppedAgentLifecycle(agentOrIssueId, state, runtimeData) {
1434
1714
  const agentId = normalizeAgentId(agentOrIssueId);
1435
1715
  const hasAgentState = true;
1436
1716
  const hasLiveTmuxSession = false;
1437
- const hasSavedSession = !!runtimeData.claudeSessionId || !!getLatestSessionIdSync(agentId);
1717
+ const sessionId = getLatestSessionIdSync(agentId) ?? runtimeData.claudeSessionId ?? null;
1718
+ const hasSavedSession = !!sessionId;
1438
1719
  const hasWorkspace = typeof state.workspace === "string" && state.workspace.length > 0;
1720
+ const hasResumableTranscript = !sessionId || !!state.harness && state.harness !== "claude-code" || !state.workspace || claudeSessionTranscriptExists(state.workspace, sessionId);
1439
1721
  const agentStatus = state.status || "unknown";
1440
1722
  const runtime = runtimeData.state || "uninitialized";
1441
1723
  const isCompleted = runtimeData.resolution === "completed";
@@ -1446,7 +1728,7 @@ function buildStoppedAgentLifecycle(agentOrIssueId, state, runtimeData) {
1446
1728
  const isRunningButStuck = false;
1447
1729
  const hasResumableBackingState = hasWorkspace && !isPlaceholder;
1448
1730
  const isOrphaned = hasSavedSession && !hasResumableBackingState || !hasWorkspace || isPlaceholder;
1449
- const requiresSessionResetBeforeFreshStart = hasSavedSession && hasResumableBackingState && (isStopped || isCrashed);
1731
+ const requiresSessionResetBeforeFreshStart = hasSavedSession && hasResumableTranscript && hasResumableBackingState && (isStopped || isCrashed);
1450
1732
  let recommendedAction = "start";
1451
1733
  let reason;
1452
1734
  if (isOrphaned) {
@@ -1455,6 +1737,9 @@ function buildStoppedAgentLifecycle(agentOrIssueId, state, runtimeData) {
1455
1737
  } else if (requiresSessionResetBeforeFreshStart) {
1456
1738
  recommendedAction = "resume";
1457
1739
  reason = `Agent ${agentId} has a resumable Claude session. Use 'pan resume ${agentOrIssueId}' to continue it, or 'pan start ${agentOrIssueId} --fresh' to start a new session (e.g. to switch model).`;
1740
+ } else if (hasSavedSession && !hasResumableTranscript && hasResumableBackingState && (isStopped || isCrashed)) {
1741
+ recommendedAction = "start";
1742
+ reason = `Agent ${agentId} has a saved Claude session id but its transcript is missing on disk (jsonl-missing). Start Agent will create a fresh session in the existing workspace.`;
1458
1743
  } else if (!hasSavedSession && isStopped) {
1459
1744
  recommendedAction = "start";
1460
1745
  reason = `Agent ${agentId} is stopped and has no saved Claude session. Start Agent will create a fresh session in the existing workspace.`;
@@ -1464,6 +1749,7 @@ function buildStoppedAgentLifecycle(agentOrIssueId, state, runtimeData) {
1464
1749
  hasAgentState,
1465
1750
  hasLiveTmuxSession,
1466
1751
  hasSavedSession,
1752
+ hasResumableTranscript,
1467
1753
  hasWorkspace,
1468
1754
  isPlaceholder,
1469
1755
  isOrphaned,
@@ -1475,9 +1761,9 @@ function buildStoppedAgentLifecycle(agentOrIssueId, state, runtimeData) {
1475
1761
  runtimeState: runtime,
1476
1762
  agentStatus,
1477
1763
  canStartFresh: !requiresSessionResetBeforeFreshStart || isOrphaned,
1478
- canResumeSession: hasSavedSession && hasResumableBackingState && (isStopped || isCrashed),
1764
+ canResumeSession: hasSavedSession && hasResumableTranscript && hasResumableBackingState && (isStopped || isCrashed),
1479
1765
  canRestartWithContext: hasWorkspace,
1480
- canResetSession: hasSavedSession && hasResumableBackingState,
1766
+ canResetSession: hasSavedSession && hasResumableTranscript && hasResumableBackingState,
1481
1767
  requiresSessionResetBeforeFreshStart,
1482
1768
  recommendedAction,
1483
1769
  reason
@@ -1537,13 +1823,14 @@ async function getWorkspaceLocation(issueId) {
1537
1823
  }
1538
1824
  } catch {}
1539
1825
  }
1540
- async function getGitStatusAsync(workspacePath) {
1826
+ async function getGitStatusAsync(issueId, workspacePath) {
1541
1827
  try {
1542
1828
  if (!existsSync(workspacePath)) return null;
1829
+ const repoDir = resolvePrimaryWorkspaceRepoDirSync(issueId, workspacePath);
1543
1830
  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 })
1831
+ execAsync$2("git rev-parse --abbrev-ref HEAD 2>/dev/null || echo \"\"", { cwd: repoDir }),
1832
+ execAsync$2("git status --porcelain 2>/dev/null | wc -l", { cwd: repoDir }),
1833
+ execAsync$2("git log -1 --pretty=format:\"%s\" 2>/dev/null || echo \"\"", { cwd: repoDir })
1547
1834
  ]);
1548
1835
  const branch = branchResult.stdout.trim();
1549
1836
  const uncommitted = uncommittedResult.stdout.trim();
@@ -1700,6 +1987,22 @@ const getAgentPendingQuestions = getAgentPendingQuestions$1;
1700
1987
  //#region routes/agents/listing.ts
1701
1988
  init_agents$1();
1702
1989
  init_tmux();
1990
+ /**
1991
+ * PAN-3070 — the health status a live agent row reports.
1992
+ *
1993
+ * A live tmux session used to mean `healthy` unconditionally, so an agent frozen
1994
+ * for hours on an unanswered tool-permission prompt was reported
1995
+ * `status: healthy` / `resolution: working` while the Decisions surface
1996
+ * simultaneously showed it as needing the operator. Two surfaces answering "is
1997
+ * this agent stuck?" from different evidence, and this one stale.
1998
+ *
1999
+ * `warning` is the value `src/lib/health.ts` already reports for an agent
2000
+ * waiting on a human, and it stays inside the fleet-view status set, so a
2001
+ * blocked agent is flagged without disappearing from any existing list.
2002
+ */
2003
+ function liveAgentHealthStatus(enrichment) {
2004
+ return isBlockedOnPendingInput(enrichment) ? "warning" : "healthy";
2005
+ }
1703
2006
  const getAgentsRoute = HttpRouter.add("GET", "/api/agents", httpHandler(Effect.gen(function* () {
1704
2007
  const now = Date.now();
1705
2008
  if (agentsCache.data && now - agentsCache.timestamp < 5e3) return jsonResponse(agentsCache.data);
@@ -1833,7 +2136,7 @@ const getAgentsRoute = HttpRouter.add("GET", "/api/agents", httpHandler(Effect.g
1833
2136
  const enrichment = await Effect.runPromise(computeAgentEnrichment(name, startedAt, hasActiveSpecialist));
1834
2137
  const workspaceLocation = isRemote ? "remote" : await getWorkspaceLocation(issueId);
1835
2138
  const workspace = isRemote && remoteState.vmName ? `/workspace (${String(remoteState.vmName)})` : state.workspace || null;
1836
- const gitStatus = workspace && !isRemote ? await getGitStatusAsync(workspace) : null;
2139
+ const gitStatus = workspace && !isRemote ? await getGitStatusAsync(issueId, workspace) : null;
1837
2140
  let contextPercent = null;
1838
2141
  let initialContextPercent = null;
1839
2142
  const agentCtxDir = join(homedir(), ".overdeck", "agents", name);
@@ -1843,12 +2146,13 @@ const getAgentsRoute = HttpRouter.add("GET", "/api/agents", httpHandler(Effect.g
1843
2146
  const initCtxFile = join(agentCtxDir, "initial-context-pct");
1844
2147
  initialContextPercent = parseInt((await readFile(initCtxFile, "utf-8").catch(() => "")).trim(), 10) || null;
1845
2148
  } catch {}
2149
+ const blockedOnPendingInput = isBlockedOnPendingInput(enrichment);
1846
2150
  return {
1847
2151
  id: name,
1848
2152
  issueId,
1849
2153
  runtime: state.harness ?? "claude-code",
1850
2154
  model: state.model || (isPlanning ? "opus" : "sonnet"),
1851
- status: "healthy",
2155
+ status: liveAgentHealthStatus(enrichment),
1852
2156
  startedAt,
1853
2157
  ...buildAgentGateFailureSnapshot(state),
1854
2158
  killCount: health.killCount || 0,
@@ -1865,7 +2169,7 @@ const getAgentsRoute = HttpRouter.add("GET", "/api/agents", httpHandler(Effect.g
1865
2169
  pendingInputCount: enrichment.pendingInputCount,
1866
2170
  pendingInputKinds: enrichment.pendingInputKinds,
1867
2171
  pendingAskUserQuestion: enrichment.pendingAskUserQuestion,
1868
- resolution: runtimeData?.resolution || enrichment.resolution || "working",
2172
+ resolution: blockedOnPendingInput ? "needs_input" : runtimeData?.resolution || enrichment.resolution || "working",
1869
2173
  resolutionCount: runtimeData?.resolutionCount || enrichment.resolutionCount || 0,
1870
2174
  contextPercent,
1871
2175
  initialContextPercent,
@@ -1951,7 +2255,7 @@ const getAgentOutputRoute = HttpRouter.add("GET", "/api/agents/:id/output", http
1951
2255
  } catch {}
1952
2256
  let stdout;
1953
2257
  if (isRemote && vmName) {
1954
- const { getRemoteAgentOutput } = await import("./remote-agents-CA3Ihlxj.js");
2258
+ const { getRemoteAgentOutput } = await import("./remote-agents-CLZB3Coc.js");
1955
2259
  stdout = await getRemoteAgentOutput(id, vmName, parseInt(String(lines), 10) || 100);
1956
2260
  } else stdout = await Effect.runPromise(capturePane(id, parseInt(String(lines), 10) || 100));
1957
2261
  if (!stdout || stdout.trim() === "" || stdout.trim() === "Session not found") {
@@ -2104,6 +2408,352 @@ const getAgentTimelineRoute = HttpRouter.add("GET", "/api/agents/:id/timeline",
2104
2408
  return jsonResponse({ timeline: events.slice(0, limit) });
2105
2409
  })));
2106
2410
  //#endregion
2411
+ //#region ../../lib/composer-commands/confirmations.ts
2412
+ const COMPOSER_CONFIRMATION_TTL_MS = 300 * 1e3;
2413
+ function composerCommandConfirmationFromBody(body) {
2414
+ if (!("confirmationNonce" in body) && !("confirmationText" in body)) return void 0;
2415
+ return {
2416
+ nonce: body["confirmationNonce"],
2417
+ typedText: body["confirmationText"]
2418
+ };
2419
+ }
2420
+ var ComposerCommandConfirmationError = class extends Error {
2421
+ code = "invalid-confirmation";
2422
+ constructor(message) {
2423
+ super(message);
2424
+ this.name = "ComposerCommandConfirmationError";
2425
+ }
2426
+ };
2427
+ function createComposerConfirmationStore(dependencies = {}) {
2428
+ const entries = /* @__PURE__ */ new Map();
2429
+ const now = dependencies.now ?? Date.now;
2430
+ const createNonce = dependencies.createNonce ?? (() => randomBytes(24).toString("base64url"));
2431
+ function pruneExpired() {
2432
+ const currentTime = now();
2433
+ for (const [nonce, entry] of entries) if (entry.expiresAt <= currentTime) entries.delete(nonce);
2434
+ }
2435
+ return {
2436
+ issue({ target, argv, policy, display }) {
2437
+ if (policy.safety === "destructive" && !policy.typedConfirmation) throw new Error(`Destructive composer policy for ${display} must define typedConfirmation.`);
2438
+ pruneExpired();
2439
+ const nonce = createNonce();
2440
+ entries.set(nonce, {
2441
+ targetKind: target.kind,
2442
+ targetId: target.id,
2443
+ argv: [...argv],
2444
+ safety: policy.safety,
2445
+ typedText: policy.typedConfirmation,
2446
+ expiresAt: now() + COMPOSER_CONFIRMATION_TTL_MS
2447
+ });
2448
+ return {
2449
+ kind: "confirmation",
2450
+ status: "confirmation_required",
2451
+ nonce,
2452
+ consequence: policy.confirmationText ?? `Running ${display} requires confirmation before Overdeck continues.`,
2453
+ ...policy.typedConfirmation ? { typedText: policy.typedConfirmation } : {}
2454
+ };
2455
+ },
2456
+ consume({ target, argv, policy, confirmation }) {
2457
+ if (typeof confirmation.nonce !== "string") throw new ComposerCommandConfirmationError("A valid confirmation nonce is required before this command can run.");
2458
+ const entry = entries.get(confirmation.nonce);
2459
+ entries.delete(confirmation.nonce);
2460
+ if (!entry) throw new ComposerCommandConfirmationError("This command confirmation is missing, invalid, or has already been used. Request a new confirmation and try again.");
2461
+ if (entry.expiresAt <= now()) throw new ComposerCommandConfirmationError("This command confirmation has expired. Request a new confirmation and try again.");
2462
+ 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.");
2463
+ if (policy.safety === "destructive" && (typeof confirmation.typedText !== "string" || confirmation.typedText !== entry.typedText)) throw new ComposerCommandConfirmationError(`Type "${entry.typedText ?? ""}" exactly to confirm this destructive command.`);
2464
+ }
2465
+ };
2466
+ }
2467
+ function sameArgv(left, right) {
2468
+ return left.length === right.length && left.every((value, index) => value === right[index]);
2469
+ }
2470
+ const composerConfirmationStore = createComposerConfirmationStore();
2471
+ //#endregion
2472
+ //#region ../../lib/composer-commands/parser.ts
2473
+ var ComposerCommandParseError = class extends Error {
2474
+ constructor(code, message, token, expected) {
2475
+ super(message);
2476
+ this.code = code;
2477
+ this.token = token;
2478
+ this.expected = expected;
2479
+ this.name = "ComposerCommandParseError";
2480
+ }
2481
+ };
2482
+ const FORBIDDEN_TOKEN = /\$\(|[;|&<>`]/;
2483
+ function expectedSyntax(entry) {
2484
+ const args = entry.args.map((argument) => {
2485
+ const name = argument.variadic ? `${argument.name}...` : argument.name;
2486
+ return argument.required ? `<${name}>` : `[${name}]`;
2487
+ });
2488
+ const options = entry.options.length > 0 ? ["[options]"] : [];
2489
+ return [
2490
+ entry.display,
2491
+ ...args,
2492
+ ...options
2493
+ ].join(" ");
2494
+ }
2495
+ function tokenize(input) {
2496
+ const tokens = [];
2497
+ let current = "";
2498
+ let quote = null;
2499
+ let escaped = false;
2500
+ const pushCurrent = () => {
2501
+ if (current.length === 0) return;
2502
+ tokens.push(current);
2503
+ current = "";
2504
+ };
2505
+ for (const character of input) {
2506
+ if (escaped) {
2507
+ current += character;
2508
+ escaped = false;
2509
+ continue;
2510
+ }
2511
+ if (character === "\\") {
2512
+ escaped = true;
2513
+ continue;
2514
+ }
2515
+ if (quote !== null) {
2516
+ if (character === quote) quote = null;
2517
+ else current += character;
2518
+ continue;
2519
+ }
2520
+ if (character === "\"" || character === "'") {
2521
+ quote = character;
2522
+ continue;
2523
+ }
2524
+ if (/\s/.test(character)) {
2525
+ pushCurrent();
2526
+ continue;
2527
+ }
2528
+ current += character;
2529
+ }
2530
+ if (escaped) current += "\\";
2531
+ if (quote !== null) throw new ComposerCommandParseError("missing-argument", `Unclosed ${quote} quote. Close the quoted value before submitting the command.`, quote, `a closing ${quote}`);
2532
+ pushCurrent();
2533
+ return tokens;
2534
+ }
2535
+ function aliasesForPath(entry) {
2536
+ let candidates = [[]];
2537
+ for (let index = 0; index < entry.path.length; index += 1) {
2538
+ const prefix = entry.path.slice(0, index + 1);
2539
+ const prefixEntry = COMPOSER_COMMAND_MANIFEST.find((candidate) => candidate.path.length === prefix.length && candidate.path.every((part, partIndex) => part === prefix[partIndex]));
2540
+ const names = [entry.path[index], ...prefixEntry?.aliases ?? []];
2541
+ candidates = candidates.flatMap((candidate) => names.map((name) => [...candidate, name]));
2542
+ }
2543
+ return candidates;
2544
+ }
2545
+ function resolveEntry(tokens) {
2546
+ const match = COMPOSER_COMMAND_MANIFEST.flatMap((entry) => aliasesForPath(entry).filter((path) => path.every((part, index) => tokens[index] === part)).map((path) => ({
2547
+ entry,
2548
+ pathLength: path.length
2549
+ }))).sort((left, right) => right.pathLength - left.pathLength)[0];
2550
+ if (match) return match;
2551
+ const token = tokens[0] ?? "";
2552
+ 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>");
2553
+ }
2554
+ function optionDefinitions(entry) {
2555
+ const definitions = /* @__PURE__ */ new Map();
2556
+ for (const option of entry.options) {
2557
+ const flags = option.flags.split(/[ ,|]+/).filter((part) => part.startsWith("-"));
2558
+ const canonicalFlag = flags.find((flag) => flag.startsWith("--")) ?? flags[0];
2559
+ for (const flag of flags) definitions.set(flag, {
2560
+ option,
2561
+ canonicalFlag
2562
+ });
2563
+ }
2564
+ return definitions;
2565
+ }
2566
+ function splitFlag(token) {
2567
+ const separator = token.indexOf("=");
2568
+ if (separator === -1) return { flag: token };
2569
+ return {
2570
+ flag: token.slice(0, separator),
2571
+ inlineValue: token.slice(separator + 1)
2572
+ };
2573
+ }
2574
+ function parseOverdeckComposerCommand(message) {
2575
+ if (!/^\/pan(?:\s|$)/.test(message)) return null;
2576
+ const forbidden = message.match(FORBIDDEN_TOKEN)?.[0];
2577
+ 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");
2578
+ const tokens = tokenize(message.slice(4).trim());
2579
+ const { entry, pathLength } = resolveEntry(tokens);
2580
+ const remaining = tokens.slice(pathLength);
2581
+ const definitions = optionDefinitions(entry);
2582
+ const positionals = [];
2583
+ const flags = [];
2584
+ for (let index = 0; index < remaining.length; index += 1) {
2585
+ const token = remaining[index];
2586
+ if (!token.startsWith("-")) {
2587
+ positionals.push(token);
2588
+ continue;
2589
+ }
2590
+ const { flag, inlineValue } = splitFlag(token);
2591
+ const definition = definitions.get(flag);
2592
+ if (definition === void 0) throw new ComposerCommandParseError("unknown-flag", `Unknown flag "${flag}" for ${entry.display}. Expected syntax: ${expectedSyntax(entry)}.`, flag, expectedSyntax(entry));
2593
+ flags.push(definition.canonicalFlag);
2594
+ if (definition.option.valueHint === null) {
2595
+ if (inlineValue !== void 0) throw new ComposerCommandParseError("unknown-flag", `Flag "${flag}" does not accept a value. Expected syntax: ${expectedSyntax(entry)}.`, token, expectedSyntax(entry));
2596
+ continue;
2597
+ }
2598
+ if (inlineValue !== void 0) {
2599
+ 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));
2600
+ if (inlineValue.length > 0) flags.push(inlineValue);
2601
+ continue;
2602
+ }
2603
+ const next = remaining[index + 1];
2604
+ const nextIsFlag = next?.startsWith("-") === true;
2605
+ 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));
2606
+ if (next !== void 0 && !nextIsFlag) {
2607
+ flags.push(next);
2608
+ index += 1;
2609
+ }
2610
+ }
2611
+ if (!(entry.args.at(-1)?.variadic === true) && positionals.length > entry.args.length) {
2612
+ const token = positionals[entry.args.length];
2613
+ throw new ComposerCommandParseError("unknown-command", `Unexpected token "${token}" for ${entry.display}. Expected syntax: ${expectedSyntax(entry)}.`, token, expectedSyntax(entry));
2614
+ }
2615
+ const missing = entry.args.find((argument, index) => argument.required && positionals[index] === void 0);
2616
+ 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));
2617
+ return {
2618
+ entry,
2619
+ argv: [
2620
+ ...entry.path,
2621
+ ...positionals,
2622
+ ...flags
2623
+ ]
2624
+ };
2625
+ }
2626
+ //#endregion
2627
+ //#region ../../lib/composer-commands/policy.ts
2628
+ init_src();
2629
+ const COMPOSER_COMMAND_POLICIES = {
2630
+ start: {
2631
+ mode: "detached",
2632
+ safety: "safe"
2633
+ },
2634
+ plan: {
2635
+ mode: "detached",
2636
+ safety: "safe"
2637
+ },
2638
+ show: {
2639
+ mode: "captured",
2640
+ safety: "safe"
2641
+ },
2642
+ status: {
2643
+ mode: "captured",
2644
+ safety: "safe"
2645
+ },
2646
+ tell: {
2647
+ mode: "captured",
2648
+ safety: "safe"
2649
+ },
2650
+ handoff: {
2651
+ mode: "ui",
2652
+ safety: "dialog",
2653
+ uiAction: "handoff",
2654
+ confirmationText: "This opens the handoff dialog for the selected conversation. Review the destination and focus before continuing."
2655
+ },
2656
+ fork: {
2657
+ mode: "ui",
2658
+ safety: "dialog",
2659
+ uiAction: "fork",
2660
+ confirmationText: "This opens the fork dialog for the selected conversation. Review the fork mode and destination before continuing."
2661
+ }
2662
+ };
2663
+ const DEFAULT_POLICY = {
2664
+ mode: "terminal-only",
2665
+ safety: "safe"
2666
+ };
2667
+ function assertPolicyOverlayIntegrity(policies = COMPOSER_COMMAND_POLICIES, manifest = COMPOSER_COMMAND_MANIFEST) {
2668
+ for (const path of Object.keys(policies)) {
2669
+ const matches = manifest.filter((entry) => entry.path.join(" ") === path);
2670
+ if (matches.length !== 1) throw new Error(`Composer command policy path "${path}" must match exactly one manifest entry; found ${matches.length}.`);
2671
+ }
2672
+ }
2673
+ function resolvePolicy(path) {
2674
+ return COMPOSER_COMMAND_POLICIES[path.join(" ")] ?? DEFAULT_POLICY;
2675
+ }
2676
+ assertPolicyOverlayIntegrity();
2677
+ //#endregion
2678
+ //#region ../../lib/composer-commands/router.ts
2679
+ const UI_COMMAND_PATTERNS = [{
2680
+ action: "handoff",
2681
+ pattern: /^\/(?:handoff|pan-handoff|pan\s+handoff)(?:\s+([\s\S]+))?$/i
2682
+ }, {
2683
+ action: "fork",
2684
+ pattern: /^\/pan\s+fork(?:\s+([\s\S]+))?$/i
2685
+ }];
2686
+ function isComposerCommandMessage(message) {
2687
+ return UI_COMMAND_PATTERNS.some(({ pattern }) => pattern.test(message)) || /^\/pan(?:\s|$)/.test(message);
2688
+ }
2689
+ async function handleComposerCommandMessage({ message, target, confirmation }, dependencies = {}) {
2690
+ for (const { action, pattern } of UI_COMMAND_PATTERNS) {
2691
+ const match = message.match(pattern);
2692
+ if (match) {
2693
+ const parsed = parseOverdeckComposerCommand(`/pan ${action}`);
2694
+ const focus = match[1]?.trim();
2695
+ if (focus) parsed.argv.push(focus);
2696
+ return handleComposerCommand({
2697
+ parsed,
2698
+ target,
2699
+ confirmation
2700
+ }, dependencies);
2701
+ }
2702
+ }
2703
+ const parsed = parseOverdeckComposerCommand(message);
2704
+ if (parsed === null) return null;
2705
+ return handleComposerCommand({
2706
+ parsed,
2707
+ target,
2708
+ confirmation
2709
+ }, dependencies);
2710
+ }
2711
+ async function handleComposerCommand({ parsed, target, confirmation }, dependencies = {}) {
2712
+ const policy = (dependencies.resolvePolicy ?? resolvePolicy)(parsed.entry.path);
2713
+ if (policy.safety !== "safe") {
2714
+ const confirmationStore = dependencies.confirmationStore ?? composerConfirmationStore;
2715
+ if (confirmation === void 0) return confirmationStore.issue({
2716
+ target,
2717
+ argv: parsed.argv,
2718
+ policy,
2719
+ display: parsed.entry.display
2720
+ });
2721
+ confirmationStore.consume({
2722
+ target,
2723
+ argv: parsed.argv,
2724
+ policy,
2725
+ confirmation
2726
+ });
2727
+ }
2728
+ if (policy.mode === "captured") return runCapturedCommand(parsed.argv);
2729
+ if (policy.mode === "detached") return runDetachedCommand(parsed.argv);
2730
+ if (policy.mode === "ui" && policy.uiAction) return uiCommandResult(policy.uiAction, parsed.argv.slice(parsed.entry.path.length).join(" ") || void 0);
2731
+ if (policy.mode === "terminal-only") return {
2732
+ kind: "terminal-only",
2733
+ status: "rejected",
2734
+ message: `${parsed.entry.display} must run in a terminal. Composer execution has not been enabled for this command.`
2735
+ };
2736
+ return missingExecutorResult(parsed.entry.display, policy);
2737
+ }
2738
+ function uiCommandResult(action, focus) {
2739
+ return {
2740
+ kind: "ui",
2741
+ status: "requires_ui",
2742
+ action,
2743
+ args: focus ? { focus } : {}
2744
+ };
2745
+ }
2746
+ function missingExecutorResult(display, policy) {
2747
+ return {
2748
+ kind: "terminal-only",
2749
+ status: "rejected",
2750
+ message: `${display} is recognized as a ${policy.mode} command, but its composer executor is not registered yet. Run it in a terminal for now.`
2751
+ };
2752
+ }
2753
+ function composerCommandResultHttpStatus(result) {
2754
+ return result.kind === "terminal-only" ? 422 : 200;
2755
+ }
2756
+ //#endregion
2107
2757
  //#region routes/agents/messaging.ts
2108
2758
  init_agents$1();
2109
2759
  async function sendAgentMessage(id, message) {
@@ -2119,6 +2769,55 @@ async function sendAgentMessage(id, message) {
2119
2769
  remote: true
2120
2770
  } : { success: true };
2121
2771
  }
2772
+ async function handleAgentMessage(id, message, confirmation) {
2773
+ try {
2774
+ if (isComposerCommandMessage(message)) {
2775
+ let agentState;
2776
+ try {
2777
+ agentState = await Effect.runPromise(getAgentState(id));
2778
+ } catch {
2779
+ return jsonResponse({
2780
+ error: `Failed to resolve agent target: ${id}`,
2781
+ code: "agent-resolution-failed"
2782
+ }, { status: 503 });
2783
+ }
2784
+ if (!agentState) return jsonResponse({
2785
+ error: `Agent not found: ${id}`,
2786
+ code: "agent-not-found"
2787
+ }, { status: 404 });
2788
+ if (!agentState.harness) return jsonResponse({
2789
+ error: `Agent harness could not be resolved: ${id}`,
2790
+ code: "agent-harness-unresolved"
2791
+ }, { status: 503 });
2792
+ const result = await handleComposerCommandMessage({
2793
+ message,
2794
+ confirmation,
2795
+ target: {
2796
+ kind: "agent",
2797
+ id,
2798
+ harness: agentState.harness,
2799
+ cwd: agentState.workspace,
2800
+ issueId: agentState.issueId
2801
+ }
2802
+ });
2803
+ if (result !== null) return jsonResponse(result, { status: composerCommandResultHttpStatus(result) });
2804
+ }
2805
+ } catch (error) {
2806
+ if (error instanceof ComposerCommandConfirmationError) return jsonResponse({
2807
+ error: error.message,
2808
+ code: error.code
2809
+ }, { status: 422 });
2810
+ if (!(error instanceof ComposerCommandParseError)) throw error;
2811
+ const status = error.code === "unknown-command" ? 404 : error.code === "unknown-flag" ? 422 : 400;
2812
+ return jsonResponse({
2813
+ error: error.message,
2814
+ code: error.code,
2815
+ token: error.token,
2816
+ expected: error.expected
2817
+ }, { status });
2818
+ }
2819
+ return jsonResponse(await sendAgentMessage(id, message));
2820
+ }
2122
2821
  function validateAgentMessageOrigin(request) {
2123
2822
  const originCheck = validateOrigin(request);
2124
2823
  if (!originCheck.ok) return {
@@ -2135,9 +2834,10 @@ function postAgentMessageLikeRoute(path) {
2135
2834
  const originCheck = validateAgentMessageOrigin(yield* HttpServerRequest.HttpServerRequest);
2136
2835
  if (!originCheck.ok) return originCheck.response;
2137
2836
  const id = (yield* HttpRouter.params)["id"] ?? "";
2138
- const { message } = yield* readJsonBody$1;
2837
+ const body = yield* readJsonBody$1;
2838
+ const { message } = body;
2139
2839
  if (!message) return jsonResponse({ error: "Message required" }, { status: 400 });
2140
- return yield* Effect.promise(() => sendAgentMessage(id, message)).pipe(Effect.map((result) => jsonResponse(result)));
2840
+ return yield* Effect.promise(() => handleAgentMessage(id, message, composerCommandConfirmationFromBody(body)));
2141
2841
  })));
2142
2842
  }
2143
2843
  const postAgentMessageRoute = postAgentMessageLikeRoute("/api/agents/:id/message");
@@ -2386,7 +3086,7 @@ async function cleanupConversationAttachments(name) {
2386
3086
  * sessions that the lifecycle poller missed. */
2387
3087
  async function cleanupOrphanedConversationAttachments() {
2388
3088
  try {
2389
- const { listConversations } = await import("./conversations-CAsJF9kh.js");
3089
+ const { listConversations } = await import("./conversations-BKDVpB-3.js");
2390
3090
  const convNames = new Set(listConversations().map((c) => c.name));
2391
3091
  const root = getConversationAttachmentsRoot();
2392
3092
  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 +3511,21 @@ async function handleConversationSwitchModel(name, body) {
2811
3511
  function getPtySupervisorSocketPath(agentId) {
2812
3512
  return join(getOverdeckHome(), "sockets", `pty-${agentId}.sock`);
2813
3513
  }
3514
+ /**
3515
+ * Pull the supervisor's own failure out of the tmux pane it died in.
3516
+ *
3517
+ * A supervisor that cannot load its native node-pty exits instantly with an
3518
+ * ERR_MODULE_NOT_FOUND on stderr; all the spawn path sees is the socket that
3519
+ * never appeared. Reporting only the timeout hides the actual cause and sent
3520
+ * an operator hunting the memory governor instead (PAN-3172).
3521
+ */
3522
+ function extractSupervisorFailure(paneText) {
3523
+ const lines = paneText.split("\n").map((line) => line.trim()).filter(Boolean);
3524
+ const errors = lines.filter((line) => /error|cannot find|ERR_[A-Z_]+|pty-supervisor:/i.test(line));
3525
+ const chosen = (errors.length > 0 ? errors : lines).slice(-3);
3526
+ if (chosen.length === 0) return null;
3527
+ return chosen.join(" | ").slice(0, 500);
3528
+ }
2814
3529
  async function waitForPtySupervisorSocket(agentId, timeoutMs = PTY_SUPERVISOR_SOCKET_WAIT_MS) {
2815
3530
  const socketPath = getPtySupervisorSocketPath(agentId);
2816
3531
  const start = Date.now();
@@ -2820,7 +3535,8 @@ async function waitForPtySupervisorSocket(agentId, timeoutMs = PTY_SUPERVISOR_SO
2820
3535
  } catch {}
2821
3536
  await new Promise((r) => setTimeout(r, 250));
2822
3537
  }
2823
- throw new Error(`Timed out waiting for PTY supervisor socket ${socketPath}`);
3538
+ const failure = extractSupervisorFailure(await capturePaneText(agentId, 40));
3539
+ throw new Error(`Timed out waiting for PTY supervisor socket ${socketPath}` + (failure ? ` — supervisor output: ${failure}` : ""));
2824
3540
  }
2825
3541
  async function extractModelFromSessionFile(sessionFile) {
2826
3542
  try {
@@ -2980,7 +3696,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
2980
3696
  const codexApprovalPolicy = codexPermMode === "full-access" ? "never" : "on-request";
2981
3697
  const codexSandboxMode = codexPermMode === "full-access" ? "danger-full-access" : codexPermMode === "read-only" ? "read-only" : "workspace-write";
2982
3698
  const codexApprovalsReviewer = codexPermMode === "auto-review" ? "auto_review" : void 0;
2983
- const { initCodexHome, extractThreadIdFromRollout } = await import("./codex-GcHuUF-k.js");
3699
+ const { initCodexHome, extractThreadIdFromRollout } = await import("./codex-o8FJwzmy.js");
2984
3700
  initCodexHome(codexHome, {
2985
3701
  trustedDir: cwd,
2986
3702
  approvalPolicy: codexApprovalPolicy,
@@ -3049,7 +3765,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
3049
3765
  } catch {}
3050
3766
  console.log(`[claude-invoke] purpose=conversation-session | model=${model || "default"} | source=conversations.ts:spawnConversationSession | session=${tmuxSession} | resume=${resume} | command="${runtimeCommand}"`);
3051
3767
  try {
3052
- const { preTrustDirectory } = await import("./workspace-manager-CWT55qeI.js");
3768
+ const { preTrustDirectory } = await import("./workspace-manager-C1F3XsnS.js");
3053
3769
  preTrustDirectory(cwd);
3054
3770
  } catch {}
3055
3771
  try {
@@ -3066,7 +3782,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
3066
3782
  const codexHomeDir = codexFields.codexHome;
3067
3783
  (async () => {
3068
3784
  try {
3069
- const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-GcHuUF-k.js");
3785
+ const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-o8FJwzmy.js");
3070
3786
  const rollout = await waitForCodexRollout(codexHomeDir, 12e4);
3071
3787
  if (rollout) {
3072
3788
  const threadId = extractThreadIdFromRollout(rollout);
@@ -3208,6 +3924,7 @@ async function handleConversationResume(name, body, deps) {
3208
3924
  });
3209
3925
  }
3210
3926
  const oldSessionId = conv.claudeSessionId;
3927
+ const resumeCause = conv.status === "ended" ? "operator" : "system";
3211
3928
  const harness = conv.harness ?? "claude-code";
3212
3929
  const modelChanged = !!model && model !== conv.model;
3213
3930
  if (!await validateCwdContainment(conv.cwd)) return jsonResponse({ error: "Invalid cwd" }, { status: 400 });
@@ -3226,6 +3943,13 @@ async function handleConversationResume(name, body, deps) {
3226
3943
  await spawnConversationSession(conv.tmuxSession, conv.cwd, oldSessionId ?? randomUUID$1(), model, effort, conv.issueId ?? void 0, canResume, harness);
3227
3944
  await waitForTmuxSession(conv.tmuxSession);
3228
3945
  await waitForConversationRuntimeReady(conv.tmuxSession, harness, "respawn");
3946
+ const resumeGatePane = await capturePaneText(conv.tmuxSession, 90).catch(() => "");
3947
+ if (resumeGatePane && paneHasBlockingChoiceMenu(resumeGatePane)) console.log(`[conversations] resume contract skipped for ${name} — the harness is showing a blocking choice menu; the operator answers it`);
3948
+ else try {
3949
+ await deliverAgentMessage(conv.tmuxSession, `CONVERSATION RESUME: ${buildResumeContract(resumeCause)}`, "conversation-resume", resolveConversationDeliveryMethod(conv));
3950
+ } catch (err) {
3951
+ console.error(`[conversations] resume contract delivery failed for ${name}:`, err instanceof Error ? err.message : String(err));
3952
+ }
3229
3953
  markConversationActive(name);
3230
3954
  return jsonResponse({
3231
3955
  ...conv,
@@ -3957,7 +4681,7 @@ const postInternalAgentPermissionRequestRoute = HttpRouter.add("POST", "/api/int
3957
4681
  error: "missing agent id"
3958
4682
  }, { status: 400 });
3959
4683
  const request = yield* HttpServerRequest.HttpServerRequest;
3960
- const { INTERNAL_TOKEN_HEADER, getInternalTokenSync } = yield* Effect.promise(() => import("./internal-token-BrcU6qfe.js"));
4684
+ const { INTERNAL_TOKEN_HEADER, getInternalTokenSync } = yield* Effect.promise(() => import("./internal-token-Ias7N8Kg.js"));
3961
4685
  const expected = getInternalTokenSync();
3962
4686
  if (!expected) return jsonResponse({
3963
4687
  ok: false,
@@ -4093,6 +4817,7 @@ const postAgentPermissionResponseRoute = HttpRouter.add("POST", "/api/agents/:id
4093
4817
  * pollers (PAN-1134). Extracted from routes/agents.ts so Pi event polling
4094
4818
  * can reuse bodyToEvent without importing a heavy route module.
4095
4819
  */
4820
+ init_src();
4096
4821
  /**
4097
4822
  * Translate a decoded body into an unsigned DomainEvent (no sequence yet).
4098
4823
  * Returns null if the body doesn't map to a runtime event.
@@ -4213,6 +4938,25 @@ const bodyToEvent = (agentId, body, timestamp) => {
4213
4938
  contextSaturatedAt: source["contextSaturatedAt"]
4214
4939
  }
4215
4940
  };
4941
+ case "linear_mcp_auth_required": return {
4942
+ type: "linear_mcp_auth.required",
4943
+ timestamp,
4944
+ payload: {
4945
+ agentId,
4946
+ issueId: source["issueId"] ?? null,
4947
+ authUrl: source["authUrl"] ?? null,
4948
+ expiresAt: source["expiresAt"] ?? null
4949
+ }
4950
+ };
4951
+ case "linear_mcp_auth_healthy": return {
4952
+ type: "linear_mcp_auth.healthy",
4953
+ timestamp,
4954
+ payload: {
4955
+ agentId,
4956
+ issueId: source["issueId"] ?? null,
4957
+ source: "hook"
4958
+ }
4959
+ };
4216
4960
  default: return null;
4217
4961
  }
4218
4962
  };
@@ -4224,7 +4968,7 @@ const getAgentHealthHistoryRoute = HttpRouter.add("GET", "/api/agents/:id/health
4224
4968
  const request = yield* HttpServerRequest.HttpServerRequest;
4225
4969
  const urlOpt = HttpServerRequest.toURL(request);
4226
4970
  const hours = Option.isSome(urlOpt) ? urlOpt.value.searchParams.get("hours") ?? "24" : "24";
4227
- const { getHealthHistory } = yield* Effect.promise(() => import("./health-events-BDOHby5Q.js"));
4971
+ const { getHealthHistory } = yield* Effect.promise(() => import("./health-events-2Z6Wa9SM.js"));
4228
4972
  const endTime = /* @__PURE__ */ new Date();
4229
4973
  const startTime = /* @__PURE__ */ new Date(endTime.getTime() - parseInt(hours) * 60 * 60 * 1e3);
4230
4974
  const events = getHealthHistory(id, startTime.toISOString(), endTime.toISOString());
@@ -4237,9 +4981,18 @@ const getAgentHealthHistoryRoute = HttpRouter.add("GET", "/api/agents/:id/health
4237
4981
  })));
4238
4982
  function emitAgentRuntimeEvent(id, body, timestamp) {
4239
4983
  return Effect.gen(function* () {
4984
+ let eventBody = body;
4985
+ if (body["kind"] === "linear_mcp_auth_required" || body["kind"] === "linear_mcp_auth_healthy") {
4986
+ const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-C63p_ftq.js"));
4987
+ const snapshot = yield* (yield* AgentStateService).get(id);
4988
+ eventBody = {
4989
+ ...body,
4990
+ issueId: snapshot?.currentIssue ?? null
4991
+ };
4992
+ }
4240
4993
  let raw;
4241
4994
  try {
4242
- raw = bodyToEvent(id, body, timestamp);
4995
+ raw = bodyToEvent(id, eventBody, timestamp);
4243
4996
  } catch (error) {
4244
4997
  return {
4245
4998
  ok: false,
@@ -4265,7 +5018,7 @@ function emitAgentRuntimeEvent(id, body, timestamp) {
4265
5018
  detail: String(decoded.failure)
4266
5019
  }, { status: 400 })
4267
5020
  };
4268
- const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-D5UGKIJL.js"));
5021
+ const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-C63p_ftq.js"));
4269
5022
  yield* (yield* AgentStateService).emit(decoded.success);
4270
5023
  return {
4271
5024
  ok: true,
@@ -4347,7 +5100,7 @@ const getAgentRuntimeRoute = HttpRouter.add("GET", "/api/agents/:id/runtime", ht
4347
5100
  success: false,
4348
5101
  error: "missing agent id"
4349
5102
  }, { status: 400 });
4350
- const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-D5UGKIJL.js"));
5103
+ const { AgentStateService } = yield* Effect.promise(() => import("./agent-state-service-C63p_ftq.js"));
4351
5104
  const snapshot = yield* (yield* AgentStateService).get(id);
4352
5105
  if (!snapshot) return jsonResponse({
4353
5106
  success: false,
@@ -4532,8 +5285,8 @@ function createAgentStopHandler(lifecycleEvent) {
4532
5285
  yield* stopAgent(id);
4533
5286
  if (stateBeforeStop?.issueId) yield* Effect.promise(async () => {
4534
5287
  try {
4535
- const { resolveProjectFromIssueSync } = await import("./projects-vjjcmiN8.js");
4536
- const { findWorkspacePath } = await import("./archive-planning-BZDgzoEj.js");
5288
+ const { resolveProjectFromIssueSync } = await import("./projects-_n3Zui6K.js");
5289
+ const { findWorkspacePath } = await import("./archive-planning-B2XplFzT.js");
4537
5290
  const issueLower = stateBeforeStop.issueId.toLowerCase();
4538
5291
  const workspacePath = findWorkspacePath(resolveProjectFromIssueSync(stateBeforeStop.issueId)?.projectPath ?? process.cwd(), issueLower);
4539
5292
  if (workspacePath) {
@@ -4673,7 +5426,7 @@ const postAgentUnpauseRoute = HttpRouter.add("POST", "/api/agents/:id/unpause",
4673
5426
  if ((yield* getWorkAgentLifecycleState(id)).canResumeSession && updatedState.troubled !== true) {
4674
5427
  resumeTriggered = true;
4675
5428
  yield* Effect.promise(() => appendAgentLifecycleLog(id, "agent.unpause_immediate_resume_triggered"));
4676
- import("./resume-BFv1PGpA.js").then(({ resumeAgent }) => resumeAgent(id)).then((result) => {
5429
+ import("./resume-mOREjlYu.js").then(({ resumeAgent }) => resumeAgent(id)).then((result) => {
4677
5430
  if (!result.success) console.warn(`[agents] immediate resume after unpause failed for ${id}: ${result.error}`);
4678
5431
  }).catch((err) => console.warn(`[agents] immediate resume after unpause errored for ${id}:`, err));
4679
5432
  }
@@ -5960,18 +6713,72 @@ const writeAutoStartXBrief = (projectRoot, workspacePath, issue) => Effect.tryPr
5960
6713
  //#region routes/agents/spawn-helpers.ts
5961
6714
  init_child_env();
5962
6715
  init_agents$1();
6716
+ function buildAgentStartPlaceholder(input) {
6717
+ return {
6718
+ state: {
6719
+ id: input.agentSessionName,
6720
+ issueId: input.issueId,
6721
+ workspace: input.workspacePath,
6722
+ role: input.role,
6723
+ ...input.effectiveHarness ? { harness: input.effectiveHarness } : {},
6724
+ model: "pending-work-spawn",
6725
+ status: "starting",
6726
+ startedAt: input.startedAt,
6727
+ startedBy: input.startedBy,
6728
+ hostOverride: input.allowHost || void 0
6729
+ },
6730
+ event: {
6731
+ type: "agent.started",
6732
+ timestamp: input.startedAt,
6733
+ payload: {
6734
+ agentId: input.agentSessionName,
6735
+ issueId: input.issueId,
6736
+ agent: {
6737
+ id: input.agentSessionName,
6738
+ issueId: input.issueId,
6739
+ workspace: input.workspacePath,
6740
+ status: "starting",
6741
+ startedAt: input.startedAt,
6742
+ role: input.role,
6743
+ startedBy: input.startedBy,
6744
+ ...input.effectiveHarness ? { runtime: input.effectiveHarness } : {}
6745
+ }
6746
+ }
6747
+ }
6748
+ };
6749
+ }
6750
+ function buildContainerStartState(input) {
6751
+ return {
6752
+ id: input.agentSessionName,
6753
+ issueId: input.issueId,
6754
+ ...input.effectiveHarness ? { harness: input.effectiveHarness } : {},
6755
+ model: "pending-container-start",
6756
+ status: input.status,
6757
+ startedAt: input.startedAt,
6758
+ workspace: input.workspacePath,
6759
+ role: input.role,
6760
+ startedBy: input.startedBy,
6761
+ hostOverride: input.allowHost || void 0
6762
+ };
6763
+ }
6764
+ async function requestWorkStartAfterContainers(input) {
6765
+ const activityId = await input.spawnPanCommand(input.args, input.workspacePath);
6766
+ await input.markWorkStartAccepted();
6767
+ await input.updateIssueStatus();
6768
+ return activityId;
6769
+ }
5963
6770
  function handleRemoteAgentSpawn(input) {
5964
6771
  return Effect.gen(function* () {
5965
- 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"));
6772
+ const { issueId, workspacePath, workspaceMetadata, spawnModel, startedBy, autoSpawnConsentRequired, projectPath, spawnGuardrails, lifecycle } = input;
6773
+ const { spawnRemoteAgent, checkRemoteSpendCap } = yield* Effect.promise(() => import("./remote-agents-CLZB3Coc.js"));
6774
+ const { createFlyProviderFromConfig } = yield* Effect.promise(() => import("./remote-CUhyqjXk.js"));
6775
+ const { loadConfigSync: loadPanConfig } = yield* Effect.promise(() => import("./config-CL3Gyvja.js"));
5969
6776
  const panConfig = loadPanConfig();
5970
6777
  const spendCap = checkRemoteSpendCap(panConfig);
5971
6778
  if (!spendCap.allowed) return jsonResponse({ error: spendCap.message }, { status: 429 });
5972
6779
  const fly = createFlyProviderFromConfig(panConfig.remote);
5973
6780
  yield* Effect.promise(() => fly.syncAllCredentials(workspaceMetadata.vmName));
5974
- const { buildWorkAgentPrompt, getTrackerContext } = yield* Effect.promise(() => import("./work-agent-prompt-Du8Vh2aJ.js"));
6781
+ const { buildWorkAgentPrompt, getTrackerContext } = yield* Effect.promise(() => import("./work-agent-prompt-ByrPAzOy.js"));
5975
6782
  const trackerContext = yield* Effect.promise(() => getTrackerContext(issueId, workspacePath));
5976
6783
  const agentPrompt = yield* Effect.promise(() => buildWorkAgentPrompt({
5977
6784
  issueId,
@@ -5989,6 +6796,8 @@ function handleRemoteAgentSpawn(input) {
5989
6796
  workspace: workspaceMetadata,
5990
6797
  prompt: agentPrompt,
5991
6798
  model: spawnModel,
6799
+ startedBy,
6800
+ autoSpawnConsentRequired,
5992
6801
  tier: fly.getResiliencyTier()
5993
6802
  }));
5994
6803
  yield* saveAgentState({
@@ -5999,7 +6808,8 @@ function handleRemoteAgentSpawn(input) {
5999
6808
  model: spawnModel,
6000
6809
  status: "starting",
6001
6810
  startedAt: state.startedAt,
6002
- harness: "claude-code"
6811
+ harness: "claude-code",
6812
+ startedBy
6003
6813
  });
6004
6814
  updateRegistryForAgentStart(state.issueId, workspacePath, state.id);
6005
6815
  yield* Effect.promise(() => Effect.runPromise(lifecycle.transitionTo(issueId, "in_progress").pipe(Effect.catch(() => Effect.void))));
@@ -6011,7 +6821,8 @@ function handleRemoteAgentSpawn(input) {
6011
6821
  model: spawnModel,
6012
6822
  status: state.status,
6013
6823
  startedAt: state.startedAt,
6014
- harness: "claude-code"
6824
+ harness: "claude-code",
6825
+ startedBy
6015
6826
  }, {
6016
6827
  type: "agent.started",
6017
6828
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -6025,7 +6836,8 @@ function handleRemoteAgentSpawn(input) {
6025
6836
  model: spawnModel,
6026
6837
  status: state.status,
6027
6838
  startedAt: state.startedAt,
6028
- lastActivity: state.lastActivity
6839
+ lastActivity: state.lastActivity,
6840
+ startedBy
6029
6841
  }
6030
6842
  }
6031
6843
  });
@@ -6053,7 +6865,7 @@ function handleRemoteAgentSpawn(input) {
6053
6865
  }
6054
6866
  function handleContainerOrchestration(input) {
6055
6867
  return Effect.gen(function* () {
6056
- const { issueId, workspacePath, devScript, agentSessionName, role, effectiveHarness, allowHost, spawnModel, spawnGuardrails, projectPath, eventStore, spawnPanCommand, updateIssueStatus } = input;
6868
+ const { issueId, workspacePath, devScript, agentSessionName, role, effectiveHarness, startedBy, allowHost, spawnModel, spawnGuardrails, projectPath, eventStore, spawnPanCommand, markWorkStartAccepted, updateIssueStatus } = input;
6057
6869
  if (existsSync(workspacePath) && existsSync(devScript)) {
6058
6870
  let dockerRunning = false;
6059
6871
  try {
@@ -6122,17 +6934,17 @@ function handleContainerOrchestration(input) {
6122
6934
  const earlyAgentId = agentSessionName;
6123
6935
  const earlyStateDir = join(homedir(), ".overdeck", "agents", earlyAgentId);
6124
6936
  yield* Effect.promise(() => mkdir(earlyStateDir, { recursive: true }));
6125
- saveAgentStateSync({
6126
- id: earlyAgentId,
6937
+ saveAgentStateSync(buildContainerStartState({
6938
+ agentSessionName: earlyAgentId,
6127
6939
  issueId,
6128
- ...effectiveHarness ? { harness: effectiveHarness } : {},
6129
- model: "pending-container-start",
6130
- status: "starting",
6131
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
6132
- workspace: workspacePath,
6940
+ workspacePath,
6133
6941
  role,
6134
- hostOverride: allowHost || void 0
6135
- });
6942
+ effectiveHarness,
6943
+ startedBy,
6944
+ allowHost,
6945
+ status: "starting",
6946
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
6947
+ }));
6136
6948
  updateRegistryForAgentStart(issueId, workspacePath, earlyAgentId);
6137
6949
  yield* Effect.promise(() => appendAgentLifecycleLog(earlyAgentId, "agent.start_waiting_for_containers", {
6138
6950
  issueId,
@@ -6190,16 +7002,17 @@ function handleContainerOrchestration(input) {
6190
7002
  waitedMs: Date.now() - startTime
6191
7003
  });
6192
7004
  if (!healthy) {
6193
- saveAgentStateSync({
6194
- id: earlyAgentId,
7005
+ saveAgentStateSync(buildContainerStartState({
7006
+ agentSessionName: earlyAgentId,
6195
7007
  issueId,
6196
- ...effectiveHarness ? { harness: effectiveHarness } : {},
6197
- model: "pending-container-start",
7008
+ workspacePath,
7009
+ role,
7010
+ effectiveHarness,
7011
+ startedBy,
7012
+ allowHost,
6198
7013
  status: "error",
6199
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
6200
- workspace: workspacePath,
6201
- role
6202
- });
7014
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
7015
+ }));
6203
7016
  return;
6204
7017
  }
6205
7018
  for (const nmDir of [join(workspacePath, "node_modules"), join(workspacePath, "src", "dashboard", "frontend", "node_modules")]) try {
@@ -6224,14 +7037,19 @@ function handleContainerOrchestration(input) {
6224
7037
  emitStartAgentPhase(issueId, "spawn", "start", "starting local work agent after containers became healthy", { workspacePath });
6225
7038
  emitStartAgentPhase(issueId, "spawn", "success", "local work agent spawn requested after container startup", {
6226
7039
  workspacePath,
6227
- activityId: await spawnPanCommand(buildPanStartArgs({
6228
- issueId,
6229
- model: spawnModel,
6230
- harness: effectiveHarness,
6231
- allowHost
6232
- }), workspacePath)
7040
+ activityId: await requestWorkStartAfterContainers({
7041
+ args: buildPanStartArgs({
7042
+ issueId,
7043
+ model: spawnModel,
7044
+ harness: effectiveHarness,
7045
+ allowHost
7046
+ }),
7047
+ workspacePath,
7048
+ spawnPanCommand,
7049
+ markWorkStartAccepted,
7050
+ updateIssueStatus
7051
+ })
6233
7052
  });
6234
- await updateIssueStatus();
6235
7053
  } catch (err) {
6236
7054
  const errorMessage = err instanceof Error ? err.message : String(err);
6237
7055
  emitStartAgentPhase(issueId, "spawn", "failure", errorMessage, { workspacePath });
@@ -6240,15 +7058,17 @@ function handleContainerOrchestration(input) {
6240
7058
  error: errorMessage
6241
7059
  }).catch(() => void 0);
6242
7060
  try {
6243
- saveAgentStateSync({
6244
- id: earlyAgentId,
7061
+ saveAgentStateSync(buildContainerStartState({
7062
+ agentSessionName: earlyAgentId,
6245
7063
  issueId,
6246
- model: "pending-container-start",
7064
+ workspacePath,
7065
+ role,
7066
+ effectiveHarness,
7067
+ startedBy,
7068
+ allowHost,
6247
7069
  status: "error",
6248
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
6249
- workspace: workspacePath,
6250
- role
6251
- });
7070
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
7071
+ }));
6252
7072
  } catch {}
6253
7073
  console.error(`[start-agent] Background container startup failed for ${issueId}:`, err);
6254
7074
  }
@@ -6287,10 +7107,12 @@ function handleContainerOrchestration(input) {
6287
7107
  //#endregion
6288
7108
  //#region routes/agents/spawn.ts
6289
7109
  init_agents$1();
7110
+ init_staffing();
6290
7111
  init_operator_interventions();
6291
7112
  init_child_env();
6292
7113
  init_harness_policy();
6293
7114
  init_activity_logger();
7115
+ init_issue_id();
6294
7116
  init_projects();
6295
7117
  init_review_status();
6296
7118
  init_state_read_home();
@@ -6328,20 +7150,17 @@ function emitDirtyWorkspaceRefusalActivity(issueId, porcelain) {
6328
7150
  });
6329
7151
  } catch {}
6330
7152
  }
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
- ]);
7153
+ /**
7154
+ * Both workspace runtime directories are Overdeck-owned in full, so both get a
7155
+ * blanket prefix match. The legacy `.pan/` allowlist only matched the collapsed
7156
+ * `?? .pan/` porcelain form plus a closed set of files — but this gate always
7157
+ * runs with `--untracked-files=all`, which expands untracked directories into
7158
+ * individual paths. A pipeline-authored `.pan/drafts/<ISSUE>.md` therefore read
7159
+ * as operator dirt and 409'd the planning→work auto-handoff (PAN-3042).
7160
+ */
6340
7161
  function isOverdeckWorkspaceRuntimePath(path) {
6341
7162
  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-");
7163
+ return path === ".pan" || path === ".pan/" || path.startsWith(".pan/");
6345
7164
  }
6346
7165
  /** True when git porcelain contains only Overdeck-owned workspace runtime files. */
6347
7166
  function isOnlyOverdeckRuntimeWorkspaceChanges(porcelain) {
@@ -6368,14 +7187,23 @@ async function spawnAfterClearingStartGates(input) {
6368
7187
  }
6369
7188
  }
6370
7189
  const postAgentsRoute = HttpRouter.add("POST", "/api/agents", httpHandler(Effect.gen(function* () {
6371
- const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
7190
+ const request = yield* HttpServerRequest.HttpServerRequest;
7191
+ const authError = rejectUnsafeDashboardMutationRequest(request);
6372
7192
  if (authError) return authError;
6373
7193
  const body = yield* readJsonBody$1;
6374
7194
  const eventStore = yield* EventStoreService;
6375
7195
  const lifecycle = yield* IssueLifecycle;
6376
7196
  yield* ReadModelService;
6377
7197
  const { issueId, projectId } = body;
7198
+ const internalRequest = yield* Effect.promise(() => isInternalAgentRequest(request));
7199
+ let startedBy;
7200
+ try {
7201
+ startedBy = resolveRequestedStartedBy(body.startedBy, internalRequest);
7202
+ } catch (error) {
7203
+ return jsonResponse({ error: error instanceof Error ? error.message : String(error) }, { status: 400 });
7204
+ }
6378
7205
  const autoStart = body.auto === true;
7206
+ const autoSpawnConsentRequired = internalRequest && body.autoSpawnConsentRequired === true;
6379
7207
  const guardrailAcknowledged = body.guardrailAcknowledged === true;
6380
7208
  const offBook = body.offBook === true;
6381
7209
  const requestedHostOverride = body.host === true || body.allowHost === true;
@@ -6534,7 +7362,7 @@ const postAgentsRoute = HttpRouter.add("POST", "/api/agents", httpHandler(Effect
6534
7362
  let spawnModel;
6535
7363
  try {
6536
7364
  spawnModel = determineModel({
6537
- model: body.model,
7365
+ model: body.model ?? resolveIssueWorkModel(issueId),
6538
7366
  role,
6539
7367
  spawnKey: `${role}:${issueId}`
6540
7368
  });
@@ -6692,7 +7520,7 @@ const postAgentsRoute = HttpRouter.add("POST", "/api/agents", httpHandler(Effect
6692
7520
  console.warn(`[start-agent] Failed to set plan.status=running (non-fatal): ${planStatusErr?.message ?? planStatusErr}`);
6693
7521
  }
6694
7522
  try {
6695
- const { appendSessionEntry, getProjectConfigFromWorkspacePath, resolveProjectForIssue } = await import("./record-CN0pj4_5.js");
7523
+ const { appendSessionEntry, getProjectConfigFromWorkspacePath, resolveProjectForIssue } = await import("./record-BTwWhtBb.js");
6696
7524
  await appendSessionEntry(resolveProjectForIssue(issueId) ?? getProjectConfigFromWorkspacePath(workspacePath), issueId, {
6697
7525
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6698
7526
  reason: "start",
@@ -6717,6 +7545,8 @@ const postAgentsRoute = HttpRouter.add("POST", "/api/agents", httpHandler(Effect
6717
7545
  workspacePath,
6718
7546
  workspaceMetadata,
6719
7547
  spawnModel,
7548
+ startedBy,
7549
+ autoSpawnConsentRequired,
6720
7550
  projectPath,
6721
7551
  spawnGuardrails,
6722
7552
  lifecycle
@@ -6810,7 +7640,11 @@ const postAgentsRoute = HttpRouter.add("POST", "/api/agents", httpHandler(Effect
6810
7640
  role,
6811
7641
  workspacePath,
6812
7642
  args,
6813
- cwd
7643
+ cwd,
7644
+ env: {
7645
+ OVERDECK_AGENT_STARTED_BY: startedBy,
7646
+ OVERDECK_AUTO_SPAWN_CONSENT_REQUIRED: autoSpawnConsentRequired ? "1" : "0"
7647
+ }
6814
7648
  })
6815
7649
  }));
6816
7650
  if (!admitted.check.decision.eligible || !admitted.result) throw new OrderDispatchReservationError(admitted.check);
@@ -6827,48 +7661,29 @@ const postAgentsRoute = HttpRouter.add("POST", "/api/agents", httpHandler(Effect
6827
7661
  agentSessionName,
6828
7662
  role,
6829
7663
  effectiveHarness,
7664
+ startedBy,
6830
7665
  allowHost,
6831
7666
  spawnModel,
6832
7667
  spawnGuardrails,
6833
7668
  projectPath,
6834
7669
  eventStore,
6835
7670
  spawnPanCommand,
7671
+ markWorkStartAccepted,
6836
7672
  updateIssueStatus
6837
7673
  });
6838
- if (containerResponse) {
6839
- if (containerResponse.status >= 200 && containerResponse.status < 300) yield* Effect.promise(markWorkStartAccepted);
6840
- return containerResponse;
6841
- }
7674
+ if (containerResponse) return containerResponse;
6842
7675
  const placeholderStartedAt = (/* @__PURE__ */ new Date()).toISOString();
6843
- const placeholderState = {
6844
- id: agentSessionName,
7676
+ const { state: placeholderState, event: placeholderEvent } = buildAgentStartPlaceholder({
7677
+ agentSessionName,
6845
7678
  issueId,
6846
- workspace: workspacePath,
7679
+ workspacePath,
6847
7680
  role,
6848
- ...effectiveHarness ? { harness: effectiveHarness } : {},
6849
- model: "pending-work-spawn",
6850
- status: "starting",
6851
- startedAt: placeholderStartedAt,
6852
- hostOverride: allowHost || void 0
6853
- };
6854
- const hasLiveTmuxSession = yield* sessionExists(agentSessionName).pipe(Effect.catch(() => Effect.succeed(true)));
6855
- const placeholderClaim = yield* claimAgentStartPlaceholderProgram(placeholderState, {
6856
- type: "agent.started",
6857
- timestamp: placeholderStartedAt,
6858
- payload: {
6859
- agentId: agentSessionName,
6860
- issueId,
6861
- agent: {
6862
- id: agentSessionName,
6863
- issueId,
6864
- workspace: workspacePath,
6865
- status: "starting",
6866
- startedAt: placeholderStartedAt,
6867
- role,
6868
- ...effectiveHarness ? { runtime: effectiveHarness } : {}
6869
- }
6870
- }
6871
- }, hasLiveTmuxSession);
7681
+ effectiveHarness,
7682
+ startedBy,
7683
+ allowHost,
7684
+ startedAt: placeholderStartedAt
7685
+ });
7686
+ const placeholderClaim = yield* claimAgentStartPlaceholderProgram(placeholderState, placeholderEvent, yield* sessionExists(agentSessionName).pipe(Effect.catch(() => Effect.succeed(true))));
6872
7687
  if (!placeholderClaim.claimed) {
6873
7688
  yield* Effect.promise(() => appendAgentLifecycleLog(agentSessionName, "agent.start_placeholder_blocked", {
6874
7689
  issueId,
@@ -7142,16 +7957,26 @@ const readJsonBody = Effect.gen(function* () {
7142
7957
  const postMergeGuard = createInFlightGuard();
7143
7958
  const _serverManagedMerges = /* @__PURE__ */ new Set();
7144
7959
  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`);
7960
+ const parsedIssueId = parseIssueIdSync(issueId.trim());
7961
+ if (!parsedIssueId) {
7962
+ console.error(`[merge] Refusing post-merge lifecycle for invalid issue ID: ${issueId}`);
7963
+ return false;
7964
+ }
7965
+ const normalizedIssueId = parsedIssueId.normalized.toUpperCase();
7966
+ const started = postMergeGuard.run(normalizedIssueId, async () => {
7967
+ const projectPath = getProjectPathForIssue(parsedIssueId.prefix);
7968
+ const { postMergeLifecycle } = await import("./merge-agent-DQTXZk8z.js");
7969
+ const lifecycleOptions = {
7970
+ ...options?.verifiedMergedRef ? { verifiedMergedRef: options.verifiedMergedRef } : {},
7971
+ ...options?.verifiedMergedRepos?.length ? { verifiedMergedRepos: options.verifiedMergedRepos } : {}
7972
+ };
7973
+ await postMergeLifecycle(normalizedIssueId, projectPath, options?.sourceBranch, Object.keys(lifecycleOptions).length > 0 ? lifecycleOptions : void 0);
7974
+ console.log(`[merge] post-merge lifecycle completed for ${normalizedIssueId}`);
7975
+ const { runMergeTrainReconcile } = await import("./merge-train-Dmrcus12.js");
7976
+ const outcomes = await runMergeTrainReconcile(normalizedIssueId);
7977
+ if (outcomes.length > 0) console.log(`[merge-train] reconciled ${outcomes.length} sibling(s) after ${normalizedIssueId}: ` + outcomes.map((o) => `${o.issueId}=${o.result}`).join(", "));
7978
+ }, (err) => console.error(`[merge] post-merge lifecycle failed for ${normalizedIssueId}:`, err));
7979
+ if (!started) console.log(`[merge] firePostMergeLifecycle: skipping ${normalizedIssueId} — already in flight`);
7155
7980
  return started;
7156
7981
  }
7157
7982
  function getProjectPathForIssue(issuePrefix) {
@@ -7168,15 +7993,15 @@ init_io();
7168
7993
  init_domain_services();
7169
7994
  init_tmux();
7170
7995
  const getSpecialistsRoute = HttpRouter.add("GET", "/api/specialists", httpHandler(Effect.gen(function* () {
7171
- const { getAllSpecialistStatus, getAllProjectSpecialistStatuses } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
7996
+ const { getAllSpecialistStatus, getAllProjectSpecialistStatuses } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7172
7997
  return jsonResponse({
7173
7998
  specialists: yield* Effect.promise(() => getAllSpecialistStatus()),
7174
7999
  projects: yield* Effect.promise(() => getAllProjectSpecialistStatuses())
7175
8000
  });
7176
8001
  })));
7177
8002
  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"));
8003
+ const { getAllSpecialists, isRunning, getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
8004
+ const { clearHookSync } = yield* Effect.promise(() => import("./hooks-D1g1jKLI.js"));
7180
8005
  const specialists = getAllSpecialists();
7181
8006
  const results = [];
7182
8007
  for (const specialist of specialists) {
@@ -7211,7 +8036,7 @@ const postSpecialistsResetAllRoute = HttpRouter.add("POST", "/api/specialists/re
7211
8036
  const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done", httpHandler(Effect.gen(function* () {
7212
8037
  const body = yield* readJsonBody;
7213
8038
  const eventStore = yield* EventStoreService;
7214
- const { specialist, issueId, status, notes, itemId } = body;
8039
+ const { specialist, issueId, status, notes, itemId, runId } = body;
7215
8040
  const validSpecialists = [
7216
8041
  "review",
7217
8042
  "test",
@@ -7232,7 +8057,7 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7232
8057
  }
7233
8058
  console.log(`[specialists/done] ${specialist} signaling ${status} for ${normalizedIssueId}`);
7234
8059
  if (specialist === "merge") {
7235
- const { reportSpecialistCompletion } = yield* Effect.promise(() => import("./specialist-completion-Ky9wCDpb.js"));
8060
+ const { reportSpecialistCompletion } = yield* Effect.promise(() => import("./specialist-completion-B07XjWD2.js"));
7236
8061
  if (yield* reportSpecialistCompletion(normalizedIssueId, {
7237
8062
  status,
7238
8063
  notes
@@ -7276,10 +8101,27 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7276
8101
  break;
7277
8102
  }
7278
8103
  const updatedStatus = setReviewStatusSync(normalizedIssueId, update);
7279
- if (specialist === "inspect" && status === "failed") yield* Effect.promise(() => reportTieredInspectFailureEscalation(normalizedIssueId, notes));
8104
+ if (specialist === "inspect" && status === "failed") {
8105
+ yield* Effect.promise(() => reportTieredInspectFailureEscalation(normalizedIssueId, notes));
8106
+ yield* Effect.promise(async () => {
8107
+ try {
8108
+ const failedItemId = itemId ?? getReviewStatusSync(normalizedIssueId)?.inspectBeadId ?? void 0;
8109
+ const project = resolveProjectFromIssueSync(normalizedIssueId);
8110
+ if (project && failedItemId) {
8111
+ const workspacePath = join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`);
8112
+ if (existsSync(workspacePath)) {
8113
+ const { onInspectComplete } = await import("./inspect-agent-CUwVmr2h.js");
8114
+ await Effect.runPromise(onInspectComplete(project.projectKey, normalizedIssueId, failedItemId, "failed", workspacePath, notes));
8115
+ }
8116
+ }
8117
+ } catch (err) {
8118
+ console.error(`[specialists/done] Error delivering failed inspect verdict for ${normalizedIssueId}:`, err);
8119
+ }
8120
+ });
8121
+ }
7280
8122
  yield* Effect.promise(async () => {
7281
8123
  try {
7282
- const { getTmuxSessionName, updateRunMetadata, makeSpecialistRegistryKey } = await import("./specialists-DM6bWjsi.js");
8124
+ const { getTmuxSessionName, updateRunMetadata, makeSpecialistRegistryKey } = await import("./specialists-Bz-wFT7R.js");
7283
8125
  const projectKey = resolveProjectFromIssueSync(normalizedIssueId)?.projectKey;
7284
8126
  const tmuxSession = projectKey ? getTmuxSessionName(`${specialist}-agent`, projectKey, normalizedIssueId) : getTmuxSessionName(`${specialist}-agent`);
7285
8127
  saveAgentRuntimeState(tmuxSession, {
@@ -7298,7 +8140,7 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7298
8140
  });
7299
8141
  console.log(`[specialists/done] Cleared registry lock for ${registryKey} (${projectKey})`);
7300
8142
  }
7301
- const { updateSpecialistHandoffStatus } = await import("./specialist-handoff-logger-CMEwYxa2.js");
8143
+ const { updateSpecialistHandoffStatus } = await import("./specialist-handoff-logger-aKSxbIgD.js");
7302
8144
  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
8145
  } catch (err) {
7304
8146
  console.error(`[specialists/done] Error managing specialist state:`, err);
@@ -7310,10 +8152,12 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7310
8152
  if (project) {
7311
8153
  const workspacePath = join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`);
7312
8154
  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}`);
8155
+ const { formatAnchorShort, snapshotWorkspaceHeadsPromise } = await import("./git-utils-Xg4PFN45.js");
8156
+ const headAnchor = await snapshotWorkspaceHeadsPromise(normalizedIssueId, workspacePath);
8157
+ if (headAnchor) {
8158
+ setReviewStatusSync(normalizedIssueId, { reviewedAtCommit: headAnchor });
8159
+ console.log(`[specialists/done] Snapshotted reviewedAtCommit=${formatAnchorShort(headAnchor)} for ${normalizedIssueId}`);
8160
+ }
7317
8161
  }
7318
8162
  }
7319
8163
  } catch (err) {
@@ -7322,11 +8166,11 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7322
8166
  });
7323
8167
  if (specialist === "inspect" && status === "passed") yield* Effect.promise(async () => {
7324
8168
  try {
7325
- const { onInspectComplete } = await import("./inspect-agent-Brtz0URj.js");
8169
+ const { onInspectComplete } = await import("./inspect-agent-CUwVmr2h.js");
7326
8170
  const project = resolveProjectFromIssueSync(normalizedIssueId);
7327
8171
  if (project) {
7328
8172
  const workspacePath = join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`);
7329
- if (existsSync(workspacePath)) await Effect.runPromise(onInspectComplete(project.projectKey, normalizedIssueId, itemId, "passed", workspacePath));
8173
+ if (existsSync(workspacePath)) await Effect.runPromise(onInspectComplete(project.projectKey, normalizedIssueId, itemId, "passed", workspacePath, notes));
7330
8174
  }
7331
8175
  } catch (err) {
7332
8176
  console.error(`[specialists/done] Error saving inspect checkpoint:`, err);
@@ -7338,7 +8182,7 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7338
8182
  if (project) {
7339
8183
  if (existsSync(join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`))) {
7340
8184
  setReviewStatusSync(normalizedIssueId, { testStatus: "passed" });
7341
- const { initEventStore } = await import("./event-store-EV2cMiXj.js");
8185
+ const { initEventStore } = await import("./event-store-5UKzh9Jf.js");
7342
8186
  await (await initEventStore()).appendAsync({
7343
8187
  type: "test.passed",
7344
8188
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -7391,8 +8235,8 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7391
8235
  if (notes?.toLowerCase().includes("conflict")) yield* Effect.promise(async () => {
7392
8236
  try {
7393
8237
  const workAgentId = `agent-${normalizedIssueId.toLowerCase()}`;
7394
- const { sessionExists } = await import("./tmux-B6z7h_vZ.js");
7395
- const { messageAgent, spawnAgent, getAgentStateSync } = await import("./agents-wi9NWzs2.js");
8238
+ const { sessionExists } = await import("./tmux-Ctk6RV5l.js");
8239
+ const { messageAgent, spawnAgent, getAgentStateSync } = await import("./agents-ePFVoZbu.js");
7396
8240
  if (await Effect.runPromise(sessionExists(workAgentId))) {
7397
8241
  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
8242
  console.log(`[specialists/done] Sent rebase instructions to ${workAgentId}`);
@@ -7406,19 +8250,38 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7406
8250
  try {
7407
8251
  const project = resolveProjectFromIssueSync(normalizedIssueId);
7408
8252
  const workspacePath = project ? join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`) : void 0;
7409
- const { deliverReviewVerdictFeedback } = await import("./review-verdict-feedback-CTd4QMBu.js");
8253
+ const { deliverReviewVerdictFeedback } = await import("./review-verdict-feedback-HwF6ODFy.js");
7410
8254
  const result = await Effect.runPromise(deliverReviewVerdictFeedback({
7411
8255
  issueId: normalizedIssueId,
7412
8256
  verdict: status === "failed" ? "failed" : "blocked",
7413
8257
  notes,
7414
8258
  workspacePath,
7415
- prUrl: updatedStatus.prUrl
8259
+ prUrl: updatedStatus.prUrl,
8260
+ ...runId ? { runId } : {}
7416
8261
  }));
7417
8262
  console.log(`[specialists/done] Delivered review verdict feedback for ${normalizedIssueId} (feedback=${result.feedbackPath ?? "none"}, synthesis=${result.synthesisPath ?? "none"}, prComment=${result.prCommentPosted})`);
7418
8263
  } catch (err) {
7419
8264
  console.warn(`[specialists/done] Failed to deliver review verdict feedback: ${err.message}`);
7420
8265
  }
7421
8266
  });
8267
+ if (specialist === "review" && status === "failed") yield* Effect.promise(async () => {
8268
+ try {
8269
+ const project = resolveProjectFromIssueSync(normalizedIssueId);
8270
+ if (project) {
8271
+ const workspacePath = join(project.projectPath, "workspaces", `feature-${normalizedIssueId.toLowerCase()}`);
8272
+ if (existsSync(workspacePath)) {
8273
+ const { formatAnchorShort, snapshotWorkspaceHeadsPromise } = await import("./git-utils-Xg4PFN45.js");
8274
+ const reviewedAtCommit = await snapshotWorkspaceHeadsPromise(normalizedIssueId, workspacePath);
8275
+ if (reviewedAtCommit) {
8276
+ setReviewStatusSync(normalizedIssueId, { reviewedAtCommit });
8277
+ console.log(`[specialists/done] Snapshotted blocked reviewedAtCommit=${formatAnchorShort(reviewedAtCommit)} for ${normalizedIssueId}`);
8278
+ }
8279
+ }
8280
+ }
8281
+ } catch (err) {
8282
+ console.error(`[specialists/done] Failed to snapshot blocked reviewedAtCommit for ${normalizedIssueId}:`, err);
8283
+ }
8284
+ });
7422
8285
  const eventRole = specialistEventRole(specialist);
7423
8286
  if (eventRole) if (status === "passed") yield* eventStore.append({
7424
8287
  type: "specialist.completed",
@@ -7447,7 +8310,7 @@ const postSpecialistsDoneRoute = HttpRouter.add("POST", "/api/specialists/done",
7447
8310
  });
7448
8311
  })));
7449
8312
  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"));
8313
+ const { cleanupAllLogsSync } = yield* Effect.promise(() => import("./specialist-logs-Dae-n52_.js"));
7451
8314
  const results = cleanupAllLogsSync();
7452
8315
  return jsonResponse({
7453
8316
  success: true,
@@ -7457,7 +8320,7 @@ const postSpecialistsLogsCleanupAllRoute = HttpRouter.add("POST", "/api/speciali
7457
8320
  });
7458
8321
  })));
7459
8322
  const getSpecialistsProjectsRoute = HttpRouter.add("GET", "/api/specialists/projects", httpHandler(Effect.gen(function* () {
7460
- const { getAllProjectSpecialistStatuses } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8323
+ const { getAllProjectSpecialistStatuses } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7461
8324
  return jsonResponse(yield* Effect.promise(() => getAllProjectSpecialistStatuses()));
7462
8325
  })));
7463
8326
  const postSpecialistWakeRoute = HttpRouter.add("POST", "/api/specialists/:name/wake", httpHandler(Effect.gen(function* () {
@@ -7501,7 +8364,7 @@ const postSpecialistReportStatusRoute = HttpRouter.add("POST", "/api/specialists
7501
8364
  "blocked",
7502
8365
  "failed"
7503
8366
  ].includes(status)) {
7504
- const { getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-DM6bWjsi.js"));
8367
+ const { getTmuxSessionName } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7505
8368
  saveAgentRuntimeState(getTmuxSessionName(name), {
7506
8369
  state: "idle",
7507
8370
  lastActivity: (/* @__PURE__ */ new Date()).toISOString()
@@ -7600,6 +8463,7 @@ const specialistsLegacyRouteLayer = Layer.mergeAll(getSpecialistsRoute, getSpeci
7600
8463
  //#endregion
7601
8464
  //#region routes/specialists/project-routes.ts
7602
8465
  init_config_yaml();
8466
+ init_project_repos();
7603
8467
  init_projects();
7604
8468
  init_review_status();
7605
8469
  init_tmux();
@@ -7622,7 +8486,7 @@ const postProjectSpecialistKillRoute = HttpRouter.add("POST", "/api/specialists/
7622
8486
  const issueId = params["issueId"];
7623
8487
  const type = params["type"];
7624
8488
  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"));
8489
+ const { getTmuxSessionName, makeSpecialistRegistryKey, getRunMetadata } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7626
8490
  const tmuxSession = getRunMetadata(project, makeSpecialistRegistryKey(type, issueId)).tmuxSession ?? getTmuxSessionName(type, project, issueId);
7627
8491
  yield* Effect.promise(() => Effect.runPromise(killSession(tmuxSession)).catch(() => {}));
7628
8492
  saveAgentRuntimeState(tmuxSession, {
@@ -7649,7 +8513,7 @@ const getProjectSpecialistRunsRoute = HttpRouter.add("GET", "/api/specialists/:p
7649
8513
  if (limitParam) limit = parseInt(limitParam, 10);
7650
8514
  if (offsetParam) offset = parseInt(offsetParam, 10);
7651
8515
  }
7652
- const { listRunLogsSync } = yield* Effect.promise(() => import("./specialist-logs-C5p8G7tx.js"));
8516
+ const { listRunLogsSync } = yield* Effect.promise(() => import("./specialist-logs-Dae-n52_.js"));
7653
8517
  return jsonResponse(listRunLogsSync(project, type, {
7654
8518
  limit,
7655
8519
  offset
@@ -7660,7 +8524,7 @@ const getProjectSpecialistRunStreamRoute = HttpRouter.add("GET", "/api/specialis
7660
8524
  const project = params["project"];
7661
8525
  const type = params["type"];
7662
8526
  const runId = params["runId"];
7663
- const { getRunLogPath, isRunLogActive } = yield* Effect.promise(() => import("./specialist-logs-C5p8G7tx.js"));
8527
+ const { getRunLogPath, isRunLogActive } = yield* Effect.promise(() => import("./specialist-logs-Dae-n52_.js"));
7664
8528
  const logPath = getRunLogPath(project, type, runId);
7665
8529
  if (!existsSync(logPath)) return jsonResponse({ error: "Run log not found" }, { status: 404 });
7666
8530
  const encoder = new TextEncoder();
@@ -7719,7 +8583,7 @@ const getProjectSpecialistRunRoute = HttpRouter.add("GET", "/api/specialists/:pr
7719
8583
  const project = params["project"];
7720
8584
  const type = params["type"];
7721
8585
  const runId = params["runId"];
7722
- const { getRunLogSync, parseLogMetadata } = yield* Effect.promise(() => import("./specialist-logs-C5p8G7tx.js"));
8586
+ const { getRunLogSync, parseLogMetadata } = yield* Effect.promise(() => import("./specialist-logs-Dae-n52_.js"));
7723
8587
  const content = getRunLogSync(project, type, runId);
7724
8588
  if (!content) return jsonResponse({ error: "Run log not found" }, { status: 404 });
7725
8589
  return jsonResponse({
@@ -7733,7 +8597,7 @@ const postProjectSpecialistRunTerminateRoute = HttpRouter.add("POST", "/api/spec
7733
8597
  const project = params["project"];
7734
8598
  const type = params["type"];
7735
8599
  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"));
8600
+ const { terminateSpecialist } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7737
8601
  yield* Effect.promise(() => terminateSpecialist(project, type));
7738
8602
  return jsonResponse({
7739
8603
  success: true,
@@ -7745,7 +8609,7 @@ const postProjectSpecialistGracePauseRoute = HttpRouter.add("POST", "/api/specia
7745
8609
  const project = params["project"];
7746
8610
  const type = params["type"];
7747
8611
  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"));
8612
+ const { pauseGracePeriod } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7749
8613
  if (pauseGracePeriod(project, type)) return jsonResponse({
7750
8614
  success: true,
7751
8615
  message: "Grace period paused"
@@ -7757,7 +8621,7 @@ const postProjectSpecialistGraceResumeRoute = HttpRouter.add("POST", "/api/speci
7757
8621
  const project = params["project"];
7758
8622
  const type = params["type"];
7759
8623
  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"));
8624
+ const { resumeGracePeriod } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7761
8625
  if (resumeGracePeriod(project, type)) return jsonResponse({
7762
8626
  success: true,
7763
8627
  message: "Grace period resumed"
@@ -7769,7 +8633,7 @@ const postProjectSpecialistGraceExitRoute = HttpRouter.add("POST", "/api/special
7769
8633
  const project = params["project"];
7770
8634
  const type = params["type"];
7771
8635
  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"));
8636
+ const { exitGracePeriod } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7773
8637
  exitGracePeriod(project, type);
7774
8638
  return jsonResponse({
7775
8639
  success: true,
@@ -7781,7 +8645,7 @@ const getProjectSpecialistGraceRoute = HttpRouter.add("GET", "/api/specialists/:
7781
8645
  const project = params["project"];
7782
8646
  const type = params["type"];
7783
8647
  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"));
8648
+ const { getGracePeriodState } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7785
8649
  const state = getGracePeriodState(project, type);
7786
8650
  if (state) return jsonResponse(state);
7787
8651
  else return jsonResponse({ error: "No active grace period" }, { status: 404 });
@@ -7790,7 +8654,7 @@ const getProjectSpecialistContextRoute = HttpRouter.add("GET", "/api/specialists
7790
8654
  const params = yield* HttpRouter.params;
7791
8655
  const project = params["project"];
7792
8656
  const type = params["type"];
7793
- const { loadContextDigest } = yield* Effect.promise(() => import("./specialist-context-Bn3dCGS2.js"));
8657
+ const { loadContextDigest } = yield* Effect.promise(() => import("./specialist-context-DJ-zFyL3.js"));
7794
8658
  const digest = loadContextDigest(project, type);
7795
8659
  if (digest) return jsonResponse({ digest });
7796
8660
  else return jsonResponse({ error: "No context digest found" }, { status: 404 });
@@ -7799,7 +8663,7 @@ const postProjectSpecialistContextRegenerateRoute = HttpRouter.add("POST", "/api
7799
8663
  const params = yield* HttpRouter.params;
7800
8664
  const project = params["project"];
7801
8665
  const type = params["type"];
7802
- const { regenerateContextDigest } = yield* Effect.promise(() => import("./specialist-context-Bn3dCGS2.js"));
8666
+ const { regenerateContextDigest } = yield* Effect.promise(() => import("./specialist-context-DJ-zFyL3.js"));
7803
8667
  const digest = yield* Effect.promise(() => regenerateContextDigest(project, type));
7804
8668
  if (digest) return jsonResponse({
7805
8669
  digest,
@@ -7818,7 +8682,7 @@ const postProjectSpecialistCompleteRoute = HttpRouter.add("POST", "/api/speciali
7818
8682
  "blocked"
7819
8683
  ].includes(status)) return jsonResponse({ error: "Valid status (passed/failed/blocked) is required" }, { status: 400 });
7820
8684
  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"));
8685
+ const { signalSpecialistCompletion } = yield* Effect.promise(() => import("./specialists-Bz-wFT7R.js"));
7822
8686
  signalSpecialistCompletion(project, type, {
7823
8687
  status,
7824
8688
  notes
@@ -7852,8 +8716,8 @@ const postProjectSpecialistLogsCleanupRoute = HttpRouter.add("POST", "/api/speci
7852
8716
  const params = yield* HttpRouter.params;
7853
8717
  const project = params["project"];
7854
8718
  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"));
8719
+ const { cleanupOldLogsSync } = yield* Effect.promise(() => import("./specialist-logs-Dae-n52_.js"));
8720
+ const { getSpecialistRetention } = yield* Effect.promise(() => import("./projects-_n3Zui6K.js"));
7857
8721
  const retention = getSpecialistRetention(project);
7858
8722
  const deleted = cleanupOldLogsSync(project, type, {
7859
8723
  maxDays: retention.max_days,
@@ -7874,21 +8738,23 @@ const postProjectReviewRestartRoute = HttpRouter.add("POST", "/api/specialists/:
7874
8738
  const project = params["project"];
7875
8739
  const issueId = params["issueId"];
7876
8740
  const { model, harness } = yield* readJsonBody;
7877
- const { killAllReviewerSessions } = yield* Effect.promise(() => import("./review-agent-DNboMyW4.js"));
8741
+ const { killAllReviewerSessions } = yield* Effect.promise(() => import("./review-agent-BTCNkq2h.js"));
7878
8742
  const killResult = yield* killAllReviewerSessions(project, issueId);
7879
8743
  const projectConfig = resolveProjectFromIssueSync(issueId);
7880
8744
  if (!projectConfig) return jsonResponse({ error: `Cannot resolve project for ${issueId}` }, { status: 404 });
7881
8745
  const workspacePath = join(projectConfig.projectPath, "workspaces", `feature-${issueId.toLowerCase()}`);
7882
8746
  if (!existsSync(workspacePath)) return jsonResponse({ error: `Workspace not found: ${workspacePath}` }, { status: 404 });
7883
- let branch = "unknown";
8747
+ const primaryRepo = resolveWorkspaceRepoRootsSync(issueId, workspacePath)[0];
8748
+ let branch = primaryRepo.sourceBranch;
7884
8749
  try {
7885
- const { stdout } = yield* Effect.promise(() => execAsync(`cd "${workspacePath}" && git branch --show-current`, {
8750
+ const { stdout } = yield* Effect.promise(() => execAsync("git branch --show-current", {
8751
+ cwd: resolvePrimaryWorkspaceRepoDirSync(issueId, workspacePath),
7886
8752
  encoding: "utf-8",
7887
8753
  timeout: 5e3
7888
8754
  }));
7889
- branch = stdout.trim() || "unknown";
8755
+ branch = stdout.trim() || primaryRepo.sourceBranch;
7890
8756
  } catch {}
7891
- const { spawnReviewRoleForIssue } = yield* Effect.promise(() => import("./review-agent-DNboMyW4.js"));
8757
+ const { spawnReviewRoleForIssue } = yield* Effect.promise(() => import("./review-agent-BTCNkq2h.js"));
7892
8758
  const prUrl = getReviewStatusSync(issueId)?.prUrl;
7893
8759
  const result = yield* spawnReviewRoleForIssue({
7894
8760
  issueId,
@@ -8037,6 +8903,6 @@ const specialistsProjectRouteLayer = Layer.mergeAll(getProjectSpecialistStatusRo
8037
8903
  */
8038
8904
  const specialistsRouteLayer = Layer.mergeAll(specialistsLegacyRouteLayer, specialistsProjectRouteLayer);
8039
8905
  //#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 };
8906
+ export { composerCommandConfirmationFromBody as $, resolveAllowedHarness as A, jsonResponse as At, cleanupUnreferencedConversationAttachments as B, handleConversationCreate as C, waitForSessionRespawn as Ct, handleConversationStop as D, validateOriginHeaders as Dt, handleConversationResume as E, validateOrigin 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, httpHandler as Ot, stopConversationRuntime as P, ComposerCommandConfirmationError as Q, cleanupConversationAttachments as R, conversationSessionAliveFromState as S, isRespawnPending as St, handleConversationRestartAll as T, isTrustedOriginForHost as Tt, getConversationAttachmentsRoot as U, ensureConversationAttachmentDir as V, hasConversationAttachment as W, resolvePolicy as X, handleComposerCommandMessage as Y, ComposerCommandParseError as Z, isPiControlChannelHarness as _, dashboardSessionCookieHeader as _t, agentsRouteLayer as a, resolveConversationGitInfo as at, validateConversationControlAckOrigin as b, rejectUnauthorizedDashboardSessionMintRequest as bt, codexConversationPendingInput as c, spawnPanCli as ct, handleConversationCodexApproval as d, resolveAgentHarness as dt, evaluateSpawnGuardrails as et, handleConversationCompact as f, resolveClaudeSessionId as ft, handleConversationThinkingLevel as g, dashboardCsrfToken as gt, handleConversationPlanAction as h, resolvePiSessionPath as ht, validateSpecialistAutoCompleteMetadata as i, resolveAgentGitInfo as it, shouldReportUnresolvedLiveSession as j, jsonStringResponse as jt, isInsideGitWorkTree as k, getDefaultCwd as kt, deliverConversationViaControlChannel as l, readLauncherPinnedSessionId as lt, handleConversationDeliveryMethod as m, resolveJsonlPath as mt, _serverManagedMerges as n, isInternalAgentRequest as nt, saveAgentStateAndEmitEvent as o, getWorkAgentLifecycleStateSync as ot, handleConversationControlAck as p, resolveCodexRolloutPath as pt, runInBatches as q, firePostMergeLifecycle as r, resolveRequestedStartedBy as rt, saveAgentStateAndEmitEventProgram as s, panCliInvocation as st, specialistsRouteLayer as t, invalidateAgentsCache as tt, handleConversationAbort as u, resolveAcpTranscriptPath as ut, pickDeliverAs as v, hasDashboardInternalToken as vt, handleConversationDelete as w, getHeaderFromMap as wt, conversationNeedsRunningRepair as x, rejectUnsafeDashboardMutationRequest as xt, resolveConversationDeliveryMethod as y, rejectUnauthorizedDashboardRequest as yt, cleanupOrphanedConversationAttachments as z };
8041
8907
 
8042
- //# sourceMappingURL=specialists-CC4r-c2s.js.map
8908
+ //# sourceMappingURL=specialists-6PWdtWcg.js.map