@overdeck/desktop 0.45.23 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (549) hide show
  1. package/drizzle/overdeck/0000_overdeck_init.sql +34 -0
  2. package/package.json +1 -1
  3. package/server/{acceptance-criteria-DOA0KgXx.js → acceptance-criteria-CCwFGICj.js} +2 -2
  4. package/server/activity-logger-CMthG6Vd.js +3 -0
  5. package/server/{activity-logger-DDlOIAML.js → activity-logger-CyteR4JO.js} +24 -13
  6. package/server/{advancing-selfheal-BBu6DSNm.js → advancing-selfheal-De1L-Sb4.js} +6 -6
  7. package/server/{agent-gc-BV1q_2EV.js → agent-gc-CBULruzm.js} +5 -5
  8. package/server/agent-state-VQk8fY9F.js +3 -0
  9. package/server/{agent-state-service-HoK8U4jW.js → agent-state-service-BlnSkRFA.js} +5 -5
  10. package/server/{agent-state-service-CnzFKSAQ.js → agent-state-service-hZpxIw1E.js} +1 -1
  11. package/server/agents-BKKkxKgK.js +3 -0
  12. package/server/{agents-B4Bjbkfv.js → agents-C5rWYhb6.js} +4 -4
  13. package/server/archive-planning-0FJ6Xd3b.js +2 -0
  14. package/server/{archive-planning-DYrYojxl.js → archive-planning-C0lAbNB_.js} +16 -24
  15. package/server/{artifact-index-jobs-C-xy7Z5v.js → artifact-index-jobs-ug6ZxIP5.js} +2 -2
  16. package/server/assemble-DnffNpOo.js +339 -0
  17. package/server/{backlog-auto-trigger-GtG71X8H.js → backlog-auto-trigger-Dh-i9PQf.js} +3 -3
  18. package/server/{behavior-B_-4EKF3.js → behavior-CfIg6pKp.js} +2 -2
  19. package/server/bridge-pool-patrol-CUFmjVDN.js +136 -0
  20. package/server/{briefing-freshness-DWdW7vUm.js → briefing-freshness-DHmCSLar.js} +2 -2
  21. package/server/{build-info-DgTqZkL5.js → build-info-BP160gU7.js} +1 -1
  22. package/server/{build-info-BT096lEl.js → build-info-CuFfxZxp.js} +5 -3
  23. package/server/{checkpoint-manager-DDqcGyu8.js → checkpoint-manager-DEWD82qK.js} +2 -2
  24. package/server/{checkpoint-manager-B7Bt29J0.js → checkpoint-manager-Dxh0FYsv.js} +1 -1
  25. package/server/checkpoint-worker.js +1 -1
  26. package/server/{checkpoints-C-AXLfYT.js → checkpoints-CZvbtLnr.js} +2 -2
  27. package/server/{checkpoints-CpgCjAlN.js → checkpoints-DMTgXuLG.js} +1 -1
  28. package/server/{claude-hooks-provision-C8wdRnN1.js → claude-hooks-provision-CN-xo-do.js} +1 -1
  29. package/server/{claude-hooks-provision-but-_qGY.js → claude-hooks-provision-fvy4RD2b.js} +13 -2
  30. package/server/{claude-permissions-H_5wHQZQ.js → claude-permissions-CN0cSCPp.js} +2 -2
  31. package/server/{claude-settings-overlay-CbSz0Dvb.js → claude-settings-overlay-CJn35FHQ.js} +2 -2
  32. package/server/{claude-settings-overlay-BTENVmYf.js → claude-settings-overlay-Dabi9slj.js} +1 -1
  33. package/server/cli-DmXETsw-.js +3 -0
  34. package/server/{cli-vBeXbPrq.js → cli-oCWYA1pE.js} +9 -9
  35. package/server/{cliproxy-Bgb2XCqi.js → cliproxy-C8mB3KuB.js} +2 -2
  36. package/server/{cliproxy-DW0V86F8.js → cliproxy-PGwTX_o8.js} +1 -1
  37. package/server/{close-issue-Dn_4c4G8.js → close-issue-D5MF5GqF.js} +5 -5
  38. package/server/{closed-issue-reaper-CWpY2uBw.js → closed-issue-reaper-CJ24u0Zt.js} +1 -1
  39. package/server/{closed-issue-reaper-hANY_ehE.js → closed-issue-reaper-Cltx86x5.js} +37 -16
  40. package/server/{codex-Dg7Is5yb.js → codex-BdEsUFWh.js} +1 -1
  41. package/server/{codex-TmSi-yTv.js → codex-Drlf5Xhf.js} +37 -8
  42. package/server/{codex-parser-C4gSH-IR.js → codex-parser-DpB89Vqa.js} +2 -2
  43. package/server/compaction-continuation-K2AxQX4H.js +200 -0
  44. package/server/{config-DjLOdbgT.js → config-B2IMcBxx.js} +4 -3
  45. package/server/{config-DUIhMN_T.js → config-DV-grfQc.js} +1 -1
  46. package/server/{config-CCvjQf27.js → config-Dr3pW6w6.js} +2 -2
  47. package/server/{config-yaml-DvyMuOle.js → config-yaml-CmOPzmBb.js} +290 -22
  48. package/server/{conflict-gate-CmrYpa47.js → conflict-gate-B9cN3SBi.js} +4 -4
  49. package/server/{conflict-gate-BSJkNTdp.js → conflict-gate-Dh754uyA.js} +1 -1
  50. package/server/context-layers-D6LZo3l1.js +4 -0
  51. package/server/context-layers-dR5YxHYB.js +37 -0
  52. package/server/{control-settings-aP1ANIlI.js → control-settings-C7DUehE1.js} +49 -19
  53. package/server/{conversation-compaction-CNbTLB86.js → conversation-compaction-BoqdDXWF.js} +8 -8
  54. package/server/{conversation-compaction-DiG5zWQq.js → conversation-compaction-Dj4FAKoZ.js} +1 -1
  55. package/server/{conversation-service-Du-MTNpJ.js → conversation-service-5aCnq1zR.js} +331 -20
  56. package/server/conversation-service-BCxl4f8Z.js +3 -0
  57. package/server/{conversations-DbOs1e9Q.js → conversations-BUpYsOZg.js} +5 -5
  58. package/server/{conversations-6mPANqvL.js → conversations-C34dyIb9.js} +1 -1
  59. package/server/{cost-Ca0YTWDw.js → cost-Bgcub5kW.js} +12 -2
  60. package/server/{cost-CW4WSe72.js → cost-CvxRrucd.js} +3 -3
  61. package/server/{cost-sync-C0VdGme1.js → cost-sync-Dv3LUaNW.js} +3 -3
  62. package/server/{dag-CdOjJVDT.js → dag-ombYYt4s.js} +2 -2
  63. package/server/{dangerous-git-ops-CT-IypG3.js → dangerous-git-ops-BcJPC5Rr.js} +1 -1
  64. package/server/dashboard-db-worker.js +7 -7
  65. package/server/deacon-DrXqT9LQ.js +4 -0
  66. package/server/{deacon-pRnyD5w9.js → deacon-hi9KLPLT.js} +2998 -2659
  67. package/server/{deacon-nudge-log-Bjg8U4Y9.js → deacon-nudge-log-BNBebzeL.js} +3 -3
  68. package/server/deacon-pending-lifecycle-Cpk0k7Hi.js +33 -0
  69. package/server/{deacon-swarm-DftYRDo8.js → deacon-swarm-DBxUaO-A.js} +13 -13
  70. package/server/deacon-swarm-I2JfX5Tg.js +2 -0
  71. package/server/deacon.js +14 -19
  72. package/server/dead-end-trip-CQcP70ND.js +13 -0
  73. package/server/delivery-Da0zEMY4.js +3 -0
  74. package/server/{deploy-patrol-Bjsho_ha.js → deploy-patrol-Df-Tmaq0.js} +69 -18
  75. package/server/deploy-queue-9SrhZR63.js +3 -0
  76. package/server/deploy-queue-UjKGYsDe.js +169 -0
  77. package/server/deploy-window-jOiPRHL0.js +3 -0
  78. package/server/{deploy-window-DeP_OIRk.js → deploy-window-rpqpWqHA.js} +40 -16
  79. package/server/{dev-supervisor-BpMoHlkR.js → dev-supervisor-CC46Ig8q.js} +2 -2
  80. package/server/{devcontainer-renderer-CtUgrVKW.js → devcontainer-renderer-68CSCRnu.js} +3 -3
  81. package/server/{dist-DyRx4cI7.js → dist-CJy72uEg.js} +1 -1
  82. package/server/dist-DSlxIU1H.js +3 -0
  83. package/server/{dist-src-BSoS7mkd.js → dist-src-Bik83hFi.js} +1 -1
  84. package/server/docker-BMVTSFL5.js +3 -0
  85. package/server/{docker-BK7HIcBj.js → docker-Dam7mbIB.js} +2 -2
  86. package/server/{dod-BrSfUHm0.js → dod-Dar-yheg.js} +8 -4
  87. package/server/durable-review-pipeline-CGZ5QBxh.js +17 -0
  88. package/server/durable-review-pipeline-jpgCJZFp.js +3 -0
  89. package/server/{ensure-devcontainer-DseivYEy.js → ensure-devcontainer-B057YA81.js} +4 -4
  90. package/server/{ensure-devcontainer-DRqaAkBR.js → ensure-devcontainer-C98V8yW-.js} +1 -1
  91. package/server/{esm-shims-CbI3BVkl.js → esm-shims-Br9BPdkR.js} +1 -1
  92. package/server/{event-store-Cr5PQwFC.js → event-store-ELqkVOn0.js} +1 -1
  93. package/server/{event-store-tdiY5eDZ.js → event-store-zY5MJHgF.js} +23 -4
  94. package/server/{events-CvvGK6LT.js → events-D6pyqhzM.js} +1 -1
  95. package/server/{events-CC1dgUpx.js → events-D9PR1IC0.js} +3 -3
  96. package/server/{factory-CynerjXO.js → factory-CRoOpGsF.js} +5 -5
  97. package/server/{feature-registry-population-B0pmAz0a.js → feature-registry-population--YUXU999.js} +4 -4
  98. package/server/{feature-registry-storage-_wUBRD3J.js → feature-registry-storage-BORBTo0y.js} +2 -2
  99. package/server/{features-Dhxz-wLc.js → features--nFkJY8v.js} +2 -2
  100. package/server/{feedback-target-iygZwmMc.js → feedback-target-C0ZzyHvU.js} +1 -1
  101. package/server/{feedback-target-CPS15Vte.js → feedback-target-Dt9BsapX.js} +8 -8
  102. package/server/{feedback-writer-C9b6ccN1.js → feedback-writer-BG0RUZiu.js} +5 -5
  103. package/server/{feedback-writer-qmiMbqTZ.js → feedback-writer-D1fm-5Z8.js} +1 -1
  104. package/server/flywheel-BekukH4i.js +2 -0
  105. package/server/flywheel-BiT3odRb.js +1092 -0
  106. package/server/flywheel-CLVB55Be.js +478 -0
  107. package/server/flywheel-merge-order-BJv1DZz1.js +462 -0
  108. package/server/flywheel-merge-order-BKw9o6ku.js +2 -0
  109. package/server/forge-CZbSg6Ds.js +383 -0
  110. package/server/forge-DK3blQb_.js +3 -0
  111. package/server/{from-CJ_aH5jD.js → from-D_4_dk7i.js} +1 -1
  112. package/server/{fts-db-CKgg0VKg.js → fts-db-BeOomFa-.js} +2 -2
  113. package/server/{fts-operations-BrL_VTRr.js → fts-operations-BdewJ_g9.js} +2 -2
  114. package/server/git-utils-CI6cwyyC.js +3 -0
  115. package/server/{git-utils-BVa07a4a.js → git-utils-ameCgDdy.js} +93 -3
  116. package/server/{github-app-CMBdIFBQ.js → github-app-CQ1Lo6LA.js} +19 -8
  117. package/server/{github-app-CPfoFAdV.js → github-app-DtAsvwzK.js} +1 -1
  118. package/server/{github-client--XVlDpwM.js → github-client-BfyDxuRN.js} +2 -2
  119. package/server/{github-client-B4QsdE-X.js → github-client-Cj0yl_07.js} +1 -1
  120. package/server/github-pr-lookup-BDq6Wznz.js +58 -0
  121. package/server/{harness-binary-CVio2m-u.js → harness-binary-DqkftwTb.js} +32 -6
  122. package/server/{harness-resolve-qHJBhy3Z.js → harness-resolve-CqMqM1Mb.js} +18 -9
  123. package/server/{health-events-C9B8y1Hm.js → health-events-CazRxJUS.js} +2 -2
  124. package/server/{health-events-CpfvuVmm.js → health-events-_xfTaOUs.js} +1 -1
  125. package/server/{hooks-DUXw8A0-.js → hooks-BO3QT1sn.js} +2 -2
  126. package/server/{hooks-ltecuFqZ.js → hooks-BnJsxlSq.js} +1 -1
  127. package/server/{hume-BEq0bUDg.js → hume-CDYJxqx-.js} +2 -2
  128. package/server/hume-Dq--7rOQ.js +3 -0
  129. package/server/{idle-stack-reaper-D7w9t3fE.js → idle-stack-reaper-BYqERdkE.js} +1 -1
  130. package/server/{idle-stack-reaper-w1ISSlhs.js → idle-stack-reaper-CnGx_PO_.js} +99 -6
  131. package/server/in-flight-guard-Bq3epG58.js +45 -0
  132. package/server/{infra-CzaSOgul.js → infra-BjuxvjdS.js} +80 -5
  133. package/server/{injection-oNZeoDhL.js → injection-DZxlV2al.js} +1 -1
  134. package/server/{injection-DZ0PfYa4.js → injection-UCf8EsjX.js} +191 -183
  135. package/server/{inspect-agent-DJKLWcVT.js → inspect-agent-6kylZnrm.js} +139 -82
  136. package/server/inspect-agent-BVwDrVrz.js +2 -0
  137. package/server/{internal-token-Bb4XeV2x.js → internal-token-DvMTQSOS.js} +2 -2
  138. package/server/{internal-token-DXdfprGr.js → internal-token-M9omeXM1.js} +1 -1
  139. package/server/{io-B3_AHDfr.js → io-VHvc0Ssp.js} +43 -26
  140. package/server/{issue-closed-zhdvQicO.js → issue-closed-B6KJkmHZ.js} +7 -7
  141. package/server/{issue-lifecycle-Dy4vd0Oa.js → issue-lifecycle-9gk3fnXN.js} +1 -1
  142. package/server/{issue-lifecycle-CreaCkjW.js → issue-lifecycle-C4Zj0WmE.js} +34 -28
  143. package/server/{issue-service-singleton-B5ushCvE.js → issue-service-singleton-DmCh7EHj.js} +10 -10
  144. package/server/{issue-service-singleton-DabvBWUp.js → issue-service-singleton-PMx8F1jr.js} +1 -1
  145. package/server/{issues-B6ToV6x1.js → issues-CgnQ1OGQ.js} +2 -2
  146. package/server/{jsonl-parser-Dhflo1SH.js → jsonl-parser-DJOH_O-w.js} +5 -4
  147. package/server/{label-cleanup-BKPJm4Hv.js → label-cleanup-Dv7AV_R1.js} +3 -3
  148. package/server/{label-reconciler-DdWbHEBu.js → label-reconciler--F85rufp.js} +4 -4
  149. package/server/{lifecycle-DfeyBDwA.js → lifecycle-CTdOWYMi.js} +2 -2
  150. package/server/{lifecycle-sycO16hj.js → lifecycle-DDN8ApVY.js} +6 -7
  151. package/server/{lifecycle-io-D8iNBcux.js → lifecycle-io-D-lGdzK3.js} +5 -5
  152. package/server/{lifecycle-io-Bsnr2K4F.js → lifecycle-io-D_zTLvP1.js} +1 -1
  153. package/server/{linear-client-D4zqMnX7.js → linear-client-BQU36QqE.js} +2 -2
  154. package/server/{linear-client-DqhDQO9k.js → linear-client-CY4O_Tu3.js} +1 -1
  155. package/server/linear-mcp-auth-BnU4TYfY.js +280 -0
  156. package/server/linear-mcp-auth-NYBq_oHZ.js +2 -0
  157. package/server/memory-fts-worker.js +1 -1
  158. package/server/{merge-C_ZEhbqI.js → merge-Bpx4jjht.js} +13 -11
  159. package/server/{merge-agent-XrB80vfT.js → merge-agent-DdMVSV2Y.js} +233 -83
  160. package/server/{merge-agent-BQM3a8z5.js → merge-agent-DrXa1CpW.js} +1 -1
  161. package/server/{merge-batch-Bwoyr8Je.js → merge-batch-C5q1c1GX.js} +1 -1
  162. package/server/merge-completeness-BMm8tMyZ.js +277 -0
  163. package/server/merge-completeness-D0ljXbk3.js +3 -0
  164. package/server/{merge-DK23JEdS.js → merge-idOG--29.js} +1 -1
  165. package/server/merge-ops-DdpTiEMt.js +2 -0
  166. package/server/merge-rebase-DGQpYJU3.js +2 -0
  167. package/server/{merge-rebase-C1KIVr0s.js → merge-rebase-xLnMlw5h.js} +3 -3
  168. package/server/merge-set-DH7ot3yz.js +89 -0
  169. package/server/merge-set-DzsOTBg5.js +3 -0
  170. package/server/{merge-sync-DZ9dojJn.js → merge-sync-CQ-LgZ1_.js} +406 -153
  171. package/server/merge-sync-Ca7F5JnQ.js +3 -0
  172. package/server/{merge-train-DxDfBTjr.js → merge-train-DTEMyIu4.js} +18 -8
  173. package/server/{merge-train-deps-CyYQUksx.js → merge-train-deps-CNPJzepw.js} +4 -4
  174. package/server/merge-verification-x3JO8Dtz.js +220 -0
  175. package/server/merged-docker-cleanup-worker-CTpC27Bs.js +107 -0
  176. package/server/merged-docker-cleanup-worker-Cdi9apm-.js +3 -0
  177. package/server/{multipart-parser-Dt8YPN5S.js → multipart-parser-IMSBfePV.js} +2 -2
  178. package/server/{no-resume-mode-Cx3K0hHi.js → no-resume-mode-C5ULAXwO.js} +1 -1
  179. package/server/node_modules/.package-lock.json +27 -27
  180. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/package.json +3 -3
  181. package/server/node_modules/@google-cloud/common/package.json +2 -2
  182. package/server/node_modules/gaxios/build/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  183. package/server/node_modules/gaxios/build/esm/tsconfig.tsbuildinfo +1 -1
  184. package/server/node_modules/gaxios/package.json +1 -1
  185. package/server/node_modules/google-auth-library/build/src/auth/googleauth.js +24 -19
  186. package/server/node_modules/google-auth-library/package.json +1 -1
  187. package/server/node_modules/google-gax/build/protos/google/api/auth.proto +2 -1
  188. package/server/node_modules/google-gax/build/protos/google/api/backend.proto +12 -1
  189. package/server/node_modules/google-gax/build/protos/google/api/billing.proto +1 -1
  190. package/server/node_modules/google-gax/build/protos/google/api/client.proto +165 -53
  191. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1/resources.proto +1 -1
  192. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1beta/quota_adjuster_settings.proto +7 -3
  193. package/server/node_modules/google-gax/build/protos/google/api/cloudquotas/v1beta/resources.proto +1 -1
  194. package/server/node_modules/google-gax/build/protos/google/api/config_change.proto +1 -1
  195. package/server/node_modules/google-gax/build/protos/google/api/context.proto +1 -1
  196. package/server/node_modules/google-gax/build/protos/google/api/control.proto +3 -3
  197. package/server/node_modules/google-gax/build/protos/google/api/distribution.proto +1 -1
  198. package/server/node_modules/google-gax/build/protos/google/api/documentation.proto +1 -1
  199. package/server/node_modules/google-gax/build/protos/google/api/endpoint.proto +1 -1
  200. package/server/node_modules/google-gax/build/protos/google/api/error_reason.proto +186 -1
  201. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/checked.proto +31 -3
  202. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/eval.proto +8 -9
  203. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/explain.proto +1 -2
  204. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/syntax.proto +20 -22
  205. package/server/node_modules/google-gax/build/protos/google/api/expr/v1alpha1/value.proto +2 -3
  206. package/server/node_modules/google-gax/build/protos/google/api/field_behavior.proto +1 -1
  207. package/server/node_modules/google-gax/build/protos/google/api/field_info.proto +1 -1
  208. package/server/node_modules/google-gax/build/protos/google/api/http.proto +1 -1
  209. package/server/node_modules/google-gax/build/protos/google/api/httpbody.proto +1 -1
  210. package/server/node_modules/google-gax/build/protos/google/api/label.proto +1 -1
  211. package/server/node_modules/google-gax/build/protos/google/api/launch_stage.proto +1 -1
  212. package/server/node_modules/google-gax/build/protos/google/api/log.proto +1 -1
  213. package/server/node_modules/google-gax/build/protos/google/api/logging.proto +1 -1
  214. package/server/node_modules/google-gax/build/protos/google/api/metric.proto +1 -1
  215. package/server/node_modules/google-gax/build/protos/google/api/monitored_resource.proto +1 -1
  216. package/server/node_modules/google-gax/build/protos/google/api/monitoring.proto +1 -1
  217. package/server/node_modules/google-gax/build/protos/google/api/policy.proto +1 -1
  218. package/server/node_modules/google-gax/build/protos/google/api/quota.proto +1 -1
  219. package/server/node_modules/google-gax/build/protos/google/api/resource.proto +1 -1
  220. package/server/node_modules/google-gax/build/protos/google/api/routing.proto +8 -4
  221. package/server/node_modules/google-gax/build/protos/google/api/service.proto +2 -3
  222. package/server/node_modules/google-gax/build/protos/google/api/source_info.proto +1 -1
  223. package/server/node_modules/google-gax/build/protos/google/api/system_parameter.proto +1 -1
  224. package/server/node_modules/google-gax/build/protos/google/api/usage.proto +7 -27
  225. package/server/node_modules/google-gax/build/protos/google/api/visibility.proto +1 -1
  226. package/server/node_modules/google-gax/build/protos/google/longrunning/operations.proto +20 -1
  227. package/server/node_modules/google-gax/build/protos/google/protobuf/any.proto +52 -108
  228. package/server/node_modules/google-gax/build/protos/google/protobuf/compiler/ruby/ruby_generated_code.proto +2 -0
  229. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_features.proto +21 -1
  230. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_file_options.proto +24 -0
  231. package/server/node_modules/google-gax/build/protos/google/protobuf/cpp_options.proto +15 -0
  232. package/server/node_modules/google-gax/build/protos/google/protobuf/descriptor.proto +118 -30
  233. package/server/node_modules/google-gax/build/protos/google/protobuf/field_mask.proto +16 -18
  234. package/server/node_modules/google-gax/build/protos/google/protobuf/internal_options.proto +8 -1
  235. package/server/node_modules/google-gax/build/protos/google/protobuf/json/json_enumval_custom_string.proto +26 -0
  236. package/server/node_modules/google-gax/build/protos/google/protobuf/json_enumvalue_options.proto +29 -0
  237. package/server/node_modules/google-gax/build/protos/google/protobuf/json_options.proto +14 -0
  238. package/server/node_modules/google-gax/build/protos/google/protobuf/struct.proto +38 -22
  239. package/server/node_modules/google-gax/build/protos/google/protobuf/test_protos/forced_micro_string.proto +3 -0
  240. package/server/node_modules/google-gax/build/protos/google/protobuf/test_protos/repeated_field_proxy_import_message.proto +14 -0
  241. package/server/node_modules/google-gax/build/protos/google/protobuf/timestamp.proto +9 -8
  242. package/server/node_modules/google-gax/build/protos/google/protobuf/util/json_format_proto3.proto +18 -0
  243. package/server/node_modules/google-gax/build/protos/google/rpc/code.proto +1 -1
  244. package/server/node_modules/google-gax/build/protos/google/rpc/context/attribute_context.proto +7 -2
  245. package/server/node_modules/google-gax/build/protos/google/rpc/context/audit_context.proto +1 -1
  246. package/server/node_modules/google-gax/build/protos/google/rpc/error_details.proto +5 -5
  247. package/server/node_modules/google-gax/build/protos/google/rpc/http.proto +1 -1
  248. package/server/node_modules/google-gax/build/protos/google/rpc/status.proto +1 -2
  249. package/server/node_modules/google-gax/build/protos/google/type/calendar_period.proto +1 -1
  250. package/server/node_modules/google-gax/build/protos/google/type/color.proto +9 -10
  251. package/server/node_modules/google-gax/build/protos/google/type/date.proto +11 -9
  252. package/server/node_modules/google-gax/build/protos/google/type/datetime.proto +17 -17
  253. package/server/node_modules/google-gax/build/protos/google/type/dayofweek.proto +1 -1
  254. package/server/node_modules/google-gax/build/protos/google/type/decimal.proto +11 -13
  255. package/server/node_modules/google-gax/build/protos/google/type/expr.proto +1 -1
  256. package/server/node_modules/google-gax/build/protos/google/type/fraction.proto +1 -1
  257. package/server/node_modules/google-gax/build/protos/google/type/interval.proto +1 -2
  258. package/server/node_modules/google-gax/build/protos/google/type/latlng.proto +4 -5
  259. package/server/node_modules/google-gax/build/protos/google/type/localized_text.proto +3 -3
  260. package/server/node_modules/google-gax/build/protos/google/type/money.proto +1 -2
  261. package/server/node_modules/google-gax/build/protos/google/type/month.proto +1 -1
  262. package/server/node_modules/google-gax/build/protos/google/type/phone_number.proto +20 -15
  263. package/server/node_modules/google-gax/build/protos/google/type/postal_address.proto +39 -39
  264. package/server/node_modules/google-gax/build/protos/google/type/quaternion.proto +4 -4
  265. package/server/node_modules/google-gax/build/protos/google/type/timeofday.proto +11 -8
  266. package/server/node_modules/google-gax/package.json +5 -5
  267. package/server/node_modules/retry-request/package.json +4 -4
  268. package/server/node_modules/teeny-request/package.json +5 -5
  269. package/server/node_modules/undici/README.md +5 -0
  270. package/server/node_modules/undici/docs/docs/api/Client.md +4 -0
  271. package/server/node_modules/undici/docs/docs/api/Dispatcher.md +6 -0
  272. package/server/node_modules/undici/docs/docs/api/Interceptors.md +59 -0
  273. package/server/node_modules/undici/docs/docs/api/MockAgent.md +27 -0
  274. package/server/node_modules/undici/docs/docs/api/MockPool.md +28 -1
  275. package/server/node_modules/undici/docs/docs/index.md +5 -0
  276. package/server/node_modules/undici/lib/cache/memory-cache-store.js +54 -9
  277. package/server/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
  278. package/server/node_modules/undici/lib/core/request.js +13 -2
  279. package/server/node_modules/undici/lib/core/util.js +6 -1
  280. package/server/node_modules/undici/lib/dispatcher/agent.js +3 -3
  281. package/server/node_modules/undici/lib/dispatcher/client-h1.js +42 -8
  282. package/server/node_modules/undici/lib/dispatcher/client-h2.js +34 -43
  283. package/server/node_modules/undici/lib/global.js +36 -16
  284. package/server/node_modules/undici/lib/handler/cache-handler.js +269 -61
  285. package/server/node_modules/undici/lib/handler/cache-revalidation-handler.js +13 -3
  286. package/server/node_modules/undici/lib/handler/redirect-handler.js +5 -2
  287. package/server/node_modules/undici/lib/handler/retry-handler.js +30 -4
  288. package/server/node_modules/undici/lib/interceptor/cache.js +159 -52
  289. package/server/node_modules/undici/lib/interceptor/decompress.js +9 -2
  290. package/server/node_modules/undici/lib/mock/mock-interceptor.js +25 -7
  291. package/server/node_modules/undici/lib/mock/mock-utils.js +39 -10
  292. package/server/node_modules/undici/lib/util/cache.js +372 -68
  293. package/server/node_modules/undici/lib/util/date.js +23 -6
  294. package/server/node_modules/undici/lib/web/cookies/util.js +78 -8
  295. package/server/node_modules/undici/lib/web/fetch/body.js +2 -1
  296. package/server/node_modules/undici/lib/web/fetch/response.js +1 -3
  297. package/server/node_modules/undici/package.json +2 -2
  298. package/server/node_modules/undici/types/client.d.ts +2 -2
  299. package/server/node_modules/undici/types/dispatcher.d.ts +3 -3
  300. package/server/node_modules/undici/types/mock-interceptor.d.ts +5 -1
  301. package/server/{orphan-proposed-reconciler-BTkDrl4R.js → orphan-proposed-reconciler-CWmOdM9-.js} +1 -1
  302. package/server/{orphan-proposed-reconciler-neK8dHQk.js → orphan-proposed-reconciler-Dg6U4ADZ.js} +24 -15
  303. package/server/package-lock.json +28 -28
  304. package/server/package.json +1 -1
  305. package/server/{pan-dir-DeVUgwA7.js → pan-dir-ubraCiUg.js} +24 -10
  306. package/server/{paths-_zEts6wc.js → paths-cXmOwSbh.js} +2 -2
  307. package/server/pending-lifecycle-claim-DEteYdS9.js +110 -0
  308. package/server/{pickup-Dd0Znxxy.js → pickup-D8xtG1J2.js} +17 -16
  309. package/server/pipeline-membership-BGSvkT2M.js +3 -0
  310. package/server/pipeline-membership-CrAPLYtf.js +57 -0
  311. package/server/{pipeline-membership-0HaEGDlH.js → pipeline-membership-gather-CET40frr.js} +177 -109
  312. package/server/pipeline-membership-gather-DTfcgxLl.js +3 -0
  313. package/server/{pipeline-notifier-D0ykk59O.js → pipeline-notifier-BuQ0e4hF.js} +2 -2
  314. package/server/{pipeline-notifier-6iCJplFZ.js → pipeline-notifier-ImNXknf0.js} +1 -1
  315. package/server/post-merge-lifecycle-worker-DbO10pum.js +50 -0
  316. package/server/{project-pipelines-2sK1apsO.js → project-pipelines-Bim6bThI.js} +2 -2
  317. package/server/project-repos-C0nuoBGv.js +98 -0
  318. package/server/project-repos-CRE6Ykow.js +3 -0
  319. package/server/projects-B03Wr-xc.js +3 -0
  320. package/server/{prompts-Dp4Tpk39.js → prompts-BEx08AIu.js} +2 -2
  321. package/server/{providers-DKkBXhxU.js → providers-D7IluJe0.js} +1 -1
  322. package/server/{providers-DV7ec8l7.js → providers-evXhiQeg.js} +7 -7
  323. package/server/public/assets/{chunk-BO2N2NFS-CltymLRg.js → chunk-BO2N2NFS-D1s4-Sqp.js} +4 -4
  324. package/server/public/assets/{diagram-OG6HWLK6-D2f6pjgA.js → diagram-OG6HWLK6-1gdMoSF7.js} +1 -1
  325. package/server/public/assets/{dist-BWR4qFiV.js → dist-CxAOHbil.js} +1 -1
  326. package/server/public/assets/{dist-DEmlBBNQ.js → dist-DqDRYW6P.js} +3 -3
  327. package/server/public/assets/{ganttDiagram-6RSMTGT7-DnfiViPK.js → ganttDiagram-6RSMTGT7-BYex-Ec7.js} +1 -1
  328. package/server/public/assets/{highlighted-body-OFNGDK62-B8Wrmj9H.js → highlighted-body-OFNGDK62-DlVkiG0S.js} +1 -1
  329. package/server/public/assets/index-Cc7cnFC4.css +1 -0
  330. package/server/public/assets/index-K0hAYCgV.js +807 -0
  331. package/server/public/assets/{linear-C9zFQpkX.js → linear-B4cuEFmO.js} +1 -1
  332. package/server/public/assets/mermaid-GHXKKRXX-DyDHFXHV.js +1 -0
  333. package/server/public/assets/{pieDiagram-4H26LBE5-lR8H7Yjd.js → pieDiagram-4H26LBE5-CBHNBIJQ.js} +1 -1
  334. package/server/public/assets/{prod-B1jCQihw.js → prod-CN2nHBvX.js} +4 -4
  335. package/server/public/assets/{quadrantDiagram-W4KKPZXB-CVQ2guem.js → quadrantDiagram-W4KKPZXB-Bom87VOQ.js} +1 -1
  336. package/server/public/assets/{sankeyDiagram-5OEKKPKP-eD1RB4gm.js → sankeyDiagram-5OEKKPKP-UrBeyLxk.js} +1 -1
  337. package/server/public/assets/{xychartDiagram-2RQKCTM6-ChEC6dQn.js → xychartDiagram-2RQKCTM6-DhkbrIxR.js} +1 -1
  338. package/server/public/index.html +2 -2
  339. package/server/{pull-requests--Ib2jTgy.js → pull-requests-Cv7LxzUN.js} +1 -1
  340. package/server/{pull-requests-CXIhdCYD.js → pull-requests-DHWiKxo7.js} +19 -10
  341. package/server/{queries-6d7Cdtm7.js → queries-DHJm7bTd.js} +1134 -203
  342. package/server/{rally-B708-nZn.js → rally-B71M9f4o.js} +3 -3
  343. package/server/rally-YDjU513q.js +3 -0
  344. package/server/{rally-api-yjQ0TfHd.js → rally-api-D5uXN08-.js} +1 -1
  345. package/server/{rally-api-nY0ZANw3.js → rally-api-Dkqmok65.js} +2 -2
  346. package/server/{rally-client-B1EJhfV0.js → rally-client-Bfqm6XI4.js} +4 -4
  347. package/server/{rally-client-CULK2XAY.js → rally-client-CxsA6ExK.js} +1 -1
  348. package/server/{reap-terminal-sessions-MWnqdLCJ.js → reap-terminal-sessions-BQ23nriz.js} +2 -2
  349. package/server/{reap-terminal-sessions-N3BTkmX_.js → reap-terminal-sessions-CvmwaqKv.js} +2 -2
  350. package/server/{rebuild-stack-Dp4eLkt4.js → rebuild-stack-0EEYReVZ.js} +36 -36
  351. package/server/rebuild-stack-qeRqHZxH.js +4 -0
  352. package/server/{reconstruct-cache-uWbZfjms.js → reconstruct-cache-BbYFsqLa.js} +7 -6
  353. package/server/record-CtroO946.js +3 -0
  354. package/server/record-update-DH6dLJID.js +3 -0
  355. package/server/{record-update-Dq0t2uBG.js → record-update-Z0QCxmMp.js} +124 -34
  356. package/server/{recovery-trip-BJtIQuag.js → recovery-trip-eJe26h-f.js} +2 -2
  357. package/server/{release-engine-DZpmGGzb.js → release-engine-lPUp-MTd.js} +5 -5
  358. package/server/{release-set-hnXd_kga.js → release-set-BwGeyZKX.js} +3 -3
  359. package/server/{remote-Br-ZWVIP.js → remote-BCd02Es1.js} +3 -3
  360. package/server/{remote-4tiENDaI.js → remote-CVGUhXMV.js} +3 -3
  361. package/server/{remote-agents-CRCg1L4H.js → remote-agents-C1bssi41.js} +2 -2
  362. package/server/{remote-agents-nmty1mLu.js → remote-agents-C_VxssLU.js} +300 -46
  363. package/server/{remote-completion-BbWNd10K.js → remote-completion-DAB0P706.js} +12 -12
  364. package/server/resume-u9byntrq.js +3 -0
  365. package/server/{review-agent-DJRO8EG8.js → review-agent-CD4RCI0Y.js} +1 -1
  366. package/server/{review-agent-sKkE1FEL.js → review-agent-CHhI66UP.js} +61 -44
  367. package/server/{review-artifacts-BLbSC4ke.js → review-artifacts-DSMRIfuJ.js} +7 -6
  368. package/server/{review-context-BgX3lcCx.js → review-context-oFuBbiEE.js} +69 -25
  369. package/server/{in-flight-guard-aQ1IxeI3.js → review-convoy-liveness-CpzrcJ5F.js} +3 -44
  370. package/server/review-status-BZH8h-6W.js +3 -0
  371. package/server/review-status-emit-CUExtHd5.js +50 -0
  372. package/server/{review-status-enrichment-tbOn_A_u.js → review-status-enrichment-QV_hQkgS.js} +4 -4
  373. package/server/{review-status-source-CxuEjLGg.js → review-status-source-CpvJnvnQ.js} +24 -3
  374. package/server/review-status-source-ylw5QZUR.js +3 -0
  375. package/server/{review-status-sync-BhSQ0d0l.js → review-status-sync-483sujRo.js} +10 -5
  376. package/server/{review-status-sync-To3-iS-N.js → review-status-sync-NaWvI9Xf.js} +1 -1
  377. package/server/review-status-yljtTd-q.js +7521 -0
  378. package/server/{review-verdict-feedback-C1Kg8n7t.js → review-verdict-feedback-BPDn4li_.js} +1 -1
  379. package/server/{review-verdict-feedback-CTRNtzXO.js → review-verdict-feedback-CELeUinh.js} +48 -8
  380. package/server/{rollup-WA0VD-Rr.js → rollup-DTNvelz9.js} +8 -8
  381. package/server/{rollup-B53Y81xK.js → rollup-DYZfq1c4.js} +1 -1
  382. package/server/{scanner-D2743cp8.js → scanner-CV35oSn4.js} +42 -14
  383. package/server/{sequence-io-Cg0zYj_E.js → sequence-io-DF_8iuhV.js} +4 -4
  384. package/server/{sequencer-agent-BGY8gjg-.js → sequencer-agent-B2WeCtGi.js} +5 -5
  385. package/server/server.js +3899 -672
  386. package/server/{service-DCpB_SGd.js → service-Br9rpBNA.js} +83 -65
  387. package/server/{session-fork-BQ8_6H32.js → session-fork-D0LY152N.js} +2 -2
  388. package/server/{session-history-CVZDpS3c.js → session-history-BUyK29eq.js} +4 -4
  389. package/server/{settings-BZ5m1UCl.js → settings-Bse1Pdcj.js} +3 -3
  390. package/server/settings-CdvIF84R.js +2 -0
  391. package/server/{settings-ylxwqwQG.js → settings-CvVGqNEs.js} +3 -2
  392. package/server/{shadow-engineering-BlxG6Xye.js → shadow-engineering-BWLa8ODz.js} +2 -2
  393. package/server/{shadow-state-Dh-HzF2J.js → shadow-state-B4fpKxOO.js} +2 -2
  394. package/server/{shadow-state-C2_epgx2.js → shadow-state-FV6PHfEW.js} +1 -1
  395. package/server/{shadow-utils-4bvjn9b3.js → shadow-utils-D7asqxOZ.js} +2 -2
  396. package/server/{ship-log-ClSMIzZX.js → ship-log-xplJ8t75.js} +1 -1
  397. package/server/{smart-compaction-CHIxLr_d.js → smart-compaction-CPp2Ykf6.js} +1 -1
  398. package/server/{smart-compaction-r4pHQBIr.js → smart-compaction-D3U_79f-.js} +8 -7
  399. package/server/{spawn-planning-session-KC_UduxD.js → spawn-planning-session-1nFi3gfk.js} +1 -1
  400. package/server/{spawn-planning-session-DWAorh2B.js → spawn-planning-session-DGfZ5B8D.js} +30 -23
  401. package/server/{specialist-completion-BXhav38U.js → specialist-completion-Br48eiDP.js} +1 -1
  402. package/server/{specialist-context-DtrYvGJ-.js → specialist-context-cVbGnTa3.js} +5 -5
  403. package/server/{specialist-handoff-logger-C45ouoZ6.js → specialist-handoff-logger-DK-GTz4s.js} +2 -2
  404. package/server/{specialist-logs-DJ3RzKxW.js → specialist-logs-Cl5-hqT8.js} +3 -3
  405. package/server/{specialists-JVO00bs7.js → specialists-CNfYO3G2.js} +1634 -457
  406. package/server/{specialists-DyFeedjn.js → specialists-Cicieuzu.js} +21 -19
  407. package/server/{specialists-D5fRZXmN.js → specialists-JHsdU3pA.js} +1 -1
  408. package/server/{specialists-DVj0hvaL.js → specialists-Tdezg_6N.js} +1 -1
  409. package/server/specs-Bt7WJDoC.js +3 -0
  410. package/server/src-CRmCHlma.js +11408 -0
  411. package/server/{src-CG9mCkP6.js → src-Ck028hjO.js} +6 -6
  412. package/server/{src-CMTQGyCK.js → src-UWcGe0Ix.js} +5 -5
  413. package/server/stack-health-CJLMrLBl.js +3 -0
  414. package/server/{stack-health-puygdaMd.js → stack-health-DqSqx0zv.js} +68 -12
  415. package/server/{stale-task-claims-BbFwCTb0.js → stale-task-claims-CYFOUNlT.js} +4 -4
  416. package/server/{staleness-Cbl_w4Bw.js → staleness-BQ-0gMYK.js} +1 -1
  417. package/server/{staleness-Bpy41ngS.js → staleness-D47CUJok.js} +1 -1
  418. package/server/{state-home-CIGjwNfJ.js → state-home-BYV7qZTW.js} +2 -2
  419. package/server/{state-mapping-BL_-3Yt8.js → state-mapping-BVldLhBf.js} +1 -1
  420. package/server/{state-migrate-Dkzaxvny.js → state-migrate-CvvBtS0Y.js} +4 -4
  421. package/server/{stuck-remediation-sY_MHHgQ.js → stuck-remediation-Wt0UVvu1.js} +1 -1
  422. package/server/{stuck-remediation-CzEov_fq.js → stuck-remediation-mkLC6G_t.js} +360 -26
  423. package/server/{substrate-bug-weights-service-BH66lhm7.js → substrate-bug-weights-service-XfLAKnmK.js} +3 -3
  424. package/server/{summary-fork-D8bXjCr7.js → summary-fork-CD7GOts0.js} +2 -2
  425. package/server/{summary-fork-DHhJIsAL.js → summary-fork-xiXBnWG9.js} +78 -12
  426. package/server/supervisor/{injection-budget-C1iPirFS.js → injection-budget-B5SbvDx2.js} +2 -41
  427. package/server/supervisor/{paths-DehGY2Fj.js → paths-K3noE4N_.js} +1 -1
  428. package/server/supervisor/pty-supervisor.js +49 -2
  429. package/server/supervisor/pty-token-B7lp0ElT.js +43 -0
  430. package/server/{supervisor-BO-Zk_h-.js → supervisor-DL788vos.js} +3 -3
  431. package/server/supervisor-UWiQNK-y.js +2 -0
  432. package/server/{swarm-readiness-CQ_fwUWF.js → swarm-readiness-BV14DF5N.js} +3 -3
  433. package/server/{system-prerequisites-Bza0ffAh.js → system-prerequisites-pdWG6ZQs.js} +56 -29
  434. package/server/{teardown-workspace-CEgauF4U.js → teardown-workspace-l2F4_zim.js} +15 -16
  435. package/server/{test-agent-queue-DXDt0Xa-.js → test-agent-queue-qakFIIGz.js} +6 -6
  436. package/server/{test-verdict-CmUBK5cT.js → test-verdict-BJYDggMm.js} +1 -1
  437. package/server/{test-verdict-DFjjIHR5.js → test-verdict-Gw-btEfb.js} +1 -1
  438. package/server/{tldr-daemon-DL566HbH.js → tldr-daemon-BKOYB616.js} +1 -1
  439. package/server/{tldr-daemon-BDtLOIlO.js → tldr-daemon-CBaWkV9k.js} +2 -2
  440. package/server/{tmux-ftABRAmc.js → tmux-B1Wbxz5o.js} +3 -3
  441. package/server/{tmux-DoThH6aj.js → tmux-DQ6jB76i.js} +1 -1
  442. package/server/tmux-dedup-DbN6MGzM.js +892 -0
  443. package/server/{token-CsOhvw42.js → token-Cxbk023d.js} +2 -2
  444. package/server/{token-util-CTmczIfW.js → token-util-CLq2MmQt.js} +1 -1
  445. package/server/token-util-zlz9U0ki.js +3 -0
  446. package/server/{tracker-config-B4itFzDo.js → tracker-config-DZ8Zn2nQ.js} +2 -2
  447. package/server/{tracker-utils-tnxxqROg.js → tracker-utils-L0FKtjq2.js} +3 -3
  448. package/server/{traefik-connect-m73vGebA.js → traefik-connect-bNX6jKkb.js} +1 -1
  449. package/server/{tunnel-B2vxjx_b.js → tunnel-BAm1XgjG.js} +3 -3
  450. package/server/{tunnel-Cgj-IGIl.js → tunnel-CjSnHdTc.js} +1 -1
  451. package/server/{types-BBNjPcqU.js → types-q67TYYg5.js} +1 -1
  452. package/server/uat-promote-verification-CKB9ZrKC.js +92 -0
  453. package/server/uat-train-Cu-4nvbf.js +2 -0
  454. package/server/uat-train-D5UjcyAa.js +0 -0
  455. package/server/validate-Cxsx5Uz1.js +179 -0
  456. package/server/{validation-CIi6pnI2.js → validation-DEaTZafj.js} +1 -1
  457. package/server/{validation-B5JxoPUS.js → validation-VZgJxmqc.js} +4 -4
  458. package/server/{verification-artifact-C-lIHfUa.js → verification-artifact-C85cRTc_.js} +1 -1
  459. package/server/{verification-artifact-BcnIbigL.js → verification-artifact-g3yuxQDL.js} +1 -1
  460. package/server/{verification-runner-CDj4lD4t.js → verification-runner-DlZI8yhw.js} +1 -1
  461. package/server/{verification-runner-Br0S_Ous.js → verification-runner-KDZIsBj4.js} +114 -107
  462. package/server/{vtt-parser-DKpNNW5i.js → vtt-parser-Jr94BF3Y.js} +1 -1
  463. package/server/{work-agent-prompt-Yb2bd3Fq.js → work-agent-prompt-C-vuP3_J.js} +20 -9
  464. package/server/workflows-CHrx_hcW.js +2 -0
  465. package/server/{workflows-C9WmILql.js → workflows-D0oip4eV.js} +161 -78
  466. package/server/{workspace-DuUdndHe.js → workspace-BqFg__wH.js} +1 -1
  467. package/server/{workspace-BVl4rihN.js → workspace-C0fH3aek.js} +3 -3
  468. package/server/workspace-anchor-drift-B4gMRHl4.js +3 -0
  469. package/server/workspace-anchor-drift-CZKofakh.js +224 -0
  470. package/server/{workspace-config-cEGcO6UT.js → workspace-config-B123aZl-.js} +1 -1
  471. package/server/workspace-manager-CDTKjjdU.js +3 -0
  472. package/server/{workspace-manager-hLUv3ADC.js → workspace-manager-CwO-Hek7.js} +206 -116
  473. package/server/{workspace-metadata-CskwzzhL.js → workspace-metadata-CQv00QwK.js} +2 -2
  474. package/server/{workspace-metadata-DNpMixRq.js → workspace-metadata-D4M8BM4W.js} +1 -1
  475. package/server/{workspaces-hWvy9eKs.js → workspaces-j1e_6aAT.js} +736 -290
  476. package/sync-sources/dev-skills/pan-dashboard-restart/SKILL.md +34 -10
  477. package/sync-sources/hooks/linear-mcp-auth-hook +97 -0
  478. package/sync-sources/hooks/record-cost-event.js +6 -4
  479. package/sync-sources/rules/ask-user-question-self-contained.md +9 -0
  480. package/sync-sources/skills/okf/README.md +11 -3
  481. package/sync-sources/skills/okf/SKILL.md +12 -1
  482. package/sync-sources/skills/okf/docs/USAGE.md +15 -0
  483. package/sync-sources/skills/okf/references/overdeck.md +28 -0
  484. package/sync-sources/skills/pan-close/SKILL.md +5 -3
  485. package/sync-sources/skills/pan-flywheel/SKILL.md +18 -1
  486. package/sync-sources/skills/pan-knowledge/SKILL.md +10 -0
  487. package/sync-sources/skills/pan-orders/SKILL.md +33 -0
  488. package/sync-sources/skills/pan-peer-review/SKILL.md +195 -0
  489. package/sync-sources/skills/pan-reload/SKILL.md +3 -3
  490. package/sync-sources/skills/pan-restart/SKILL.md +5 -4
  491. package/sync-sources/skills/pan-review/SKILL.md +7 -1
  492. package/sync-sources/skills/pan-start/SKILL.md +4 -0
  493. package/sync-sources/skills/pan-sync-main/SKILL.md +9 -8
  494. package/sync-sources/skills/pipeline-status/SKILL.md +10 -1
  495. package/sync-sources/skills/workspace-add-repo/SKILL.md +16 -1
  496. package/sync-sources/templates/traefik/dynamic/overdeck.yml.template +10 -0
  497. package/server/activity-logger-OEUBdfZ8.js +0 -3
  498. package/server/agent-state-Bg0lhqwj.js +0 -3
  499. package/server/agents-FlIgQ3ql.js +0 -3
  500. package/server/archive-planning-zkJb3BeM.js +0 -3
  501. package/server/cli-BsVIHwzC.js +0 -3
  502. package/server/context-layers-B3Nt58jl.js +0 -4
  503. package/server/context-layers-ZYFcWiyc.js +0 -165
  504. package/server/conversation-service-Up7FEzIC.js +0 -3
  505. package/server/deacon-DYSEJb48.js +0 -4
  506. package/server/deacon-swarm-9jRLS5Ke.js +0 -2
  507. package/server/deploy-window-CM6W1-c6.js +0 -3
  508. package/server/dist-Bd3vn0Hw.js +0 -3
  509. package/server/flywheel-DMCUzDWg.js +0 -2
  510. package/server/flywheel-DSSpWmqF.js +0 -522
  511. package/server/flywheel-DcBkQvgE.js +0 -207
  512. package/server/flywheel-merge-order-C-6zRLvM.js +0 -2
  513. package/server/flywheel-merge-order-DxbQKE1d.js +0 -244
  514. package/server/forge-B-ZWyTRm.js +0 -2
  515. package/server/forge-Ch9gCFod.js +0 -270
  516. package/server/git-utils-Dry_Ka_D.js +0 -3
  517. package/server/github-pr-lookup-BRbDW-qk.js +0 -44
  518. package/server/hume-B_DbflNM.js +0 -3
  519. package/server/inspect-agent-ch-F-5Ci.js +0 -2
  520. package/server/launcher-generator-CHVm7bGT.js +0 -379
  521. package/server/layers-DzxSTGNA.js +0 -93
  522. package/server/merge-blockers-BsFjGrQ8.js +0 -41
  523. package/server/merge-ops-DlB1IM0Y.js +0 -2
  524. package/server/merge-set-DLz0MkGT.js +0 -139
  525. package/server/merge-set-DnSYdBEp.js +0 -3
  526. package/server/merge-sync-SSv3E-pl.js +0 -3
  527. package/server/merge-verification-CSizH3HY.js +0 -124
  528. package/server/projects-9SkRpES9.js +0 -3
  529. package/server/public/assets/index-CUr1xv8w.css +0 -1
  530. package/server/public/assets/index-CsSuZQBI.js +0 -802
  531. package/server/public/assets/mermaid-GHXKKRXX-BUAB8hqt.js +0 -1
  532. package/server/rally-njs_mJrt.js +0 -3
  533. package/server/rebuild-stack-kA7XngID.js +0 -3
  534. package/server/record-t6V-3Dcj.js +0 -3
  535. package/server/record-update-DACtKh6_.js +0 -3
  536. package/server/resume-CcKqnTvE.js +0 -3
  537. package/server/review-status-A7quS5KJ.js +0 -1454
  538. package/server/review-status-C6n6-9f_.js +0 -3
  539. package/server/settings-D0OSwos5.js +0 -2
  540. package/server/specs-nN45DG2X.js +0 -3
  541. package/server/src-U7_kTPEE.js +0 -4733
  542. package/server/stack-health-Df0YEZKa.js +0 -3
  543. package/server/supervisor-BPy-o1A8.js +0 -2
  544. package/server/token-util-DrHg8abn.js +0 -3
  545. package/server/tracker-utils-BePq_oj-.js +0 -3
  546. package/server/uat-train-CuEn0t9M.js +0 -2152
  547. package/server/uat-train-cKfM-_WW.js +0 -2
  548. package/server/workflows-D90rMOya.js +0 -2
  549. package/server/workspace-manager-ZTdJAy9M.js +0 -3
@@ -1,51 +1,54 @@
1
1
  import { n as __esmMin, o as __toESM } from "./rolldown-runtime-DNCzzKnI.js";
2
- import { B as getProviderEnvSync, Br as getOverdeckHome, C as TIERED_EXECUTION_DIFFICULTIES, D as resolveTieredExecutionEnabled, Ft as resolveProjectForIssue, G as setupCredentialFileAuthSync, Gr as sessionFilePath, H as init_providers, It as writeAgentHarnessModelSync, K as ensureOpenAICompatibleProxyRunning, L as clearCredentialFileAuthSync, Mt as readIssueRecordForWorkspaceSync, Nr as encodeClaudeProjectDir, Nt as readIssueRecordSync, O as resolveTieredExecutionEnabledForIssue, Ot as init_record, Qn as resolveBareNumericIdSync, R as getBuiltInDefaultHarness, S as DEFAULT_TIERED_EXECUTION_CONFIG, T as init_tier_table, Tn as init_projects, Ur as packageRoot, V as getProviderForModelSync, Vr as init_paths, Wr as resolveOhmypiExtensionPath, Yn as init_issue_id, dt as fnv1a32, er as require_dist, et as init_roles, f as loadConfigSync, fn as findProjectByPathSync, ft as init_percent, gn as getIssuePrefix, hr as AGENTS_DIR, in as shouldCommitLegacyWorkspaceArtifacts, ir as FsError, it as getModelCapabilitySync, l as isClaudeCodeChannelsMcpEnabled, lt as resolveModelIdSync, mr as init_errors, nn as init_state_read_home, nr as ClaudeCredentialParseError, ot as hasModelCapabilitySync, q as init_openai_compatible_proxy, st as init_model_capabilities, t as init_config_yaml, tt as resolveModel, u as isTldrEnabledSync, ut as fmix32, vn as getProjectSwarmHotspots, yn as getProjectSync, zn as resolveProjectFromIssueSync } from "./config-yaml-DvyMuOle.js";
3
- import { a as init_activity_logger, n as emitActivityEntrySync, r as emitActivityTtsSync } from "./activity-logger-DDlOIAML.js";
4
- import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-CzaSOgul.js";
5
- import { $ as init_child_env, A as listPaneValues, D as killSession, E as isPaneDead, H as sessionExists, O as killSessionSync, P as listSessionsSync, R as sendEscapeKeyAsync, U as sessionExistsSync, V as sendRawKeystroke, W as setOption, X as BLANKED_PROVIDER_ENV, a as capturePaneSync, c as createSessionSync, i as capturePane, m as exactPaneTarget, s as createSession, w as init_tmux, z as sendKeys } from "./tmux-ftABRAmc.js";
6
- import { a as init_event_store, i as initEventStore } from "./event-store-tdiY5eDZ.js";
7
- import { a as OHMYPI_BEHAVIOR, o as getHarnessBehavior } from "./src-U7_kTPEE.js";
8
- import { D as listOverdeckAgentStatesSync, E as init_agent_state_sync, O as saveOverdeckAgentStateSync, T as getOverdeckAgentStateSync, h as resetPipelineVerdictsForWorkStartSync, l as init_review_status } from "./review-status-A7quS5KJ.js";
9
- import { i as countAgentsByStatus, o as init_agents$1 } from "./agents-B4Bjbkfv.js";
10
- import { n as ensureSessionContextBriefingFile, r as init_briefing_freshness } from "./briefing-freshness-DWdW7vUm.js";
11
- import { o as getPricingSync, s as init_cost } from "./cost-Ca0YTWDw.js";
12
- import { _ as init_tier_metrics, g as estimateFeedDeliveryTokens, v as recordTierFeedDelivery } from "./cost-sync-C0VdGme1.js";
13
- import { a as persistCurrentSessionId, d as isAgentStateServiceInProcess, i as logLauncherSessionPinned, l as getRuntimeSnapshot, n as createFreshSessionIdentity, o as init_persistent_logger, r as init_session_history, s as logAgentLifecycleSync, u as init_agent_runtime_mirror } from "./session-history-CVZDpS3c.js";
14
- import { t as init_behavior } from "./behavior-B_-4EKF3.js";
15
- import { i as ensureInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-Bb4XeV2x.js";
16
- import { i as readReviewStatusMap, n as init_review_status_source, r as isRoleTerminal } from "./review-status-source-CxuEjLGg.js";
17
- import { m as readWorkspacePlanSync, o as init_io } from "./io-B3_AHDfr.js";
18
- import { c as bridgeGeminiAuthToCliproxy, d as getCliproxyAuthDir, g as getCliproxyLogPath, l as decodeJwtPayload$1, p as getCliproxyClientEnv, s as bridgeCodexAuthToCliproxySync, v as init_cliproxy } from "./cliproxy-Bgb2XCqi.js";
19
- import { L as normalizeHarness, R as reactivateConversationForSpawn, S as getConversationByName, k as init_conversations, y as createConversation } from "./conversations-DbOs1e9Q.js";
20
- import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population-B0pmAz0a.js";
21
- import { a as readCavemanVariant, n as init_workspace } from "./workspace-BVl4rihN.js";
22
- import { a as requireModelOverrideSync, i as normalizeModelOverrideSync, n as init_launcher_generator, o as shellQuoteModelIdSync, r as init_model_validation, t as generateLauncherScriptSync } from "./launcher-generator-CHVm7bGT.js";
23
- import { a as init_claude_permissions, r as getClaudePermissionFlagsStringSync } from "./claude-permissions-H_5wHQZQ.js";
24
- import { h as workspaceContextFile, o as init_layers } from "./layers-DzxSTGNA.js";
25
- import { a as extractThreadIdFromRollout, c as initCodexHome, l as init_codex, o as findLatestRollout } from "./codex-TmSi-yTv.js";
26
- import { n as init_harness_binary, r as prepareHarnessLaunch } from "./harness-binary-CVio2m-u.js";
27
- import { f as init_config, m as loadConfigSync$1 } from "./config-CCvjQf27.js";
28
- import { a as getFlywheelActiveRunIdSync, s as init_control_settings } from "./control-settings-aP1ANIlI.js";
29
- import { n as createTrackerFromConfig, r as init_factory, t as createTracker } from "./factory-CynerjXO.js";
30
- import { a as init_stack_health, i as getWorkspaceStackHealth } from "./stack-health-puygdaMd.js";
31
- import { i as createActiveSlice, l as init_dag, o as getDispatchableItems, s as groupItemsByWave } from "./dag-CdOjJVDT.js";
32
- import { c as generateFixedPointPromptSync, f as initHookSync, n as checkHookSync, p as init_hooks } from "./hooks-DUXw8A0-.js";
33
- import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-qHJBhy3Z.js";
34
- import { a as loadCloisterConfigSync, r as init_config$1 } from "./config-DjLOdbgT.js";
35
- import { t as init_reap_terminal_sessions } from "./reap-terminal-sessions-N3BTkmX_.js";
36
- import { c as isStateMigrated, o as init_state_home } from "./state-home-CIGjwNfJ.js";
37
- import { n as provisionClaudeHooks, t as init_claude_hooks_provision } from "./claude-hooks-provision-but-_qGY.js";
38
- import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-D8iNBcux.js";
39
- import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-CQ_fwUWF.js";
2
+ import { B as getProviderEnvSync, C as TIERED_EXECUTION_DIFFICULTIES, Cr as ClaudeCredentialParseError, D as resolveTieredExecutionEnabled, Fr as init_errors, G as setupCredentialFileAuthSync, Gn as init_projects, H as init_providers, In as getIssuePrefix, Ir as AGENTS_DIR, K as ensureOpenAICompatibleProxyRunning, L as clearCredentialFileAuthSync, Mn as findProjectByPathSync, O as resolveTieredExecutionEnabledForIssue, Pt as init_record, R as getBuiltInDefaultHarness, Rn as getProjectSwarmHotspots, Rt as readIssueRecordForWorkspaceSync, S as DEFAULT_TIERED_EXECUTION_CONFIG, Sn as init_state_read_home, T as init_tier_table, Tr as FsError, Ut as writeAgentHarnessModelSync, V as getProviderForModelSync, Vt as resolveProjectForIssue, ar as resolveProjectFromIssueSync, ci as init_paths, di as resolveOhmypiExtensionPath, dt as fmix32, ei as encodeClaudeProjectDir, et as init_roles, f as loadConfigSync, fi as sessionFilePath, ft as fnv1a32, gr as init_issue_id, it as getModelCapabilitySync, l as isClaudeCodeChannelsMcpEnabled, li as isDevMode, lt as resolveModelIdSync, ot as hasModelCapabilitySync, pt as init_percent, q as init_openai_compatible_proxy, si as getOverdeckHome, st as init_model_capabilities, t as init_config_yaml, tt as resolveModel, u as isTldrEnabledSync, ui as packageRoot, ut as CLIPROXY_GPT56_CONTEXT_WINDOW, wn as shouldCommitLegacyWorkspaceArtifacts, xr as require_dist, yr as resolveBareNumericIdSync, zn as getProjectSync, zt as readIssueRecordSync } from "./config-yaml-CmOPzmBb.js";
3
+ import { i as emitActivityTtsSync, o as init_activity_logger, r as emitActivityEntrySync } from "./activity-logger-CyteR4JO.js";
4
+ import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-BjuxvjdS.js";
5
+ import { A as listPaneValues, D as killSession, E as isPaneDead, H as sessionExists, O as killSessionSync, P as listSessionsSync, Q as BLANKED_PROVIDER_ENV, R as sendEscapeKeyAsync, U as sessionExistsSync, V as sendRawKeystroke, W as setOption, a as capturePaneSync, c as createSessionSync, i as capturePane, m as exactPaneTarget, s as createSession, tt as init_child_env, w as init_tmux, z as sendKeys } from "./tmux-B1Wbxz5o.js";
6
+ import { a as init_event_store, i as initEventStore } from "./event-store-zY5MJHgF.js";
7
+ import { o as OHMYPI_BEHAVIOR, s as getHarnessBehavior } from "./src-CRmCHlma.js";
8
+ import { F as init_pipeline_agent_reader, G as saveOverdeckAgentStateSync, H as getOverdeckAgentStateSync, I as registerPipelineTelemetryAgentReader, S as setReviewStatusSync, U as init_agent_state_sync, W as listOverdeckAgentStatesSync, f as init_review_status, u as getReviewStatusSync, v as resetPipelineVerdictsForWorkStartSync } from "./review-status-yljtTd-q.js";
9
+ import { i as countAgentsByStatus, o as init_agents$1 } from "./agents-C5rWYhb6.js";
10
+ import { n as ensureSessionContextBriefingFile, r as init_briefing_freshness } from "./briefing-freshness-DHmCSLar.js";
11
+ import { o as getPricingSync, s as init_cost } from "./cost-Bgcub5kW.js";
12
+ import { _ as init_tier_metrics, g as estimateFeedDeliveryTokens, v as recordTierFeedDelivery } from "./cost-sync-Dv3LUaNW.js";
13
+ import { a as persistCurrentSessionId, d as isAgentStateServiceInProcess, i as logLauncherSessionPinned, l as getRuntimeSnapshot, n as createFreshSessionIdentity, o as init_persistent_logger, r as init_session_history, s as logAgentLifecycleSync, u as init_agent_runtime_mirror } from "./session-history-BUyK29eq.js";
14
+ import { t as init_behavior } from "./behavior-CfIg6pKp.js";
15
+ import { i as ensureInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-DvMTQSOS.js";
16
+ import { i as readReviewStatusMap, n as init_review_status_source, r as isRoleTerminal } from "./review-status-source-CpvJnvnQ.js";
17
+ import { m as readWorkspacePlanSync, o as init_io } from "./io-VHvc0Ssp.js";
18
+ import { c as bridgeGeminiAuthToCliproxy, d as getCliproxyAuthDir, g as getCliproxyLogPath, l as decodeJwtPayload$1, p as getCliproxyClientEnv, s as bridgeCodexAuthToCliproxySync, v as init_cliproxy } from "./cliproxy-C8mB3KuB.js";
19
+ import { L as normalizeHarness, R as reactivateConversationForSpawn, S as getConversationByName, k as init_conversations, y as createConversation } from "./conversations-BUpYsOZg.js";
20
+ import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population--YUXU999.js";
21
+ import { a as readCavemanVariant, n as init_workspace } from "./workspace-C0fH3aek.js";
22
+ import { _ as shellQuoteModelIdSync, d as generateLauncherScriptSync, f as init_launcher_generator, g as requireModelOverrideSync, h as normalizeModelOverrideSync, i as completeKeyedSubmit, l as init_tmux_dedup, m as init_model_validation, u as sendKeysDedup } from "./tmux-dedup-DbN6MGzM.js";
23
+ import { a as init_claude_permissions, r as getClaudePermissionFlagsStringSync } from "./claude-permissions-CN0cSCPp.js";
24
+ import { E as init_layers, I as workspaceContextFile, P as resolveWorkspaceContextFile, c as init_render, i as workspaceContextWithoutProjectLayer, l as renderGlobalLayer, r as init_assemble, u as renderProjectLayer, v as init_harness, y as renderForHarness } from "./assemble-DnffNpOo.js";
25
+ import { a as extractThreadIdFromRollout, c as initCodexHome, l as init_codex, o as findLatestRollout } from "./codex-Drlf5Xhf.js";
26
+ import { i as prepareHarnessLaunch, r as init_harness_binary } from "./harness-binary-DqkftwTb.js";
27
+ import { f as init_config, m as loadConfigSync$1 } from "./config-Dr3pW6w6.js";
28
+ import { a as getFlywheelActiveRunIdSync, s as init_control_settings } from "./control-settings-C7DUehE1.js";
29
+ import { n as createTrackerFromConfig, r as init_factory, t as createTracker } from "./factory-CRoOpGsF.js";
30
+ import { a as getWorkspaceStackHealth, s as init_stack_health } from "./stack-health-DqSqx0zv.js";
31
+ import { i as createActiveSlice, l as init_dag, o as getDispatchableItems, s as groupItemsByWave } from "./dag-ombYYt4s.js";
32
+ import { c as generateFixedPointPromptSync, f as initHookSync, n as checkHookSync, p as init_hooks } from "./hooks-BO3QT1sn.js";
33
+ import { a as init_git_utils, c as rehydrateHeadAnchor, l as renderWorkspaceGitShowPromise } from "./git-utils-ameCgDdy.js";
34
+ import { n as init_workspace_anchor_drift, t as evaluateWorkspaceAnchorDrift } from "./workspace-anchor-drift-CZKofakh.js";
35
+ import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-CqMqM1Mb.js";
36
+ import { a as loadCloisterConfigSync, r as init_config$1 } from "./config-B2IMcBxx.js";
37
+ import { t as init_reap_terminal_sessions } from "./reap-terminal-sessions-CvmwaqKv.js";
38
+ import { c as isStateMigrated, o as init_state_home } from "./state-home-BYV7qZTW.js";
39
+ import { n as provisionClaudeHooks, t as init_claude_hooks_provision } from "./claude-hooks-provision-fvy4RD2b.js";
40
+ import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-D-lGdzK3.js";
41
+ import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-BV14DF5N.js";
42
+ import { createRequire } from "node:module";
40
43
  import { dirname, join, relative } from "node:path";
41
44
  import { Data, Duration, Effect, FileSystem } from "effect";
42
- import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, statfsSync, unlinkSync, writeFileSync } from "fs";
43
- import { basename as basename$1, dirname as dirname$1, join as join$1, resolve as resolve$1 } from "path";
45
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, statfsSync, unlinkSync, writeFileSync } from "fs";
46
+ import { basename as basename$1, dirname as dirname$1, join as join$1, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
44
47
  import { homedir } from "os";
45
48
  import { cpus as cpus$1, loadavg as loadavg$1, platform as platform$1, totalmem as totalmem$1 } from "node:os";
46
49
  import { chmodSync as chmodSync$1, closeSync as closeSync$1, constants, cpSync, createReadStream as createReadStream$1, existsSync as existsSync$1, mkdirSync as mkdirSync$1, openSync as openSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, renameSync as renameSync$1, rmSync as rmSync$1, statSync as statSync$1, unlinkSync as unlinkSync$1, writeFileSync as writeFileSync$1, writeSync } from "node:fs";
47
- import { chmod, mkdir, readFile, stat as stat$1, writeFile } from "node:fs/promises";
48
- import { randomUUID } from "crypto";
50
+ import { chmod, mkdir, readFile, readdir, readlink, stat as stat$1, writeFile } from "node:fs/promises";
51
+ import { createHash, randomUUID } from "crypto";
49
52
  import { ChildProcess } from "effect/unstable/process";
50
53
  import { mkdir as mkdir$1, open as open$1, readFile as readFile$1, readdir as readdir$1, rename as rename$1, rm as rm$1, stat as stat$2, writeFile as writeFile$1 } from "fs/promises";
51
54
  import { platform as platform$2 } from "process";
@@ -1098,6 +1101,31 @@ var init_identity = __esmMin((() => {
1098
1101
  SINGLETON_AGENT_IDS = new Set(["flywheel-orchestrator", "sequencer-runner"]);
1099
1102
  }));
1100
1103
  //#endregion
1104
+ //#region ../../lib/deploy/active-dashboard-bundle.ts
1105
+ function activeDashboardBundleFile() {
1106
+ return join$1(getOverdeckHome(), "active-dashboard-bundle.json");
1107
+ }
1108
+ function isInside(parent, candidate) {
1109
+ const pathFromParent = relative$1(resolve$1(parent), resolve$1(candidate));
1110
+ return pathFromParent === "" || pathFromParent !== ".." && !pathFromParent.startsWith(`..${sep$1}`);
1111
+ }
1112
+ function readActiveDashboardBundleSync() {
1113
+ try {
1114
+ const parsed = JSON.parse(readFileSync(activeDashboardBundleFile(), "utf8"));
1115
+ if (typeof parsed.repoRoot !== "string" || typeof parsed.deployRoot !== "string" || typeof parsed.serverPath !== "string" || !isInside(parsed.deployRoot, parsed.serverPath) || !existsSync(parsed.serverPath)) return null;
1116
+ return {
1117
+ repoRoot: resolve$1(parsed.repoRoot),
1118
+ deployRoot: resolve$1(parsed.deployRoot),
1119
+ serverPath: resolve$1(parsed.serverPath)
1120
+ };
1121
+ } catch {
1122
+ return null;
1123
+ }
1124
+ }
1125
+ var init_active_dashboard_bundle = __esmMin((() => {
1126
+ init_paths();
1127
+ }));
1128
+ //#endregion
1101
1129
  //#region ../../lib/channels/pty-supervisor-locate.ts
1102
1130
  /**
1103
1131
  * Locate (and if necessary materialize) the PTY supervisor artifact.
@@ -1124,15 +1152,63 @@ var init_identity = __esmMin((() => {
1124
1152
  * (content-hash keyed over the whole staged tree, so an app upgrade
1125
1153
  * refreshes it even when only non-entry files changed) and the vendored
1126
1154
  * packages land under node_modules/ there for normal Node resolution.
1155
+ * 3. <activeBundle.repoRoot>/dist/pty-supervisor.js — the primary checkout a
1156
+ * `pan reload` deployment was built from (PAN-3172).
1127
1157
  *
1128
- * Missing everywhere is a build/packaging defect and throws — never silently
1129
- * degrade a spawn that the caller expects to be supervised.
1158
+ * A candidate is only accepted when its own bare imports actually resolve from
1159
+ * where it sits. Existence alone is not enough: `pan reload` runs the dashboard
1160
+ * out of ~/.overdeck/deployments/dashboard/.pan-reload-generation-{a,b}, and a
1161
+ * generation whose node_modules cannot resolve @lydell/node-pty produces a
1162
+ * supervisor that dies on ERR_MODULE_NOT_FOUND before it ever binds its socket
1163
+ * — every conversation spawned afterwards then died on a socket timeout with no
1164
+ * hint of the real cause (PAN-3172). Falling through to the primary checkout,
1165
+ * whose node_modules is complete, keeps spawns alive; that copy is the same
1166
+ * build, since activateDashboardDeployment() copies the generation's dist/ into
1167
+ * the primary checkout.
1168
+ *
1169
+ * Missing (or unresolvable) everywhere is a build/packaging defect and throws —
1170
+ * never silently degrade a spawn that the caller expects to be supervised.
1171
+ */
1172
+ /**
1173
+ * Bare package specifiers the built supervisor imports but cannot resolve from
1174
+ * its own location. Empty means the artifact can start where it sits.
1175
+ *
1176
+ * Only a genuine module-not-found counts. A package that is present but whose
1177
+ * exports refuse the `require` condition still resolves under `import`, so it
1178
+ * must not be reported as missing.
1130
1179
  */
1180
+ function unresolvedSupervisorImports(scriptPath) {
1181
+ const source = readFileSync$1(scriptPath, "utf8");
1182
+ const requireFrom = createRequire(scriptPath);
1183
+ const missing = /* @__PURE__ */ new Set();
1184
+ for (const match of source.matchAll(IMPORT_SOURCE_PATTERN)) {
1185
+ const specifier = match[2];
1186
+ if (!specifier || !PACKAGE_SPECIFIER_PATTERN.test(specifier)) continue;
1187
+ try {
1188
+ requireFrom.resolve(specifier);
1189
+ } catch (error) {
1190
+ const code = error.code;
1191
+ if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") missing.add(specifier);
1192
+ }
1193
+ }
1194
+ return [...missing];
1195
+ }
1131
1196
  function resolvePtySupervisorScriptPath() {
1132
- const built = join(packageRoot, "dist", "pty-supervisor.js");
1133
- if (existsSync$1(built)) return built;
1134
- const staged = join(moduleDir, "supervisor");
1135
- if (existsSync$1(join(staged, "pty-supervisor.js"))) return materializePtySupervisorRuntime(staged);
1197
+ const activeBundle = readActiveDashboardBundleSync();
1198
+ const candidates = [
1199
+ join(packageRoot, "dist", "pty-supervisor.js"),
1200
+ join(moduleDir, "supervisor", "pty-supervisor.js"),
1201
+ ...activeBundle ? [join(activeBundle.repoRoot, "dist", "pty-supervisor.js")] : []
1202
+ ];
1203
+ const rejected = [];
1204
+ for (const candidate of candidates) {
1205
+ if (!existsSync$1(candidate)) continue;
1206
+ const entry = dirname(candidate) === join(moduleDir, "supervisor") ? materializePtySupervisorRuntime(dirname(candidate)) : candidate;
1207
+ const missing = unresolvedSupervisorImports(entry);
1208
+ if (missing.length === 0) return entry;
1209
+ rejected.push(`${entry} cannot resolve ${missing.join(", ")}`);
1210
+ }
1211
+ if (rejected.length > 0) throw new Error(`pty-supervisor cannot start — its dependencies are missing from every built copy: ${rejected.join("; ")}. Reinstall dependencies where the dashboard is running from (\`bun install\`), then rebuild.`);
1136
1212
  throw new Error("pty-supervisor build artifact missing — run `npm run build`.");
1137
1213
  }
1138
1214
  /**
@@ -1191,10 +1267,13 @@ function materializePtySupervisorRuntime(stagedDir, overdeckHome = getOverdeckHo
1191
1267
  }
1192
1268
  return entry;
1193
1269
  }
1194
- var moduleDir;
1270
+ var moduleDir, IMPORT_SOURCE_PATTERN, PACKAGE_SPECIFIER_PATTERN;
1195
1271
  var init_pty_supervisor_locate = __esmMin((() => {
1272
+ init_active_dashboard_bundle();
1196
1273
  init_paths();
1197
1274
  moduleDir = dirname(fileURLToPath(import.meta.url));
1275
+ IMPORT_SOURCE_PATTERN = /\b(?:from|import)\s*\(?\s*(["'])([^"'\n]+)\1/g;
1276
+ PACKAGE_SPECIFIER_PATTERN = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(?:\/[^\s]*)?$/;
1198
1277
  }));
1199
1278
  //#endregion
1200
1279
  //#region ../../lib/pty-token.ts
@@ -1669,6 +1748,33 @@ function decideResumeGate(block, intent, context = {}) {
1669
1748
  reason: block.reason
1670
1749
  };
1671
1750
  }
1751
+ if (intent === "merge-preparation") {
1752
+ if (block.gate === "paused") {
1753
+ if (block.yieldedByScheduler === true) return {
1754
+ decision: "proceed",
1755
+ clearYield: true
1756
+ };
1757
+ return {
1758
+ decision: "block",
1759
+ reason: `${block.reason}; run pan unpause before merging`,
1760
+ needsYou: true
1761
+ };
1762
+ }
1763
+ if (block.gate === "troubled") return {
1764
+ decision: "block",
1765
+ reason: `${block.reason}; run pan untroubled after investigating the crash`,
1766
+ needsYou: true
1767
+ };
1768
+ if (block.gate === "stopped-by-user") return {
1769
+ decision: "proceed",
1770
+ clearStoppedByUser: true
1771
+ };
1772
+ return {
1773
+ decision: "proceed",
1774
+ overrideFailureBackoff: true,
1775
+ warning: `Merge preparation overrides ${block.reason}`
1776
+ };
1777
+ }
1672
1778
  if (intent === "operator-start") {
1673
1779
  if (block.gate === "paused") return {
1674
1780
  decision: "block",
@@ -1747,12 +1853,14 @@ var init_agent_state = __esmMin((() => {
1747
1853
  init_persistent_logger();
1748
1854
  init_feature_registry_population();
1749
1855
  init_identity();
1856
+ init_pipeline_agent_reader();
1750
1857
  SESSION_EXITED_BEFORE_KICKOFF = "session-exited-before-kickoff";
1751
1858
  toAgentFsError = (operation, path, cause) => new FsError({
1752
1859
  operation,
1753
1860
  path,
1754
1861
  cause
1755
1862
  });
1863
+ registerPipelineTelemetryAgentReader(getAgentStateSync);
1756
1864
  getAgentState = (agentId) => {
1757
1865
  return Effect.try({
1758
1866
  try: () => getAgentStateSync(agentId),
@@ -1827,6 +1935,33 @@ var init_agent_state = __esmMin((() => {
1827
1935
  function buildDefaultResumeContinueMessage(issueId) {
1828
1936
  return `You are resuming work on ${issueId}. Read .pan/continue.json for context and pick up where you left off — do not wait for further instructions.`;
1829
1937
  }
1938
+ /** Completed marker check: the agent dir's own markers, or the workspace's. */
1939
+ function hasCompletionMarkerForAgent(state) {
1940
+ const agentDir = getAgentDir(state.id);
1941
+ if (existsSync(join$1(agentDir, "completed")) || existsSync(join$1(agentDir, "completed.processed"))) return true;
1942
+ const workspace = state.workspace;
1943
+ if (workspace && (existsSync(join$1(workspace, ".pan", "completed")) || existsSync(join$1(workspace, ".pan", "completed.processed")))) return true;
1944
+ return false;
1945
+ }
1946
+ /**
1947
+ * PAN-2974 (root cause B): the resume kickoff is phase-aware. Telling an agent
1948
+ * whose work was already handed off (completed marker) to "pick up where you
1949
+ * left off — do not wait for further instructions" makes it re-drive pipeline
1950
+ * stages on its own authority — 2026-07-21 MIN-882: a post-reboot resume
1951
+ * re-ran verification, restored config, and fired `pan review request` /
1952
+ * `pan review restart` while the operator was mid-UAT on finished work.
1953
+ * A handed-off agent gets a PASSIVE restore instead; only agents that crashed
1954
+ * mid-implementation get the aggressive kickoff.
1955
+ */
1956
+ function buildResumeContinueMessage(state) {
1957
+ const issueId = state.issueId;
1958
+ if (hasCompletionMarkerForAgent(state)) return [
1959
+ `Your session for ${issueId} was restored after a restart.`,
1960
+ `The work was already handed off — a completed marker exists. Do NOT re-drive pipeline stages (review, test, verify, merge) on your own authority.`,
1961
+ `Stay available for the operator and act only on new instructions.`
1962
+ ].join(" ");
1963
+ return buildDefaultResumeContinueMessage(issueId);
1964
+ }
1830
1965
  async function buildResumeMessageForAgent(state, fallbackMessage, callerMessage) {
1831
1966
  if (state.role !== "work" || state.kickoffDelivered !== false) return {
1832
1967
  message: callerMessage ?? fallbackMessage,
@@ -2541,7 +2676,7 @@ var init_provider_env = __esmMin((() => {
2541
2676
  "NOUS_API_KEY",
2542
2677
  "DASHSCOPE_API_KEY"
2543
2678
  ];
2544
- GPT_56_CODEX_CLIENT_CONTEXT_WINDOW = 372e3;
2679
+ GPT_56_CODEX_CLIENT_CONTEXT_WINDOW = CLIPROXY_GPT56_CONTEXT_WINDOW;
2545
2680
  GPT_56_MODELS = new Set([
2546
2681
  "gpt-5.6-sol",
2547
2682
  "gpt-5.6-terra",
@@ -2656,6 +2791,34 @@ var init_claude_auth = __esmMin((() => {
2656
2791
  });
2657
2792
  }));
2658
2793
  //#endregion
2794
+ //#region ../../lib/acp/context.ts
2795
+ function materializeAcpContextFile(agentDir, workspace) {
2796
+ const sections = [renderGlobalLayer("acp", isDevMode())];
2797
+ const project = findProjectByPathSync(workspace);
2798
+ if (project) sections.push(renderProjectLayer(project.path, "acp"));
2799
+ const workspaceFile = resolveWorkspaceContextFile(workspace);
2800
+ if (existsSync$1(workspaceFile)) {
2801
+ const workspaceContent = readFileSync$1(workspaceFile, "utf8");
2802
+ const workspaceOnly = project ? workspaceContextWithoutProjectLayer(workspaceContent) : workspaceContent;
2803
+ sections.push(renderForHarness(workspaceOnly, "acp").trim());
2804
+ }
2805
+ const content = sections.filter((section) => section.trim().length > 0).join(SECTION_SEPARATOR);
2806
+ const contextPath = join(agentDir, "acp-context.md");
2807
+ mkdirSync$1(dirname(contextPath), { recursive: true });
2808
+ writeFileSync$1(contextPath, `${content.trim()}\n`, { mode: 384 });
2809
+ return contextPath;
2810
+ }
2811
+ var SECTION_SEPARATOR;
2812
+ var init_context = __esmMin((() => {
2813
+ init_assemble();
2814
+ init_harness();
2815
+ init_layers();
2816
+ init_render();
2817
+ init_paths();
2818
+ init_projects();
2819
+ SECTION_SEPARATOR = "\n\n---\n\n";
2820
+ }));
2821
+ //#endregion
2659
2822
  //#region ../../lib/runtimes/ohmypi-fifo.ts
2660
2823
  /**
2661
2824
  * oh-my-pi (omp) RPC named-pipe lifecycle (PAN-1989).
@@ -2815,6 +2978,8 @@ async function writeLauncherScriptAtomic(launcherScript, content) {
2815
2978
  await rename$1(tmp, launcherScript);
2816
2979
  }
2817
2980
  async function claudeSystemPromptFiles(workspace, harness) {
2981
+ const behavior = getHarnessBehavior(harness);
2982
+ if (behavior.contextLayerKind === "acp") return [];
2818
2983
  const files = [];
2819
2984
  const contextFile = workspaceContextFile(workspace);
2820
2985
  try {
@@ -2824,14 +2989,13 @@ async function claudeSystemPromptFiles(workspace, harness) {
2824
2989
  if (!isNodeNotFound(error)) throw error;
2825
2990
  }
2826
2991
  files.push(await ensureSessionContextBriefingFile());
2827
- const behavior = getHarnessBehavior(harness);
2828
2992
  if (behavior.contextLayerKind === "pi") {
2829
- const { piGlobalContextFile } = await import("./context-layers-B3Nt58jl.js");
2993
+ const { piGlobalContextFile } = await import("./context-layers-D6LZo3l1.js");
2830
2994
  const globalFile = piGlobalContextFile();
2831
2995
  if (existsSync(globalFile)) files.unshift(globalFile);
2832
2996
  }
2833
2997
  if (behavior.contextLayerKind === "codex") {
2834
- const { codexGlobalContextFile } = await import("./context-layers-B3Nt58jl.js");
2998
+ const { codexGlobalContextFile } = await import("./context-layers-D6LZo3l1.js");
2835
2999
  const globalFile = codexGlobalContextFile();
2836
3000
  if (existsSync(globalFile)) files.unshift(globalFile);
2837
3001
  }
@@ -2887,6 +3051,18 @@ async function getOhmypiLauncherFields(agentId, model) {
2887
3051
  model
2888
3052
  };
2889
3053
  }
3054
+ function getAcpLauncherFields(agentId, model, workspace, binaryPath, _role) {
3055
+ return {
3056
+ harness: "acp",
3057
+ acpAgentId: agentId,
3058
+ acpProvider: getProviderForModelSync(model).name,
3059
+ acpWorkspace: workspace,
3060
+ acpBinaryPath: binaryPath,
3061
+ acpContextFile: materializeAcpContextFile(getAgentDir(agentId), workspace),
3062
+ model,
3063
+ unsetProviderEnv: true
3064
+ };
3065
+ }
2890
3066
  function getCodexLauncherFields(agentId, model, workspacePath, role) {
2891
3067
  const codexHome = join$1(homedir(), ".overdeck", "agents", agentId, "codex-home");
2892
3068
  const codexConfig = loadConfigSync().config.codex;
@@ -3048,12 +3224,45 @@ async function waitForCodexAppServerReady(agentId, timeoutSec = 30, deps = {}) {
3048
3224
  const detail = lastError ? ` Last status error: ${lastError}` : ` Last state: ${lastState}.`;
3049
3225
  throw new Error(`Timed out waiting for Codex app-server readiness for ${agentId}.${detail}`);
3050
3226
  }
3227
+ async function waitForAcpHostReady(agentId, timeoutSec = 30, deps = {}) {
3228
+ const now = deps.now ?? (() => Date.now());
3229
+ const sleep = deps.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms)));
3230
+ const sessionExistsForAgent = deps.sessionExists ?? (async (id) => Effect.runPromise(sessionExists(id)));
3231
+ const readText = deps.readText ?? ((path) => readFileSync(path, "utf8"));
3232
+ const pathExists = deps.pathExists ?? existsSync;
3233
+ const agentDir = getAgentDir(agentId);
3234
+ const sessionIdPath = join$1(agentDir, "acp-session-id");
3235
+ const errorPath = join$1(agentDir, "acp-launch-error");
3236
+ const tokenPath = join$1(agentDir, "acp-token");
3237
+ const socketPath = join$1(getOverdeckHome(), "sockets", `acp-${agentId}.sock`);
3238
+ const deadline = now() + timeoutSec * 1e3;
3239
+ while (now() < deadline) {
3240
+ if (pathExists(errorPath)) {
3241
+ const launchError = readText(errorPath).trim();
3242
+ if (launchError) throw new Error(`ACP host ${agentId} failed to start: ${launchError}`);
3243
+ }
3244
+ if (!await sessionExistsForAgent(agentId)) throw new Error(`ACP host session ${agentId} exited before readiness.`);
3245
+ try {
3246
+ const sessionId = readText(sessionIdPath).trim();
3247
+ const token = readText(tokenPath).trim();
3248
+ if (sessionId && token && pathExists(socketPath)) return;
3249
+ } catch (error) {
3250
+ if (!isNodeNotFound(error)) throw error;
3251
+ }
3252
+ await sleep(500);
3253
+ }
3254
+ throw new Error(`Timed out waiting for ACP host readiness for ${agentId}.`);
3255
+ }
3051
3256
  async function waitForPromptReady(agentId, harness, timeoutSec = 30) {
3052
3257
  const readinessKind = harness === "codex" && loadConfigSync().config.codex?.transport !== "tui" ? "codex-app-server-ready" : getHarnessBehavior(harness).readinessKind;
3053
3258
  if (readinessKind === "codex-app-server-ready") {
3054
3259
  await waitForCodexAppServerReady(agentId, timeoutSec);
3055
3260
  return true;
3056
3261
  }
3262
+ if (readinessKind === "acp-host-ready") {
3263
+ await waitForAcpHostReady(agentId, timeoutSec);
3264
+ return true;
3265
+ }
3057
3266
  if (readinessKind === "codex-tui-prompt") return waitForCodexTuiReady(agentId, timeoutSec);
3058
3267
  return waitForReadySignal(agentId, timeoutSec);
3059
3268
  }
@@ -3081,7 +3290,7 @@ async function injectPiPromptTimeMemory(agentId, prompt) {
3081
3290
  agentRole: agentState.role ?? "work",
3082
3291
  agentHarness: agentState.harness ?? "claude-code"
3083
3292
  };
3084
- const { injectPromptTimeMemory } = await import("./injection-oNZeoDhL.js");
3293
+ const { injectPromptTimeMemory } = await import("./injection-DZxlV2al.js");
3085
3294
  const result = await injectPromptTimeMemory({
3086
3295
  prompt,
3087
3296
  identity,
@@ -3115,7 +3324,7 @@ async function injectPiConversationMemory(opts, prompt) {
3115
3324
  agentRole: "work",
3116
3325
  agentHarness: "ohmypi"
3117
3326
  };
3118
- const { injectPromptTimeMemory } = await import("./injection-oNZeoDhL.js");
3327
+ const { injectPromptTimeMemory } = await import("./injection-DZxlV2al.js");
3119
3328
  const result = await injectPromptTimeMemory({
3120
3329
  prompt,
3121
3330
  identity,
@@ -3176,6 +3385,7 @@ async function getAgentRuntimeBaseCommand(model, agentName, agentDefinition, har
3176
3385
  const behavior = getHarnessBehavior(harness);
3177
3386
  if (behavior.launchCommandKind === "ohmypi-rpc") return `omp --mode rpc --model ${quotedModel}`;
3178
3387
  if (behavior.launchCommandKind === "codex-work-tui") return `codex`;
3388
+ if (behavior.launchCommandKind === "acp-host") return "acp-host";
3179
3389
  if (process.env.OVERDECK_TEST_HARNESS_COMMAND) return process.env.OVERDECK_TEST_HARNESS_COMMAND;
3180
3390
  const provider = getProviderForModelSync(validatedModel);
3181
3391
  const nameFlag = agentName ? ` --name ${agentName}` : "";
@@ -3273,6 +3483,7 @@ async function getRoleRuntimeBaseCommand(model, agentName, role, harness = "clau
3273
3483
  return `omp --mode rpc --model ${quotedModel}`;
3274
3484
  }
3275
3485
  if (behavior.launchCommandKind === "codex-work-tui") return `codex`;
3486
+ if (behavior.launchCommandKind === "acp-host") return "acp-host";
3276
3487
  if (process.env.OVERDECK_TEST_HARNESS_COMMAND) return process.env.OVERDECK_TEST_HARNESS_COMMAND;
3277
3488
  const provider = getProviderForModelSync(validatedModel);
3278
3489
  const requestedDefinitionPath = roleAgentDefinitionPath(role, subRole);
@@ -3283,7 +3494,7 @@ async function getRoleRuntimeBaseCommand(model, agentName, role, harness = "clau
3283
3494
  }
3284
3495
  const roleInject = definitionPath ? roleSystemPromptInjectionSync(definitionPath, effort) : "";
3285
3496
  const nameFlag = ` --name ${agentName}`;
3286
- const effortFlag = !definitionPath && effort ? ` --effort ${effort}` : "";
3497
+ const effortFlag = !definitionPath ? ` --effort ${effort ?? "high"}` : "";
3287
3498
  const permissionFlags = ` ${getClaudePermissionFlagsStringSync()}`;
3288
3499
  const printFlag = "";
3289
3500
  if (provider.name === "openai" && await getProviderAuthMode(validatedModel) === "subscription") return `claude${printFlag}${roleInject}${permissionFlags} --model ${shellQuoteModelIdSync(CLI_PROXY_MODEL_ALIASES[validatedModel] ?? validatedModel)}${effortFlag}${nameFlag}`;
@@ -3297,6 +3508,7 @@ var init_runtime_command = __esmMin((() => {
3297
3508
  init_briefing_freshness();
3298
3509
  init_claude_auth();
3299
3510
  init_layers();
3511
+ init_context();
3300
3512
  init_behavior();
3301
3513
  init_codex();
3302
3514
  init_ohmypi_fifo();
@@ -3639,20 +3851,25 @@ async function transitionIssueToInReview(issueId, workspacePath) {
3639
3851
  async function buildAgentLaunchConfig(opts) {
3640
3852
  const model = requireModelOverrideSync(opts.model);
3641
3853
  try {
3642
- const { injectOverdeckInfraDeny } = await import("./claude-settings-overlay-BTENVmYf.js");
3854
+ const { injectOverdeckInfraDeny } = await import("./claude-settings-overlay-Dabi9slj.js");
3643
3855
  await Effect.runPromise(injectOverdeckInfraDeny(opts.workspace));
3644
3856
  } catch (err) {
3645
3857
  console.warn(`[agents] injectOverdeckInfraDeny failed for ${opts.agentId} (non-fatal): ${err instanceof Error ? err.message : err}`);
3646
3858
  }
3647
- const providerEnv = await getProviderEnvForModel(model);
3648
- const provider = getProviderForModelSync(model);
3649
- if (provider.authType === "credential-file") setupCredentialFileAuthSync(provider, opts.workspace);
3650
- else clearCredentialFileAuthSync(opts.workspace);
3651
- const providerExports = await getProviderExportsForModel(model);
3652
- const launchRole = opts.isPlanning ? "plan" : opts.role;
3653
3859
  const behavior = getHarnessBehavior(opts.harness);
3860
+ const isAcp = behavior.launchCommandKind === "acp-host";
3861
+ const providerEnv = isAcp ? {} : await getProviderEnvForModel(model);
3862
+ if (!isAcp) {
3863
+ const provider = getProviderForModelSync(model);
3864
+ if (provider.authType === "credential-file") setupCredentialFileAuthSync(provider, opts.workspace);
3865
+ else clearCredentialFileAuthSync(opts.workspace);
3866
+ }
3867
+ const providerExports = isAcp ? void 0 : await getProviderExportsForModel(model);
3868
+ const launchRole = opts.isPlanning ? "plan" : opts.role;
3654
3869
  const piLauncherFields = behavior.usesRpcFifo ? await getOhmypiLauncherFields(opts.agentId, model) : {};
3655
3870
  const codexLauncherFields = behavior.usesCodexHome ? getCodexLauncherFields(opts.agentId, model, opts.workspace, launchRole) : {};
3871
+ if (isAcp && !opts.harnessBinaryPath) throw new Error("ACP launch requires the executable path resolved by preflight");
3872
+ const acpLauncherFields = isAcp ? getAcpLauncherFields(opts.agentId, model, opts.workspace, opts.harnessBinaryPath, launchRole) : {};
3656
3873
  if (opts.spawnMode === "resume" && opts.resumeSessionId) return {
3657
3874
  launcherContent: generateLauncherScriptSync({
3658
3875
  role: launchRole,
@@ -3663,7 +3880,7 @@ async function buildAgentLaunchConfig(opts) {
3663
3880
  providerExports,
3664
3881
  baseCommand: behavior.launchCommandKind !== "claude-code" ? await getAgentRuntimeBaseCommand(model, opts.agentId, launchRole, opts.harness) : `claude ${getClaudePermissionFlagsStringSync()}${roleSystemPromptInjectionSync(roleAgentDefinitionPath(launchRole))}`,
3665
3882
  resumeSessionId: opts.resumeSessionId,
3666
- model: behavior.launchCommandKind !== "claude-code" || providerExports.includes("ANTHROPIC_BASE_URL") ? model : void 0,
3883
+ model: behavior.launchCommandKind !== "claude-code" || providerExports?.includes("ANTHROPIC_BASE_URL") ? model : void 0,
3667
3884
  extraArgs: behavior.launchCommandKind !== "claude-code" ? void 0 : `--name ${opts.agentId}`,
3668
3885
  appendSystemPromptFiles: await claudeSystemPromptFiles(opts.workspace, opts.harness),
3669
3886
  extraEnvExports: opts.extraEnvExports,
@@ -3671,7 +3888,8 @@ async function buildAgentLaunchConfig(opts) {
3671
3888
  supervisorScriptPath: opts.supervisorScriptPath,
3672
3889
  promptInline: opts.promptInline,
3673
3890
  ...piLauncherFields,
3674
- ...codexLauncherFields
3891
+ ...codexLauncherFields,
3892
+ ...acpLauncherFields
3675
3893
  }),
3676
3894
  providerEnv
3677
3895
  };
@@ -3695,6 +3913,7 @@ async function buildAgentLaunchConfig(opts) {
3695
3913
  promptInline: opts.promptInline,
3696
3914
  ...piLauncherFields,
3697
3915
  ...codexLauncherFields,
3916
+ ...acpLauncherFields,
3698
3917
  ...opts.channelsBridgeMcpConfig ? {
3699
3918
  channelsBridgeMcpConfig: opts.channelsBridgeMcpConfig,
3700
3919
  channelsBridgeServerName: opts.channelsBridgeServerName ?? "overdeck-bridge"
@@ -3720,7 +3939,7 @@ async function retrieveSpawnTimeMemoryContext(input) {
3720
3939
  agentRole: input.role,
3721
3940
  agentHarness: input.harness
3722
3941
  };
3723
- const { injectPromptTimeMemory } = await import("./injection-oNZeoDhL.js");
3942
+ const { injectPromptTimeMemory } = await import("./injection-DZxlV2al.js");
3724
3943
  return (await injectPromptTimeMemory({
3725
3944
  prompt: input.prompt,
3726
3945
  identity,
@@ -3811,7 +4030,7 @@ async function assertWorkspaceStackHealthyForSpawn(issueId, role, allowHost = fa
3811
4030
  record.attempts += 1;
3812
4031
  spawnStackRebuildState.set(normalizedIssue, record);
3813
4032
  console.log(`[agents] Workspace stack for ${normalizedIssue} unhealthy (${details}) — rebuilding before spawn (attempt ${record.attempts}/${SPAWN_STACK_REBUILD_MAX_ATTEMPTS})`);
3814
- const { rebuildWorkspaceStack } = await import("./rebuild-stack-kA7XngID.js");
4033
+ const { rebuildWorkspaceStack } = await import("./rebuild-stack-qeRqHZxH.js");
3815
4034
  const result = await Effect.runPromise(rebuildWorkspaceStack(issueId, { onProgress: (m) => console.log(`[agents] ${normalizedIssue} stack rebuild: ${m}`) })).catch((err) => ({
3816
4035
  success: false,
3817
4036
  error: err instanceof Error ? err.message : String(err)
@@ -3927,6 +4146,64 @@ var init_cv = __esmMin((() => {
3927
4146
  init_errors();
3928
4147
  }));
3929
4148
  //#endregion
4149
+ //#region ../../lib/cloister/verdict-preservation.ts
4150
+ /** Decide whether a fresh work-agent session may keep verdicts earned by the current code. */
4151
+ async function shouldPreservePipelineVerdicts(issueId, workspacePath) {
4152
+ try {
4153
+ const status = getReviewStatusSync(issueId);
4154
+ if (!status) return {
4155
+ preserve: false,
4156
+ reason: "no pipeline verdicts are recorded"
4157
+ };
4158
+ if (!status.reviewedAtCommit) return {
4159
+ preserve: false,
4160
+ reason: "the review verdict has no commit anchor"
4161
+ };
4162
+ if (status.reviewStatus !== "passed" && status.reviewStatus !== "skipped") return {
4163
+ preserve: false,
4164
+ reason: `review is ${status.reviewStatus}`
4165
+ };
4166
+ if (status.testStatus !== "passed") return {
4167
+ preserve: false,
4168
+ reason: `tests are ${status.testStatus}`
4169
+ };
4170
+ if (status.verificationStatus !== "passed") return {
4171
+ preserve: false,
4172
+ reason: `verification is ${status.verificationStatus ?? "missing"}`
4173
+ };
4174
+ const verdict = await evaluateWorkspaceAnchorDrift(issueId, workspacePath, rehydrateHeadAnchor(status.reviewedAtCommit));
4175
+ switch (verdict.kind) {
4176
+ case "current": return {
4177
+ preserve: true,
4178
+ reason: "workspace HEAD matches the reviewed commit anchor"
4179
+ };
4180
+ case "benign": return {
4181
+ preserve: true,
4182
+ reason: "workspace HEAD moved without changing the reviewed code",
4183
+ refreshedAnchor: verdict.currentAnchor
4184
+ };
4185
+ case "drifted": return {
4186
+ preserve: false,
4187
+ reason: "workspace code changed after review"
4188
+ };
4189
+ case "unreadable": return {
4190
+ preserve: false,
4191
+ reason: "the current workspace commit anchor is unreadable"
4192
+ };
4193
+ }
4194
+ } catch (error) {
4195
+ return {
4196
+ preserve: false,
4197
+ reason: `verdict preservation check failed: ${error instanceof Error ? error.message : String(error)}`
4198
+ };
4199
+ }
4200
+ }
4201
+ var init_verdict_preservation = __esmMin((() => {
4202
+ init_git_utils();
4203
+ init_review_status();
4204
+ init_workspace_anchor_drift();
4205
+ }));
4206
+ //#endregion
3930
4207
  //#region ../../lib/bridge-token.ts
3931
4208
  function bridgeTokensDir() {
3932
4209
  return join(getOverdeckHome(), "bridge-tokens");
@@ -4198,22 +4475,27 @@ async function appendChannelDeliveryLog(agentId, entry) {
4198
4475
  await (await import("fs/promises")).appendFile(join$1(dir, `bridge-${agentId}.log`), `${line}\n`, "utf-8");
4199
4476
  } catch {}
4200
4477
  }
4201
- function readAppServerTokenSync(agentId) {
4478
+ function readSocketTokenSync(agentId, filename) {
4202
4479
  try {
4203
- const tokenPath = join$1(overdeckHomeForSockets(), "agents", agentId, "appserver-token");
4480
+ const tokenPath = join$1(overdeckHomeForSockets(), "agents", agentId, filename);
4204
4481
  if (!existsSync(tokenPath)) return null;
4205
4482
  return readFileSync(tokenPath, "utf-8").trim() || null;
4206
4483
  } catch {
4207
4484
  return null;
4208
4485
  }
4209
4486
  }
4487
+ function readAppServerTokenSync(agentId) {
4488
+ return readSocketTokenSync(agentId, "appserver-token");
4489
+ }
4490
+ function readAcpTokenSync(agentId) {
4491
+ return readSocketTokenSync(agentId, "acp-token");
4492
+ }
4210
4493
  /**
4211
4494
  * POST a JSON body to a Unix-domain socket using node:net + a hand-rolled
4212
4495
  * minimal HTTP/1.1 request. Resolves on a 200-class response, rejects on any
4213
- * error including socket-not-found, connection refused, write timeout, or
4214
- * non-2xx status. Kept tiny on purpose: this is a hot path, only one caller,
4215
- * and the whole point of a fallback to tmux is that we do not need a robust
4216
- * HTTP client here.
4496
+ * error including socket-not-found, connection refused, an optional client
4497
+ * timeout, or non-2xx status. Kept tiny on purpose because this is a hot path
4498
+ * and these local protocol hosts need only a narrow HTTP client.
4217
4499
  */
4218
4500
  async function postUnixSocketJson(socketPath, body, timeoutMs, token, tokenHeader = BRIDGE_TOKEN_HEADER) {
4219
4501
  const payload = JSON.stringify(body);
@@ -4261,13 +4543,15 @@ async function postUnixSocketJson(socketPath, body, timeoutMs, token, tokenHeade
4261
4543
  });
4262
4544
  return;
4263
4545
  }
4264
- finishErr(/* @__PURE__ */ new Error(`socket POST: status ${status}: ${responseBody.slice(0, 100)}`));
4546
+ finishErr(new SocketPostStatusError(status, `socket POST: status ${status}: ${responseBody.slice(0, 100)}`));
4265
4547
  });
4266
4548
  });
4267
- timeout = setTimeout(() => {
4268
- req.destroy(/* @__PURE__ */ new Error("socket POST timeout"));
4269
- }, timeoutMs);
4270
- timeout.unref?.();
4549
+ if (timeoutMs !== void 0) {
4550
+ timeout = setTimeout(() => {
4551
+ req.destroy(/* @__PURE__ */ new Error("socket POST timeout"));
4552
+ }, timeoutMs);
4553
+ timeout.unref?.();
4554
+ }
4271
4555
  req.on("error", (err) => {
4272
4556
  finishErr(err);
4273
4557
  });
@@ -4277,11 +4561,13 @@ async function postUnixSocketJson(socketPath, body, timeoutMs, token, tokenHeade
4277
4561
  }
4278
4562
  /**
4279
4563
  * Single delivery primitive for orchestrator-to-work-agent messages. Auto mode
4280
- * tries the PTY supervisor socket, then legacy Channels MCP, then tmux. Explicit
4281
- * socket methods are strict and throw instead of falling back.
4564
+ * tries persistent protocol hosts, the PTY supervisor socket, legacy Channels
4565
+ * MCP, then tmux. Explicit socket methods and ACP targets are strict: ACP prompts
4566
+ * cannot fall back to terminal injection because only session/prompt reaches the agent.
4282
4567
  */
4283
- async function deliverAgentMessage(agentId, message, caller = "unknown", deliveryMethod) {
4568
+ async function deliverAgentMessage(agentId, message, caller = "unknown", deliveryMethod, opts = {}) {
4284
4569
  const normalizedId = normalizeAgentId(agentId);
4570
+ const dedupKey = opts.dedupKey;
4285
4571
  let channelsEnabled = false;
4286
4572
  let resolvedMethod = deliveryMethod;
4287
4573
  let state = null;
@@ -4292,6 +4578,9 @@ async function deliverAgentMessage(agentId, message, caller = "unknown", deliver
4292
4578
  } catch {
4293
4579
  resolvedMethod ??= "auto";
4294
4580
  }
4581
+ const isAcpTarget = state?.harness === "acp";
4582
+ if (isAcpTarget && resolvedMethod !== "auto") throw new Error(`MessageDeliveryFailed: ACP delivery failed for ${normalizedId} (${caller}): ACP requires authenticated host RPC delivery`);
4583
+ if (dedupKey !== void 0) return deliverKeyedAgentMessage(normalizedId, message, caller, resolvedMethod ?? "auto", isAcpTarget, dedupKey);
4295
4584
  if (resolvedMethod === "tmux") {
4296
4585
  await assertTmuxTargetCanReceive(normalizedId, caller);
4297
4586
  await Effect.runPromise(sendKeys(normalizedId, message));
@@ -4301,7 +4590,7 @@ async function deliverAgentMessage(agentId, message, caller = "unknown", deliver
4301
4590
  };
4302
4591
  }
4303
4592
  let appServerFailure;
4304
- if (resolvedMethod === "auto") {
4593
+ if (resolvedMethod === "auto" && !isAcpTarget) {
4305
4594
  const appServerSocketPath = join$1(overdeckHomeForSockets(), "sockets", `appserver-${normalizedId}.sock`);
4306
4595
  if (existsSync(appServerSocketPath)) {
4307
4596
  const appServerToken = readAppServerTokenSync(normalizedId);
@@ -4327,6 +4616,39 @@ async function deliverAgentMessage(agentId, message, caller = "unknown", deliver
4327
4616
  }
4328
4617
  }
4329
4618
  }
4619
+ let acpFailure;
4620
+ if (resolvedMethod === "auto") {
4621
+ const acpSocketPath = join$1(overdeckHomeForSockets(), "sockets", `acp-${normalizedId}.sock`);
4622
+ const acpSocketExists = existsSync(acpSocketPath);
4623
+ if (isAcpTarget || acpSocketExists) {
4624
+ const acpToken = readAcpTokenSync(normalizedId);
4625
+ if (!acpSocketExists) acpFailure = "socket-missing";
4626
+ else if (!acpToken) acpFailure = "acp-token-missing";
4627
+ else try {
4628
+ await postUnixSocketJson(acpSocketPath, {
4629
+ op: "message",
4630
+ content: message,
4631
+ meta: { caller }
4632
+ }, 8e3, acpToken);
4633
+ await appendChannelDeliveryLog(normalizedId, {
4634
+ path: "acp",
4635
+ caller
4636
+ });
4637
+ return {
4638
+ ok: true,
4639
+ path: "acp"
4640
+ };
4641
+ } catch (err) {
4642
+ acpFailure = `socket-post-failed: ${err instanceof Error ? err.message : String(err)}`;
4643
+ }
4644
+ await appendChannelDeliveryLog(normalizedId, {
4645
+ path: "acp",
4646
+ reason: acpFailure,
4647
+ caller
4648
+ });
4649
+ throw new Error(`MessageDeliveryFailed: ACP delivery failed for ${normalizedId} (${caller}): ${acpFailure}`);
4650
+ }
4651
+ }
4330
4652
  let supervisorFailure;
4331
4653
  if (resolvedMethod === "auto" || resolvedMethod === "supervisor") {
4332
4654
  const supervisorSocketPath = join$1(overdeckHomeForSockets(), "sockets", `pty-${normalizedId}.sock`);
@@ -4383,6 +4705,7 @@ async function deliverAgentMessage(agentId, message, caller = "unknown", deliver
4383
4705
  reason: channelFailure,
4384
4706
  caller,
4385
4707
  ...appServerFailure ? { appServer: appServerFailure } : {},
4708
+ ...acpFailure ? { acp: acpFailure } : {},
4386
4709
  ...supervisorFailure ? { "pty-supervisor": supervisorFailure } : {},
4387
4710
  ...channelFailure ? { channels: channelFailure } : {}
4388
4711
  });
@@ -4402,6 +4725,83 @@ async function deliverAgentMessage(agentId, message, caller = "unknown", deliver
4402
4725
  };
4403
4726
  }
4404
4727
  /**
4728
+ * Keyed delivery cascade (PAN-2997). Only two tiers may carry a keyed
4729
+ * message, because only their crash-independent components enforce the key
4730
+ * across the COMPLETE visible side effect:
4731
+ *
4732
+ * - the PTY supervisor reserves the key synchronously (closing the concurrent
4733
+ * same-key race) and completes it only after its single-request
4734
+ * content-plus-Enter injection succeeds; and
4735
+ * - the tmux fallback keeps two-phase pending/terminal session markers owned
4736
+ * by the tmux server across paste, settle, and submit.
4737
+ *
4738
+ * App-server, ACP, and Channels acknowledge receipt without enforcing the
4739
+ * key, so they are never used for keyed payloads: a dashboard crash after
4740
+ * their side effect but before the caller's acknowledgment would replay the
4741
+ * wake. Explicitly requesting one of them with a key is a loud error, not a
4742
+ * silent downgrade.
4743
+ */
4744
+ async function deliverKeyedAgentMessage(normalizedId, message, caller, resolvedMethod, isAcpTarget, dedupKey) {
4745
+ if (isAcpTarget) throw new Error(`MessageDeliveryFailed: keyed delivery failed for ${normalizedId} (${caller}): the ACP tier cannot enforce a dedup key`);
4746
+ if (resolvedMethod === "channels") throw new Error(`MessageDeliveryFailed: keyed delivery failed for ${normalizedId} (${caller}): the Channels tier cannot enforce a dedup key`);
4747
+ if (resolvedMethod === "tmux") return deliverKeyedViaTmux(normalizedId, message, caller, dedupKey);
4748
+ let supervisorFailure;
4749
+ const supervisorSocketPath = join$1(overdeckHomeForSockets(), "sockets", `pty-${normalizedId}.sock`);
4750
+ const ptyToken = await readPtyToken(normalizedId);
4751
+ if (!existsSync(supervisorSocketPath)) supervisorFailure = "socket-missing";
4752
+ else if (!ptyToken) supervisorFailure = "pty-token-missing";
4753
+ else try {
4754
+ const supervisorResponse = await postUnixSocketJson(supervisorSocketPath, {
4755
+ content: message,
4756
+ meta: { caller },
4757
+ dedupKey
4758
+ }, supervisorInjectionBudgetMs(message.length) + SUPERVISOR_CLIENT_MARGIN_MS, ptyToken, PTY_TOKEN_HEADER);
4759
+ await appendChannelDeliveryLog(normalizedId, {
4760
+ path: "supervisor",
4761
+ caller
4762
+ });
4763
+ let deduplicated = false;
4764
+ try {
4765
+ deduplicated = JSON.parse(supervisorResponse.body).deduplicated === true;
4766
+ } catch {}
4767
+ return {
4768
+ ok: true,
4769
+ path: "supervisor",
4770
+ deduplicated
4771
+ };
4772
+ } catch (err) {
4773
+ const reason = err instanceof Error ? err.message : String(err);
4774
+ if (!(err instanceof SocketPostStatusError)) throw new AmbiguousKeyedDeliveryError(normalizedId, caller, reason);
4775
+ supervisorFailure = `socket-post-failed: ${reason}`;
4776
+ }
4777
+ if (resolvedMethod === "supervisor") throw new Error(`MessageDeliveryFailed: PTY supervisor delivery failed for ${normalizedId} (${caller}): ${supervisorFailure}`);
4778
+ await appendChannelDeliveryLog(normalizedId, {
4779
+ path: "tmux",
4780
+ reason: supervisorFailure,
4781
+ caller
4782
+ });
4783
+ return {
4784
+ ...await deliverKeyedViaTmux(normalizedId, message, caller, dedupKey),
4785
+ failure: supervisorFailure
4786
+ };
4787
+ }
4788
+ /**
4789
+ * Keyed tmux delivery: paste under the two-phase marker protocol, then
4790
+ * complete the submit. A replay that finds the pending marker completes the
4791
+ * prior attempt's submission WITHOUT re-pasting; a terminal marker suppresses
4792
+ * the replay entirely.
4793
+ */
4794
+ async function deliverKeyedViaTmux(normalizedId, message, caller, dedupKey) {
4795
+ await assertTmuxTargetCanReceive(normalizedId, caller);
4796
+ const phase = await sendKeysDedup(normalizedId, message, dedupKey, caller);
4797
+ if (phase !== "deduplicated") await completeKeyedSubmit(normalizedId, dedupKey);
4798
+ return {
4799
+ ok: true,
4800
+ path: "tmux",
4801
+ deduplicated: phase === "deduplicated"
4802
+ };
4803
+ }
4804
+ /**
4405
4805
  * PAN-2228: loud failure semantics for the tmux tier. `tmux send-keys` into a
4406
4806
  * session whose pane process has EXITED (a remain-on-exit corpse) succeeds at the
4407
4807
  * tmux level while the message lands nowhere — the zombie-kickoff failure mode
@@ -4560,16 +4960,31 @@ async function setAgentDeliveryMethod(agentId, deliveryMethod) {
4560
4960
  state.deliveryMethod = deliveryMethod;
4561
4961
  await Effect.runPromise(saveAgentState(state));
4562
4962
  }
4563
- var RESUME_TRANSCRIPT_CONFIRM_TIMEOUT_MS, RESUME_TRANSCRIPT_CONFIRM_INTERVAL_MS;
4963
+ var SocketPostStatusError, AmbiguousKeyedDeliveryError, RESUME_TRANSCRIPT_CONFIRM_TIMEOUT_MS, RESUME_TRANSCRIPT_CONFIRM_INTERVAL_MS;
4564
4964
  var init_delivery = __esmMin((() => {
4565
4965
  init_behavior();
4566
4966
  init_agents();
4567
4967
  init_runtime_state();
4568
4968
  init_tmux();
4969
+ init_tmux_dedup();
4569
4970
  init_bridge_token();
4570
4971
  init_pty_token();
4571
4972
  init_injection_budget();
4572
4973
  init_transcript_landing();
4974
+ SocketPostStatusError = class extends Error {
4975
+ status;
4976
+ constructor(status, message) {
4977
+ super(message);
4978
+ this.name = "SocketPostStatusError";
4979
+ this.status = status;
4980
+ }
4981
+ };
4982
+ AmbiguousKeyedDeliveryError = class extends Error {
4983
+ constructor(agentId, caller, reason) {
4984
+ super(`MessageDeliveryFailed: ambiguous keyed delivery for ${agentId} (${caller}): ${reason} — the supervisor may have completed the injection; NOT crossing to the tmux tier with the same key`);
4985
+ this.name = "AmbiguousKeyedDeliveryError";
4986
+ }
4987
+ };
4573
4988
  RESUME_TRANSCRIPT_CONFIRM_TIMEOUT_MS = 3e3;
4574
4989
  RESUME_TRANSCRIPT_CONFIRM_INTERVAL_MS = 100;
4575
4990
  }));
@@ -4915,6 +5330,12 @@ function stopAgentSync(agentId) {
4915
5330
  killSessionSync(normalizedId);
4916
5331
  }
4917
5332
  killLauncherProcessSync(normalizedId);
5333
+ try {
5334
+ rmSync(join$1(AGENTS_DIR, normalizedId, "git-guard"), {
5335
+ recursive: true,
5336
+ force: true
5337
+ });
5338
+ } catch {}
4918
5339
  const state = getAgentStateSync(normalizedId);
4919
5340
  if (state) {
4920
5341
  if (!state.id) state.id = normalizedId;
@@ -4969,6 +5390,14 @@ var init_termination = __esmMin((() => {
4969
5390
  throw cause;
4970
5391
  }
4971
5392
  }).pipe(Effect.catch(() => Effect.void));
5393
+ yield* Effect.promise(async () => {
5394
+ try {
5395
+ await rm$1(join$1(AGENTS_DIR, normalizedId, "git-guard"), {
5396
+ recursive: true,
5397
+ force: true
5398
+ });
5399
+ } catch {}
5400
+ });
4972
5401
  const state = yield* getAgentState(normalizedId);
4973
5402
  if (state) {
4974
5403
  if (!state.id) state.id = normalizedId;
@@ -5054,18 +5483,18 @@ async function spawnRun(issueId, role, options = {}) {
5054
5483
  let reapWarmIdle = false;
5055
5484
  const advancing = role === "review" || role === "test" || role === "ship";
5056
5485
  try {
5057
- const { isPaneDead } = await import("./tmux-DoThH6aj.js");
5486
+ const { isPaneDead } = await import("./tmux-DQ6jB76i.js");
5058
5487
  if (await Effect.runPromise(isPaneDead(agentId))) reapWarmIdle = true;
5059
5488
  else if (advancing) {
5060
- const { getReviewStatusSync } = await import("./review-status-C6n6-9f_.js");
5061
- const { isRoleTerminal } = await import("./reap-terminal-sessions-MWnqdLCJ.js");
5489
+ const { getReviewStatusSync } = await import("./review-status-BZH8h-6W.js");
5490
+ const { isRoleTerminal } = await import("./reap-terminal-sessions-BQ23nriz.js");
5062
5491
  const status = getReviewStatusSync(issueId);
5063
5492
  reapWarmIdle = !!status && isRoleTerminal(role, status);
5064
5493
  }
5065
5494
  } catch {}
5066
5495
  if (!reapWarmIdle) throw new Error(`Role run ${agentId} already running. Use 'pan tell' to message it.`);
5067
5496
  console.log(`[spawn] ${agentId} is warm-idle from the previous cycle — reaping it for the new ${role} dispatch (PAN-2579)`);
5068
- const { killSession } = await import("./tmux-DoThH6aj.js");
5497
+ const { killSession } = await import("./tmux-DQ6jB76i.js");
5069
5498
  await Effect.runPromise(killSession(agentId)).catch(() => {});
5070
5499
  }
5071
5500
  await assertWorkspaceStackHealthyForSpawn(issueId, role, options.allowHost, workspace);
@@ -5075,11 +5504,12 @@ async function spawnRun(issueId, role, options = {}) {
5075
5504
  role,
5076
5505
  model: selectedModel
5077
5506
  });
5507
+ const isAcp = getHarnessBehavior(resolvedHarness).launchCommandKind === "acp-host";
5078
5508
  const harnessLaunch = await prepareHarnessLaunch(resolvedHarness);
5079
5509
  assertCodexNativeAuthForSpawn(resolvedHarness, listAgentStates());
5080
5510
  await ensureLifecycleHooksBeforeLaunch(agentId, resolvedHarness);
5081
5511
  if (getProviderForModelSync(selectedModel).name === "openai" && await getProviderAuthMode(selectedModel) === "subscription") {
5082
- const { isCliproxyRunning } = await import("./cliproxy-DW0V86F8.js");
5512
+ const { isCliproxyRunning } = await import("./cliproxy-PGwTX_o8.js");
5083
5513
  if (!await Effect.runPromise(isCliproxyRunning())) throw new Error("CLIProxyAPI sidecar is not running. GPT subscription role runs route through a local cliproxy process managed by `pan up`. Run `pan up` (or restart the dashboard) before spawning a GPT role run.");
5084
5514
  }
5085
5515
  const state = {
@@ -5102,6 +5532,7 @@ async function spawnRun(issueId, role, options = {}) {
5102
5532
  const shouldDeliverPromptViaTmux = shouldRegisterConversation && resolvedHarness === "claude-code";
5103
5533
  const shouldDeliverPromptViaPi = shouldRegisterConversation && resolvedHarness === "ohmypi";
5104
5534
  const shouldDeliverPromptViaCodexTui = shouldRegisterConversation && resolvedHarness === "codex";
5535
+ const shouldDeliverPromptViaAcp = resolvedHarness === "acp";
5105
5536
  const prompt = options.prompt ? await withSpawnTimeMemoryContext({
5106
5537
  prompt: options.prompt,
5107
5538
  issueId,
@@ -5112,26 +5543,29 @@ async function spawnRun(issueId, role, options = {}) {
5112
5543
  }) : "";
5113
5544
  let promptFile;
5114
5545
  const tracksKickoffDelivery = role === "flywheel";
5115
- if (prompt && (tracksKickoffDelivery || !shouldDeliverPromptViaTmux && !shouldDeliverPromptViaPi && !shouldDeliverPromptViaCodexTui)) {
5546
+ if (prompt && !shouldDeliverPromptViaAcp && (tracksKickoffDelivery || !shouldDeliverPromptViaTmux && !shouldDeliverPromptViaPi && !shouldDeliverPromptViaCodexTui)) {
5116
5547
  promptFile = join$1(getAgentDir(agentId), "initial-prompt.md");
5117
5548
  await writeFile$1(promptFile, prompt);
5118
- if (tracksKickoffDelivery) {
5119
- state.kickoffDelivered = false;
5120
- await Effect.runPromise(saveAgentState(state));
5121
- }
5122
5549
  }
5123
- const provider = getProviderForModelSync(selectedModel);
5124
- if (provider.authType === "credential-file") setupCredentialFileAuthSync(provider, workspace);
5125
- else clearCredentialFileAuthSync(workspace);
5126
- const providerExports = await getProviderExportsForModel(selectedModel);
5127
- const providerEnv = await getProviderEnvForModel(selectedModel);
5550
+ if (prompt && tracksKickoffDelivery) {
5551
+ state.kickoffDelivered = false;
5552
+ await Effect.runPromise(saveAgentState(state));
5553
+ }
5554
+ if (!isAcp) {
5555
+ const provider = getProviderForModelSync(selectedModel);
5556
+ if (provider.authType === "credential-file") setupCredentialFileAuthSync(provider, workspace);
5557
+ else clearCredentialFileAuthSync(workspace);
5558
+ }
5559
+ const providerExports = isAcp ? void 0 : await getProviderExportsForModel(selectedModel);
5560
+ const providerEnv = isAcp ? {} : await getProviderEnvForModel(selectedModel);
5128
5561
  const piLauncherFields = resolvedHarness === "ohmypi" ? await getOhmypiLauncherFields(agentId, selectedModel) : {};
5129
5562
  const codexLauncherFields = resolvedHarness === "codex" ? getCodexLauncherFields(agentId, selectedModel, workspace, role) : {};
5563
+ const acpLauncherFields = isAcp ? getAcpLauncherFields(agentId, selectedModel, workspace, harnessLaunch.binaryPath, role) : {};
5130
5564
  let sessionId;
5131
5565
  let rawSessionId;
5132
5566
  if (shouldRegisterConversation) {
5133
- rawSessionId = options.resumeSessionId ?? randomUUID();
5134
- try {
5567
+ rawSessionId = isAcp ? options.resumeSessionId : options.resumeSessionId ?? randomUUID();
5568
+ if (!isAcp && rawSessionId) try {
5135
5569
  const agentDir = getAgentDir(agentId);
5136
5570
  await mkdir$1(agentDir, { recursive: true });
5137
5571
  await writeFile$1(join$1(agentDir, "session.id"), rawSessionId, "utf-8");
@@ -5184,14 +5618,15 @@ async function spawnRun(issueId, role, options = {}) {
5184
5618
  reviewSignal: void 0,
5185
5619
  trapHup: void 0,
5186
5620
  ...piLauncherFields,
5187
- ...codexLauncherFields
5621
+ ...codexLauncherFields,
5622
+ ...acpLauncherFields
5188
5623
  });
5189
5624
  const launcherScript = join$1(getAgentDir(agentId), "launcher.sh");
5190
5625
  await writeLauncherScriptAtomic(launcherScript, launcherContent);
5191
5626
  const claudeCmd = `bash ${launcherScript}`;
5192
5627
  console.log(`[claude-invoke] purpose=role-run | role=${role} | model=${state.model} | source=agents.ts:spawnRun | session=${agentId} | command="${claudeCmd}"`);
5193
5628
  try {
5194
- const { preTrustDirectory } = await import("./workspace-manager-ZTdJAy9M.js");
5629
+ const { preTrustDirectory } = await import("./workspace-manager-CDTKjjdU.js");
5195
5630
  preTrustDirectory(workspace);
5196
5631
  } catch {}
5197
5632
  clearReadySignal(agentId);
@@ -5216,7 +5651,22 @@ async function spawnRun(issueId, role, options = {}) {
5216
5651
  await Effect.runPromise(setOption(agentId, "destroy-unattached", "off"));
5217
5652
  await Effect.runPromise(setOption(exactPaneTarget(agentId), "remain-on-exit", "on"));
5218
5653
  if (prompt) {
5219
- if (shouldDeliverPromptViaPi) try {
5654
+ if (shouldDeliverPromptViaAcp) try {
5655
+ await waitForPromptReady(agentId, resolvedHarness, 30);
5656
+ const delivery = await deliverAgentMessage(agentId, prompt, "spawnRun:initial-prompt");
5657
+ if (!delivery.ok) throw new Error(delivery.failure ?? `ACP delivery returned ok=false via ${delivery.path}`);
5658
+ if (tracksKickoffDelivery) {
5659
+ state.kickoffDelivered = true;
5660
+ await Effect.runPromise(saveAgentState(state));
5661
+ }
5662
+ } catch (err) {
5663
+ const message = err instanceof Error ? err.message : String(err);
5664
+ console.error(`[${agentId}] ACP prompt delivery failed:`, message);
5665
+ if (tracksKickoffDelivery) await recordKickoffDeliveryFailure(state, issueId, role);
5666
+ await Effect.runPromise(stopAgent(agentId));
5667
+ throw new Error(`Agent ${agentId} kickoff delivery failed: ${message}`);
5668
+ }
5669
+ else if (shouldDeliverPromptViaPi) try {
5220
5670
  await writeOhmypiAgentPrompt(agentId, prompt);
5221
5671
  if (tracksKickoffDelivery) {
5222
5672
  state.kickoffDelivered = true;
@@ -5241,9 +5691,9 @@ async function spawnRun(issueId, role, options = {}) {
5241
5691
  }
5242
5692
  markAgentRunning(state);
5243
5693
  try {
5244
- const { stdout } = await execAsync$2("git rev-parse --short=8 HEAD", { cwd: workspace });
5245
- const head = stdout.trim();
5246
- if (head) state.roleRunHead = head;
5694
+ const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-CI6cwyyC.js");
5695
+ const headAnchor = await snapshotWorkspaceHeadsPromise(issueId, workspace);
5696
+ if (headAnchor) state.roleRunHead = headAnchor;
5247
5697
  } catch {}
5248
5698
  await Effect.runPromise(saveAgentState(state));
5249
5699
  if (role !== "review") emitActivityEntrySync({
@@ -5271,7 +5721,7 @@ async function spawnAgent(options) {
5271
5721
  });
5272
5722
  console.log(`[DEBUG] Selected model: ${selectedModel}`);
5273
5723
  if (getProviderForModelSync(selectedModel).name === "openai" && await getProviderAuthMode(selectedModel) === "subscription") {
5274
- const { isCliproxyRunning } = await import("./cliproxy-DW0V86F8.js");
5724
+ const { isCliproxyRunning } = await import("./cliproxy-PGwTX_o8.js");
5275
5725
  if (!await Effect.runPromise(isCliproxyRunning())) throw new Error("CLIProxyAPI sidecar is not running. GPT subscription agents route through a local cliproxy process managed by `pan up`. Run `pan up` (or restart the dashboard) before spawning a GPT agent.");
5276
5726
  }
5277
5727
  const resolvedHarness = await resolveHarness({
@@ -5279,6 +5729,7 @@ async function spawnAgent(options) {
5279
5729
  role,
5280
5730
  model: selectedModel
5281
5731
  });
5732
+ const isAcp = getHarnessBehavior(resolvedHarness).launchCommandKind === "acp-host";
5282
5733
  const harnessLaunch = await prepareHarnessLaunch(resolvedHarness);
5283
5734
  assertCodexNativeAuthForSpawn(resolvedHarness, listAgentStates());
5284
5735
  await ensureLifecycleHooksBeforeLaunch(agentId, resolvedHarness);
@@ -5300,10 +5751,11 @@ async function spawnAgent(options) {
5300
5751
  saveAgentStateSync(state);
5301
5752
  if (role === "work") {
5302
5753
  try {
5303
- if (resetPipelineVerdictsForWorkStartSync(options.issueId)) {
5304
- const { resetPostMergeState } = await import("./merge-agent-BQM3a8z5.js");
5305
- resetPostMergeState(options.issueId);
5306
- }
5754
+ const preservation = await shouldPreservePipelineVerdicts(options.issueId, options.workspace);
5755
+ if (preservation.preserve) {
5756
+ if (preservation.refreshedAnchor) setReviewStatusSync(options.issueId, { reviewedAtCommit: preservation.refreshedAnchor });
5757
+ console.log(`[spawn] Preserved pipeline verdicts for ${options.issueId} — ${preservation.reason}`);
5758
+ } else if (resetPipelineVerdictsForWorkStartSync(options.issueId)) (await import("./merge-agent-DrXa1CpW.js")).resetPostMergeState(options.issueId);
5307
5759
  } catch (err) {
5308
5760
  console.warn(`[agents] Could not reset stale pipeline verdicts for ${options.issueId}: ${err instanceof Error ? err.message : String(err)}`);
5309
5761
  }
@@ -5312,7 +5764,7 @@ async function spawnAgent(options) {
5312
5764
  });
5313
5765
  }
5314
5766
  if (role === "work") try {
5315
- const { writeStoryFeatureContext } = await import("./work-agent-prompt-Yb2bd3Fq.js");
5767
+ const { writeStoryFeatureContext } = await import("./work-agent-prompt-C-vuP3_J.js");
5316
5768
  await writeStoryFeatureContext(options.workspace, options.issueId);
5317
5769
  } catch (ctxErr) {
5318
5770
  console.warn(`[agents] Could not write story feature context for ${options.issueId}: ${ctxErr.message}`);
@@ -5351,17 +5803,15 @@ async function spawnAgent(options) {
5351
5803
  });
5352
5804
  const promptFile = join$1(getAgentDir(agentId), "initial-prompt.md");
5353
5805
  const tracksKickoffDelivery = role === "work" || role === "strike";
5354
- if (prompt) {
5355
- await writeFile$1(promptFile, prompt);
5356
- if (tracksKickoffDelivery) {
5357
- state.kickoffDelivered = false;
5358
- saveAgentStateSync(state);
5359
- }
5806
+ if (prompt && !isAcp) await writeFile$1(promptFile, prompt);
5807
+ if (prompt && tracksKickoffDelivery) {
5808
+ state.kickoffDelivered = false;
5809
+ saveAgentStateSync(state);
5360
5810
  }
5361
5811
  try {
5362
5812
  const venvPath = join$1(options.workspace, ".venv");
5363
5813
  if (isTldrEnabledSync() && existsSync(venvPath)) {
5364
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DL566HbH.js");
5814
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-BKOYB616.js");
5365
5815
  const tldrService = getTldrDaemonServiceSync(options.workspace, venvPath);
5366
5816
  if (!(await tldrService.getStatus()).running) {
5367
5817
  await tldrService.start(true);
@@ -5391,6 +5841,7 @@ async function spawnAgent(options) {
5391
5841
  useSupervisor: supervisorLaunch.useSupervisor,
5392
5842
  supervisorScriptPath: supervisorLaunch.supervisorScriptPath,
5393
5843
  harness: state.harness ?? "claude-code",
5844
+ harnessBinaryPath: harnessLaunch.binaryPath,
5394
5845
  sessionId: state.sessionId,
5395
5846
  extraEnvExports: [harnessLaunch.pathExport, ...flywheelEnvExports(flywheelEnv)],
5396
5847
  effort: options.effort
@@ -5401,13 +5852,13 @@ async function spawnAgent(options) {
5401
5852
  const claudeCmd = `bash ${launcherScript}`;
5402
5853
  console.log(`[claude-invoke] purpose=work-agent | model=${state.model} | source=agents.ts:spawnAgent | session=${agentId} | command="${claudeCmd}"`);
5403
5854
  try {
5404
- const { preTrustDirectory } = await import("./workspace-manager-ZTdJAy9M.js");
5855
+ const { preTrustDirectory } = await import("./workspace-manager-CDTKjjdU.js");
5405
5856
  preTrustDirectory(options.workspace);
5406
5857
  } catch {}
5407
5858
  try {
5408
- const { isGitHubAppConfigured, generateInstallationToken, configureWorkspaceForBot } = await import("./github-app-CPfoFAdV.js");
5859
+ const { isGitHubAppConfigured, generateInstallationToken, configureWorkspaceForBot } = await import("./github-app-DtAsvwzK.js");
5409
5860
  if (isGitHubAppConfigured()) {
5410
- const { findProjectByPathSync } = await import("./projects-9SkRpES9.js");
5861
+ const { findProjectByPathSync } = await import("./projects-B03Wr-xc.js");
5411
5862
  const ghRepo = findProjectByPathSync(resolve$1(options.workspace, "..", ".."))?.github_repo;
5412
5863
  if (ghRepo) {
5413
5864
  const [owner, repo] = ghRepo.split("/");
@@ -5437,7 +5888,22 @@ async function spawnAgent(options) {
5437
5888
  sessionHarness: resolvedHarness
5438
5889
  });
5439
5890
  const dismissChannelsDialogPromise = channelsBridgeMcpConfig ? dismissDevChannelsDialog(agentId).catch(() => void 0) : null;
5440
- if (prompt && resolvedHarness === "ohmypi") try {
5891
+ if (prompt && isAcp) try {
5892
+ await waitForPromptReady(agentId, resolvedHarness, 30);
5893
+ const delivery = await deliverAgentMessage(agentId, prompt, "spawnAgent:initial-prompt");
5894
+ if (!delivery.ok) throw new Error(delivery.failure ?? `ACP delivery returned ok=false via ${delivery.path}`);
5895
+ if (tracksKickoffDelivery) {
5896
+ state.kickoffDelivered = true;
5897
+ saveAgentStateSync(state);
5898
+ }
5899
+ } catch (err) {
5900
+ const message = err instanceof Error ? err.message : String(err);
5901
+ console.error(`[${agentId}] ACP prompt delivery failed:`, message);
5902
+ if (tracksKickoffDelivery) await recordKickoffDeliveryFailure(state, options.issueId, role);
5903
+ await Effect.runPromise(stopAgent(agentId));
5904
+ throw new Error(`Agent ${agentId} kickoff delivery failed: ${message}`);
5905
+ }
5906
+ else if (prompt && resolvedHarness === "ohmypi") try {
5441
5907
  await writeOhmypiAgentPrompt(agentId, prompt);
5442
5908
  if (tracksKickoffDelivery) {
5443
5909
  state.kickoffDelivered = true;
@@ -5470,7 +5936,7 @@ async function spawnAgent(options) {
5470
5936
  const codexHomeForAgent = join$1(homedir(), ".overdeck", "agents", agentId, "codex-home");
5471
5937
  (async () => {
5472
5938
  try {
5473
- const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-Dg7Is5yb.js");
5939
+ const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-BdEsUFWh.js");
5474
5940
  const rollout = await waitForCodexRollout(codexHomeForAgent, 12e4);
5475
5941
  if (rollout) {
5476
5942
  const threadId = extractThreadIdFromRollout(rollout);
@@ -5572,6 +6038,7 @@ var init_spawn = __esmMin((() => {
5572
6038
  init_launcher_generator();
5573
6039
  init_providers();
5574
6040
  init_review_status();
6041
+ init_verdict_preservation();
5575
6042
  init_harness_resolve();
5576
6043
  init_harness_binary();
5577
6044
  init_codex_auth();
@@ -6098,6 +6565,11 @@ function pickFreshestExistingSessionIdSync(agentId, candidates) {
6098
6565
  function getLatestSessionIdSync(agentId) {
6099
6566
  const codexThreadId = resolveCodexThreadIdSync(agentId);
6100
6567
  if (codexThreadId) return codexThreadId;
6568
+ const agentState = getAgentStateSync(agentId);
6569
+ if (agentState?.harness && getHarnessBehavior(agentState.harness).sessionIdSource === "acp-session-id") try {
6570
+ const acpSessionId = readFileSync(join$1(getAgentDir(agentId), "acp-session-id"), "utf-8").trim();
6571
+ if (acpSessionId) return acpSessionId;
6572
+ } catch {}
6101
6573
  const fromSessionFile = getSessionId(agentId);
6102
6574
  if (fromSessionFile) return fromSessionFile;
6103
6575
  const sessionsFile = join$1(getAgentDir(agentId), "sessions.json");
@@ -6119,7 +6591,6 @@ function getLatestSessionIdSync(agentId) {
6119
6591
  if (threadId) return threadId;
6120
6592
  }
6121
6593
  } catch {}
6122
- const agentState = getAgentStateSync(agentId);
6123
6594
  if (agentState?.harness && getHarnessBehavior(agentState.harness).sessionIdSource === "transcript-jsonl") {
6124
6595
  const ohmypiSessionId = resolveLatestOhmypiSessionId(agentId);
6125
6596
  if (ohmypiSessionId) return ohmypiSessionId;
@@ -6194,11 +6665,81 @@ function sessionRotationRefused(opts) {
6194
6665
  }
6195
6666
  var init_session_rotation = __esmMin((() => {}));
6196
6667
  //#endregion
6668
+ //#region ../../lib/agents/monitor-transport.ts
6669
+ /**
6670
+ * PAN-3015: pull-based monitor transport for Claude Code sessions.
6671
+ *
6672
+ * A `pan monitor` process runs as a background task INSIDE the agent's Claude
6673
+ * Code session. Claude Code surfaces background-command stdout to the model at
6674
+ * the next turn boundary (and wakes an idle session), so a message printed by
6675
+ * the monitor reaches the model without any keystroke injection — no composer
6676
+ * paste, no echo confirmation, no Enter timing.
6677
+ *
6678
+ * This module holds the shared pieces: the presence protocol senders use to
6679
+ * decide the monitor tier is live, the mail-file format, and the drain logic.
6680
+ * The long-running loop lives in `src/cli/commands/monitor.ts`; the delivery
6681
+ * decision lives in `messageAgent` (src/lib/agents/messaging.ts) — mid-session
6682
+ * tells only, never kickoff/resume (no monitor exists before the first turn).
6683
+ * See docs/MONITOR-TRANSPORT.md.
6684
+ */
6685
+ function monitorPresencePath(agentId) {
6686
+ return join$1(getAgentDir(agentId), "monitor.json");
6687
+ }
6688
+ function isPidAlive(pid) {
6689
+ try {
6690
+ process.kill(pid, 0);
6691
+ return true;
6692
+ } catch {
6693
+ return false;
6694
+ }
6695
+ }
6696
+ /**
6697
+ * A monitor counts as live only with BOTH a fresh heartbeat and a live pid —
6698
+ * a dead monitor must fall through to keystroke transports, not strand the
6699
+ * message unread (it stays durable in mail/ either way).
6700
+ */
6701
+ function isMonitorLive(agentId, nowMs = Date.now()) {
6702
+ try {
6703
+ const raw = readFileSync(monitorPresencePath(agentId), "utf-8");
6704
+ const presence = JSON.parse(raw);
6705
+ if (typeof presence.pid !== "number" || typeof presence.heartbeatAt !== "string") return false;
6706
+ const beatMs = Date.parse(presence.heartbeatAt);
6707
+ if (!Number.isFinite(beatMs) || nowMs - beatMs > 45e3) return false;
6708
+ return isPidAlive(presence.pid);
6709
+ } catch {
6710
+ return false;
6711
+ }
6712
+ }
6713
+ /**
6714
+ * Mail-file format (PAN-3015 adds the provenance header; the legacy format is
6715
+ * `# Message\n\n<body>` and must keep parsing):
6716
+ *
6717
+ * # Message
6718
+ *
6719
+ * source: pan-tell
6720
+ * date: 2026-07-24T00:00:00.000Z
6721
+ *
6722
+ * <body>
6723
+ */
6724
+ function formatMailFileContent(body, source, date) {
6725
+ return `# Message\n\nsource: ${source}\ndate: ${date.toISOString()}\n\n${body}\n`;
6726
+ }
6727
+ var init_monitor_transport = __esmMin((() => {
6728
+ init_agent_state();
6729
+ }));
6730
+ //#endregion
6197
6731
  //#region ../../lib/agents/messaging.ts
6198
- function queueAgentMail(agentId, message, pendingTurnEndDelivery = false) {
6732
+ function queueAgentMail(agentId, message, pendingTurnEndDelivery = false, dedupKey, source) {
6199
6733
  const mailDir = join$1(getAgentDir(agentId), "mail");
6200
6734
  mkdirSync(mailDir, { recursive: true });
6201
- writeFileSync(join$1(mailDir, `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}${pendingTurnEndDelivery ? ".pending" : ""}.md`), `# Message\n\n${message}\n`);
6735
+ const now = /* @__PURE__ */ new Date();
6736
+ const filename = dedupKey !== void 0 ? `dedup-${createHash("sha256").update(dedupKey).digest("hex").slice(0, 24)}.md` : `${now.toISOString().replace(/[:.]/g, "-")}${pendingTurnEndDelivery ? ".pending" : ""}.md`;
6737
+ const content = source ? formatMailFileContent(message, source, now) : `# Message\n\n${message}\n`;
6738
+ writeFileSync(join$1(mailDir, filename), content);
6739
+ }
6740
+ function resolveAgentDeliveryMethod(state) {
6741
+ if (state?.harness === "acp") return "auto";
6742
+ return resilientDeliveryMethod(state?.deliveryMethod);
6202
6743
  }
6203
6744
  function claimCodexIdleTurn(agentId) {
6204
6745
  try {
@@ -6221,6 +6762,34 @@ async function appendTellInterventionForUserSource(normalizedId, caller) {
6221
6762
  source: caller
6222
6763
  });
6223
6764
  }
6765
+ /** Call the delivery door with the idempotency key only when one is set, so
6766
+ * unkeyed callers keep their exact pre-key call shape. */
6767
+ function deliverWithOptionalKey(normalizedId, message, caller, deliveryMethod, dedupKey) {
6768
+ return dedupKey !== void 0 ? deliverAgentMessage(normalizedId, message, caller, deliveryMethod, { dedupKey }) : deliverAgentMessage(normalizedId, message, caller, deliveryMethod);
6769
+ }
6770
+ /**
6771
+ * Keyed delivery to an agent that must be resumed first (PAN-2997 review
6772
+ * cycle 7). The keyed message NEVER rides the resume kickoff prompt: the
6773
+ * kickoff is delivered by components that cannot enforce the key, so a
6774
+ * dashboard crash after the kickoff but before any post-hoc key bookkeeping
6775
+ * would replay the wake. Instead the agent is resumed with its bare
6776
+ * auto-continue prompt, and the keyed message then goes through the keyed
6777
+ * delivery door, where the crash-independent component — the new session's
6778
+ * supervisor key set or the tmux session's two-phase markers — enforces
6779
+ * at-most-once across the whole replay window.
6780
+ */
6781
+ async function resumeThenDeliverKeyed(normalizedId, message, caller, agentState, dedupKey) {
6782
+ const { resumeAgent } = await import("./agents-BKKkxKgK.js");
6783
+ const result = await resumeAgent(normalizedId);
6784
+ if (!result.success) throw new Error(`Failed to auto-resume agent: ${result.error}`);
6785
+ const delivery = await deliverAgentMessage(normalizedId, message, `messageAgent:${caller}`, resolveAgentDeliveryMethod(agentState), { dedupKey });
6786
+ await appendTellInterventionForUserSource(normalizedId, caller);
6787
+ return {
6788
+ delivered: delivery.ok,
6789
+ queuedToMail: false,
6790
+ ...delivery.deduplicated ? { deduplicated: true } : {}
6791
+ };
6792
+ }
6224
6793
  async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6225
6794
  const normalizedId = normalizeAgentId(agentId);
6226
6795
  const agentState = getAgentStateSync(normalizedId);
@@ -6241,45 +6810,65 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6241
6810
  };
6242
6811
  if (agentState?.paused === true) {
6243
6812
  const gateBlockReason = getAgentResumeGateBlockReason(agentState)?.reason ?? "agent is paused";
6244
- queueAgentMail(normalizedId, message);
6813
+ queueAgentMail(normalizedId, message, false, opts.dedupKey);
6245
6814
  logAgentLifecycleSync(normalizedId, `messageAgent queued mail without resume: ${gateBlockReason}`);
6246
6815
  console.log(`[agents] Queued message for ${normalizedId}; ${gateBlockReason}`);
6247
- return;
6816
+ return {
6817
+ delivered: false,
6818
+ queuedToMail: true,
6819
+ reason: gateBlockReason
6820
+ };
6248
6821
  }
6249
6822
  if (getAgentRuntimeStateSync(normalizedId)?.state === "suspended") {
6250
6823
  const suspendedGate = decideMessageGate();
6251
6824
  if (suspendedGate.decision !== "proceed") {
6252
6825
  const gateBlockReason = suspendedGate.reason ?? "agent is gated";
6253
- queueAgentMail(normalizedId, message);
6826
+ queueAgentMail(normalizedId, message, false, opts.dedupKey);
6254
6827
  logAgentLifecycleSync(normalizedId, `messageAgent queued mail without resume: ${gateBlockReason}`);
6255
6828
  console.log(`[agents] Queued message for ${normalizedId}; ${gateBlockReason}`);
6256
- return;
6829
+ return {
6830
+ delivered: false,
6831
+ queuedToMail: true,
6832
+ reason: gateBlockReason
6833
+ };
6257
6834
  }
6258
6835
  console.log(`[agents] Auto-resuming suspended agent ${normalizedId} to deliver message`);
6259
- const { resumeAgent } = await import("./agents-FlIgQ3ql.js");
6836
+ if (opts.dedupKey !== void 0) return resumeThenDeliverKeyed(normalizedId, message, caller, agentState, opts.dedupKey);
6837
+ const { resumeAgent } = await import("./agents-BKKkxKgK.js");
6260
6838
  const result = await resumeAgent(normalizedId, message);
6261
6839
  if (!result.success) throw new Error(`Failed to auto-resume agent: ${result.error}`);
6262
6840
  if (result.messageDelivered === false) throw new Error(`Agent resumed but ready signal did not fire — message not delivered. Feedback is in the mail queue.`);
6263
6841
  await appendTellInterventionForUserSource(normalizedId, caller);
6264
- return;
6842
+ return {
6843
+ delivered: true,
6844
+ queuedToMail: false
6845
+ };
6265
6846
  }
6266
6847
  if (agentState && agentState.status === "stopped") {
6267
6848
  const stoppedGate = decideMessageGate();
6268
6849
  if (stoppedGate.decision !== "proceed") {
6269
6850
  const gateBlockReason = stoppedGate.reason ?? "agent is gated";
6270
- queueAgentMail(normalizedId, message);
6851
+ queueAgentMail(normalizedId, message, false, opts.dedupKey);
6271
6852
  logAgentLifecycleSync(normalizedId, `messageAgent queued mail without resume: ${gateBlockReason}`);
6272
6853
  console.log(`[agents] Queued message for ${normalizedId}; ${gateBlockReason}`);
6273
- return;
6854
+ return {
6855
+ delivered: false,
6856
+ queuedToMail: true,
6857
+ reason: gateBlockReason
6858
+ };
6274
6859
  }
6275
6860
  console.log(`[agents] Auto-resuming stopped agent ${normalizedId} to deliver feedback (session exists: ${await Effect.runPromise(sessionExists(normalizedId))})`);
6276
- const { resumeAgent } = await import("./agents-FlIgQ3ql.js");
6861
+ if (opts.dedupKey !== void 0) return resumeThenDeliverKeyed(normalizedId, message, caller, agentState, opts.dedupKey);
6862
+ const { resumeAgent } = await import("./agents-BKKkxKgK.js");
6277
6863
  const resumeResult = await resumeAgent(normalizedId, message);
6278
- queueAgentMail(normalizedId, message);
6864
+ queueAgentMail(normalizedId, message, false);
6279
6865
  if (resumeResult.success && resumeResult.messageDelivered !== false) {
6280
6866
  await appendTellInterventionForUserSource(normalizedId, caller);
6281
6867
  console.log(`[agents] Resumed ${normalizedId} and delivered feedback`);
6282
- return;
6868
+ return {
6869
+ delivered: true,
6870
+ queuedToMail: true
6871
+ };
6283
6872
  }
6284
6873
  if (!resumeResult.success) console.warn(`[agents] Resume failed for ${normalizedId}: ${resumeResult.error} — falling back to fresh launch`);
6285
6874
  else console.warn(`[agents] Resume succeeded for ${normalizedId} but message not delivered (ready signal timed out) — falling back to fresh launch`);
@@ -6292,7 +6881,11 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6292
6881
  message: `${normalizedId}: ${stopMsg}`,
6293
6882
  issueId: agentState.issueId
6294
6883
  });
6295
- return;
6884
+ return {
6885
+ delivered: false,
6886
+ queuedToMail: true,
6887
+ reason: stopMsg
6888
+ };
6296
6889
  }
6297
6890
  const providerEnv = agentState.model ? await getProviderEnvForModel(agentState.model) : {};
6298
6891
  if (agentState.model) {
@@ -6310,7 +6903,7 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6310
6903
  const resumeModel = agentState.model || "claude-sonnet-4-6";
6311
6904
  const fallbackHarness = agentState.harness ?? "claude-code";
6312
6905
  const harnessLaunch = await prepareHarnessLaunch(fallbackHarness);
6313
- const { assertWorkspaceStackHealthyForSpawn } = await import("./agents-FlIgQ3ql.js");
6906
+ const { assertWorkspaceStackHealthyForSpawn } = await import("./agents-BKKkxKgK.js");
6314
6907
  await assertWorkspaceStackHealthyForSpawn(agentState.issueId || normalizedId.replace(/^agent-/, "").toUpperCase(), resumeRole, agentState.hostOverride === true, agentState.workspace);
6315
6908
  const fallbackPiFields = fallbackHarness === "ohmypi" ? await getOhmypiLauncherFields(normalizedId, resumeModel) : {};
6316
6909
  const fallbackCodexFields = fallbackHarness === "codex" ? getCodexLauncherFields(normalizedId, resumeModel, agentState.workspace, resumeRole) : {};
@@ -6341,7 +6934,10 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6341
6934
  saveAgentStateSync(agentState);
6342
6935
  const ready = await waitForPromptReady(normalizedId, fallbackHarness, 30);
6343
6936
  const resumeMessage = await buildResumeMessageForAgent(agentState, `You are resuming work on ${agentState.issueId}. Check .pan/feedback/ for specialist feedback that arrived while you were stopped, then continue working.\n\n${message}`, message);
6937
+ let delivered = false;
6938
+ let reason;
6344
6939
  if (resumeMessage.error) {
6940
+ reason = resumeMessage.error;
6345
6941
  console.error(`[agents] Fallback-restarted ${normalizedId} but ${resumeMessage.error}`);
6346
6942
  emitActivityEntrySync({
6347
6943
  source: "work-agent",
@@ -6350,7 +6946,6 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6350
6946
  issueId: agentState.issueId
6351
6947
  });
6352
6948
  } else if (ready && resumeMessage.message) {
6353
- let delivered = false;
6354
6949
  if (fallbackHarness === "claude-code") {
6355
6950
  const fallbackSessionId = getLatestSessionIdSync(normalizedId);
6356
6951
  if (fallbackSessionId) {
@@ -6360,65 +6955,131 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6360
6955
  sessionId: fallbackSessionId,
6361
6956
  message: resumeMessage.message,
6362
6957
  caller: "resumeAgent:resume-prompt",
6363
- deliveryMethod: resilientDeliveryMethod(agentState.deliveryMethod)
6958
+ deliveryMethod: resolveAgentDeliveryMethod(agentState)
6364
6959
  });
6365
6960
  delivered = delivery.delivered;
6366
- if (!delivery.delivered) console.error(`[agents] Fallback resume prompt did not land after ${delivery.attempts} delivery attempts`);
6367
- } else console.error(`[agents] Fallback-restarted ${normalizedId} but no session id was recorded — feedback in mail queue`);
6368
- } else delivered = (await deliverAgentMessage(normalizedId, resumeMessage.message, "resumeAgent:resume-prompt", resilientDeliveryMethod(agentState.deliveryMethod))).ok;
6961
+ if (!delivery.delivered) {
6962
+ reason = `resume prompt did not land after ${delivery.attempts} delivery attempts`;
6963
+ console.error(`[agents] Fallback resume prompt did not land after ${delivery.attempts} delivery attempts`);
6964
+ }
6965
+ } else {
6966
+ reason = "no session id was recorded";
6967
+ console.error(`[agents] Fallback-restarted ${normalizedId} but no session id was recorded — feedback in mail queue`);
6968
+ }
6969
+ } else {
6970
+ const delivery = await deliverWithOptionalKey(normalizedId, resumeMessage.message, "resumeAgent:resume-prompt", resolveAgentDeliveryMethod(agentState), opts.dedupKey);
6971
+ delivered = delivery.ok;
6972
+ if (!delivery.ok) reason = "resume prompt delivery failed";
6973
+ }
6369
6974
  if (delivered) {
6370
6975
  if (resumeMessage.redeliveringKickoff) markKickoffRedelivered(agentState);
6371
6976
  await appendTellInterventionForUserSource(normalizedId, caller);
6372
6977
  console.log(`[agents] Fallback-restarted ${normalizedId} and delivered feedback`);
6373
6978
  }
6374
- } else console.warn(`[agents] Fallback-restarted ${normalizedId} but ready signal not detected — feedback in mail queue`);
6375
- return;
6979
+ } else {
6980
+ reason = "ready signal not detected";
6981
+ console.warn(`[agents] Fallback-restarted ${normalizedId} but ready signal not detected — feedback in mail queue`);
6982
+ }
6983
+ return {
6984
+ delivered,
6985
+ queuedToMail: true,
6986
+ ...reason ? { reason } : {}
6987
+ };
6376
6988
  }
6377
- const { loadRemoteAgentState, sendToRemoteAgent } = await import("./remote-agents-CRCg1L4H.js");
6989
+ const { loadRemoteAgentState, sendToRemoteAgent } = await import("./remote-agents-C1bssi41.js");
6378
6990
  const remoteState = loadRemoteAgentState(normalizedId);
6379
6991
  if (remoteState && remoteState.vmName) {
6380
6992
  console.log(`[agents] Sending message to remote agent ${normalizedId} on ${remoteState.vmName}`);
6993
+ if (opts.dedupKey !== void 0) {
6994
+ const { sendToRemoteAgentKeyed } = await import("./remote-agents-C1bssi41.js");
6995
+ const remoteOutcome = await sendToRemoteAgentKeyed(normalizedId, remoteState.vmName, message, opts.dedupKey);
6996
+ queueAgentMail(normalizedId, message, false, opts.dedupKey);
6997
+ await appendTellInterventionForUserSource(normalizedId, caller);
6998
+ return {
6999
+ delivered: true,
7000
+ queuedToMail: true,
7001
+ ...remoteOutcome === "deduplicated" ? {
7002
+ reason: "deduplicated",
7003
+ deduplicated: true
7004
+ } : {}
7005
+ };
7006
+ }
6381
7007
  await sendToRemoteAgent(normalizedId, remoteState.vmName, message);
6382
- queueAgentMail(normalizedId, message);
7008
+ queueAgentMail(normalizedId, message, false);
6383
7009
  await appendTellInterventionForUserSource(normalizedId, caller);
6384
- return;
7010
+ return {
7011
+ delivered: true,
7012
+ queuedToMail: true
7013
+ };
6385
7014
  }
6386
7015
  const expectedHarness = agentState?.harness ?? "claude-code";
7016
+ if (expectedHarness === "claude-code" && opts.dedupKey === void 0 && isMonitorLive(normalizedId)) {
7017
+ queueAgentMail(normalizedId, message, false, opts.dedupKey, caller);
7018
+ logAgentLifecycleSync(normalizedId, `messageAgent delivered via monitor mail (caller: ${caller})`);
7019
+ console.log(`[agents] Delivered message to ${normalizedId} via monitor inbox`);
7020
+ await appendTellInterventionForUserSource(normalizedId, caller);
7021
+ return {
7022
+ delivered: true,
7023
+ queuedToMail: true,
7024
+ reason: "monitor"
7025
+ };
7026
+ }
6387
7027
  let appServerState;
6388
7028
  try {
6389
7029
  appServerState = (await getCodexAppServerStatus(normalizedId)).state;
6390
7030
  } catch {}
6391
7031
  if (appServerState && appServerState !== "closed" && appServerState !== "error") {
6392
7032
  if (!claimCodexIdleTurn(normalizedId)) {
6393
- queueAgentMail(normalizedId, message, true);
7033
+ queueAgentMail(normalizedId, message, true, opts.dedupKey);
6394
7034
  logAgentLifecycleSync(normalizedId, "messageAgent queued mail for codex turn-end delivery: agent busy");
6395
7035
  console.log(`[agents] Queued message for ${normalizedId}; codex agent is mid-turn`);
6396
7036
  await appendTellInterventionForUserSource(normalizedId, caller);
6397
- return;
7037
+ return {
7038
+ delivered: true,
7039
+ queuedToMail: true,
7040
+ reason: "queued for turn-end delivery"
7041
+ };
6398
7042
  }
6399
- const deliveryMethod = resilientDeliveryMethod(agentState?.deliveryMethod);
6400
- await deliverAgentMessage(normalizedId, message, `messageAgent:${caller}`, deliveryMethod);
6401
- queueAgentMail(normalizedId, message);
7043
+ const deliveryMethod = resolveAgentDeliveryMethod(agentState);
7044
+ const delivery = await deliverWithOptionalKey(normalizedId, message, `messageAgent:${caller}`, deliveryMethod, opts.dedupKey);
7045
+ queueAgentMail(normalizedId, message, false, opts.dedupKey);
6402
7046
  await appendTellInterventionForUserSource(normalizedId, caller);
6403
- return;
7047
+ return {
7048
+ delivered: delivery.ok,
7049
+ queuedToMail: true,
7050
+ ...delivery.deduplicated ? { deduplicated: true } : {}
7051
+ };
6404
7052
  }
6405
7053
  if (!await Effect.runPromise(sessionExists(normalizedId))) throw new Error(`Agent ${normalizedId} not running`);
6406
7054
  const panePids = await Effect.runPromise(listPaneValues(normalizedId, "#{pane_pid}"));
6407
7055
  if (panePids.length > 0 && !await hasAgentRuntimeInSubtree(panePids[0], expectedHarness)) {
6408
7056
  console.warn(`[agents] ${normalizedId} tmux session is a zombie (no ${expectedHarness} runtime) — attempting resume`);
6409
- const { resumeAgent } = await import("./agents-FlIgQ3ql.js");
7057
+ if (opts.dedupKey !== void 0) return resumeThenDeliverKeyed(normalizedId, message, caller, agentState, opts.dedupKey);
7058
+ const { resumeAgent } = await import("./agents-BKKkxKgK.js");
6410
7059
  const resumeResult = await resumeAgent(normalizedId, message);
6411
7060
  if (resumeResult.success) {
6412
- if (resumeResult.messageDelivered !== false) await appendTellInterventionForUserSource(normalizedId, caller);
6413
- return;
7061
+ const delivered = resumeResult.messageDelivered !== false;
7062
+ if (delivered) await appendTellInterventionForUserSource(normalizedId, caller);
7063
+ return {
7064
+ delivered,
7065
+ queuedToMail: false
7066
+ };
6414
7067
  }
6415
7068
  throw new Error(`Agent ${normalizedId} session is dead and resume failed: ${resumeResult.error}`);
6416
7069
  }
6417
7070
  if (!await waitForAgentIdle(normalizedId, 5e3)) console.warn(`[agents] ${normalizedId} not at idle prompt after 5s — sending message anyway`);
6418
- const deliveryMethod = resilientDeliveryMethod(agentState?.deliveryMethod);
6419
- await deliverAgentMessage(normalizedId, message, `messageAgent:${caller}`, deliveryMethod);
6420
- queueAgentMail(normalizedId, message);
7071
+ const deliveryMethod = resolveAgentDeliveryMethod(agentState);
7072
+ const delivery = await deliverWithOptionalKey(normalizedId, message, `messageAgent:${caller}`, deliveryMethod, opts.dedupKey);
7073
+ if (opts.dedupKey === void 0) queueAgentMail(normalizedId, message, false);
6421
7074
  await appendTellInterventionForUserSource(normalizedId, caller);
7075
+ return {
7076
+ delivered: delivery.ok,
7077
+ queuedToMail: opts.dedupKey === void 0,
7078
+ ...delivery.deduplicated ? { deduplicated: true } : {}
7079
+ };
7080
+ }
7081
+ async function messageAgentWithOutcome(agentId, message, caller = "internal", opts = {}) {
7082
+ return (await messageAgent(agentId, message, caller, opts)).delivered ? "delivered" : "queued";
6422
7083
  }
6423
7084
  var USER_MESSAGE_INTERVENTION_SOURCES;
6424
7085
  var init_messaging = __esmMin((() => {
@@ -6435,6 +7096,7 @@ var init_messaging = __esmMin((() => {
6435
7096
  init_agent_state();
6436
7097
  init_activity();
6437
7098
  init_delivery();
7099
+ init_monitor_transport();
6438
7100
  init_runtime_state();
6439
7101
  init_runtime_command();
6440
7102
  init_supervisor_channels();
@@ -6487,6 +7149,54 @@ var init_context_overflow = __esmMin((() => {
6487
7149
  ];
6488
7150
  }));
6489
7151
  //#endregion
7152
+ //#region ../../lib/agents/session-pointers.ts
7153
+ /**
7154
+ * Clear every mutable pointer that can make a later launch resume an old
7155
+ * session. Claude JSONL transcripts live outside the agent directory and are
7156
+ * deliberately never touched.
7157
+ */
7158
+ async function clearAgentSessionPointers(agentId) {
7159
+ const agentDir = getAgentDir(agentId);
7160
+ const cleared = [];
7161
+ for (const name of [
7162
+ "session.id",
7163
+ "sessions.json",
7164
+ "codex-thread-id",
7165
+ "launcher.sh"
7166
+ ]) {
7167
+ const path = join(agentDir, name);
7168
+ if (!existsSync$1(path)) continue;
7169
+ unlinkSync$1(path);
7170
+ cleared.push(name);
7171
+ }
7172
+ const runtimeFile = join(agentDir, "runtime.json");
7173
+ if (existsSync$1(runtimeFile)) try {
7174
+ const runtime = JSON.parse(readFileSync$1(runtimeFile, "utf-8"));
7175
+ if (Object.prototype.hasOwnProperty.call(runtime, "claudeSessionId")) {
7176
+ delete runtime.claudeSessionId;
7177
+ writeFileSync$1(runtimeFile, JSON.stringify(runtime, null, 2));
7178
+ cleared.push("runtime.json:claudeSessionId");
7179
+ }
7180
+ } catch {}
7181
+ const state = getAgentStateSync(agentId);
7182
+ if (state?.sessionId) {
7183
+ delete state.sessionId;
7184
+ saveAgentStateSync(state);
7185
+ cleared.push("agents.session_id");
7186
+ }
7187
+ await Effect.runPromise(emitAgentEvent(agentId, {
7188
+ kind: "model_set",
7189
+ model: state?.model ?? "unknown",
7190
+ claudeSessionId: null
7191
+ }));
7192
+ cleared.push("runtime.claudeSessionId");
7193
+ return { cleared };
7194
+ }
7195
+ var init_session_pointers = __esmMin((() => {
7196
+ init_agent_runtime();
7197
+ init_agent_state();
7198
+ }));
7199
+ //#endregion
6490
7200
  //#region ../../lib/agents/resume.ts
6491
7201
  /**
6492
7202
  * Resume a suspended agent (PAN-80)
@@ -6519,7 +7229,7 @@ async function buildCompactRecoverySeed(agentId) {
6519
7229
  if (agentState?.workspace && sessionId) {
6520
7230
  const sessionFile = sessionFilePath(agentState.workspace, sessionId);
6521
7231
  try {
6522
- const [{ getConversationCompactionSettings }, { generateSmartSummary }] = await Promise.all([import("./conversation-compaction-DiG5zWQq.js"), import("./smart-compaction-CHIxLr_d.js")]);
7232
+ const [{ getConversationCompactionSettings }, { generateSmartSummary }] = await Promise.all([import("./conversation-compaction-Dj4FAKoZ.js"), import("./smart-compaction-CPp2Ykf6.js")]);
6523
7233
  const settings = getConversationCompactionSettings();
6524
7234
  summary = (await Effect.runPromise(generateSmartSummary({
6525
7235
  jsonlPath: sessionFile,
@@ -6530,7 +7240,7 @@ async function buildCompactRecoverySeed(agentId) {
6530
7240
  } catch (err) {
6531
7241
  logAgentLifecycleSync(normalizedId, `compact-recovery smart summary failed (${err instanceof Error ? err.message : String(err)}); trying heuristic fallback`);
6532
7242
  try {
6533
- const { generateFallbackSummary } = await import("./summary-fork-D8bXjCr7.js");
7243
+ const { generateFallbackSummary } = await import("./summary-fork-CD7GOts0.js");
6534
7244
  summary = await Effect.runPromise(generateFallbackSummary(sessionFile));
6535
7245
  } catch (fallbackErr) {
6536
7246
  logAgentLifecycleSync(normalizedId, `compact-recovery fallback summary failed (${fallbackErr instanceof Error ? fallbackErr.message : String(fallbackErr)}); seeding with reseed instructions only`);
@@ -6655,7 +7365,13 @@ async function resumeAgent(agentId, message, opts) {
6655
7365
  if (legacyHarnessMigrated) resumeDriftReasons.push(`legacy harness ${priorHarness}→${effectiveHarness} (PAN-1797 re-default)`);
6656
7366
  const piDeadRecovery = effectiveHarness === "ohmypi" && !piProcessWasAlive && !compactSeed && resumeDriftReasons.length === 0;
6657
7367
  if (piDeadRecovery) logAgentLifecycleSync(normalizedId, "resumeAgent: dead ohmypi process — fresh-launching for recovery instead of omp --resume (PAN-2009)");
6658
- const shouldResumeSavedSession = !compactSeed && resumeDriftReasons.length === 0 && !piDeadRecovery;
7368
+ const expectedClaudeJsonl = sessionFilePath(agentState.workspace, sessionId);
7369
+ const claudeJsonlMissingRecovery = effectiveHarness === "claude-code" && !compactSeed && resumeDriftReasons.length === 0 && !existsSync(expectedClaudeJsonl);
7370
+ if (claudeJsonlMissingRecovery) {
7371
+ logAgentLifecycleSync(normalizedId, `resumeAgent: saved Claude transcript is missing at ${expectedClaudeJsonl} — clearing stale pointers and fresh-launching (PAN-2895)`);
7372
+ await clearAgentSessionPointers(normalizedId);
7373
+ }
7374
+ const shouldResumeSavedSession = !compactSeed && resumeDriftReasons.length === 0 && !piDeadRecovery && !claudeJsonlMissingRecovery;
6659
7375
  if (sessionRotationRefused({
6660
7376
  compactSeed: Boolean(compactSeed),
6661
7377
  driftReasons: resumeDriftReasons,
@@ -6676,12 +7392,14 @@ async function resumeAgent(agentId, message, opts) {
6676
7392
  }
6677
7393
  const freshSessionId = !shouldResumeSavedSession && effectiveHarness === "claude-code" ? randomUUID() : void 0;
6678
7394
  if (resumeDriftReasons.length > 0) logAgentLifecycleSync(normalizedId, `resumeAgent: starting fresh session instead of --resume because session origin drifted (${resumeDriftReasons.join(", ")})`);
6679
- if (freshSessionId) saveSessionId(normalizedId, freshSessionId);
6680
- else if (!shouldResumeSavedSession) try {
7395
+ if (freshSessionId) {
7396
+ saveSessionId(normalizedId, freshSessionId);
7397
+ agentState.sessionId = freshSessionId;
7398
+ } else if (!shouldResumeSavedSession) try {
6681
7399
  unlinkSync(join$1(getAgentDir(normalizedId), "session.id"));
6682
7400
  } catch {}
6683
7401
  const issueId = agentState.issueId || normalizedId.replace(/^agent-/, "").toUpperCase();
6684
- const defaultResumeMessage = buildDefaultResumeContinueMessage(issueId);
7402
+ const defaultResumeMessage = buildResumeContinueMessage(agentState);
6685
7403
  const resumeMessage = compactSeed ? {
6686
7404
  message: message ? `${compactSeed}\n\n${message}` : compactSeed,
6687
7405
  redeliveringKickoff: false
@@ -6715,6 +7433,7 @@ async function resumeAgent(agentId, message, opts) {
6715
7433
  } : {},
6716
7434
  sessionId: freshSessionId,
6717
7435
  harness: effectiveHarness,
7436
+ harnessBinaryPath: harnessLaunch.binaryPath,
6718
7437
  useSupervisor: supervisorLaunch.useSupervisor,
6719
7438
  supervisorScriptPath: supervisorLaunch.supervisorScriptPath,
6720
7439
  extraEnvExports: [harnessLaunch.pathExport]
@@ -6730,6 +7449,11 @@ async function resumeAgent(agentId, message, opts) {
6730
7449
  CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
6731
7450
  ...providerEnv
6732
7451
  } }));
7452
+ if (freshSessionId) await saveAgentRuntimeState(normalizedId, {
7453
+ claudeSessionId: freshSessionId,
7454
+ sessionModel: model,
7455
+ sessionHarness: effectiveHarness
7456
+ });
6733
7457
  let messageDelivered = false;
6734
7458
  if (effectiveHarness === "ohmypi") try {
6735
7459
  await writeOhmypiAgentPrompt(normalizedId, effectiveMessage);
@@ -6739,7 +7463,18 @@ async function resumeAgent(agentId, message, opts) {
6739
7463
  const msg = err instanceof Error ? err.message : String(err);
6740
7464
  console.error(`[resumeAgent] ohmypi prompt delivery failed: ${msg}`);
6741
7465
  }
6742
- else if (effectiveHarness === "codex") {
7466
+ else if (effectiveHarness === "acp") {
7467
+ const delivery = await deliverInitialPromptWithRetry(normalizedId, effectiveMessage, "resumeAgent:acp-continue");
7468
+ messageDelivered = delivery.ok;
7469
+ if (delivery.ok && resumeMessage.redeliveringKickoff) markKickoffRedelivered(agentState);
7470
+ if (!delivery.ok) {
7471
+ await Effect.runPromise(killSession(normalizedId));
7472
+ return {
7473
+ success: false,
7474
+ error: `ACP continue prompt did not land: ${delivery.failure ?? "unknown failure"}`
7475
+ };
7476
+ }
7477
+ } else if (effectiveHarness === "codex") {
6743
7478
  const delivery = await deliverInitialPromptWithRetry(normalizedId, effectiveMessage, "resumeAgent:codex-continue", resilientDeliveryMethod(agentState.deliveryMethod));
6744
7479
  messageDelivered = delivery.ok;
6745
7480
  if (delivery.ok && resumeMessage.redeliveringKickoff) markKickoffRedelivered(agentState);
@@ -6768,6 +7503,9 @@ async function resumeAgent(agentId, message, opts) {
6768
7503
  } else if (piDeadRecovery) {
6769
7504
  console.log(`[agents] Respawned ${normalizedId} fresh because the prior Pi process was dead (archived session ${sessionId})`);
6770
7505
  logAgentLifecycleSync(normalizedId, `resumeAgent SUCCESS: fresh respawn after dead Pi process (archived sessionId=${sessionId}), messageDelivered=${messageDelivered}`);
7506
+ } else if (claudeJsonlMissingRecovery) {
7507
+ console.log(`[agents] Respawned ${normalizedId} fresh because the saved Claude transcript was missing (stale session ${sessionId}${freshSessionId ? `, new session ${freshSessionId}` : ""})`);
7508
+ logAgentLifecycleSync(normalizedId, `resumeAgent SUCCESS: fresh respawn after missing Claude JSONL (stale sessionId=${sessionId}${freshSessionId ? `, newSessionId=${freshSessionId}` : ""}), messageDelivered=${messageDelivered}`);
6771
7509
  } else if (!shouldResumeSavedSession) {
6772
7510
  console.log(`[agents] Respawned ${normalizedId} fresh because session origin drifted (archived session ${sessionId}${freshSessionId ? `, new session ${freshSessionId}` : ""})`);
6773
7511
  logAgentLifecycleSync(normalizedId, `resumeAgent SUCCESS: fresh respawn after origin drift (archived sessionId=${sessionId}${freshSessionId ? `, newSessionId=${freshSessionId}` : ""}), messageDelivered=${messageDelivered}`);
@@ -6850,6 +7588,7 @@ var init_resume = __esmMin((() => {
6850
7588
  init_tmux();
6851
7589
  init_agent_state();
6852
7590
  init_activity();
7591
+ init_session_pointers();
6853
7592
  init_delivery();
6854
7593
  init_identity();
6855
7594
  init_runtime_state();
@@ -6885,7 +7624,7 @@ var init_graceful_restart = __esmMin((() => {
6885
7624
  //#endregion
6886
7625
  //#region ../../lib/agents/recovery.ts
6887
7626
  function resolveRecoveryResumeSessionId(agentId, harness) {
6888
- if (harness !== "codex") return void 0;
7627
+ if (harness !== "codex" && harness !== "acp") return void 0;
6889
7628
  return getLatestSessionIdSync(agentId) ?? void 0;
6890
7629
  }
6891
7630
  async function restartAgent(agentId, opts = {}) {
@@ -6945,6 +7684,7 @@ async function restartAgent(agentId, opts = {}) {
6945
7684
  role: agentState.role,
6946
7685
  isPlanning: agentState.role === "plan",
6947
7686
  harness: effectiveHarness,
7687
+ harnessBinaryPath: harnessLaunch.binaryPath,
6948
7688
  useSupervisor: supervisorLaunch.useSupervisor,
6949
7689
  supervisorScriptPath: supervisorLaunch.supervisorScriptPath,
6950
7690
  extraEnvExports: [harnessLaunch.pathExport]
@@ -6962,18 +7702,20 @@ async function restartAgent(agentId, opts = {}) {
6962
7702
  GIT_SEQUENCE_EDITOR: "false",
6963
7703
  ...providerEnv
6964
7704
  } }));
6965
- const prompt = message || `You are resuming work on ${agentState.issueId}. Read .pan/continue.json for context and pick up where you left off.`;
7705
+ const prompt = message || buildResumeContinueMessage(agentState);
6966
7706
  if (effectiveHarness === "ohmypi") try {
6967
7707
  await writeOhmypiAgentPrompt(normalizedId, prompt);
6968
7708
  } catch (err) {
6969
7709
  const msg = err instanceof Error ? err.message : String(err);
6970
7710
  console.error(`[restartAgent] ohmypi prompt delivery failed for ${normalizedId}: ${msg}`);
6971
7711
  }
6972
- else if (await waitForPromptReady(normalizedId, effectiveHarness, 30)) {
7712
+ else {
7713
+ if (!await waitForPromptReady(normalizedId, effectiveHarness, 30)) throw new Error(`${getHarnessBehavior(effectiveHarness).displayName} did not become ready within 30s for ${normalizedId}`);
6973
7714
  await new Promise((r) => setTimeout(r, 500));
6974
- if (effectiveHarness === "codex") await deliverAgentMessage(normalizedId, prompt, "restartAgent:continue-prompt", resilientDeliveryMethod(agentState.deliveryMethod));
6975
- else await Effect.runPromise(sendKeys(normalizedId, prompt));
6976
- } else console.error(`[restartAgent] ${effectiveHarness === "codex" ? "Codex" : "Claude"} did not become ready within 30s for ${normalizedId}`);
7715
+ if (effectiveHarness === "codex" || effectiveHarness === "acp") {
7716
+ if (!(await deliverAgentMessage(normalizedId, prompt, "restartAgent:continue-prompt", effectiveHarness === "codex" ? resilientDeliveryMethod(agentState.deliveryMethod) : void 0)).ok) throw new Error(`${getHarnessBehavior(effectiveHarness).displayName} continue prompt delivery failed`);
7717
+ } else await Effect.runPromise(sendKeys(normalizedId, prompt));
7718
+ }
6977
7719
  markAgentRunning(agentState);
6978
7720
  saveAgentStateSync(agentState);
6979
7721
  await saveAgentRuntimeState(normalizedId, {
@@ -6984,6 +7726,7 @@ async function restartAgent(agentId, opts = {}) {
6984
7726
  return { success: true };
6985
7727
  } catch (error) {
6986
7728
  const msg = error instanceof Error ? error.message : String(error);
7729
+ await Effect.runPromise(stopAgent(normalizedId)).catch(() => void 0);
6987
7730
  logAgentLifecycleSync(normalizedId, `restartAgent FAILED: ${msg}`);
6988
7731
  return {
6989
7732
  success: false,
@@ -7086,6 +7829,7 @@ async function recoverAgent(agentId, opts = {}) {
7086
7829
  role: recoveryRole,
7087
7830
  isPlanning: recoveryRole === "plan",
7088
7831
  harness: "ohmypi",
7832
+ harnessBinaryPath: harnessLaunch.binaryPath,
7089
7833
  extraEnvExports: [harnessLaunch.pathExport]
7090
7834
  });
7091
7835
  const launcherScript = join$1(getAgentDir(normalizedId), "launcher.sh");
@@ -7109,6 +7853,42 @@ async function recoverAgent(agentId, opts = {}) {
7109
7853
  logAgentLifecycleSync(normalizedId, `recoverAgent SUCCESS: recoveryCount=${health.recoveryCount} (ohmypi)`);
7110
7854
  return state;
7111
7855
  }
7856
+ if (recoveryHarness === "acp") {
7857
+ const resumeSessionId = resolveRecoveryResumeSessionId(normalizedId, recoveryHarness);
7858
+ const { launcherContent, providerEnv: acpProviderEnv } = await buildAgentLaunchConfig({
7859
+ agentId: normalizedId,
7860
+ model: state.model,
7861
+ workspace: state.workspace,
7862
+ role: recoveryRole,
7863
+ isPlanning: recoveryRole === "plan",
7864
+ ...resumeSessionId ? {
7865
+ spawnMode: "resume",
7866
+ resumeSessionId
7867
+ } : {},
7868
+ harness: "acp",
7869
+ harnessBinaryPath: harnessLaunch.binaryPath,
7870
+ extraEnvExports: [harnessLaunch.pathExport]
7871
+ });
7872
+ const launcherScript = join$1(getAgentDir(normalizedId), "launcher.sh");
7873
+ await writeLauncherScriptAtomic(launcherScript, launcherContent);
7874
+ await Effect.runPromise(createSession(normalizedId, state.workspace, `bash ${launcherScript}`, { env: {
7875
+ ...BLANKED_PROVIDER_ENV,
7876
+ OVERDECK_AGENT_ID: normalizedId,
7877
+ OVERDECK_ISSUE_ID: state.issueId || "",
7878
+ OVERDECK_SESSION_TYPE: recoveryRole,
7879
+ CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
7880
+ ...acpProviderEnv
7881
+ } }));
7882
+ const delivery = await deliverInitialPromptWithRetry(normalizedId, recoveryPrompt, "recoverAgent:acp-recovery-prompt");
7883
+ if (!delivery.ok) {
7884
+ await Effect.runPromise(stopAgent(normalizedId));
7885
+ throw new Error(`ACP recovery prompt delivery failed for ${normalizedId}: ${delivery.failure ?? "unknown failure"}`);
7886
+ }
7887
+ markAgentRunning(state);
7888
+ saveAgentStateSync(state);
7889
+ logAgentLifecycleSync(normalizedId, `recoverAgent SUCCESS: recoveryCount=${health.recoveryCount} (acp)`);
7890
+ return state;
7891
+ }
7112
7892
  const recoveryCodexFields = recoveryHarness === "codex" ? getCodexLauncherFields(normalizedId, state.model, state.workspace, recoveryRole) : {};
7113
7893
  const recoveryLauncherContent = generateLauncherScriptSync({
7114
7894
  role: recoveryRole,
@@ -7210,6 +7990,7 @@ var init_recovery = __esmMin((() => {
7210
7990
  init_persistent_logger();
7211
7991
  init_providers();
7212
7992
  init_conversations();
7993
+ init_behavior();
7213
7994
  init_tmux();
7214
7995
  init_agent_state();
7215
7996
  init_delivery();
@@ -7481,11 +8262,11 @@ async function renderCommitFeedDiff(workspace, sha, feedConfig = DEFAULT_FEED_CO
7481
8262
  ".",
7482
8263
  ...feedConfig.exclude.map((glob) => `:(exclude)${glob}`)
7483
8264
  ] : [];
7484
- const diff = await gitShow(workspace, sha, pathspecArgs);
8265
+ const diff = await renderWorkspaceGitShowPromise(deps.issueId, workspace, sha, pathspecArgs, gitShow);
7485
8266
  const maxBytes = feedConfig.max_diff_bytes;
7486
8267
  if (maxBytes === null || Buffer.byteLength(diff, "utf-8") <= maxBytes) return diff;
7487
8268
  return [
7488
- (await gitShow(workspace, sha, ["--stat", ...pathspecArgs])).trimEnd(),
8269
+ (await renderWorkspaceGitShowPromise(deps.issueId, workspace, sha, ["--stat", ...pathspecArgs], gitShow)).trimEnd(),
7489
8270
  "",
7490
8271
  `[tiered_execution.feed.max_diff_bytes truncated commit diff: ${Buffer.byteLength(diff, "utf-8")} bytes exceeded ${maxBytes} bytes]`,
7491
8272
  ""
@@ -7527,7 +8308,10 @@ function composeCommitFeedMessage(sha, itemTitle, diff, callout) {
7527
8308
  async function broadcastCommit(options) {
7528
8309
  const feedConfig = options.feedConfig ?? DEFAULT_FEED_CONFIG;
7529
8310
  if (shouldSkipFeedSubject(options.commitSubject ?? options.itemTitle, feedConfig)) return [];
7530
- const renderDiff = options.renderDiff ?? (options.gitShow ? (workspace, sha) => options.gitShow(workspace, sha) : renderCommitFeedDiff);
8311
+ const renderDiff = options.renderDiff ?? ((workspace, sha, config) => renderCommitFeedDiff(workspace, sha, config, {
8312
+ issueId: options.issueId,
8313
+ gitShow: options.gitShow ? (repoPath, repoSha) => options.gitShow(repoPath, repoSha) : void 0
8314
+ }));
7531
8315
  const deliver = options.deliver ?? deliverAgentMessage;
7532
8316
  const recordDelivery = options.recordDelivery ?? recordTierFeedDelivery;
7533
8317
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
@@ -7576,6 +8360,7 @@ async function broadcastCommit(options) {
7576
8360
  }
7577
8361
  var execFileAsync$5, DEFAULT_FEED_CONFIG;
7578
8362
  var init_tier_feed = __esmMin((() => {
8363
+ init_git_utils();
7579
8364
  init_delivery();
7580
8365
  init_tier_metrics();
7581
8366
  init_tier_table();
@@ -7793,13 +8578,19 @@ Rules:
7793
8578
  - Do not use any other endpoint or side channel for the verdict.
7794
8579
  - Only review this commit against this bead's acceptance criteria — compile, lint, and tests are the verification gate's job, and code style is the review convoy's job.`;
7795
8580
  }
7796
- async function getCommitDiff(workspacePath, sha) {
7797
- const { stdout } = await execFileAsync$4("git", ["show", sha], {
7798
- cwd: workspacePath,
7799
- encoding: "utf-8",
7800
- maxBuffer: 10 * 1024 * 1024
8581
+ async function getCommitDiff(issueId, workspacePath, sha) {
8582
+ return renderWorkspaceGitShowPromise(issueId, workspacePath, sha, [], async (repoPath, repoSha, args) => {
8583
+ const { stdout } = await execFileAsync$4("git", [
8584
+ "show",
8585
+ repoSha,
8586
+ ...args
8587
+ ], {
8588
+ cwd: repoPath,
8589
+ encoding: "utf-8",
8590
+ maxBuffer: 10 * 1024 * 1024
8591
+ });
8592
+ return stdout;
7801
8593
  });
7802
- return stdout;
7803
8594
  }
7804
8595
  /**
7805
8596
  * Deliver one subscribed commit to the standing supervisor for review:
@@ -7809,7 +8600,7 @@ async function getCommitDiff(workspacePath, sha) {
7809
8600
  */
7810
8601
  async function deliverCommitForReview(options) {
7811
8602
  const deliver = options.deps?.deliver ?? deliverAgentMessage;
7812
- const diff = await (options.deps?.getDiff ?? getCommitDiff)(options.workspacePath, options.sha);
8603
+ const diff = await (options.deps?.getDiff ?? ((workspacePath, sha) => getCommitDiff(options.issueId, workspacePath, sha)))(options.workspacePath, options.sha);
7813
8604
  const traces = Array.isArray(options.item.metadata?.traces) ? options.item.metadata.traces : [];
7814
8605
  const frText = options.prdMarkdown && traces.length > 0 ? extractTracedFrText(options.prdMarkdown, traces) : void 0;
7815
8606
  const message = buildSupervisorReviewMessage({
@@ -7826,6 +8617,7 @@ async function deliverCommitForReview(options) {
7826
8617
  }
7827
8618
  var SUPERVISOR_SUB_ROLE, execFileAsync$4;
7828
8619
  var init_tier_supervisor = __esmMin((() => {
8620
+ init_git_utils();
7829
8621
  init_delivery();
7830
8622
  init_spawn_prep();
7831
8623
  init_spawn();
@@ -7840,7 +8632,7 @@ var init_tier_supervisor = __esmMin((() => {
7840
8632
  * from `git log <base>..HEAD`, oldest commit first.
7841
8633
  */
7842
8634
  async function replayStandingAgent(target, options = {}) {
7843
- const deps = replayDeps(options.deps);
8635
+ const deps = replayDeps(options.deps, target.issueId);
7844
8636
  const replayTarget = target.kind === "tier" ? {
7845
8637
  ...target,
7846
8638
  ...resolveReplaySlot(target, deps)
@@ -7865,7 +8657,7 @@ async function replayCrashedStandingAgent(target, options = {}) {
7865
8657
  */
7866
8658
  async function compactAtTierRunBoundary(options) {
7867
8659
  if (!shouldReplayCompactAtTierRunBoundary(options.compaction)) return null;
7868
- const deps = replayDeps(options.deps);
8660
+ const deps = replayDeps(options.deps, options.target.issueId);
7869
8661
  const rerouted = resolveReroutedReplayTarget(options.target);
7870
8662
  if (!rerouted) {
7871
8663
  if (options.target.agentId) await deps.stop(options.target.agentId);
@@ -8028,27 +8820,34 @@ async function runGitLog(workspace, base) {
8028
8820
  };
8029
8821
  }).filter((entry) => entry.sha.trim().length > 0);
8030
8822
  }
8031
- async function runGitShow(workspace, sha) {
8032
- const { stdout } = await execFileAsync$3("git", ["show", sha], {
8033
- cwd: workspace,
8034
- encoding: "utf-8",
8035
- maxBuffer: 16 * 1024 * 1024
8823
+ async function runGitShow(issueId, workspace, sha) {
8824
+ return renderWorkspaceGitShowPromise(issueId, workspace, sha, [], async (repoPath, repoSha, args) => {
8825
+ const { stdout } = await execFileAsync$3("git", [
8826
+ "show",
8827
+ repoSha,
8828
+ ...args
8829
+ ], {
8830
+ cwd: repoPath,
8831
+ encoding: "utf-8",
8832
+ maxBuffer: 16 * 1024 * 1024
8833
+ });
8834
+ return stdout;
8036
8835
  });
8037
- return stdout;
8038
8836
  }
8039
- function replayDeps(deps = {}) {
8837
+ function replayDeps(deps = {}, issueId) {
8040
8838
  return {
8041
8839
  spawn: deps.spawn ?? spawnRun,
8042
8840
  deliver: deps.deliver ?? deliverAgentMessage,
8043
8841
  stop: deps.stop ?? stopAgent,
8044
8842
  gitLog: deps.gitLog ?? runGitLog,
8045
- gitShow: deps.gitShow ?? runGitShow,
8046
- renderDiff: deps.renderDiff ?? (deps.gitShow ? (workspace, sha) => deps.gitShow(workspace, sha) : renderCommitFeedDiff),
8843
+ gitShow: deps.gitShow ?? ((workspace, sha) => runGitShow(issueId, workspace, sha)),
8844
+ renderDiff: deps.renderDiff ?? (deps.gitShow ? (workspace, sha) => deps.gitShow(workspace, sha) : (workspace, sha, feedConfig) => renderCommitFeedDiff(workspace, sha, feedConfig, { issueId })),
8047
8845
  listSlotOwnership: deps.listSlotOwnership ?? listSlotOwnership
8048
8846
  };
8049
8847
  }
8050
8848
  var execFileAsync$3, DEFAULT_REPLAY_THRESHOLD;
8051
8849
  var init_tier_replay = __esmMin((() => {
8850
+ init_git_utils();
8052
8851
  init_model_capabilities();
8053
8852
  init_delivery();
8054
8853
  init_spawn();
@@ -8196,7 +8995,7 @@ async function command(adapters, executable, args) {
8196
8995
  return null;
8197
8996
  }
8198
8997
  }
8199
- function createDarwinHostHealthCollector(adapters = defaultAdapters$1) {
8998
+ function createDarwinHostHealthCollector(adapters = defaultAdapters$2) {
8200
8999
  return {
8201
9000
  platform: "darwin",
8202
9001
  async sample(previous) {
@@ -8236,6 +9035,9 @@ function createDarwinHostHealthCollector(adapters = defaultAdapters$1) {
8236
9035
  committedMemoryBytes: unavailable("macOS does not expose Linux Committed_AS."),
8237
9036
  commitLimitBytes: unavailable("macOS does not expose Linux CommitLimit."),
8238
9037
  virtualCommitmentPercent: unavailable("macOS virtual commitment is unavailable."),
9038
+ inotifyWatchesUsed: unavailable("inotify is Linux-only."),
9039
+ inotifyWatchesMax: unavailable("inotify is Linux-only."),
9040
+ inotifyWatchesUsedPercent: unavailable("inotify is Linux-only."),
8239
9041
  counters: {
8240
9042
  cpu: cpuCounters,
8241
9043
  swap: vmStat?.swap ?? null
@@ -8244,7 +9046,7 @@ function createDarwinHostHealthCollector(adapters = defaultAdapters$1) {
8244
9046
  }
8245
9047
  };
8246
9048
  }
8247
- var execFileAsync$2, COMMAND_TIMEOUT_MS, MIB, DARWIN_MEMORY_PRESSURE_DEFAULTS, defaultAdapters$1;
9049
+ var execFileAsync$2, COMMAND_TIMEOUT_MS, MIB, DARWIN_MEMORY_PRESSURE_DEFAULTS, defaultAdapters$2;
8248
9050
  var init_darwin = __esmMin((() => {
8249
9051
  init_types();
8250
9052
  execFileAsync$2 = promisify(execFile);
@@ -8256,7 +9058,7 @@ var init_darwin = __esmMin((() => {
8256
9058
  swapActivityWarningBytesPerMinute: 64 * MIB,
8257
9059
  swapActivityCriticalBytesPerMinute: 256 * MIB
8258
9060
  });
8259
- defaultAdapters$1 = {
9061
+ defaultAdapters$2 = {
8260
9062
  execFile: async (command, args, timeoutMs) => {
8261
9063
  const { stdout } = await execFileAsync$2(command, [...args], {
8262
9064
  encoding: "utf-8",
@@ -8271,6 +9073,121 @@ var init_darwin = __esmMin((() => {
8271
9073
  };
8272
9074
  }));
8273
9075
  //#endregion
9076
+ //#region ../../lib/system-health/inotify.ts
9077
+ /**
9078
+ * inotify watch/instance accounting for the local user.
9079
+ *
9080
+ * inotify watches are a per-UID kernel budget (fs.inotify.max_user_watches)
9081
+ * shared by every process the user runs — host processes and Docker
9082
+ * containers alike, since containers share the kernel and (in Overdeck's
9083
+ * setups) the same uid. When the budget is exhausted, any program that
9084
+ * tries to add a watch fails with ENOSPC; the classic symptom is a Vite
9085
+ * dev server dying at startup while everything else looks healthy
9086
+ * (PAN-3063, the 2026-07-25 MIN-898 incident).
9087
+ *
9088
+ * The kernel exposes no aggregate usage counter, so the only way to measure
9089
+ * usage is to walk /proc/<pid>/fd for anon_inode:inotify descriptors and sum
9090
+ * the `inotify wd:` lines in the matching fdinfo files. Unprivileged scans
9091
+ * can only read same-uid processes, which conveniently matches the per-UID
9092
+ * scope of the budget itself.
9093
+ */
9094
+ /** Counts `inotify wd:` entries in a /proc/<pid>/fdinfo/<fd> payload. */
9095
+ function countInotifyWatches(fdinfoContent) {
9096
+ let count = 0;
9097
+ for (const line of fdinfoContent.split("\n")) if (line.startsWith("inotify wd:")) count += 1;
9098
+ return count;
9099
+ }
9100
+ function parseProcLimit(content) {
9101
+ const value = Number(content.trim());
9102
+ return Number.isFinite(value) && value > 0 ? value : null;
9103
+ }
9104
+ async function readLimit(adapters, path) {
9105
+ try {
9106
+ return parseProcLimit(await adapters.readFile(path));
9107
+ } catch {
9108
+ return null;
9109
+ }
9110
+ }
9111
+ async function scanPid(adapters, pid) {
9112
+ let fds;
9113
+ try {
9114
+ fds = await adapters.readdir(`/proc/${pid}/fd`);
9115
+ } catch {
9116
+ return null;
9117
+ }
9118
+ let watches = 0;
9119
+ let instances = 0;
9120
+ for (const fd of fds) {
9121
+ let target;
9122
+ try {
9123
+ target = await adapters.readlink(`/proc/${pid}/fd/${fd}`);
9124
+ } catch {
9125
+ continue;
9126
+ }
9127
+ if (!target.includes("inotify")) continue;
9128
+ instances += 1;
9129
+ try {
9130
+ watches += countInotifyWatches(await adapters.readFile(`/proc/${pid}/fdinfo/${fd}`));
9131
+ } catch {}
9132
+ }
9133
+ if (instances === 0) return null;
9134
+ return {
9135
+ pid,
9136
+ watches,
9137
+ instances
9138
+ };
9139
+ }
9140
+ async function readCommand(adapters, pid) {
9141
+ try {
9142
+ const command = (await adapters.readFile(`/proc/${pid}/cmdline`)).replaceAll("\0", " ").trim();
9143
+ return command.length > 120 ? `${command.slice(0, 117)}…` : command;
9144
+ } catch {
9145
+ return `pid ${pid}`;
9146
+ }
9147
+ }
9148
+ /**
9149
+ * Walks /proc and totals inotify watches and instances held by processes
9150
+ * this user can read. Returns null when /proc is unavailable (non-Linux).
9151
+ */
9152
+ async function sampleInotify(adapters = defaultAdapters$1) {
9153
+ let procEntries;
9154
+ try {
9155
+ procEntries = await adapters.readdir("/proc");
9156
+ } catch {
9157
+ return null;
9158
+ }
9159
+ const pids = procEntries.filter((entry) => /^\d+$/.test(entry)).map(Number);
9160
+ const scans = [];
9161
+ for (let i = 0; i < pids.length; i += PID_SCAN_CONCURRENCY) {
9162
+ const chunk = pids.slice(i, i + PID_SCAN_CONCURRENCY);
9163
+ const results = await Promise.all(chunk.map((pid) => scanPid(adapters, pid)));
9164
+ for (const result of results) if (result) scans.push(result);
9165
+ }
9166
+ const [watchesMax, instancesMax] = await Promise.all([readLimit(adapters, "/proc/sys/fs/inotify/max_user_watches"), readLimit(adapters, "/proc/sys/fs/inotify/max_user_instances")]);
9167
+ const top = [...scans].sort((a, b) => b.watches - a.watches).slice(0, 5);
9168
+ const topConsumers = await Promise.all(top.map(async (scan) => ({
9169
+ pid: scan.pid,
9170
+ watches: scan.watches,
9171
+ command: await readCommand(adapters, scan.pid)
9172
+ })));
9173
+ return {
9174
+ watchesUsed: scans.reduce((sum, scan) => sum + scan.watches, 0),
9175
+ watchesMax,
9176
+ instancesUsed: scans.reduce((sum, scan) => sum + scan.instances, 0),
9177
+ instancesMax,
9178
+ topConsumers
9179
+ };
9180
+ }
9181
+ var PID_SCAN_CONCURRENCY, defaultAdapters$1;
9182
+ var init_inotify = __esmMin((() => {
9183
+ PID_SCAN_CONCURRENCY = 32;
9184
+ defaultAdapters$1 = {
9185
+ readdir: (path) => readdir(path),
9186
+ readlink: (path) => readlink(path),
9187
+ readFile: (path) => readFile(path, "utf-8")
9188
+ };
9189
+ }));
9190
+ //#endregion
8274
9191
  //#region ../../lib/system-health/linux.ts
8275
9192
  function parseMemInfo(content) {
8276
9193
  const values = /* @__PURE__ */ new Map();
@@ -8364,10 +9281,16 @@ function percent(part, total) {
8364
9281
  return Math.round(part / total * 1e3) / 10;
8365
9282
  }
8366
9283
  function createLinuxHostHealthCollector(adapters = defaultAdapters) {
9284
+ let inotifyCache = null;
8367
9285
  return {
8368
9286
  platform: "linux",
8369
9287
  async sample(previous) {
8370
9288
  const sampledAtMs = adapters.now();
9289
+ if (!inotifyCache || sampledAtMs - inotifyCache.atMs >= 6e4) inotifyCache = {
9290
+ atMs: sampledAtMs,
9291
+ sample: await adapters.sampleInotify().catch(() => null)
9292
+ };
9293
+ const inotify = inotifyCache.sample;
8371
9294
  const [memInfo, procStat, pressure, vmstat, loadAverage, pageSizeBytes] = await Promise.all([
8372
9295
  readParsed(adapters, "/proc/meminfo", parseMemInfo),
8373
9296
  readParsed(adapters, "/proc/stat", parseProcStat),
@@ -8407,6 +9330,9 @@ function createLinuxHostHealthCollector(adapters = defaultAdapters) {
8407
9330
  committedMemoryBytes: committedMemoryBytes == null ? unavailable("Committed_AS is unavailable.") : available(committedMemoryBytes),
8408
9331
  commitLimitBytes: commitLimitBytes == null ? unavailable("CommitLimit is unavailable.") : available(commitLimitBytes),
8409
9332
  virtualCommitmentPercent: committedMemoryBytes == null || commitLimitBytes == null ? unavailable("Virtual commitment cannot be derived.") : available(percent(committedMemoryBytes, commitLimitBytes)),
9333
+ inotifyWatchesUsed: inotify == null ? unavailable("inotify usage could not be scanned from /proc.") : available(inotify.watchesUsed),
9334
+ inotifyWatchesMax: inotify?.watchesMax == null ? unavailable("fs.inotify.max_user_watches is unavailable.") : available(inotify.watchesMax),
9335
+ inotifyWatchesUsedPercent: inotify == null || inotify.watchesMax == null ? unavailable("inotify watch utilization cannot be derived.") : available(percent(inotify.watchesUsed, inotify.watchesMax)),
8410
9336
  counters: {
8411
9337
  cpu: cpuCounters,
8412
9338
  swap: swapCounters
@@ -8417,6 +9343,7 @@ function createLinuxHostHealthCollector(adapters = defaultAdapters) {
8417
9343
  }
8418
9344
  var execFileAsync$1, KB, LINUX_MEMORY_PRESSURE_DEFAULTS, defaultAdapters;
8419
9345
  var init_linux = __esmMin((() => {
9346
+ init_inotify();
8420
9347
  init_types();
8421
9348
  execFileAsync$1 = promisify(execFile);
8422
9349
  KB = 1024;
@@ -8437,7 +9364,8 @@ var init_linux = __esmMin((() => {
8437
9364
  if (!Number.isFinite(value) || value <= 0) throw new Error("getconf returned an invalid page size");
8438
9365
  return value;
8439
9366
  },
8440
- now: () => Date.now()
9367
+ now: () => Date.now(),
9368
+ sampleInotify: () => sampleInotify()
8441
9369
  };
8442
9370
  }));
8443
9371
  //#endregion
@@ -8492,6 +9420,9 @@ function createUnsupportedCollector(platform = "unsupported") {
8492
9420
  committedMemoryBytes: signal(),
8493
9421
  commitLimitBytes: signal(),
8494
9422
  virtualCommitmentPercent: signal(),
9423
+ inotifyWatchesUsed: signal(),
9424
+ inotifyWatchesMax: signal(),
9425
+ inotifyWatchesUsedPercent: signal(),
8495
9426
  counters: {
8496
9427
  cpu: null,
8497
9428
  swap: null
@@ -8644,7 +9575,7 @@ var init_runtime_census = __esmMin((() => {
8644
9575
  ]);
8645
9576
  runtimeCensusService = createRuntimeCensusService({
8646
9577
  listPanes: async () => {
8647
- const { listAllPaneRecords } = await import("./tmux-DoThH6aj.js");
9578
+ const { listAllPaneRecords } = await import("./tmux-DQ6jB76i.js");
8648
9579
  return Effect.runPromise(listAllPaneRecords());
8649
9580
  },
8650
9581
  readProcesses: readRuntimeProcessTable
@@ -8798,6 +9729,6 @@ var init_queries = __esmMin((() => {
8798
9729
  });
8799
9730
  }));
8800
9731
  //#endregion
8801
- export { appendActivity as $, recordAgentFailure as $n, OHMYPI_AGENT_READY_TIMEOUT_SECONDS as $t, spawnTierSupervisor as A, writeChannelsBridgeMcpConfig as An, init_codex_auth as Ar, deliverAgentPermissionDecision as At, detectCrashedAgents as B, getAgentDir as Bn, assertWorkspaceStackHealthyForSpawn as Bt, replayCrashedStandingAgent as C, validateProviderHealth as Cn, getAgentRuntimeStateSync as Cr, tryReserveAdvancingSlot as Ct, init_tier_supervisor as D, decideChannelsForWorkAgent as Dn, init_agent_runtime as Dr, init_memory_verdict_cache as Dt, deliverCommitForReview as E, buildDefaultResumeContinueMessage as En, getAgentRuntimeSnapshot as Er, getCachedMemoryVerdict as Et, init_tier_escalation as F, clearAgentPausedSync as Fn, init_transcript_landing as Ft, resumeAgent as G, init_agent_state as Gn, transitionIssueToInProgress as Gt, restartAgent as H, getAgentState as Hn, defaultRunWorkspace as Ht, init_slot_reconcile as I, clearAgentTroubled as In, probeTranscriptSince as It, isContextOverflowTail as J, isRole as Jn, providerDefaultHarnessSync as Jt, init_context_overflow as K, isAgentPaused as Kn, transitionIssueToInReview as Kt, listSlotAssignments as L, clearAgentTroubledSync as Ln, BRIDGE_TOKEN_HEADER as Lt, broadcastCommit as M, SESSION_EXITED_BEFORE_KICKOFF as Mn, init_ohmypi_parser as Mr, deliverResumeMessageWithTranscriptConfirmation as Mt, init_tier_feed as N, __testInternals as Nn, parseOhmypiSessionCostResultSync as Nr, setAgentDeliveryMethod as Nt, loadPrdDraft as O, decideSupervisorForWorkAgent as On, applyCodexAuthBurnFlag as Or, setCachedMemoryVerdict as Ot, decideEscalation as P, clearAgentPaused as Pn, captureTranscriptUserRecordSnapshot as Pt, operatorInterventionEvent as Q, markAgentTroubled as Qn, resolveTier as Qt, reconcileSlotState as R, clearYieldForResumeSync as Rn, init_bridge_token as Rt, contextWindowForModel as S, init_provider_health as Sn, getAgentRuntimeState as Sr, resetPatrolDispatchBudget as St, shouldReplayCompactAtTierRunBoundary as T, init_openai_auth as Tn, saveAgentRuntimeState as Tr, workResumeSlotsAvailable as Tt, buildCompactRecoverySeed as U, getAgentStateFilePath as Un, init_spawn_prep as Ut, recoverAgent as V, getAgentResumeGateBlockReason as Vn, buildAgentLaunchConfig as Vt, init_resume as W, getAgentStateSync as Wn, retrieveSpawnTimeMemoryContext as Wt, messageAgent as X, markAgentRunningState as Xn, resolveStaffing as Xt, init_messaging as Y, markAgentRunning as Yn, resolveImplicitStaffing as Yt, init_operator_interventions as Z, markAgentStoppedState as Zn, init_resolve_tier as Zt, init_linux as _, buildSpawnEnvForModel as _n, isQualifiedAgentId as _r, emergencyBrake as _t, listRunningAgentsSync as a, getRoleRuntimeBaseCommand as an, setAgentPaused as ar, saveSessionId as at, init_agents as b, getProviderExportsForModel as bn, waitForAgentIdle as br, releaseAdvancingSlot as bt, getRuntimeCensus as c, roleAgentDefinitionPath as cn, wipeAgentStateDirs as cr, init_spawn as ct, panePidsForSession as d, piFifoPaths as dn, readAgentHarnessModelRecordSync as dr, init_termination as dt, describeOhmypiSpawnFailure as en, recordAgentFailureSync as er, getActivity as et, refreshRuntimeCensus as f, init_ohmypi_fifo as fn, init_pty_token as fr, stopAgent as ft, LINUX_MEMORY_PRESSURE_DEFAULTS as g, buildCavemanExports as gn, clearReadySignal as gr, describeRunningAgents as gt, init_collector as h, init_claude_auth as hn, resolvePtySupervisorScriptPath as hr, countRunningSwarmSlotsForIssue as ht, listRunningAgents as i, getProviderAuthMode as in, saveAgentStateSync as ir, init_activity as it, supervisorAgentId as j, GOVERNOR_SLOT_PAUSE_REASON_PREFIX as jn, paneShowsCodexAuthBurn as jr, deliverInitialPromptWithRetry as jt, shouldSupervise as k, dismissDevChannelsDialog as kn, checkCodexAuthStatus as kr, deliverAgentMessage as kt, getRuntimeCensusSnapshot as l, waitForPromptReady as ln, writeAgentStateJsonSync as lr, spawnAgent as lt, createHostHealthCollector as m, getClaudeAuthStatus as mn, init_pty_supervisor_locate as mr, countRunningAgents as mt, init_queries as n, getCodexLauncherFields as nn, resetAgentFailureCount as nr, getLatestSessionIdSync as nt, warnOnBareNumericIssueIds as o, init_runtime_command as on, setAgentPausedSync as or, createOhmypiRuntimeSync as ot, runtimeCensusHasHarnessProcess as p, ohmypiFifoPaths as pn, writePtyToken as pr, stopAgentSync as pt, isContextOverflowError as q, isAgentTroubled as qn, init_staffing as qt, listAgentStates as r, getOhmypiLauncherFields as rn, saveAgentState as rr, getSessionId as rt, descendantPidsForSession as s, injectPiConversationMemory as sn, setAgentYieldedSync as sr, init_ohmypi as st, dropLegacyAgentStatesMissingRoleAsync as t, getAgentRuntimeBaseCommand as tn, recordStartupSessionExit as tr, getLatestSessionId as tt, init_runtime_census as u, init_pi_fifo as un, init_agent_record_sync as ur, spawnRun as ut, DARWIN_MEMORY_PRESSURE_DEFAULTS as v, determineModel as vn, normalizeAgentId as vr, getConcurrencyLimits as vt, replayStandingAgent as w, getOpenAIAuthStatus as wn, init_runtime_state as wr, tryReserveSwarmSlot as wt, compactAtTierRunBoundary as x, getProviderTmuxFlags as xn, waitForReadySignal as xr, releaseSwarmSlot as xt, init_darwin as y, getProviderEnvForModel as yn, resolveAgentTargetSync as yr, init_concurrency as yt, autoRecoverAgents as z, decideResumeGate as zn, writeBridgeTokenSync as zt };
9732
+ export { operatorInterventionEvent as $, getAgentDir as $n, providerDefaultHarnessSync as $t, spawnTierSupervisor as A, getProviderExportsForModel as An, isQualifiedAgentId as Ar, AmbiguousKeyedDeliveryError as At, detectCrashedAgents as B, dismissDevChannelsDialog as Bn, init_agent_runtime as Br, init_transcript_landing as Bt, replayCrashedStandingAgent as C, materializeAcpContextFile as Cn, init_agent_record_sync as Cr, resetPatrolDispatchBudget as Ct, init_tier_supervisor as D, buildSpawnEnvForModel as Dn, init_pty_supervisor_locate as Dr, getCachedMemoryVerdict as Dt, deliverCommitForReview as E, buildCavemanExports as En, writePtyToken as Er, workResumeSlotsAvailable as Et, init_tier_escalation as F, init_openai_auth as Fn, getAgentRuntimeState as Fr, deliverResumeMessageWithTranscriptConfirmation as Ft, resumeAgent as G, SESSION_EXITED_BEFORE_KICKOFF as Gn, init_ohmypi_parser as Gr, assertWorkspaceStackHealthyForSpawn as Gt, restartAgent as H, init_supervisor_channels as Hn, checkCodexAuthStatus as Hr, BRIDGE_TOKEN_HEADER as Ht, init_slot_reconcile as I, buildDefaultResumeContinueMessage as In, getAgentRuntimeStateSync as Ir, init_delivery as It, isContextOverflowTail as J, clearAgentPausedSync as Jn, init_spawn_prep as Jt, init_context_overflow as K, __testInternals as Kn, parseOhmypiSessionCostResultSync as Kr, buildAgentLaunchConfig as Kt, listSlotAssignments as L, buildResumeContinueMessage as Ln, init_runtime_state as Lr, resilientDeliveryMethod as Lt, broadcastCommit as M, init_provider_health as Mn, resolveAgentTargetSync as Mr, deliverAgentMessage as Mt, init_tier_feed as N, validateProviderHealth as Nn, waitForAgentIdle as Nr, deliverAgentPermissionDecision as Nt, loadPrdDraft as O, determineModel as On, resolvePtySupervisorScriptPath as Or, init_memory_verdict_cache as Ot, decideEscalation as P, getOpenAIAuthStatus as Pn, waitForReadySignal as Pr, deliverInitialPromptWithRetry as Pt, init_operator_interventions as Q, decideResumeGate as Qn, init_staffing as Qt, reconcileSlotState as R, decideChannelsForWorkAgent as Rn, saveAgentRuntimeState as Rr, setAgentDeliveryMethod as Rt, contextWindowForModel as S, init_context as Sn, writeAgentStateJsonSync as Sr, releaseSwarmSlot as St, shouldReplayCompactAtTierRunBoundary as T, init_claude_auth as Tn, init_pty_token as Tr, tryReserveSwarmSlot as Tt, buildCompactRecoverySeed as U, writeChannelsBridgeMcpConfig as Un, init_codex_auth as Ur, init_bridge_token as Ut, recoverAgent as V, hasCompletionMarkerForAgent as Vn, applyCodexAuthBurnFlag as Vr, probeTranscriptSince as Vt, init_resume as W, GOVERNOR_SLOT_PAUSE_REASON_PREFIX as Wn, paneShowsCodexAuthBurn as Wr, writeBridgeTokenSync as Wt, messageAgent as X, clearAgentTroubledSync as Xn, transitionIssueToInProgress as Xt, init_messaging as Y, clearAgentTroubled as Yn, retrieveSpawnTimeMemoryContext as Yt, messageAgentWithOutcome as Z, clearYieldForResumeSync as Zn, transitionIssueToInReview as Zt, init_linux as _, waitForPromptReady as _n, saveAgentStateSync as _r, describeRunningAgents as _t, listRunningAgentsSync as a, OHMYPI_AGENT_READY_TIMEOUT_SECONDS as an, isAgentPaused as ar, init_activity as at, init_agents as b, init_ohmypi_fifo as bn, setAgentYieldedSync as br, init_concurrency as bt, getRuntimeCensus as c, getAgentRuntimeBaseCommand as cn, markAgentRunning as cr, init_ohmypi as ct, panePidsForSession as d, getProviderAuthMode as dn, markAgentTroubled as dr, spawnRun as dt, resolveImplicitStaffing as en, getAgentResumeGateBlockReason as er, appendActivity as et, refreshRuntimeCensus as f, getRoleRuntimeBaseCommand as fn, recordAgentFailure as fr, init_termination as ft, LINUX_MEMORY_PRESSURE_DEFAULTS as g, waitForAcpHostReady as gn, saveAgentState as gr, countRunningSwarmSlotsForIssue as gt, init_collector as h, roleAgentDefinitionPath as hn, resetAgentFailureCount as hr, countRunningAgents as ht, listRunningAgents as i, resolveTier as in, init_agent_state as ir, getSessionId as it, supervisorAgentId as j, getProviderTmuxFlags as jn, normalizeAgentId as jr, SocketPostStatusError as jt, shouldSupervise as k, getProviderEnvForModel as kn, clearReadySignal as kr, setCachedMemoryVerdict as kt, getRuntimeCensusSnapshot as l, getCodexLauncherFields as ln, markAgentRunningState as lr, init_spawn as lt, createHostHealthCollector as m, injectPiConversationMemory as mn, recordStartupSessionExit as mr, stopAgentSync as mt, init_queries as n, resolveStaffing as nn, getAgentStateFilePath as nr, getLatestSessionId as nt, warnOnBareNumericIssueIds as o, describeOhmypiSpawnFailure as on, isAgentTroubled as or, saveSessionId as ot, runtimeCensusHasHarnessProcess as p, init_runtime_command as pn, recordAgentFailureSync as pr, stopAgent as pt, isContextOverflowError as q, clearAgentPaused as qn, defaultRunWorkspace as qt, listAgentStates as r, init_resolve_tier as rn, getAgentStateSync as rr, getLatestSessionIdSync as rt, descendantPidsForSession as s, getAcpLauncherFields as sn, isRole as sr, createOhmypiRuntimeSync as st, dropLegacyAgentStatesMissingRoleAsync as t, resolveIssueWorkModel as tn, getAgentState as tr, getActivity as tt, init_runtime_census as u, getOhmypiLauncherFields as un, markAgentStoppedState as ur, spawnAgent as ut, DARWIN_MEMORY_PRESSURE_DEFAULTS as v, init_pi_fifo as vn, setAgentPaused as vr, emergencyBrake as vt, replayStandingAgent as w, getClaudeAuthStatus as wn, readAgentHarnessModelRecordSync as wr, tryReserveAdvancingSlot as wt, compactAtTierRunBoundary as x, ohmypiFifoPaths as xn, wipeAgentStateDirs as xr, releaseAdvancingSlot as xt, init_darwin as y, piFifoPaths as yn, setAgentPausedSync as yr, getConcurrencyLimits as yt, autoRecoverAgents as z, decideSupervisorForWorkAgent as zn, getAgentRuntimeSnapshot as zr, captureTranscriptUserRecordSnapshot as zt };
8802
9733
 
8803
- //# sourceMappingURL=queries-6d7Cdtm7.js.map
9734
+ //# sourceMappingURL=queries-DHJm7bTd.js.map