@overdeck/desktop 0.47.0 → 0.48.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 (444) hide show
  1. package/drizzle/overdeck/0000_overdeck_init.sql +59 -0
  2. package/package.json +1 -1
  3. package/server/{acceptance-criteria-10Ur5Dne.js → acceptance-criteria-DmtLDbtt.js} +2 -2
  4. package/server/{activity-logger-CyteR4JO.js → activity-logger-Co5qljIj.js} +55 -4
  5. package/server/activity-logger-K7FYGF_z.js +3 -0
  6. package/server/{advancing-selfheal-BNwqxseD.js → advancing-selfheal-8AR68Asf.js} +6 -6
  7. package/server/{agent-gc-C3h9Or3a.js → agent-gc-BmYeT6eH.js} +5 -5
  8. package/server/agent-state-Dq3s84-P.js +3 -0
  9. package/server/{agent-state-service-C63p_ftq.js → agent-state-service-DK1Vay1E.js} +1 -1
  10. package/server/{agent-state-service-Ds6OeFvo.js → agent-state-service-rjnzpHDx.js} +6 -6
  11. package/server/agent-state-source-Ds968-j6.js +21 -0
  12. package/server/{agents-J5mEnekq.js → agents-Dls7tfJH.js} +5 -5
  13. package/server/agents-IPSa5kzn.js +3 -0
  14. package/server/{archive-planning-BwhxeP7C.js → archive-planning-Cq7cyinS.js} +51 -24
  15. package/server/archive-planning-MbkGCBIY.js +2 -0
  16. package/server/{artifact-index-jobs-D1q_vR3V.js → artifact-index-jobs-Dj_8kpTd.js} +3 -3
  17. package/server/{assemble-Bgwqv-Ro.js → assemble-BTCmbcfH.js} +20 -13
  18. package/server/{auto-spawn-consent-CQ9Bi9q6.js → auto-spawn-consent-lXqRJ1Dr.js} +304 -121
  19. package/server/{backlog-auto-trigger-n1lzPgN4.js → backlog-auto-trigger-Dn-amzt6.js} +3 -3
  20. package/server/{behavior-td6-xhQk.js → behavior-DIMQMRzs.js} +2 -2
  21. package/server/{boot-reconciled-stop-events-C7gGe3oB.js → boot-reconciled-stop-events-D6SeUTIr.js} +1 -1
  22. package/server/{bridge-pool-patrol-CYH2OLb5.js → bridge-pool-patrol-BEjt-xF3.js} +2 -2
  23. package/server/{briefing-freshness-DRqZ8lAz.js → briefing-freshness-3PNmL_p3.js} +2 -2
  24. package/server/{build-info-7yiEpl6u.js → build-info-CJg813Hm.js} +3 -3
  25. package/server/{build-info-CpG__c63.js → build-info-CXyeFsXu.js} +1 -1
  26. package/server/{checkpoint-manager-CkKmB0wZ.js → checkpoint-manager-9t7G5c1V.js} +1 -1
  27. package/server/{checkpoint-manager-DBcyNR8w.js → checkpoint-manager-B2G38R3p.js} +3 -3
  28. package/server/checkpoint-worker.js +1 -1
  29. package/server/{checkpoints-Wm963lm8.js → checkpoints-CuBgiXO-.js} +1 -1
  30. package/server/{checkpoints-D95apurL.js → checkpoints-VTZMd4Qm.js} +2 -2
  31. package/server/{claude-hooks-provision-Bjitl9aI.js → claude-hooks-provision-55SyQaPz.js} +2 -2
  32. package/server/{claude-hooks-provision-4RPxNkE8.js → claude-hooks-provision-CEUT-CZd.js} +1 -1
  33. package/server/{claude-permissions-CpbpvUQ2.js → claude-permissions-Cn0dIu2i.js} +2 -2
  34. package/server/{claude-settings-overlay-BzkHYDwR.js → claude-settings-overlay-B19hdzSA.js} +1 -1
  35. package/server/{claude-settings-overlay-_H9Yrzab.js → claude-settings-overlay-Yg_ANh81.js} +2 -2
  36. package/server/{cli-Cte9ZFGn.js → cli-C9S84iTy.js} +79 -22
  37. package/server/cli-M1cwZ__d.js +3 -0
  38. package/server/{cliproxy-C5fMJ7rY.js → cliproxy-CJq3KXU6.js} +2 -2
  39. package/server/{cliproxy-DaAbWMjC.js → cliproxy-DgEZlr7Y.js} +1 -1
  40. package/server/{close-issue-BPh1ARCF.js → close-issue-DPxRddGR.js} +5 -5
  41. package/server/{closed-issue-reaper-DoOZqGFK.js → closed-issue-reaper-C5Zn4GRS.js} +13 -13
  42. package/server/{closed-issue-reaper-DHRfRMrp.js → closed-issue-reaper-D-2B48Ri.js} +1 -1
  43. package/server/{codex-o8FJwzmy.js → codex-B3n_rkwn.js} +1 -1
  44. package/server/{codex-BzGDW_d3.js → codex-CjkD1PJu.js} +6 -6
  45. package/server/{codex-parser-Dt-ycU8L.js → codex-parser-DpB1Il-P.js} +2 -2
  46. package/server/{compaction-continuation-CvXpbZ4w.js → compaction-continuation-DZD9ukSE.js} +3 -3
  47. package/server/{config-CL3Gyvja.js → config-C5saf4Ja.js} +1 -1
  48. package/server/{config-BvLe652W.js → config-DnLJATZk.js} +2 -2
  49. package/server/{config-Bi3u1VK7.js → config-DvM8jtQK.js} +2 -2
  50. package/server/{config-yaml-CxdwhAIA.js → config-yaml-BSCqwmX0.js} +11299 -10972
  51. package/server/{conflict-gate-CX80JYYS.js → conflict-gate-DXa_L28t.js} +1 -1
  52. package/server/{conflict-gate-E4nt7ZeS.js → conflict-gate-WfVqgalf.js} +4 -4
  53. package/server/{context-layers-DAG83UZt.js → context-layers-D7UqH9Ab.js} +2 -2
  54. package/server/{context-layers-C_IIysnm.js → context-layers-Dpz3Vd6d.js} +3 -3
  55. package/server/{control-settings-CiqGxXnc.js → control-settings-DVf6pKyv.js} +4 -4
  56. package/server/{conversation-compaction-BE3CNtHF.js → conversation-compaction-5XuH6OBn.js} +1 -1
  57. package/server/{conversation-compaction-D6-yLtqt.js → conversation-compaction-COrbnX1J.js} +8 -8
  58. package/server/{conversation-service-DBxoYMDl.js → conversation-service-BufdtnZF.js} +169 -10
  59. package/server/{conversation-service-D_TS2b1r.js → conversation-service-DnUyIiLb.js} +1 -1
  60. package/server/{conversations-D0UEdLtk.js → conversations-B4rxz-Wl.js} +17 -10
  61. package/server/{conversations-BKDVpB-3.js → conversations-D1bwxQMy.js} +1 -1
  62. package/server/{cost-DpgYmYqR.js → cost-CpFDrJUS.js} +46 -2
  63. package/server/{cost-DS1s0DbG.js → cost-KLuwKCW9.js} +3 -3
  64. package/server/{cost-sync-tOCCGnEt.js → cost-sync-cesi9dp8.js} +3 -3
  65. package/server/{dag-BtkgLeqY.js → dag-BYiFMqpU.js} +2 -2
  66. package/server/{dangerous-git-ops-CFLykHWt.js → dangerous-git-ops-BKvd3-Hk.js} +1 -1
  67. package/server/dashboard-db-worker.js +7 -7
  68. package/server/{deacon-BIblC-WX.js → deacon-BbsWw8a6.js} +3 -3
  69. package/server/{deacon-pLRLbPvR.js → deacon-HdEh0Esp.js} +863 -214
  70. package/server/deacon-event-client-C93rvOT7.js +237 -0
  71. package/server/deacon-event-client-Ck5Ei7Mn.js +3 -0
  72. package/server/{deacon-nudge-log-B08gF0mh.js → deacon-nudge-log-BND_97Wo.js} +4 -3
  73. package/server/{deacon-pending-lifecycle-B-Io84AP.js → deacon-pending-lifecycle-CD3YsiQK.js} +3 -3
  74. package/server/deacon-swarm-DgWADWd_.js +2 -0
  75. package/server/{deacon-swarm-v5PMun-m.js → deacon-swarm-rqrl4TMs.js} +39 -18
  76. package/server/deacon.js +12 -210
  77. package/server/{dead-end-trip-D8A3msX9.js → dead-end-trip-DSF23CLX.js} +4 -3
  78. package/server/dead-end-trip-zKlS4v6f.js +2 -0
  79. package/server/delivery-CsbQdZkS.js +3 -0
  80. package/server/{deploy-patrol-sYgOxLeb.js → deploy-patrol-kARAkji4.js} +17 -21
  81. package/server/{deploy-queue-VfohaPN_.js → deploy-queue-Bj0HJT1i.js} +2 -2
  82. package/server/{deploy-queue-gHJBycaF.js → deploy-queue-rjTUy1RM.js} +1 -1
  83. package/server/{deploy-window-D4DQb8VP.js → deploy-window-B2IM-9G5.js} +10 -44
  84. package/server/{deploy-window-CFRZ0-kt.js → deploy-window-BNFWnA8D.js} +1 -1
  85. package/server/{dev-supervisor-DiOBDM1c.js → dev-supervisor-B1mZYXz4.js} +2 -2
  86. package/server/{devcontainer-renderer-BUOIlfgD.js → devcontainer-renderer-B-o68Z5B.js} +3 -3
  87. package/server/{dist-C3A8B8wM.js → dist-3W--cGMa.js} +1 -1
  88. package/server/dist-BR0QtwmS.js +3 -0
  89. package/server/{dist-src-C0adpegX.js → dist-src-C-Vk2jNk.js} +1 -1
  90. package/server/{docker-Y3PElJb0.js → docker-DH3jUYg1.js} +1 -1
  91. package/server/{docker-BJzlkqYB.js → docker-meuLKLzV.js} +27 -20
  92. package/server/{dod-DlNtcH6n.js → dod-D7-9dCOD.js} +1 -1
  93. package/server/{driver-CKVGi51s.js → driver-CmsY2RLl.js} +1 -1
  94. package/server/{durable-review-pipeline-DP6bIcOY.js → durable-review-pipeline-CStTgOAf.js} +1 -1
  95. package/server/{durable-review-pipeline-Cibps-Rg.js → durable-review-pipeline-Chq0lzjL.js} +1 -1
  96. package/server/{ensure-devcontainer-DMAbWqtQ.js → ensure-devcontainer-BE3llBWP.js} +1 -1
  97. package/server/{ensure-devcontainer-BAofzBPv.js → ensure-devcontainer-BXrY7C2Z.js} +4 -4
  98. package/server/{esm-shims-BeObUkaw.js → esm-shims-Bzy4ZzNU.js} +1 -1
  99. package/server/event-store-COd2tOx8.js +3 -0
  100. package/server/{event-store-CrHcVC5_.js → event-store-D_AR-Y78.js} +184 -11
  101. package/server/{events-CF8QDbuV.js → events-CCkFWa7X.js} +1 -1
  102. package/server/{events-BNrvchBg.js → events-zjDQozet.js} +3 -3
  103. package/server/{factory-Cmm9Hsho.js → factory-DhavwKVc.js} +5 -5
  104. package/server/{feature-registry-population-B6HpNWRy.js → feature-registry-population-DWGBKyWd.js} +4 -4
  105. package/server/{feature-registry-storage-DJEFx1Pf.js → feature-registry-storage-C5DkXmCM.js} +3 -3
  106. package/server/{features-D5km80UI.js → features-CC47YcCX.js} +2 -2
  107. package/server/{feedback-target-BJ5ZADsu.js → feedback-target-D9Tex35_.js} +1 -1
  108. package/server/{feedback-target-DSxEL6lP.js → feedback-target-DoRCR3L-.js} +18 -7
  109. package/server/{feedback-writer-CoB9Z6aU.js → feedback-writer-CTSuA6lw.js} +1 -1
  110. package/server/{feedback-writer-C27Hak8a.js → feedback-writer-DdsBdtNL.js} +5 -5
  111. package/server/{flywheel-DZZdtiOL.js → flywheel-DHWHzaYK.js} +1 -1
  112. package/server/{flywheel-f662Q-y2.js → flywheel-DJQa9az8.js} +14 -14
  113. package/server/{flywheel-BHx8XuMr.js → flywheel-TacAI9MA.js} +21 -17
  114. package/server/{flywheel-merge-order-Dil0LmdN.js → flywheel-merge-order-D2foPh88.js} +1 -1
  115. package/server/{flywheel-merge-order-D_xLMbJU.js → flywheel-merge-order-DRtex2Dt.js} +7 -7
  116. package/server/forge-CdlCG9aS.js +3 -0
  117. package/server/{forge-BaKGCya6.js → forge-c8LeC-tw.js} +2 -2
  118. package/server/{from-B3tZbB55.js → from-BogSwvr2.js} +1 -1
  119. package/server/{fs-lock-Bre3sGoz.js → fs-lock-D_GeJtXl.js} +3 -3
  120. package/server/{fts-operations-B9jG8wa3.js → fts-operations-DP9R-8Q3.js} +3 -3
  121. package/server/{git-utils-Xg4PFN45.js → git-utils-C31x1lpE.js} +1 -1
  122. package/server/{git-utils-CsvYfJU3.js → git-utils-xQ74FoSn.js} +5 -4
  123. package/server/{github-app-Bmg4R9mv.js → github-app-CpQSDlv8.js} +1 -1
  124. package/server/{github-app-CmNk0zLU.js → github-app-D2QuvZ3j.js} +3 -3
  125. package/server/{github-client-qazkPrg0.js → github-client-D9YvJX5D.js} +3 -3
  126. package/server/{github-client-B6KM9_wA.js → github-client-Tpi3PmKX.js} +1 -1
  127. package/server/{github-pr-lookup-DAcVeRLK.js → github-pr-lookup-DvBMv-IW.js} +2 -2
  128. package/server/{harness-binary-BSpiXaLw.js → harness-binary-BHxWf_sX.js} +7 -6
  129. package/server/{harness-resolve-BAJu5MX8.js → harness-resolve-bj9WMABA.js} +4 -4
  130. package/server/{health-events-BwX32k8d.js → health-events-bCDPn59Z.js} +2 -2
  131. package/server/{health-events-2Z6Wa9SM.js → health-events-qo7Ss34U.js} +1 -1
  132. package/server/{hooks-DbtbimEf.js → hooks-Dyxtg5fk.js} +2 -2
  133. package/server/{hooks-D1g1jKLI.js → hooks-X2XHBB2b.js} +1 -1
  134. package/server/{hume-DXNiu6nQ.js → hume-DrZEGpqc.js} +2 -2
  135. package/server/hume-YPsy4UA8.js +3 -0
  136. package/server/{idle-stack-reaper-Cy-dQzW4.js → idle-stack-reaper-CJ1ygW0p.js} +37 -7
  137. package/server/{idle-stack-reaper-CRA1e0jr.js → idle-stack-reaper-uJGOb-vu.js} +1 -1
  138. package/server/{in-flight-guard-D-sSkADM.js → in-flight-guard-CG2Eo-rr.js} +1 -1
  139. package/server/{infra-BDQDRopn.js → infra-CTrmVqc_.js} +111 -6
  140. package/server/{injection-Bl8d_jHZ.js → injection-BisQ0lpX.js} +1 -1
  141. package/server/{injection-6AGnXxlj.js → injection-C9sxqbc2.js} +73 -193
  142. package/server/{inspect-agent-nXdIptyh.js → inspect-agent-BoSO51YC.js} +12 -12
  143. package/server/inspect-agent-BykeOH4a.js +2 -0
  144. package/server/{internal-token-DzK385vD.js → internal-token-AvXePaQT.js} +2 -2
  145. package/server/{internal-token-Ias7N8Kg.js → internal-token-Djkj-yqK.js} +1 -1
  146. package/server/{io-B00PBNku.js → io-mxOWMZ7I.js} +6 -6
  147. package/server/{issue-closed-BehTG1be.js → issue-closed-Bj_bCv_0.js} +7 -7
  148. package/server/{issue-lifecycle-BqSuQvbn.js → issue-lifecycle-A5YIpDZE.js} +1 -1
  149. package/server/{issue-lifecycle-Birk-ifu.js → issue-lifecycle-BXUqaHzF.js} +32 -28
  150. package/server/{issue-service-singleton-C6ZduvuY.js → issue-service-singleton-BPNEXczv.js} +11 -11
  151. package/server/{issue-service-singleton-B2wXiIlw.js → issue-service-singleton-CcaHjKPR.js} +1 -1
  152. package/server/{issues-DQ5-LatB.js → issues-AX-YBeAQ.js} +2 -2
  153. package/server/{jsonl-parser-BDpnGFCl.js → jsonl-parser-CgYWQ20q.js} +7 -3
  154. package/server/kimi-code-BYbme0aV.js +579 -0
  155. package/server/kimi-code-D_Ppt82c.js +3 -0
  156. package/server/kimi-parser-B-JBg3Pv.js +147 -0
  157. package/server/{label-cleanup-Dwnky8FG.js → label-cleanup-sXUlgdM0.js} +3 -3
  158. package/server/{lifecycle-B4Xdb4cY.js → lifecycle-D2X3al0D.js} +2 -2
  159. package/server/{lifecycle-B3s4sM1G.js → lifecycle-DjlljAZ1.js} +6 -6
  160. package/server/{lifecycle-io-CzTHEooc.js → lifecycle-io-C5nVk55o.js} +1 -1
  161. package/server/{lifecycle-io-DCo6s6ks.js → lifecycle-io-NPm1YtIG.js} +5 -5
  162. package/server/{linear-client-CnbtHiic.js → linear-client--luYwCZg.js} +1 -1
  163. package/server/{linear-client-9uq7fhiV.js → linear-client-B8pLegW1.js} +3 -3
  164. package/server/{linear-mcp-auth-BxUOzswy.js → linear-mcp-auth-BQVWV0I3.js} +6 -6
  165. package/server/{linear-mcp-auth-D46fBCLf.js → linear-mcp-auth-Dx81Zl4G.js} +1 -1
  166. package/server/memory-fts-worker.js +1 -1
  167. package/server/{merge-DiW9RdSB.js → merge-Bx5Bh9pi.js} +3 -3
  168. package/server/{merge-sr8Nrnmi.js → merge-Dqmh_zja.js} +1 -1
  169. package/server/{merge-agent-BLUgRsz3.js → merge-agent-DP9AUY29.js} +33 -33
  170. package/server/{merge-agent-DQTXZk8z.js → merge-agent-DWd0KfiS.js} +1 -1
  171. package/server/{merge-batch-Cp_j9BGk.js → merge-batch-BdmvTEAC.js} +1 -1
  172. package/server/{merge-completeness-BLbB5-6n.js → merge-completeness-BfRwFjRx.js} +1 -1
  173. package/server/{merge-completeness-B46KqhtY.js → merge-completeness-C1FevcDT.js} +4 -4
  174. package/server/merge-ops-B98tKc1e.js +2 -0
  175. package/server/merge-rebase-BLykMwPO.js +2 -0
  176. package/server/{merge-rebase-DIkBjgwq.js → merge-rebase-BX1xKsrE.js} +2 -2
  177. package/server/{merge-set-CBgHfwM0.js → merge-set-DsLjjLEV.js} +4 -4
  178. package/server/{merge-set-DeUxFsC3.js → merge-set-H6epHOsw.js} +1 -1
  179. package/server/{merge-sync-kr4vqyjM.js → merge-sync-BEdfsQV4.js} +2 -2
  180. package/server/{merge-sync-CpGmk6Ch.js → merge-sync-BebcWWGA.js} +1 -1
  181. package/server/{merge-train-Dmrcus12.js → merge-train-D1I0lNOT.js} +4 -4
  182. package/server/{merge-train-deps-D_uGX91G.js → merge-train-deps-D_-C0Pk2.js} +4 -4
  183. package/server/{merge-verification-NvaAd8CZ.js → merge-verification-DN1Ov9bU.js} +6 -6
  184. package/server/{merged-docker-cleanup-worker-Y1R06TEl.js → merged-docker-cleanup-worker-CfXSr2pA.js} +4 -4
  185. package/server/{merged-docker-cleanup-worker-DH_hrGPI.js → merged-docker-cleanup-worker-ybsPyHjB.js} +1 -1
  186. package/server/{multipart-parser-R-oC8dQg.js → multipart-parser-CL5QG8iv.js} +2 -2
  187. package/server/{no-resume-mode-BgD0JUmM.js → no-resume-mode-DUR7Hi98.js} +1 -1
  188. package/server/node_modules/.package-lock.json +7 -7
  189. package/server/node_modules/brace-expansion/README.md +23 -1
  190. package/server/node_modules/brace-expansion/index.js +206 -85
  191. package/server/node_modules/brace-expansion/package.json +1 -1
  192. package/server/node_modules/msgpackr/dist/index-no-eval.cjs +34 -28
  193. package/server/node_modules/msgpackr/dist/index-no-eval.cjs.map +1 -1
  194. package/server/node_modules/msgpackr/dist/index-no-eval.min.js +1 -1
  195. package/server/node_modules/msgpackr/dist/index-no-eval.min.js.map +1 -1
  196. package/server/node_modules/msgpackr/dist/index.js +34 -28
  197. package/server/node_modules/msgpackr/dist/index.js.map +1 -1
  198. package/server/node_modules/msgpackr/dist/index.min.js +1 -1
  199. package/server/node_modules/msgpackr/dist/index.min.js.map +1 -1
  200. package/server/node_modules/msgpackr/dist/node.cjs +36 -29
  201. package/server/node_modules/msgpackr/dist/node.cjs.map +1 -1
  202. package/server/node_modules/msgpackr/dist/test.js +63 -32
  203. package/server/node_modules/msgpackr/dist/test.js.map +1 -1
  204. package/server/node_modules/msgpackr/dist/unpack-no-eval.cjs +34 -28
  205. package/server/node_modules/msgpackr/dist/unpack-no-eval.cjs.map +1 -1
  206. package/server/node_modules/msgpackr/package.json +1 -1
  207. package/server/node_modules/msgpackr/unpack.js +34 -28
  208. package/server/{orphan-proposed-reconciler-DcgTPPFY.js → orphan-proposed-reconciler-CEW1maPl.js} +1 -1
  209. package/server/{orphan-proposed-reconciler-B6vJHxtX.js → orphan-proposed-reconciler-DfqHZftT.js} +23 -22
  210. package/server/package-lock.json +8 -8
  211. package/server/package.json +1 -1
  212. package/server/{pan-dir-DMzF5wne.js → pan-dir-DhgKfO86.js} +21 -6
  213. package/server/{paths-sJBSb7Ul.js → paths-BUuhi6jM.js} +17 -17
  214. package/server/{pending-lifecycle-claim-DilzGfgk.js → pending-lifecycle-claim-DJlA1rTR.js} +2 -2
  215. package/server/{persistent-logger-H_VjuOu7.js → persistent-logger-s8cbpFNV.js} +2 -2
  216. package/server/{pickup-DWhqzliO.js → pickup-2AxtB3dW.js} +1 -1
  217. package/server/{pipeline-membership-C88VBnhJ.js → pipeline-membership-2_okL5bm.js} +1 -1
  218. package/server/{pipeline-membership-D9SBvItj.js → pipeline-membership-Dqv6_0ig.js} +1 -1
  219. package/server/{pipeline-membership-gather-4eR-7Tqy.js → pipeline-membership-gather-4F1-tXKI.js} +1 -1
  220. package/server/{pipeline-membership-gather-CeVGnNJ2.js → pipeline-membership-gather-CtJ_7aGf.js} +149 -17
  221. package/server/{pipeline-notifier-DT6xLFao.js → pipeline-notifier-CO9rxJgB.js} +1 -1
  222. package/server/{pipeline-notifier-D0ALV6Nw.js → pipeline-notifier-DDfVBJhJ.js} +2 -2
  223. package/server/{post-merge-lifecycle-worker-8HIeS_J6.js → post-merge-lifecycle-worker-DmSOkeNp.js} +3 -3
  224. package/server/{project-pipelines-9SKt2bEc.js → project-pipelines-72WE8GVK.js} +2 -2
  225. package/server/{project-repos-B5pIphKg.js → project-repos-BAqDwtvi.js} +16 -11
  226. package/server/project-repos-Df90Zw7Y.js +3 -0
  227. package/server/projects-WqMWCdpa.js +3 -0
  228. package/server/{prompts-CgzMBvQF.js → prompts-XkL10m8M.js} +2 -2
  229. package/server/{providers-BJQSnAAp.js → providers-ClGPGkQ8.js} +15 -12
  230. package/server/providers-DFUOed8u.js +3 -0
  231. package/server/public/assets/{chunk-BO2N2NFS-D_pGACYN.js → chunk-BO2N2NFS-CeQUdPxr.js} +4 -4
  232. package/server/public/assets/{diagram-OG6HWLK6-BO6fe3hH.js → diagram-OG6HWLK6-B7rgk4yT.js} +1 -1
  233. package/server/public/assets/{dist-5zingMiA.js → dist-2RPazfXY.js} +3 -3
  234. package/server/public/assets/{dist-CVxhbI2E.js → dist-B9NInrVZ.js} +1 -1
  235. package/server/public/assets/{ganttDiagram-6RSMTGT7-Bgj4A7kp.js → ganttDiagram-6RSMTGT7-Bxp0gV14.js} +1 -1
  236. package/server/public/assets/{highlighted-body-OFNGDK62-DNPK7_cm.js → highlighted-body-OFNGDK62-CzoRTVlC.js} +1 -1
  237. package/server/public/assets/index-Cml-kHo6.css +1 -0
  238. package/server/public/assets/{index-DEpY-D1O.js → index-CvN8cEgs.js} +216 -215
  239. package/server/public/assets/{linear-BB0jQT16.js → linear-CFEEl3ND.js} +1 -1
  240. package/server/public/assets/mermaid-GHXKKRXX-CpV7nCBM.js +1 -0
  241. package/server/public/assets/{pieDiagram-4H26LBE5-DeGIzzpZ.js → pieDiagram-4H26LBE5-BeR8R0cr.js} +1 -1
  242. package/server/public/assets/{prod-XBLvikex.js → prod-CYjzjCrn.js} +4 -4
  243. package/server/public/assets/{quadrantDiagram-W4KKPZXB-BV9SLeWz.js → quadrantDiagram-W4KKPZXB-BpcTkFuW.js} +1 -1
  244. package/server/public/assets/{sankeyDiagram-5OEKKPKP-Dwja0gj8.js → sankeyDiagram-5OEKKPKP-Bx2ETEV5.js} +1 -1
  245. package/server/public/assets/{xychartDiagram-2RQKCTM6-DCB4qvfw.js → xychartDiagram-2RQKCTM6-BKgEAFaj.js} +1 -1
  246. package/server/public/index.html +2 -2
  247. package/server/{pull-requests-7BgLDsIo.js → pull-requests-B-KrUph5.js} +3 -3
  248. package/server/{pull-requests-Dq0y6IxE.js → pull-requests-DK5k92B4.js} +1 -1
  249. package/server/{queries-C-MUZaIy.js → queries-DVpl1vsU.js} +1212 -193
  250. package/server/{rally-CPysR4T_.js → rally-DbE561hD.js} +3 -3
  251. package/server/rally-O_st_X7n.js +3 -0
  252. package/server/{rally-api-8Ptlp2os.js → rally-api-CZLeEd2C.js} +2 -2
  253. package/server/{rally-api-CgosKdKL.js → rally-api-DaHtn5QN.js} +1 -1
  254. package/server/{rally-client-CCX0hADj.js → rally-client-C-MAl8ur.js} +1 -1
  255. package/server/{rally-client-iYMHWQD7.js → rally-client-Ch3zRsBX.js} +5 -5
  256. package/server/{reap-terminal-sessions-Qf-9LVQc.js → reap-terminal-sessions-C1n0ALRb.js} +2 -2
  257. package/server/{reap-terminal-sessions-4Xg9NGA8.js → reap-terminal-sessions-DegFS2p1.js} +2 -2
  258. package/server/{rebuild-stack-CMdgaylx.js → rebuild-stack-C9Li44A3.js} +20 -10
  259. package/server/{rebuild-stack-DqcOVmJO.js → rebuild-stack-qC0jCNm6.js} +2 -2
  260. package/server/{reconstruct-cache-CMZJ_Vjq.js → reconstruct-cache-BHyiAg02.js} +7 -7
  261. package/server/record-aVzu-LGm.js +3 -0
  262. package/server/record-update-CZh46a2f.js +617 -0
  263. package/server/{record-update-DhI7eySG.js → record-update-DtdJK2Iw.js} +1 -1
  264. package/server/recovery-trip-CSNWSLDn.js +77 -0
  265. package/server/recovery-trip-_16hFKv4.js +3 -0
  266. package/server/{release-engine-B2X9AfFC.js → release-engine-Be5MX5GP.js} +5 -5
  267. package/server/{release-set-G4XKyQ8K.js → release-set-DJv_O6PS.js} +3 -3
  268. package/server/{remote-BXarMvqf.js → remote-BMM3uH2J.js} +3 -3
  269. package/server/{remote-CUhyqjXk.js → remote-C0xVTHA5.js} +3 -3
  270. package/server/{remote-agents-CLZB3Coc.js → remote-agents-BIIoc5pD.js} +1 -1
  271. package/server/{remote-agents-Bba-MgSA.js → remote-agents-EUiZ26bj.js} +7 -7
  272. package/server/{remote-completion-CwAp79EC.js → remote-completion-BS4tJUn8.js} +13 -13
  273. package/server/resolver-BvHd6RE4.js +163 -0
  274. package/server/resume-9thEqAQR.js +3 -0
  275. package/server/{review-agent--pOptAEV.js → review-agent-BHGaBoBu.js} +29 -29
  276. package/server/{review-agent-BTCNkq2h.js → review-agent-CD3RQ-tc.js} +1 -1
  277. package/server/{review-artifacts-BNmw8dWE.js → review-artifacts-DyhajWso.js} +6 -6
  278. package/server/{review-context-DFxYOOJW.js → review-context-B-dlsPnx.js} +9 -9
  279. package/server/{review-convoy-liveness-BgU_1jJf.js → review-convoy-liveness-D7M-s_nS.js} +2 -2
  280. package/server/{review-status-Dma9SFaN.js → review-status-B6wYcOtP.js} +1 -1
  281. package/server/{review-status-CGvlA4o_.js → review-status-CKLk5aZ-.js} +308 -58
  282. package/server/{review-status-emit-DURrmGYX.js → review-status-emit-CJ7UmEVU.js} +3 -3
  283. package/server/{review-status-enrichment-8NiNXi5W.js → review-status-enrichment-DJRgGX7-.js} +3 -3
  284. package/server/review-status-limits-4EJDCGHO.js +7 -0
  285. package/server/{review-status-source-DIk1JSow.js → review-status-source-7nU3Z2wL.js} +1 -1
  286. package/server/{review-status-source-BLx_1siH.js → review-status-source-BsDYGfyv.js} +1 -1
  287. package/server/{review-status-sync-muT-EBp2.js → review-status-sync-BLssMTEW.js} +1 -1
  288. package/server/{review-status-sync-0GxOqeqF.js → review-status-sync-BxBeHRde.js} +35 -11
  289. package/server/{review-verdict-feedback-xJNdqBnX.js → review-verdict-feedback-5jWuzgpc.js} +90 -16
  290. package/server/{review-verdict-feedback-HwF6ODFy.js → review-verdict-feedback-HRY9P4bN.js} +1 -1
  291. package/server/{rollup-BQaol5TX.js → rollup-BGIrCEkU.js} +79 -44
  292. package/server/rollup-CZB4UL9q.js +3 -0
  293. package/server/{scanner-C-D2cFdX.js → scanner-DydjXPrz.js} +16 -9
  294. package/server/search-DdtIjAiu.js +395 -0
  295. package/server/{sequence-io-Bmf1EZM5.js → sequence-io-Fw-cLyDs.js} +4 -4
  296. package/server/{sequencer-agent-CigMyKh2.js → sequencer-agent-BcpGMt5x.js} +15 -10
  297. package/server/server.js +1258 -438
  298. package/server/{service-CD0DvFvD.js → service-BFFkGsG4.js} +58 -58
  299. package/server/{session-fork-B6cQ5eya.js → session-fork-D0V-3e5P.js} +2 -2
  300. package/server/{session-history-3ON_IJjm.js → session-history-Bta5l9jY.js} +5 -5
  301. package/server/{settings-PilbFZAM.js → settings-Ce8B1daF.js} +2 -2
  302. package/server/{settings-VN0qOh4U.js → settings-E3FnEIUx.js} +3 -3
  303. package/server/settings-eOOJpxi_.js +2 -0
  304. package/server/{shadow-engineering-DXvx77oE.js → shadow-engineering-Mt9nJO4i.js} +3 -3
  305. package/server/{shadow-state-CZBp7pwq.js → shadow-state-Bzj_AZCV.js} +1 -1
  306. package/server/{shadow-state-BBk_zacw.js → shadow-state-DrkhoVSx.js} +2 -2
  307. package/server/{shadow-utils-DdZ05AJS.js → shadow-utils-H1GfqP06.js} +2 -2
  308. package/server/{ship-log-7kJfjUX2.js → ship-log-CFUIo4PR.js} +1 -1
  309. package/server/{smart-compaction-8fA5k5XN.js → smart-compaction-DSTq-Wua.js} +1 -1
  310. package/server/{smart-compaction-ByhL9cRS.js → smart-compaction-Hzp3KCJX.js} +7 -7
  311. package/server/{spawn-planning-session-vLUJoFjy.js → spawn-planning-session-C0uSA2SL.js} +2 -2
  312. package/server/{spawn-planning-session-pcF-YeFE.js → spawn-planning-session-DN4son31.js} +23 -21
  313. package/server/{specialist-completion-B07XjWD2.js → specialist-completion-Cf6tpIh1.js} +1 -1
  314. package/server/{specialist-context-DJ-zFyL3.js → specialist-context-DEUEkjIQ.js} +5 -5
  315. package/server/{specialist-handoff-logger-aKSxbIgD.js → specialist-handoff-logger-D_LmQDj3.js} +2 -2
  316. package/server/{specialist-logs-Dae-n52_.js → specialist-logs-7Ynue0R7.js} +3 -3
  317. package/server/{specialists-KR3pKulN.js → specialists-CQwBEGlD.js} +1 -1
  318. package/server/{specialists-6PWdtWcg.js → specialists-DAjPgYs_.js} +504 -238
  319. package/server/{specialists-DUiExaxb.js → specialists-Hr6iW9fU.js} +18 -18
  320. package/server/{specialists-Bz-wFT7R.js → specialists-MOoeB4A8.js} +1 -1
  321. package/server/specs-Dl88cbKY.js +3 -0
  322. package/server/{src-B948bGVR.js → src-BYdwL_n-.js} +668 -64
  323. package/server/{src-vHy2-oCv.js → src-DQnkPN2i.js} +3 -3
  324. package/server/{src-rac0Mepv.js → src-DhfDV0o4.js} +6 -6
  325. package/server/{stack-health-DqLTiEu4.js → stack-health-D_iKwNRg.js} +107 -16
  326. package/server/stack-health-deVSdDwn.js +3 -0
  327. package/server/{stale-task-claims-Cab_Fo_Z.js → stale-task-claims-BYJGqhLI.js} +5 -5
  328. package/server/{staleness-CGTZyp6V.js → staleness-CopBDKnA.js} +1 -1
  329. package/server/{staleness-C-a5rBxF.js → staleness-D8WeMUHd.js} +1 -1
  330. package/server/{state-home-722Dkx92.js → state-home-DjN8qduI.js} +24 -3
  331. package/server/{state-mapping-CybR81Uf.js → state-mapping-DlM7OYRW.js} +1 -1
  332. package/server/{state-migrate-2u8wIpoL.js → state-migrate-a2p1gtD7.js} +4 -4
  333. package/server/state-mirror-Cv_XgvT5.js +121 -0
  334. package/server/{stuck-remediation-r1TJu68G.js → stuck-remediation-CXJX_kki.js} +1 -1
  335. package/server/{stuck-remediation-CC6q3eqQ.js → stuck-remediation-CbCRSz1v.js} +31 -732
  336. package/server/{substrate-bug-weights-service-CzIyyWFT.js → substrate-bug-weights-service-DxpopNd9.js} +3 -3
  337. package/server/{summary-fork-BqgmgPDt.js → summary-fork-B61fjRJn.js} +2 -2
  338. package/server/{summary-fork-Df2WFijM.js → summary-fork-B9pszUJN.js} +91 -10
  339. package/server/supervisor/{injection-budget-Cg_KIb3o.js → injection-budget-Ar7hgyJq.js} +1 -1
  340. package/server/supervisor/pty-supervisor.js +12 -3
  341. package/server/supervisor/{pty-token-BbjwEUUM.js → pty-token-CXCFU0Z8.js} +1 -1
  342. package/server/{supervisor-BxqSpjcN.js → supervisor-BvnxbuuF.js} +6 -4
  343. package/server/supervisor-C69kpqvd.js +2 -0
  344. package/server/{swarm-readiness-DfFxa9-n.js → swarm-readiness-vTw1kqGa.js} +3 -3
  345. package/server/{system-prerequisites-ICLSkhhZ.js → system-prerequisites-LLzTEqsK.js} +3 -3
  346. package/server/{teardown-workspace-DRdi_CPa.js → teardown-workspace-CqKKVJr1.js} +15 -15
  347. package/server/{test-agent-queue-A_-p-i0I.js → test-agent-queue-CWMq7oyG.js} +8 -7
  348. package/server/{test-verdict-BHgTAwIG.js → test-verdict-NdtgRBuA.js} +1 -1
  349. package/server/{test-verdict-C4i9aqEP.js → test-verdict-diIWE6hz.js} +15 -3
  350. package/server/{tldr-daemon-CvWXBhX1.js → tldr-daemon-B1Jhrtc8.js} +1 -1
  351. package/server/{tldr-daemon-wvsU6bKv.js → tldr-daemon-Bpls1CJB.js} +2 -2
  352. package/server/{tmux-CfDHob9M.js → tmux-CImZaX4q.js} +10 -16
  353. package/server/tmux-Cjpx8L8u.js +4 -0
  354. package/server/{token-DrxwytsZ.js → token-Bgpjo3tE.js} +2 -2
  355. package/server/token-util-BsjFll-k.js +3 -0
  356. package/server/{token-util-B48BlCba.js → token-util-BymbpkJp.js} +1 -1
  357. package/server/{tracker-config-BcPMElRB.js → tracker-config-4DaKVTfc.js} +2 -2
  358. package/server/{tracker-utils-CJ6BHjcD.js → tracker-utils-BDeAXC-q.js} +2 -2
  359. package/server/{traefik-connect-DZ6nMYMj.js → traefik-connect-CC5FyxYj.js} +1 -1
  360. package/server/{tunnel-Bp-dRHZz.js → tunnel-CDWkeceJ.js} +1 -1
  361. package/server/{tunnel-DUbUPElU.js → tunnel-CPf5M-Pc.js} +3 -3
  362. package/server/{typed-errors-DyjseiB6.js → typed-errors-9K7Dq_Vn.js} +1 -1
  363. package/server/{typed-errors-CKeoDdU3.js → typed-errors-DrS5fb5z.js} +1 -1
  364. package/server/{types-Cm5ASJbq.js → types-DzlUKiuf.js} +4 -3
  365. package/server/{types-Di8wdakq.js → types-kI9ik8XO.js} +1 -1
  366. package/server/{uat-promote-verification-CoJuh7XO.js → uat-promote-verification-c_pxoxEc.js} +5 -5
  367. package/server/{uat-train-4Q0k06CQ.js → uat-train-CWGxBdJO.js} +0 -0
  368. package/server/{uat-train-Dewoatps.js → uat-train-CfCYd2ve.js} +1 -1
  369. package/server/{validate-B0C8p66t.js → validate-f3ItVCfm.js} +3 -3
  370. package/server/{validation-hVOwQk8T.js → validation-5G_wQtea.js} +1 -1
  371. package/server/{validation-B_kIRfNe.js → validation-7tSiCM82.js} +4 -4
  372. package/server/{verification-artifact-BxlxTiYK.js → verification-artifact-9h9dH8uX.js} +1 -1
  373. package/server/{verification-artifact-D70AtckY.js → verification-artifact-C_4WJnf6.js} +1 -1
  374. package/server/{verification-runner-Bc3cJvpC.js → verification-runner-BV5F6wrA.js} +1 -1
  375. package/server/{verification-runner-KZTz6u72.js → verification-runner-D58KmBhK.js} +18 -38
  376. package/server/{vtt-parser-CE_i3Bcw.js → vtt-parser-2iT9OHa9.js} +1 -1
  377. package/server/{work-agent-prompt-ByrPAzOy.js → work-agent-prompt-D03s4DD1.js} +9 -9
  378. package/server/{workflows-D0vP1WrK.js → workflows-BMBwLYPV.js} +281 -98
  379. package/server/workflows-BOmWGpIh.js +2 -0
  380. package/server/{workspace-DQkRPLlQ.js → workspace-BgflNCH0.js} +3 -3
  381. package/server/{workspace-COWvdibH.js → workspace-Cn9ywfSW.js} +1 -1
  382. package/server/{workspace-anchor-drift-pwz23TI1.js → workspace-anchor-drift-C8Fy3shi.js} +1 -1
  383. package/server/{workspace-anchor-drift-DXYIAHzr.js → workspace-anchor-drift-CMiNncwq.js} +5 -8
  384. package/server/{workspace-config-BdZM4PvZ.js → workspace-config-aUc2nIz6.js} +1 -1
  385. package/server/{workspace-manager-BPgTrG66.js → workspace-manager-Bem7ZBs9.js} +521 -292
  386. package/server/workspace-manager-C0CpNh3t.js +3 -0
  387. package/server/{workspace-metadata-CdjzAP8x.js → workspace-metadata-C5iSlPRo.js} +1 -1
  388. package/server/{workspace-metadata-DkO_iTLo.js → workspace-metadata-UKmTYmDQ.js} +2 -2
  389. package/server/{workspaces-CRBJikLp.js → workspaces-DqxgwDZ8.js} +143 -113
  390. package/sync-sources/hooks/notification-hook +12 -1
  391. package/sync-sources/hooks/pan-hook-lib.sh +226 -0
  392. package/sync-sources/hooks/session-start-hook +31 -4
  393. package/sync-sources/hooks/work-agent-stop-hook +23 -1
  394. package/sync-sources/skills/pan-memory/SKILL.md +19 -3
  395. package/sync-sources/skills/pan-projects/SKILL.md +9 -0
  396. package/sync-sources/skills/pan-restart/SKILL.md +26 -7
  397. package/sync-sources/skills/pan-workspace/SKILL.md +77 -0
  398. package/server/activity-logger-CMthG6Vd.js +0 -3
  399. package/server/agent-state-CYXJVG72.js +0 -3
  400. package/server/agents-ePFVoZbu.js +0 -3
  401. package/server/archive-planning-B2XplFzT.js +0 -2
  402. package/server/cli-CjOCSnfj.js +0 -3
  403. package/server/deacon-swarm-B1XkIvfr.js +0 -2
  404. package/server/delivery-BX9HR4wQ.js +0 -3
  405. package/server/dist-B3YPQa5A.js +0 -3
  406. package/server/event-store-5UKzh9Jf.js +0 -3
  407. package/server/forge-B5o319qI.js +0 -3
  408. package/server/fts-db-IVc4_M3f.js +0 -146
  409. package/server/hume-VUCNbTgn.js +0 -3
  410. package/server/inspect-agent-CUwVmr2h.js +0 -2
  411. package/server/merge-ops-1abz6O_P.js +0 -2
  412. package/server/merge-rebase-CJJVAJuz.js +0 -2
  413. package/server/node_modules/brace-expansion/.tap/coverage/8b906b8c-e21f-40b5-8c0d-214d8c2682c5.json +0 -757
  414. package/server/node_modules/brace-expansion/.tap/processinfo/8b906b8c-e21f-40b5-8c0d-214d8c2682c5.json +0 -719
  415. package/server/node_modules/brace-expansion/ADVISORY-CVE-2026-14257.md +0 -107
  416. package/server/node_modules/brace-expansion/dist/commonjs/index.d.ts +0 -8
  417. package/server/node_modules/brace-expansion/dist/commonjs/index.d.ts.map +0 -1
  418. package/server/node_modules/brace-expansion/dist/commonjs/index.js +0 -263
  419. package/server/node_modules/brace-expansion/dist/commonjs/index.js.map +0 -1
  420. package/server/node_modules/brace-expansion/dist/commonjs/package.json +0 -3
  421. package/server/node_modules/brace-expansion/dist/esm/index.d.ts +0 -8
  422. package/server/node_modules/brace-expansion/dist/esm/index.d.ts.map +0 -1
  423. package/server/node_modules/brace-expansion/dist/esm/index.js +0 -259
  424. package/server/node_modules/brace-expansion/dist/esm/index.js.map +0 -1
  425. package/server/node_modules/brace-expansion/dist/esm/package.json +0 -3
  426. package/server/project-repos-DPjOdfPa.js +0 -3
  427. package/server/projects-_n3Zui6K.js +0 -3
  428. package/server/providers-BI1mOBQ4.js +0 -3
  429. package/server/public/assets/index-Ddkcz3WT.css +0 -1
  430. package/server/public/assets/mermaid-GHXKKRXX-BzPfaQJ1.js +0 -1
  431. package/server/rally-D_VW4bJv.js +0 -3
  432. package/server/record-BTwWhtBb.js +0 -3
  433. package/server/record-update-DaOKS7Wb.js +0 -277
  434. package/server/recovery-trip-DDH-02ng.js +0 -44
  435. package/server/resume-mOREjlYu.js +0 -3
  436. package/server/rollup-BR4t_wck.js +0 -3
  437. package/server/settings-CVmWiJ-r.js +0 -2
  438. package/server/specs--enInima.js +0 -3
  439. package/server/stack-health-BikqHSjn.js +0 -3
  440. package/server/supervisor-B4anCCSm.js +0 -2
  441. package/server/tmux-Ctk6RV5l.js +0 -3
  442. package/server/token-util-D411CAq9.js +0 -3
  443. package/server/workflows-DtDX08ed.js +0 -2
  444. package/server/workspace-manager-C1F3XsnS.js +0 -3
@@ -1,45 +1,47 @@
1
1
  import { n as __esmMin, o as __toESM } from "./rolldown-runtime-DNCzzKnI.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 getOverdeckHome, di as packageRoot, dt as fmix32, ei as claudeSessionTranscriptExists, et as init_roles, f as loadConfigSync, fi as resolveOhmypiExtensionPath, ft as fnv1a32, gr as init_issue_id, it as getModelCapabilitySync, l as isClaudeCodeChannelsMcpEnabled, li as init_paths, lt as resolveModelIdSync, ot as hasModelCapabilitySync, pi as sessionFilePath, pt as init_percent, q as init_openai_compatible_proxy, st as init_model_capabilities, t as init_config_yaml, ti as encodeClaudeProjectDir, tt as resolveModel, u as isTldrEnabledSync, ui as isDevMode, 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-CxdwhAIA.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-BDQDRopn.js";
5
- import { 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, a as capturePaneSync, c as createSessionSync, i as capturePane, m as exactPaneTarget, ot as init_child_env, rt as BLANKED_PROVIDER_ENV, s as createSession, w as init_tmux, z as sendKeys } from "./tmux-CfDHob9M.js";
6
- import { a as init_event_store, i as initEventStore } from "./event-store-CrHcVC5_.js";
7
- import { o as OHMYPI_BEHAVIOR, s as getHarnessBehavior } from "./src-B948bGVR.js";
8
- import { C as setReviewStatusSync, I as init_pipeline_agent_reader, J as getOverdeckAgentStateSync, L as registerPipelineTelemetryAgentReader, X as listOverdeckAgentStatesSync, Y as init_agent_state_sync, Z as saveOverdeckAgentStateSync, d as getReviewStatusSync, p as init_review_status, y as resetPipelineVerdictsForWorkStartSync } from "./review-status-CGvlA4o_.js";
9
- import { n as logAgentLifecycleSync, t as init_persistent_logger } from "./persistent-logger-H_VjuOu7.js";
10
- import { i as countAgentsByStatus, o as init_agents$1 } from "./agents-J5mEnekq.js";
11
- import { n as ensureSessionContextBriefingFile, r as init_briefing_freshness } from "./briefing-freshness-DRqZ8lAz.js";
12
- import { o as getPricingSync, s as init_cost } from "./cost-DpgYmYqR.js";
13
- import { _ as init_tier_metrics, g as estimateFeedDeliveryTokens, v as recordTierFeedDelivery } from "./cost-sync-tOCCGnEt.js";
14
- import { a as persistCurrentSessionId, c as isAgentStateServiceInProcess, i as logLauncherSessionPinned, n as createFreshSessionIdentity, o as getRuntimeSnapshot, r as init_session_history, s as init_agent_runtime_mirror } from "./session-history-3ON_IJjm.js";
15
- import { t as init_behavior } from "./behavior-td6-xhQk.js";
16
- import { i as ensureInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-DzK385vD.js";
17
- import { i as readReviewStatusMap, n as init_review_status_source, r as isRoleTerminal } from "./review-status-source-DIk1JSow.js";
18
- import { m as readWorkspacePlanSync, o as init_io } from "./io-B00PBNku.js";
19
- 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-C5fMJ7rY.js";
20
- import { L as normalizeHarness, R as reactivateConversationForSpawn, S as getConversationByName, k as init_conversations, y as createConversation } from "./conversations-D0UEdLtk.js";
21
- import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population-B6HpNWRy.js";
22
- import { a as readCavemanVariant, n as init_workspace } from "./workspace-DQkRPLlQ.js";
23
- import { C as init_launcher_generator, D as requireModelOverrideSync, E as normalizeModelOverrideSync, O as shellQuoteModelIdSync, S as generateLauncherScriptSync, T as init_model_validation, _ as init_tmux_dedup, b as isOperatorStartedBy, f as completeKeyedSubmit, i as init_auto_spawn_consent, s as withAutoSpawnConsentClaim, v as sendKeysDedup, x as normalizeFlywheelRunId, y as init_provenance } from "./auto-spawn-consent-CQ9Bi9q6.js";
24
- import { a as init_claude_permissions, r as getClaudePermissionFlagsStringSync } from "./claude-permissions-CpbpvUQ2.js";
25
- 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-Bgwqv-Ro.js";
26
- import { a as extractThreadIdFromRollout, c as initCodexHome, l as init_codex, o as findLatestRollout } from "./codex-BzGDW_d3.js";
27
- import { i as prepareHarnessLaunch, r as init_harness_binary } from "./harness-binary-BSpiXaLw.js";
28
- import { f as init_config, m as loadConfigSync$1 } from "./config-BvLe652W.js";
29
- import { a as getFlywheelActiveRunIdSync, c as init_control_settings } from "./control-settings-CiqGxXnc.js";
30
- import { n as createTrackerFromConfig, r as init_factory, t as createTracker } from "./factory-Cmm9Hsho.js";
31
- import { a as getWorkspaceStackHealth, s as init_stack_health } from "./stack-health-DqLTiEu4.js";
32
- import { i as createActiveSlice, l as init_dag, o as getDispatchableItems, s as groupItemsByWave } from "./dag-BtkgLeqY.js";
33
- import { c as generateFixedPointPromptSync, f as initHookSync, n as checkHookSync, p as init_hooks } from "./hooks-DbtbimEf.js";
34
- import { a as init_git_utils, c as rehydrateHeadAnchor, l as renderWorkspaceGitShowPromise } from "./git-utils-CsvYfJU3.js";
35
- import { n as init_workspace_anchor_drift, t as evaluateWorkspaceAnchorDrift } from "./workspace-anchor-drift-DXYIAHzr.js";
36
- import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-BAJu5MX8.js";
37
- import { a as loadCloisterConfigSync, r as init_config$1 } from "./config-Bi3u1VK7.js";
38
- import { t as init_reap_terminal_sessions } from "./reap-terminal-sessions-Qf-9LVQc.js";
39
- import { c as isStateMigrated, o as init_state_home } from "./state-home-722Dkx92.js";
40
- import { n as provisionClaudeHooks, t as init_claude_hooks_provision } from "./claude-hooks-provision-Bjitl9aI.js";
41
- import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-DCo6s6ks.js";
42
- import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-DfFxa9-n.js";
2
+ import { $t as getIssuePrefix, Ar as FsError, C as TIERED_EXECUTION_DIFFICULTIES, Cr as init_percent, D as resolveTieredExecutionEnabled, Hr as AGENTS_DIR, In as resolveBareNumericIdSync, Kn as clearCredentialFileAuthSync, Mn as extractPrefixSync, Nn as init_issue_id, O as resolveTieredExecutionEnabledForIssue, Or as ClaudeCredentialParseError, Q as readIssueRecordSync, Rn as require_dist, Rr as TmuxError, S as DEFAULT_TIERED_EXECUTION_CONFIG, Sn as resolveProjectFromIssueSync, Sr as fnv1a32, T as init_tier_table, Vr as init_errors, Vt as shouldCommitLegacyWorkspaceArtifacts, Xn as getProviderForModelSync, Yn as getProviderEnvSync, Yt as findProjectByPathSync, Z as readIssueRecordForWorkspaceSync, Zn as init_providers, _i as packageRoot, _r as init_model_capabilities, br as CLIPROXY_GPT56_CONTEXT_WINDOW, cn as init_projects, dr as resolveModel, er as resolveKimiCodeModelAlias, et as resolveProjectForIssue, f as loadConfigSync, gi as isDevMode, gr as hasModelCapabilitySync, hi as init_paths, l as isClaudeCodeChannelsMcpEnabled, mi as getOverdeckHome, mr as getModelCapabilitySync, nn as getProjectSync, nr as ensureOpenAICompatibleProxyRunning, nt as writeAgentHarnessModelSync, oi as claudeSessionTranscriptExists, q as init_record, qn as getBuiltInDefaultHarness, rr as init_openai_compatible_proxy, si as encodeClaudeProjectDir, t as init_config_yaml, tn as getProjectSwarmHotspots, tr as setupCredentialFileAuthSync, u as isTldrEnabledSync, ur as init_roles, vi as resolveOhmypiExtensionPath, xr as fmix32, yi as sessionFilePath, yr as resolveModelIdSync, zt as init_state_read_home } from "./config-yaml-BSCqwmX0.js";
3
+ import { f as init_config, m as loadConfigSync$1 } from "./config-DnLJATZk.js";
4
+ import { a as emitActivityEntrySync, c as init_activity_logger, o as emitActivityTtsSync } from "./activity-logger-Co5qljIj.js";
5
+ import { d as getOverdeckDatabaseSync, f as init_infra } from "./infra-CTrmVqc_.js";
6
+ import { B as sendRawKeystroke, C as init_tmux, D as killSessionSync, E as killSession, H as sessionExistsSync, L as sendEscapeKeyAsync, N as listSessionsSync, R as sendKeys, T as isPaneDead, U as setOption, V as sessionExists, at as init_child_env, i as capturePaneSync, k as listPaneValues, nt as BLANKED_PROVIDER_ENV, o as createSession, p as exactPaneTarget, r as capturePane, s as createSessionSync } from "./tmux-CImZaX4q.js";
7
+ import { a as getWorkspaceForIssue, o as init_resolver } from "./resolver-BvHd6RE4.js";
8
+ import { a as init_event_store, i as initEventStore } from "./event-store-D_AR-Y78.js";
9
+ import { o as OHMYPI_BEHAVIOR, s as getHarnessBehavior } from "./src-BYdwL_n-.js";
10
+ import { $ as listOverdeckAgentStatesSync, C as setReviewStatusSync, I as init_pipeline_agent_reader, L as registerPipelineTelemetryAgentReader, Q as init_agent_state_sync, Z as getOverdeckAgentStateSync, d as getReviewStatusSync, et as saveOverdeckAgentStateSync, p as init_review_status, y as resetPipelineVerdictsForWorkStartSync } from "./review-status-CKLk5aZ-.js";
11
+ import { n as logAgentLifecycleSync, t as init_persistent_logger } from "./persistent-logger-s8cbpFNV.js";
12
+ import { i as countAgentsByStatus, o as init_agents$1 } from "./agents-Dls7tfJH.js";
13
+ import { n as ensureSessionContextBriefingFile, r as init_briefing_freshness } from "./briefing-freshness-3PNmL_p3.js";
14
+ import { o as getPricingSync, s as init_cost } from "./cost-CpFDrJUS.js";
15
+ import { _ as init_tier_metrics, g as estimateFeedDeliveryTokens, v as recordTierFeedDelivery } from "./cost-sync-cesi9dp8.js";
16
+ import { a as persistCurrentSessionId, c as isAgentStateServiceInProcess, i as logLauncherSessionPinned, n as createFreshSessionIdentity, o as getRuntimeSnapshot, r as init_session_history, s as init_agent_runtime_mirror } from "./session-history-Bta5l9jY.js";
17
+ import { t as init_behavior } from "./behavior-DIMQMRzs.js";
18
+ import { a as init_tracker_config, t as getGitHubConfig } from "./tracker-config-4DaKVTfc.js";
19
+ import { i as ensureInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-AvXePaQT.js";
20
+ import { i as readReviewStatusMap, n as init_review_status_source, r as isRoleTerminal } from "./review-status-source-7nU3Z2wL.js";
21
+ import { N as getProjectPanPaths, P as init_paths$1, h as readWorkspacePlanSync, s as init_io } from "./io-mxOWMZ7I.js";
22
+ 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-CJq3KXU6.js";
23
+ import { L as normalizeHarness, R as reactivateConversationForSpawn, S as getConversationByName, k as init_conversations, y as createConversation } from "./conversations-B4rxz-Wl.js";
24
+ import { n as recordFeatureRegistryLifecycle, t as init_feature_registry_population } from "./feature-registry-population-DWGBKyWd.js";
25
+ import { a as readCavemanVariant, n as init_workspace } from "./workspace-BgflNCH0.js";
26
+ import { C as generateLauncherScriptSync, D as normalizeModelOverrideSync, E as init_model_validation, O as requireModelOverrideSync, S as normalizeFlywheelRunId, _ as init_tmux_dedup, b as init_provenance, f as completeKeyedSubmit, i as init_auto_spawn_consent, k as shellQuoteModelIdSync, s as withAutoSpawnConsentClaim, w as init_launcher_generator, x as isOperatorStartedBy, y as sendKeysDedup } from "./auto-spawn-consent-lXqRJ1Dr.js";
27
+ import { a as init_claude_permissions, r as getClaudePermissionFlagsStringSync } from "./claude-permissions-Cn0dIu2i.js";
28
+ 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-BTCmbcfH.js";
29
+ import { a as extractThreadIdFromRollout, c as initCodexHome, l as init_codex, o as findLatestRollout } from "./codex-CjkD1PJu.js";
30
+ import { i as prepareHarnessLaunch, r as init_harness_binary } from "./harness-binary-BHxWf_sX.js";
31
+ import { a as getFlywheelActiveRunIdSync, c as init_control_settings } from "./control-settings-DVf6pKyv.js";
32
+ import { n as createTrackerFromConfig, r as init_factory, t as createTracker } from "./factory-DhavwKVc.js";
33
+ import { c as init_stack_health, o as getWorkspaceStackHealth } from "./stack-health-D_iKwNRg.js";
34
+ import { i as createActiveSlice, l as init_dag, o as getDispatchableItems, s as groupItemsByWave } from "./dag-BYiFMqpU.js";
35
+ import { c as generateFixedPointPromptSync, f as initHookSync, n as checkHookSync, p as init_hooks } from "./hooks-Dyxtg5fk.js";
36
+ import { a as init_git_utils, c as rehydrateHeadAnchor, l as renderWorkspaceGitShowPromise } from "./git-utils-xQ74FoSn.js";
37
+ import { n as init_workspace_anchor_drift, t as evaluateWorkspaceAnchorDrift } from "./workspace-anchor-drift-CMiNncwq.js";
38
+ import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-bj9WMABA.js";
39
+ import { a as loadCloisterConfigSync, r as init_config$1 } from "./config-DvM8jtQK.js";
40
+ import { t as init_reap_terminal_sessions } from "./reap-terminal-sessions-C1n0ALRb.js";
41
+ import { c as isStateMigrated, o as init_state_home } from "./state-home-DjN8qduI.js";
42
+ import { n as provisionClaudeHooks, t as init_claude_hooks_provision } from "./claude-hooks-provision-55SyQaPz.js";
43
+ import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-NPm1YtIG.js";
44
+ import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-vTw1kqGa.js";
43
45
  import { createRequire } from "node:module";
44
46
  import { dirname, join, relative } from "node:path";
45
47
  import { Data, Duration, Effect, FileSystem } from "effect";
@@ -50,14 +52,14 @@ import { cpus as cpus$1, loadavg as loadavg$1, platform as platform$1, totalmem
50
52
  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";
51
53
  import { chmod, mkdir, readFile, readdir, readlink, stat as stat$1, writeFile } from "node:fs/promises";
52
54
  import { createHash, randomUUID } from "crypto";
55
+ 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, unlink as unlink$1, writeFile as writeFile$1 } from "fs/promises";
53
56
  import { ChildProcess } from "effect/unstable/process";
54
- 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";
55
57
  import { platform as platform$2 } from "process";
56
58
  import { exec, execFile } from "node:child_process";
57
59
  import { promisify } from "node:util";
60
+ import { createHash as createHash$1, randomBytes, randomUUID as randomUUID$1 } from "node:crypto";
58
61
  import { exec as exec$1, execSync } from "child_process";
59
62
  import { promisify as promisify$1 } from "util";
60
- import { createHash as createHash$1, randomBytes, randomUUID as randomUUID$1 } from "node:crypto";
61
63
  import { fileURLToPath } from "node:url";
62
64
  import { request } from "node:http";
63
65
  import { ChildProcessSpawner as ChildProcessSpawner$1 } from "effect/unstable/process/ChildProcessSpawner";
@@ -1102,6 +1104,47 @@ var init_identity = __esmMin((() => {
1102
1104
  SINGLETON_AGENT_IDS = new Set(["flywheel-orchestrator", "sequencer-runner"]);
1103
1105
  }));
1104
1106
  //#endregion
1107
+ //#region ../../lib/bundle-imports.ts
1108
+ /**
1109
+ * Resolve a built bundle's bare imports the way Node will at boot.
1110
+ *
1111
+ * Existence is not bootability. A bundle file can sit on disk in perfect shape
1112
+ * while the node_modules it will be loaded against is incomplete, and the only
1113
+ * symptom is `ERR_MODULE_NOT_FOUND` after the process has already replaced the
1114
+ * healthy one (PAN-3172 for the PTY supervisor, PAN-3264 for the dashboard
1115
+ * server). Probing from the bundle's own location turns that into a check a
1116
+ * caller can make *before* it launches or switches over.
1117
+ */
1118
+ /**
1119
+ * Bare package specifiers the bundle imports but cannot resolve from its own
1120
+ * location. Empty means the artifact can start where it sits.
1121
+ *
1122
+ * Only a genuine module-not-found counts. A package that is present but whose
1123
+ * exports refuse the `require` condition still resolves under `import`, so it
1124
+ * must not be reported as missing.
1125
+ */
1126
+ function unresolvedBundleImports(scriptPath) {
1127
+ const source = readFileSync$1(scriptPath, "utf8");
1128
+ const requireFrom = createRequire(scriptPath);
1129
+ const missing = /* @__PURE__ */ new Set();
1130
+ for (const match of source.matchAll(IMPORT_SOURCE_PATTERN)) {
1131
+ const specifier = match[2];
1132
+ if (!specifier || !PACKAGE_SPECIFIER_PATTERN.test(specifier)) continue;
1133
+ try {
1134
+ requireFrom.resolve(specifier);
1135
+ } catch (error) {
1136
+ const code = error.code;
1137
+ if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") missing.add(specifier);
1138
+ }
1139
+ }
1140
+ return [...missing];
1141
+ }
1142
+ var IMPORT_SOURCE_PATTERN, PACKAGE_SPECIFIER_PATTERN;
1143
+ var init_bundle_imports = __esmMin((() => {
1144
+ IMPORT_SOURCE_PATTERN = /\b(?:from|import)\s*\(?\s*(["'])([^"'\n]+)\1/g;
1145
+ PACKAGE_SPECIFIER_PATTERN = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(?:\/[^\s]*)?$/;
1146
+ }));
1147
+ //#endregion
1105
1148
  //#region ../../lib/deploy/active-dashboard-bundle.ts
1106
1149
  function activeDashboardBundleFile() {
1107
1150
  return join$1(getOverdeckHome(), "active-dashboard-bundle.json");
@@ -1170,30 +1213,6 @@ var init_active_dashboard_bundle = __esmMin((() => {
1170
1213
  * Missing (or unresolvable) everywhere is a build/packaging defect and throws —
1171
1214
  * never silently degrade a spawn that the caller expects to be supervised.
1172
1215
  */
1173
- /**
1174
- * Bare package specifiers the built supervisor imports but cannot resolve from
1175
- * its own location. Empty means the artifact can start where it sits.
1176
- *
1177
- * Only a genuine module-not-found counts. A package that is present but whose
1178
- * exports refuse the `require` condition still resolves under `import`, so it
1179
- * must not be reported as missing.
1180
- */
1181
- function unresolvedSupervisorImports(scriptPath) {
1182
- const source = readFileSync$1(scriptPath, "utf8");
1183
- const requireFrom = createRequire(scriptPath);
1184
- const missing = /* @__PURE__ */ new Set();
1185
- for (const match of source.matchAll(IMPORT_SOURCE_PATTERN)) {
1186
- const specifier = match[2];
1187
- if (!specifier || !PACKAGE_SPECIFIER_PATTERN.test(specifier)) continue;
1188
- try {
1189
- requireFrom.resolve(specifier);
1190
- } catch (error) {
1191
- const code = error.code;
1192
- if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") missing.add(specifier);
1193
- }
1194
- }
1195
- return [...missing];
1196
- }
1197
1216
  function resolvePtySupervisorScriptPath() {
1198
1217
  const activeBundle = readActiveDashboardBundleSync();
1199
1218
  const candidates = [
@@ -1268,13 +1287,13 @@ function materializePtySupervisorRuntime(stagedDir, overdeckHome = getOverdeckHo
1268
1287
  }
1269
1288
  return entry;
1270
1289
  }
1271
- var moduleDir, IMPORT_SOURCE_PATTERN, PACKAGE_SPECIFIER_PATTERN;
1290
+ var moduleDir, unresolvedSupervisorImports;
1272
1291
  var init_pty_supervisor_locate = __esmMin((() => {
1292
+ init_bundle_imports();
1273
1293
  init_active_dashboard_bundle();
1274
1294
  init_paths();
1275
1295
  moduleDir = dirname(fileURLToPath(import.meta.url));
1276
- IMPORT_SOURCE_PATTERN = /\b(?:from|import)\s*\(?\s*(["'])([^"'\n]+)\1/g;
1277
- PACKAGE_SPECIFIER_PATTERN = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(?:\/[^\s]*)?$/;
1296
+ unresolvedSupervisorImports = unresolvedBundleImports;
1278
1297
  }));
1279
1298
  //#endregion
1280
1299
  //#region ../../lib/pty-token.ts
@@ -2055,7 +2074,6 @@ async function prepareSupervisorForFreshLaunch(agentId, options, state) {
2055
2074
  };
2056
2075
  }
2057
2076
  async function prepareSupervisorForRelaunch(agentId, state, model, harness) {
2058
- if (state.supervisorEnabled !== true) return { useSupervisor: false };
2059
2077
  const relaunchState = {
2060
2078
  ...state,
2061
2079
  model,
@@ -2064,12 +2082,13 @@ async function prepareSupervisorForRelaunch(agentId, state, model, harness) {
2064
2082
  if (!decideSupervisorForWorkAgent(agentId, {
2065
2083
  issueId: state.issueId || agentId.replace(/^agent-/, "").toUpperCase(),
2066
2084
  workspace: state.workspace,
2067
- role: "work",
2085
+ role: state.role,
2068
2086
  model,
2069
2087
  harness,
2070
2088
  allowHost: state.hostOverride
2071
2089
  }, relaunchState).eligible) {
2072
2090
  delete state.supervisorEnabled;
2091
+ await removeStaleSupervisorSocket(agentId);
2073
2092
  return { useSupervisor: false };
2074
2093
  }
2075
2094
  const supervisorScriptPath = resolvePtySupervisorScriptPath();
@@ -2080,6 +2099,14 @@ async function prepareSupervisorForRelaunch(agentId, state, model, harness) {
2080
2099
  supervisorScriptPath
2081
2100
  };
2082
2101
  }
2102
+ /** Remove a dead supervisor socket so delivery probes fail fast to the next tier (PAN-3257). */
2103
+ async function removeStaleSupervisorSocket(agentId) {
2104
+ const socketPath = join$1(getOverdeckHome(), "sockets", `pty-${agentId}.sock`);
2105
+ try {
2106
+ await unlink$1(socketPath);
2107
+ console.log(`[${agentId}] removed stale supervisor socket at ${socketPath}`);
2108
+ } catch {}
2109
+ }
2083
2110
  /**
2084
2111
  * Decide whether to enable Claude Code Channels for a work-agent launch.
2085
2112
  *
@@ -2215,6 +2242,7 @@ var init_supervisor_channels = __esmMin((() => {
2215
2242
  init_config_yaml();
2216
2243
  init_behavior();
2217
2244
  init_pty_supervisor_locate();
2245
+ init_paths();
2218
2246
  init_providers();
2219
2247
  init_pty_token();
2220
2248
  init_resume_contract();
@@ -2533,13 +2561,14 @@ var init_provider_health = __esmMin((() => {
2533
2561
  * Reads the current API key from settings so resumed/recovered agents
2534
2562
  * always use the latest key.
2535
2563
  */
2536
- async function getProviderEnvForModel(model) {
2564
+ async function getProviderEnvForModel(model, harness) {
2537
2565
  const provider = getProviderForModelSync(model);
2538
2566
  if (provider.name === "anthropic") return {};
2567
+ if (provider.name === "kimi" && harness === "kimi-code") return getProviderEnvSync(provider, "", harness);
2539
2568
  const { config } = loadConfigSync();
2540
2569
  if (provider.name === "openrouter") {
2541
2570
  const apiKey = config.apiKeys.openrouter;
2542
- if (apiKey) return getProviderEnvSync(provider, apiKey);
2571
+ if (apiKey) return getProviderEnvSync(provider, apiKey, harness);
2543
2572
  throw new Error(`OpenRouter API key not configured. Add your key in Settings → OpenRouter before using model "${model}".`);
2544
2573
  }
2545
2574
  const apiKey = config.apiKeys[provider.name];
@@ -2557,7 +2586,7 @@ async function getProviderEnvForModel(model) {
2557
2586
  if (apiKey) {
2558
2587
  if (provider.name === "nous") await Effect.runPromise(ensureOpenAICompatibleProxyRunning());
2559
2588
  await Effect.runPromise(validateProviderHealth(model, apiKey));
2560
- return getProviderEnvSync(provider, apiKey);
2589
+ return getProviderEnvSync(provider, apiKey, harness);
2561
2590
  }
2562
2591
  throw new Error(`No API key configured for ${provider.displayName}. Configure it in Settings before using model "${model}".`);
2563
2592
  }
@@ -2576,8 +2605,8 @@ function getClaudeCodeContextPolicyForModel(model) {
2576
2605
  };
2577
2606
  return { autoCompactWindow: contextWindow };
2578
2607
  }
2579
- async function getProviderExportsForModel(model) {
2580
- const envVars = await getProviderEnvForModel(model);
2608
+ async function getProviderExportsForModel(model, harness) {
2609
+ const envVars = await getProviderEnvForModel(model, harness);
2581
2610
  const unsetLines = PROVIDER_ENV_KEYS.map((key) => `unset ${key}`);
2582
2611
  const contextPolicy = getClaudeCodeContextPolicyForModel(model);
2583
2612
  const exportLines = Object.entries(envVars).map(([k, v]) => `export ${k}="${v.replace(/"/g, "\\\"")}"`);
@@ -2685,7 +2714,8 @@ var init_provider_env = __esmMin((() => {
2685
2714
  "MIMO_API_KEY",
2686
2715
  "OPENROUTER_API_KEY",
2687
2716
  "NOUS_API_KEY",
2688
- "DASHSCOPE_API_KEY"
2717
+ "DASHSCOPE_API_KEY",
2718
+ "QUANTUMLLAMA_API_KEY"
2689
2719
  ];
2690
2720
  GPT_56_CODEX_CLIENT_CONTEXT_WINDOW = CLIPROXY_GPT56_CONTEXT_WINDOW;
2691
2721
  GPT_56_MODELS = new Set([
@@ -2874,7 +2904,7 @@ async function createOhmypiFifoPromise(agentId, home) {
2874
2904
  mode: 448
2875
2905
  });
2876
2906
  if (existsSync$1(paths.fifoPath)) unlinkSync$1(paths.fifoPath);
2877
- await execAsync$7(`mkfifo -m 600 ${shellQuote$1(paths.fifoPath)}`);
2907
+ await execAsync$8(`mkfifo -m 600 ${shellQuote$1(paths.fifoPath)}`);
2878
2908
  return paths.fifoPath;
2879
2909
  }
2880
2910
  /**
@@ -2916,10 +2946,10 @@ function shellQuote$1(s) {
2916
2946
  if (/^[A-Za-z0-9._/-]+$/.test(s)) return s;
2917
2947
  return `'${s.replace(/'/g, `'\\''`)}'`;
2918
2948
  }
2919
- var execAsync$7, OhmypiNotReady, OhmypiFifoError, createOhmypiFifo;
2949
+ var execAsync$8, OhmypiNotReady, OhmypiFifoError, createOhmypiFifo;
2920
2950
  var init_ohmypi_fifo = __esmMin((() => {
2921
2951
  init_paths();
2922
- execAsync$7 = promisify(exec);
2952
+ execAsync$8 = promisify(exec);
2923
2953
  OhmypiNotReady = class extends Error {
2924
2954
  code = "OHMYPI_NOT_READY";
2925
2955
  constructor(message) {
@@ -3001,12 +3031,12 @@ async function claudeSystemPromptFiles(workspace, harness) {
3001
3031
  }
3002
3032
  files.push(await ensureSessionContextBriefingFile());
3003
3033
  if (behavior.contextLayerKind === "pi") {
3004
- const { piGlobalContextFile } = await import("./context-layers-DAG83UZt.js");
3034
+ const { piGlobalContextFile } = await import("./context-layers-D7UqH9Ab.js");
3005
3035
  const globalFile = piGlobalContextFile();
3006
3036
  if (existsSync(globalFile)) files.unshift(globalFile);
3007
3037
  }
3008
3038
  if (behavior.contextLayerKind === "codex") {
3009
- const { codexGlobalContextFile } = await import("./context-layers-DAG83UZt.js");
3039
+ const { codexGlobalContextFile } = await import("./context-layers-D7UqH9Ab.js");
3010
3040
  const globalFile = codexGlobalContextFile();
3011
3041
  if (existsSync(globalFile)) files.unshift(globalFile);
3012
3042
  }
@@ -3033,14 +3063,14 @@ async function hasAgentRuntimeInSubtree(rootPid, harness = "claude-code") {
3033
3063
  if (seen.has(pid) || !/^\d+$/.test(pid)) continue;
3034
3064
  seen.add(pid);
3035
3065
  try {
3036
- const { stdout: comm } = await execAsync$5(`ps -p ${pid} -o comm=`);
3066
+ const { stdout: comm } = await execAsync$6(`ps -p ${pid} -o comm=`);
3037
3067
  const name = comm.trim();
3038
3068
  if (expectedProcessNames.has(name)) return true;
3039
3069
  } catch {
3040
3070
  continue;
3041
3071
  }
3042
3072
  try {
3043
- const { stdout: kids } = await execAsync$5(`pgrep -P ${pid}`);
3073
+ const { stdout: kids } = await execAsync$6(`pgrep -P ${pid}`);
3044
3074
  for (const kid of kids.trim().split("\n").filter(Boolean)) queue.push(kid);
3045
3075
  } catch {}
3046
3076
  }
@@ -3074,6 +3104,15 @@ function getAcpLauncherFields(agentId, model, workspace, binaryPath, _role) {
3074
3104
  unsetProviderEnv: true
3075
3105
  };
3076
3106
  }
3107
+ function getKimiCodeLauncherFields(model) {
3108
+ return {
3109
+ harness: "kimi-code",
3110
+ kimiCodeModel: resolveKimiCodeModelAlias(model),
3111
+ kimiCodeYolo: true,
3112
+ model,
3113
+ unsetProviderEnv: true
3114
+ };
3115
+ }
3077
3116
  function getCodexLauncherFields(agentId, model, workspacePath, role) {
3078
3117
  const codexHome = join$1(homedir(), ".overdeck", "agents", agentId, "codex-home");
3079
3118
  const codexConfig = loadConfigSync().config.codex;
@@ -3130,6 +3169,30 @@ function describeOhmypiSpawnFailure(agentId) {
3130
3169
  } catch {}
3131
3170
  return parts.length ? ` [${parts.join(" ")}]` : "";
3132
3171
  }
3172
+ /**
3173
+ * PAN-1837: readinessKind 'kimi-session-signal' has no consumer of its own —
3174
+ * without this branch, waitForPromptReady's default case waits for Claude
3175
+ * Code's ready-signal file, which the native kimi binary never writes, so
3176
+ * every kimi-code spawn times out after 30s (confirmed live: wi14 e2e run).
3177
+ * Ready is defined the same way as the codex TUI branch above: the pane must
3178
+ * show both the input box (a `>` inside its box-drawn border) and the bottom
3179
+ * status line (verified live against installed kimi 0.29.2 — the status line
3180
+ * always renders `context: N% (…)` regardless of --yolo/model).
3181
+ */
3182
+ async function waitForKimiCodeTuiReady(agentId, timeoutSec = 30) {
3183
+ const deadline = Date.now() + timeoutSec * 1e3;
3184
+ while (Date.now() < deadline) {
3185
+ try {
3186
+ if (!await Effect.runPromise(sessionExists(agentId))) return false;
3187
+ const pane = await Effect.runPromise(capturePane(agentId, 80));
3188
+ const hasInputPrompt = /[│|]\s*>\s*[│|]?/.test(pane);
3189
+ const hasStatusLine = /context:\s*\d+%/.test(pane);
3190
+ if (hasInputPrompt && hasStatusLine) return true;
3191
+ } catch {}
3192
+ await new Promise((r) => setTimeout(r, 500));
3193
+ }
3194
+ return false;
3195
+ }
3133
3196
  async function waitForCodexTuiReady(agentId, timeoutSec = 30) {
3134
3197
  const deadline = Date.now() + timeoutSec * 1e3;
3135
3198
  while (Date.now() < deadline) {
@@ -3275,6 +3338,7 @@ async function waitForPromptReady(agentId, harness, timeoutSec = 30) {
3275
3338
  return true;
3276
3339
  }
3277
3340
  if (readinessKind === "codex-tui-prompt") return waitForCodexTuiReady(agentId, timeoutSec);
3341
+ if (readinessKind === "kimi-session-signal") return waitForKimiCodeTuiReady(agentId, timeoutSec);
3278
3342
  return waitForReadySignal(agentId, timeoutSec);
3279
3343
  }
3280
3344
  function inferMemoryProjectId(workspacePath) {
@@ -3301,7 +3365,7 @@ async function injectPiPromptTimeMemory(agentId, prompt) {
3301
3365
  agentRole: agentState.role ?? "work",
3302
3366
  agentHarness: agentState.harness ?? "claude-code"
3303
3367
  };
3304
- const { injectPromptTimeMemory } = await import("./injection-Bl8d_jHZ.js");
3368
+ const { injectPromptTimeMemory } = await import("./injection-BisQ0lpX.js");
3305
3369
  const result = await injectPromptTimeMemory({
3306
3370
  prompt,
3307
3371
  identity,
@@ -3335,7 +3399,7 @@ async function injectPiConversationMemory(opts, prompt) {
3335
3399
  agentRole: "work",
3336
3400
  agentHarness: "ohmypi"
3337
3401
  };
3338
- const { injectPromptTimeMemory } = await import("./injection-Bl8d_jHZ.js");
3402
+ const { injectPromptTimeMemory } = await import("./injection-BisQ0lpX.js");
3339
3403
  const result = await injectPromptTimeMemory({
3340
3404
  prompt,
3341
3405
  identity,
@@ -3397,6 +3461,7 @@ async function getAgentRuntimeBaseCommand(model, agentName, agentDefinition, har
3397
3461
  if (behavior.launchCommandKind === "ohmypi-rpc") return `omp --mode rpc --model ${quotedModel}`;
3398
3462
  if (behavior.launchCommandKind === "codex-work-tui") return `codex`;
3399
3463
  if (behavior.launchCommandKind === "acp-host") return "acp-host";
3464
+ if (behavior.launchCommandKind === "kimi-code-tui") return "kimi-code";
3400
3465
  if (process.env.OVERDECK_TEST_HARNESS_COMMAND) return process.env.OVERDECK_TEST_HARNESS_COMMAND;
3401
3466
  const provider = getProviderForModelSync(validatedModel);
3402
3467
  const nameFlag = agentName ? ` --name ${agentName}` : "";
@@ -3495,6 +3560,7 @@ async function getRoleRuntimeBaseCommand(model, agentName, role, harness = "clau
3495
3560
  }
3496
3561
  if (behavior.launchCommandKind === "codex-work-tui") return `codex`;
3497
3562
  if (behavior.launchCommandKind === "acp-host") return "acp-host";
3563
+ if (behavior.launchCommandKind === "kimi-code-tui") return "kimi-code";
3498
3564
  if (process.env.OVERDECK_TEST_HARNESS_COMMAND) return process.env.OVERDECK_TEST_HARNESS_COMMAND;
3499
3565
  const provider = getProviderForModelSync(validatedModel);
3500
3566
  const requestedDefinitionPath = roleAgentDefinitionPath(role, subRole);
@@ -3511,7 +3577,7 @@ async function getRoleRuntimeBaseCommand(model, agentName, role, harness = "clau
3511
3577
  if (provider.name === "openai" && await getProviderAuthMode(validatedModel) === "subscription") return `claude${printFlag}${roleInject}${permissionFlags} --model ${shellQuoteModelIdSync(CLI_PROXY_MODEL_ALIASES[validatedModel] ?? validatedModel)}${effortFlag}${nameFlag}`;
3512
3578
  return `claude${printFlag}${roleInject}${permissionFlags} --model ${quotedModel}${effortFlag}${nameFlag}`;
3513
3579
  }
3514
- var import_dist, execAsync$5, missingRoleDefinitionWarnings, OHMYPI_AGENT_READY_TIMEOUT_SECONDS;
3580
+ var import_dist, execAsync$6, missingRoleDefinitionWarnings, OHMYPI_AGENT_READY_TIMEOUT_SECONDS;
3515
3581
  var init_runtime_command = __esmMin((() => {
3516
3582
  import_dist = /* @__PURE__ */ __toESM(require_dist(), 1);
3517
3583
  init_claude_permissions();
@@ -3532,7 +3598,7 @@ var init_runtime_command = __esmMin((() => {
3532
3598
  init_agent_state();
3533
3599
  init_identity();
3534
3600
  init_provider_env();
3535
- execAsync$5 = promisify$1(exec$1);
3601
+ execAsync$6 = promisify$1(exec$1);
3536
3602
  missingRoleDefinitionWarnings = /* @__PURE__ */ new Set();
3537
3603
  OHMYPI_AGENT_READY_TIMEOUT_SECONDS = 120;
3538
3604
  }));
@@ -3862,23 +3928,24 @@ async function transitionIssueToInReview(issueId, workspacePath) {
3862
3928
  async function buildAgentLaunchConfig(opts) {
3863
3929
  const model = requireModelOverrideSync(opts.model);
3864
3930
  try {
3865
- const { injectOverdeckInfraDeny } = await import("./claude-settings-overlay-BzkHYDwR.js");
3931
+ const { injectOverdeckInfraDeny } = await import("./claude-settings-overlay-B19hdzSA.js");
3866
3932
  await Effect.runPromise(injectOverdeckInfraDeny(opts.workspace));
3867
3933
  } catch (err) {
3868
3934
  console.warn(`[agents] injectOverdeckInfraDeny failed for ${opts.agentId} (non-fatal): ${err instanceof Error ? err.message : err}`);
3869
3935
  }
3870
3936
  const behavior = getHarnessBehavior(opts.harness);
3871
3937
  const isAcp = behavior.launchCommandKind === "acp-host";
3872
- const providerEnv = isAcp ? {} : await getProviderEnvForModel(model);
3938
+ const providerEnv = isAcp ? {} : await getProviderEnvForModel(model, opts.harness);
3873
3939
  if (!isAcp) {
3874
3940
  const provider = getProviderForModelSync(model);
3875
3941
  if (provider.authType === "credential-file") setupCredentialFileAuthSync(provider, opts.workspace);
3876
3942
  else clearCredentialFileAuthSync(opts.workspace);
3877
3943
  }
3878
- const providerExports = isAcp ? void 0 : await getProviderExportsForModel(model);
3944
+ const providerExports = isAcp ? void 0 : await getProviderExportsForModel(model, opts.harness);
3879
3945
  const launchRole = opts.isPlanning ? "plan" : opts.role;
3880
3946
  const piLauncherFields = behavior.usesRpcFifo ? await getOhmypiLauncherFields(opts.agentId, model) : {};
3881
3947
  const codexLauncherFields = behavior.usesCodexHome ? getCodexLauncherFields(opts.agentId, model, opts.workspace, launchRole) : {};
3948
+ const kimiCodeLauncherFields = behavior.launchCommandKind === "kimi-code-tui" ? getKimiCodeLauncherFields(model) : {};
3882
3949
  if (isAcp && !opts.harnessBinaryPath) throw new Error("ACP launch requires the executable path resolved by preflight");
3883
3950
  const acpLauncherFields = isAcp ? getAcpLauncherFields(opts.agentId, model, opts.workspace, opts.harnessBinaryPath, launchRole) : {};
3884
3951
  if (opts.spawnMode === "resume" && opts.resumeSessionId) return {
@@ -3901,7 +3968,8 @@ async function buildAgentLaunchConfig(opts) {
3901
3968
  promptInline: opts.promptInline,
3902
3969
  ...piLauncherFields,
3903
3970
  ...codexLauncherFields,
3904
- ...acpLauncherFields
3971
+ ...acpLauncherFields,
3972
+ ...kimiCodeLauncherFields
3905
3973
  }),
3906
3974
  providerEnv
3907
3975
  };
@@ -3927,6 +3995,7 @@ async function buildAgentLaunchConfig(opts) {
3927
3995
  ...piLauncherFields,
3928
3996
  ...codexLauncherFields,
3929
3997
  ...acpLauncherFields,
3998
+ ...kimiCodeLauncherFields,
3930
3999
  ...opts.channelsBridgeMcpConfig ? {
3931
4000
  channelsBridgeMcpConfig: opts.channelsBridgeMcpConfig,
3932
4001
  channelsBridgeServerName: opts.channelsBridgeServerName ?? "overdeck-bridge"
@@ -3952,7 +4021,7 @@ async function retrieveSpawnTimeMemoryContext(input) {
3952
4021
  agentRole: input.role,
3953
4022
  agentHarness: input.harness
3954
4023
  };
3955
- const { injectPromptTimeMemory } = await import("./injection-Bl8d_jHZ.js");
4024
+ const { injectPromptTimeMemory } = await import("./injection-BisQ0lpX.js");
3956
4025
  return (await injectPromptTimeMemory({
3957
4026
  prompt: input.prompt,
3958
4027
  identity,
@@ -4043,7 +4112,7 @@ async function assertWorkspaceStackHealthyForSpawn(issueId, role, allowHost = fa
4043
4112
  record.attempts += 1;
4044
4113
  spawnStackRebuildState.set(normalizedIssue, record);
4045
4114
  console.log(`[agents] Workspace stack for ${normalizedIssue} unhealthy (${details}) — rebuilding before spawn (attempt ${record.attempts}/${SPAWN_STACK_REBUILD_MAX_ATTEMPTS})`);
4046
- const { rebuildWorkspaceStack } = await import("./rebuild-stack-DqcOVmJO.js");
4115
+ const { rebuildWorkspaceStack } = await import("./rebuild-stack-qC0jCNm6.js");
4047
4116
  const result = await Effect.runPromise(rebuildWorkspaceStack(issueId, { onProgress: (m) => console.log(`[agents] ${normalizedIssue} stack rebuild: ${m}`) })).catch((err) => ({
4048
4117
  success: false,
4049
4118
  error: err instanceof Error ? err.message : String(err)
@@ -4505,6 +4574,22 @@ function readAcpTokenSync(agentId) {
4505
4574
  return readSocketTokenSync(agentId, "acp-token");
4506
4575
  }
4507
4576
  /**
4577
+ * Pure, exported for tests (PAN-1837): classify a keyed supervisor POST
4578
+ * failure. Connect-phase errors (refused / socket path gone / permission)
4579
+ * fire before any bytes reach the supervisor, so the injection definitively
4580
+ * did NOT happen — a stale socket file left by a crashed supervisor refuses
4581
+ * every connection forever, and treating that as ambiguous strands keyed
4582
+ * deliveries permanently. A received non-2xx means the supervisor answered
4583
+ * and recorded no key. Everything else (timeout, reset mid-response) is
4584
+ * genuinely ambiguous.
4585
+ */
4586
+ function keyedSupervisorFailureKind(err) {
4587
+ const code = err?.code;
4588
+ if (code === "ECONNREFUSED" || code === "ENOENT" || code === "EACCES") return "connect-failed";
4589
+ if (err instanceof SocketPostStatusError) return "status";
4590
+ return "ambiguous";
4591
+ }
4592
+ /**
4508
4593
  * POST a JSON body to a Unix-domain socket using node:net + a hand-rolled
4509
4594
  * minimal HTTP/1.1 request. Resolves on a 200-class response, rejects on any
4510
4595
  * error including socket-not-found, connection refused, an optional client
@@ -4785,8 +4870,9 @@ async function deliverKeyedAgentMessage(normalizedId, message, caller, resolvedM
4785
4870
  };
4786
4871
  } catch (err) {
4787
4872
  const reason = err instanceof Error ? err.message : String(err);
4788
- if (!(err instanceof SocketPostStatusError)) throw new AmbiguousKeyedDeliveryError(normalizedId, caller, reason);
4789
- supervisorFailure = `socket-post-failed: ${reason}`;
4873
+ const kind = keyedSupervisorFailureKind(err);
4874
+ if (kind === "ambiguous") throw new AmbiguousKeyedDeliveryError(normalizedId, caller, reason);
4875
+ supervisorFailure = `${kind === "connect-failed" ? "socket-connect-failed" : "socket-post-failed"}: ${reason}`;
4790
4876
  }
4791
4877
  if (resolvedMethod === "supervisor") throw new Error(`MessageDeliveryFailed: PTY supervisor delivery failed for ${normalizedId} (${caller}): ${supervisorFailure}`);
4792
4878
  await appendChannelDeliveryLog(normalizedId, {
@@ -4801,9 +4887,10 @@ async function deliverKeyedAgentMessage(normalizedId, message, caller, resolvedM
4801
4887
  }
4802
4888
  /**
4803
4889
  * Keyed tmux delivery: paste under the two-phase marker protocol, then
4804
- * complete the submit. A replay that finds the pending marker completes the
4805
- * prior attempt's submission WITHOUT re-pasting; a terminal marker suppresses
4806
- * the replay entirely.
4890
+ * complete the submit. Pending claims carry a strictly-read payload state:
4891
+ * unverified requires active-composer proof, while enter-attempted preserves
4892
+ * no-repaste rollback recovery. Unset legacy/unknown states fail closed. A
4893
+ * terminal marker suppresses the replay entirely.
4807
4894
  */
4808
4895
  async function deliverKeyedViaTmux(normalizedId, message, caller, dedupKey) {
4809
4896
  await assertTmuxTargetCanReceive(normalizedId, caller);
@@ -4999,7 +5086,7 @@ var init_delivery = __esmMin((() => {
4999
5086
  this.name = "AmbiguousKeyedDeliveryError";
5000
5087
  }
5001
5088
  };
5002
- RESUME_TRANSCRIPT_CONFIRM_TIMEOUT_MS = 3e3;
5089
+ RESUME_TRANSCRIPT_CONFIRM_TIMEOUT_MS = 3e4;
5003
5090
  RESUME_TRANSCRIPT_CONFIRM_INTERVAL_MS = 100;
5004
5091
  }));
5005
5092
  //#endregion
@@ -5312,7 +5399,7 @@ async function killLauncherProcessAsync(agentId) {
5312
5399
  const launcherPath = join$1(AGENTS_DIR, agentId, "launcher.sh");
5313
5400
  let pidsOut;
5314
5401
  try {
5315
- const { stdout } = await execAsync$4(`pgrep -f ${JSON.stringify(launcherPath)}`);
5402
+ const { stdout } = await execAsync$5(`pgrep -f ${JSON.stringify(launcherPath)}`);
5316
5403
  pidsOut = stdout.trim();
5317
5404
  } catch {
5318
5405
  return;
@@ -5362,14 +5449,14 @@ function stopAgentSync(agentId) {
5362
5449
  lastActivity: (/* @__PURE__ */ new Date()).toISOString()
5363
5450
  });
5364
5451
  }
5365
- var execAsync$4, stopAgent;
5452
+ var execAsync$5, stopAgent;
5366
5453
  var init_termination = __esmMin((() => {
5367
5454
  init_agents();
5368
5455
  init_agent_runtime();
5369
5456
  init_paths();
5370
5457
  init_tmux();
5371
5458
  init_errors();
5372
- execAsync$4 = promisify$1(exec$1);
5459
+ execAsync$5 = promisify$1(exec$1);
5373
5460
  stopAgent = (agentId) => {
5374
5461
  const normalizedId = normalizeAgentId(agentId);
5375
5462
  return Effect.gen(function* () {
@@ -5481,21 +5568,21 @@ async function ensureRegisteredSlotWorktree(baseWorkspace, slot) {
5481
5568
  const branchExists = await gitBranchExists(baseWorkspace, slot.branch);
5482
5569
  const target = JSON.stringify(slot.workspace);
5483
5570
  const branch = JSON.stringify(slot.branch);
5484
- await execAsync$3(branchExists ? `git worktree add ${target} ${branch}` : `git worktree add -b ${branch} ${target} HEAD`, { cwd: baseWorkspace });
5571
+ await execAsync$4(branchExists ? `git worktree add ${target} ${branch}` : `git worktree add -b ${branch} ${target} HEAD`, { cwd: baseWorkspace });
5485
5572
  }
5486
5573
  async function gitBranchExists(workspace, branch) {
5487
5574
  try {
5488
- await execAsync$3(`git show-ref --verify --quiet ${JSON.stringify(`refs/heads/${branch}`)}`, { cwd: workspace });
5575
+ await execAsync$4(`git show-ref --verify --quiet ${JSON.stringify(`refs/heads/${branch}`)}`, { cwd: workspace });
5489
5576
  return true;
5490
5577
  } catch {
5491
5578
  return false;
5492
5579
  }
5493
5580
  }
5494
- var execAsync$3;
5581
+ var execAsync$4;
5495
5582
  var init_registered_slot_spawn = __esmMin((() => {
5496
5583
  init_dag();
5497
5584
  init_io();
5498
- execAsync$3 = promisify(exec);
5585
+ execAsync$4 = promisify(exec);
5499
5586
  }));
5500
5587
  //#endregion
5501
5588
  //#region ../../lib/agents/spawn.ts
@@ -5560,18 +5647,18 @@ async function spawnRunWithoutConsentClaim(issueId, role, options, acceptConsent
5560
5647
  let reapWarmIdle = false;
5561
5648
  const advancing = role === "review" || role === "test" || role === "ship";
5562
5649
  try {
5563
- const { isPaneDead } = await import("./tmux-Ctk6RV5l.js");
5650
+ const { isPaneDead } = await import("./tmux-Cjpx8L8u.js");
5564
5651
  if (await Effect.runPromise(isPaneDead(agentId))) reapWarmIdle = true;
5565
5652
  else if (advancing) {
5566
- const { getReviewStatusSync } = await import("./review-status-Dma9SFaN.js");
5567
- const { isRoleTerminal } = await import("./reap-terminal-sessions-4Xg9NGA8.js");
5653
+ const { getReviewStatusSync } = await import("./review-status-B6wYcOtP.js");
5654
+ const { isRoleTerminal } = await import("./reap-terminal-sessions-DegFS2p1.js");
5568
5655
  const status = getReviewStatusSync(issueId);
5569
5656
  reapWarmIdle = !!status && isRoleTerminal(role, status);
5570
5657
  }
5571
5658
  } catch {}
5572
5659
  if (!reapWarmIdle) throw new Error(`Role run ${agentId} already running. Use 'pan tell' to message it.`);
5573
5660
  console.log(`[spawn] ${agentId} is warm-idle from the previous cycle — reaping it for the new ${role} dispatch (PAN-2579)`);
5574
- const { killSession } = await import("./tmux-Ctk6RV5l.js");
5661
+ const { killSession } = await import("./tmux-Cjpx8L8u.js");
5575
5662
  await Effect.runPromise(killSession(agentId)).catch(() => {});
5576
5663
  }
5577
5664
  await assertWorkspaceStackHealthyForSpawn(issueId, role, options.allowHost, workspace);
@@ -5586,7 +5673,7 @@ async function spawnRunWithoutConsentClaim(issueId, role, options, acceptConsent
5586
5673
  assertCodexNativeAuthForSpawn(resolvedHarness, listAgentStates());
5587
5674
  await ensureLifecycleHooksBeforeLaunch(agentId, resolvedHarness);
5588
5675
  if (getProviderForModelSync(selectedModel).name === "openai" && await getProviderAuthMode(selectedModel) === "subscription") {
5589
- const { isCliproxyRunning } = await import("./cliproxy-DaAbWMjC.js");
5676
+ const { isCliproxyRunning } = await import("./cliproxy-DgEZlr7Y.js");
5590
5677
  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.");
5591
5678
  }
5592
5679
  const state = {
@@ -5611,6 +5698,7 @@ async function spawnRunWithoutConsentClaim(issueId, role, options, acceptConsent
5611
5698
  const shouldDeliverPromptViaTmux = shouldRegisterConversation && resolvedHarness === "claude-code";
5612
5699
  const shouldDeliverPromptViaPi = shouldRegisterConversation && resolvedHarness === "ohmypi";
5613
5700
  const shouldDeliverPromptViaCodexTui = shouldRegisterConversation && resolvedHarness === "codex";
5701
+ const shouldDeliverPromptViaKimiCode = shouldRegisterConversation && resolvedHarness === "kimi-code";
5614
5702
  const shouldDeliverPromptViaAcp = resolvedHarness === "acp";
5615
5703
  const prompt = options.prompt ? await withSpawnTimeMemoryContext({
5616
5704
  prompt: options.prompt,
@@ -5622,7 +5710,7 @@ async function spawnRunWithoutConsentClaim(issueId, role, options, acceptConsent
5622
5710
  }) : "";
5623
5711
  let promptFile;
5624
5712
  const tracksKickoffDelivery = role === "flywheel";
5625
- if (prompt && !shouldDeliverPromptViaAcp && (tracksKickoffDelivery || !shouldDeliverPromptViaTmux && !shouldDeliverPromptViaPi && !shouldDeliverPromptViaCodexTui)) {
5713
+ if (prompt && !shouldDeliverPromptViaAcp && (tracksKickoffDelivery || !shouldDeliverPromptViaTmux && !shouldDeliverPromptViaPi && !shouldDeliverPromptViaCodexTui && !shouldDeliverPromptViaKimiCode)) {
5626
5714
  promptFile = join$1(getAgentDir(agentId), "initial-prompt.md");
5627
5715
  await writeFile$1(promptFile, prompt);
5628
5716
  }
@@ -5635,11 +5723,12 @@ async function spawnRunWithoutConsentClaim(issueId, role, options, acceptConsent
5635
5723
  if (provider.authType === "credential-file") setupCredentialFileAuthSync(provider, workspace);
5636
5724
  else clearCredentialFileAuthSync(workspace);
5637
5725
  }
5638
- const providerExports = isAcp ? void 0 : await getProviderExportsForModel(selectedModel);
5639
- const providerEnv = isAcp ? {} : await getProviderEnvForModel(selectedModel);
5726
+ const providerExports = isAcp ? void 0 : await getProviderExportsForModel(selectedModel, resolvedHarness);
5727
+ const providerEnv = isAcp ? {} : await getProviderEnvForModel(selectedModel, resolvedHarness);
5640
5728
  const piLauncherFields = resolvedHarness === "ohmypi" ? await getOhmypiLauncherFields(agentId, selectedModel) : {};
5641
5729
  const codexLauncherFields = resolvedHarness === "codex" ? getCodexLauncherFields(agentId, selectedModel, workspace, role) : {};
5642
5730
  const acpLauncherFields = isAcp ? getAcpLauncherFields(agentId, selectedModel, workspace, harnessLaunch.binaryPath, role) : {};
5731
+ const kimiCodeLauncherFields = resolvedHarness === "kimi-code" ? getKimiCodeLauncherFields(selectedModel) : {};
5643
5732
  let sessionId;
5644
5733
  let rawSessionId;
5645
5734
  if (shouldRegisterConversation) {
@@ -5698,14 +5787,15 @@ async function spawnRunWithoutConsentClaim(issueId, role, options, acceptConsent
5698
5787
  trapHup: void 0,
5699
5788
  ...piLauncherFields,
5700
5789
  ...codexLauncherFields,
5701
- ...acpLauncherFields
5790
+ ...acpLauncherFields,
5791
+ ...kimiCodeLauncherFields
5702
5792
  });
5703
5793
  const launcherScript = join$1(getAgentDir(agentId), "launcher.sh");
5704
5794
  await writeLauncherScriptAtomic(launcherScript, launcherContent);
5705
5795
  const claudeCmd = `bash ${launcherScript}`;
5706
5796
  console.log(`[claude-invoke] purpose=role-run | role=${role} | model=${state.model} | source=agents.ts:spawnRun | session=${agentId} | command="${claudeCmd}"`);
5707
5797
  try {
5708
- const { preTrustDirectory } = await import("./workspace-manager-C1F3XsnS.js");
5798
+ const { preTrustDirectory } = await import("./workspace-manager-C0CpNh3t.js");
5709
5799
  preTrustDirectory(workspace);
5710
5800
  } catch {}
5711
5801
  clearReadySignal(agentId);
@@ -5755,7 +5845,7 @@ async function spawnRunWithoutConsentClaim(issueId, role, options, acceptConsent
5755
5845
  } catch (err) {
5756
5846
  console.error(`[${agentId}] ohmypi prompt delivery failed:`, err instanceof Error ? err.message : String(err));
5757
5847
  }
5758
- else if (shouldDeliverPromptViaTmux || shouldDeliverPromptViaCodexTui) if (tracksKickoffDelivery) {
5848
+ else if (shouldDeliverPromptViaTmux || shouldDeliverPromptViaCodexTui || shouldDeliverPromptViaKimiCode) if (tracksKickoffDelivery) {
5759
5849
  const delivery = await deliverInitialPromptWithRetry(agentId, prompt, "spawnRun:initial-prompt");
5760
5850
  if (delivery.ok) {
5761
5851
  state.kickoffDelivered = true;
@@ -5767,11 +5857,11 @@ async function spawnRunWithoutConsentClaim(issueId, role, options, acceptConsent
5767
5857
  } else if (await waitForPromptReady(agentId, resolvedHarness, 30)) {
5768
5858
  await new Promise((resolve) => setTimeout(resolve, 500));
5769
5859
  await deliverAgentMessage(agentId, prompt, "spawnRun:initial-prompt");
5770
- } else console.error(`[${agentId}] ${resolvedHarness === "codex" ? "Codex" : "Claude"} did not become ready within 30s`);
5860
+ } else console.error(`[${agentId}] ${getHarnessBehavior(resolvedHarness).displayName} did not become ready within 30s`);
5771
5861
  }
5772
5862
  markAgentRunning(state);
5773
5863
  try {
5774
- const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-Xg4PFN45.js");
5864
+ const { snapshotWorkspaceHeadsPromise } = await import("./git-utils-C31x1lpE.js");
5775
5865
  const headAnchor = await snapshotWorkspaceHeadsPromise(issueId, workspace);
5776
5866
  if (headAnchor) state.roleRunHead = headAnchor;
5777
5867
  } catch {}
@@ -5813,7 +5903,7 @@ async function spawnAgentWithoutConsentClaim(options, acceptConsent) {
5813
5903
  });
5814
5904
  console.log(`[DEBUG] Selected model: ${selectedModel}`);
5815
5905
  if (getProviderForModelSync(selectedModel).name === "openai" && await getProviderAuthMode(selectedModel) === "subscription") {
5816
- const { isCliproxyRunning } = await import("./cliproxy-DaAbWMjC.js");
5906
+ const { isCliproxyRunning } = await import("./cliproxy-DgEZlr7Y.js");
5817
5907
  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.");
5818
5908
  }
5819
5909
  const resolvedHarness = await resolveHarness({
@@ -5851,7 +5941,7 @@ async function spawnAgentWithoutConsentClaim(options, acceptConsent) {
5851
5941
  if (preservation.preserve) {
5852
5942
  if (preservation.refreshedAnchor) setReviewStatusSync(options.issueId, { reviewedAtCommit: preservation.refreshedAnchor });
5853
5943
  console.log(`[spawn] Preserved pipeline verdicts for ${options.issueId} — ${preservation.reason}`);
5854
- } else if (resetPipelineVerdictsForWorkStartSync(options.issueId)) (await import("./merge-agent-DQTXZk8z.js")).resetPostMergeState(options.issueId);
5944
+ } else if (resetPipelineVerdictsForWorkStartSync(options.issueId)) (await import("./merge-agent-DWd0KfiS.js")).resetPostMergeState(options.issueId);
5855
5945
  } catch (err) {
5856
5946
  console.warn(`[agents] Could not reset stale pipeline verdicts for ${options.issueId}: ${err instanceof Error ? err.message : String(err)}`);
5857
5947
  }
@@ -5860,7 +5950,7 @@ async function spawnAgentWithoutConsentClaim(options, acceptConsent) {
5860
5950
  });
5861
5951
  }
5862
5952
  if (role === "work") try {
5863
- const { writeStoryFeatureContext } = await import("./work-agent-prompt-ByrPAzOy.js");
5953
+ const { writeStoryFeatureContext } = await import("./work-agent-prompt-D03s4DD1.js");
5864
5954
  await writeStoryFeatureContext(options.workspace, options.issueId);
5865
5955
  } catch (ctxErr) {
5866
5956
  console.warn(`[agents] Could not write story feature context for ${options.issueId}: ${ctxErr.message}`);
@@ -5870,12 +5960,12 @@ async function spawnAgentWithoutConsentClaim(options, acceptConsent) {
5870
5960
  const project = findProjectByPathSync(workspace);
5871
5961
  if (project && !shouldCommitLegacyWorkspaceArtifacts(await isStateMigrated(project))) console.warn(`[agents] Deferred legacy .pan/ index cleanup for ${options.issueId} — migrated projects use gitignored .overdeck/ runtime files; historical entries retire with the branch`);
5872
5962
  else {
5873
- const { stdout: trackedFiles } = await execAsync$2("git ls-files .pan/continue.json .pan/spec.vbrief.json", { cwd: workspace });
5963
+ const { stdout: trackedFiles } = await execAsync$3("git ls-files .pan/continue.json .pan/spec.vbrief.json", { cwd: workspace });
5874
5964
  if (trackedFiles.trim()) {
5875
- const { stdout: porcelain } = await execAsync$2("git status --porcelain -- .pan/", { cwd: workspace });
5965
+ const { stdout: porcelain } = await execAsync$3("git status --porcelain -- .pan/", { cwd: workspace });
5876
5966
  if (!porcelain.trim()) {
5877
- await execAsync$2("git rm --cached --ignore-unmatch .pan/continue.json .pan/spec.vbrief.json", { cwd: workspace });
5878
- await execAsync$2("git commit -m \"chore: untrack workspace .pan/ artifacts (PAN-1215)\"", { cwd: workspace });
5967
+ await execAsync$3("git rm --cached --ignore-unmatch .pan/continue.json .pan/spec.vbrief.json", { cwd: workspace });
5968
+ await execAsync$3("git commit -m \"chore: untrack workspace .pan/ artifacts (PAN-1215)\"", { cwd: workspace });
5879
5969
  console.log(`[agents] Untracked workspace .pan/ artifacts for ${options.issueId}`);
5880
5970
  } else console.warn(`[agents] Skipping .pan/ untrack for ${options.issueId} — .pan/ paths have uncommitted changes`);
5881
5971
  }
@@ -5907,7 +5997,7 @@ async function spawnAgentWithoutConsentClaim(options, acceptConsent) {
5907
5997
  try {
5908
5998
  const venvPath = join$1(options.workspace, ".venv");
5909
5999
  if (isTldrEnabledSync() && existsSync(venvPath)) {
5910
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CvWXBhX1.js");
6000
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-B1Jhrtc8.js");
5911
6001
  const tldrService = getTldrDaemonServiceSync(options.workspace, venvPath);
5912
6002
  if (!(await tldrService.getStatus()).running) {
5913
6003
  await tldrService.start(true);
@@ -5947,13 +6037,13 @@ async function spawnAgentWithoutConsentClaim(options, acceptConsent) {
5947
6037
  const claudeCmd = `bash ${launcherScript}`;
5948
6038
  console.log(`[claude-invoke] purpose=work-agent | model=${state.model} | source=agents.ts:spawnAgent | session=${agentId} | command="${claudeCmd}"`);
5949
6039
  try {
5950
- const { preTrustDirectory } = await import("./workspace-manager-C1F3XsnS.js");
6040
+ const { preTrustDirectory } = await import("./workspace-manager-C0CpNh3t.js");
5951
6041
  preTrustDirectory(options.workspace);
5952
6042
  } catch {}
5953
6043
  try {
5954
- const { isGitHubAppConfigured, generateInstallationToken, configureWorkspaceForBot } = await import("./github-app-Bmg4R9mv.js");
6044
+ const { isGitHubAppConfigured, generateInstallationToken, configureWorkspaceForBot } = await import("./github-app-CpQSDlv8.js");
5955
6045
  if (isGitHubAppConfigured()) {
5956
- const { findProjectByPathSync } = await import("./projects-_n3Zui6K.js");
6046
+ const { findProjectByPathSync } = await import("./projects-WqMWCdpa.js");
5957
6047
  const ghRepo = findProjectByPathSync(resolve$1(options.workspace, "..", ".."))?.github_repo;
5958
6048
  if (ghRepo) {
5959
6049
  const [owner, repo] = ghRepo.split("/");
@@ -5966,18 +6056,42 @@ async function spawnAgentWithoutConsentClaim(options, acceptConsent) {
5966
6056
  console.warn(`[${agentId}] GitHub App config failed (falling back to SSH): ${err.message}`);
5967
6057
  }
5968
6058
  clearReadySignal(agentId);
5969
- await Effect.runPromise(createSession(agentId, options.workspace, claudeCmd, { env: {
5970
- ...BLANKED_PROVIDER_ENV,
5971
- TERM: "xterm-256color",
5972
- OVERDECK_AGENT_ID: agentId,
5973
- OVERDECK_ISSUE_ID: options.issueId,
5974
- OVERDECK_SESSION_TYPE: role,
5975
- OVERDECK_AGENT_STARTED_BY: startedBy,
5976
- CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
5977
- GIT_SEQUENCE_EDITOR: "false",
5978
- ...flywheelEnv,
5979
- ...providerEnv
5980
- } }));
6059
+ const launchAndCaptureKimiSession = async () => {
6060
+ let kimiExistingSessionsBefore;
6061
+ if (resolvedHarness === "kimi-code") try {
6062
+ const { kimiSessionsRoot } = await import("./kimi-code-D_Ppt82c.js");
6063
+ kimiExistingSessionsBefore = new Set(await readdir$1(kimiSessionsRoot(join$1(homedir(), ".kimi-code"), options.workspace)));
6064
+ } catch {
6065
+ kimiExistingSessionsBefore = /* @__PURE__ */ new Set();
6066
+ }
6067
+ await Effect.runPromise(createSession(agentId, options.workspace, claudeCmd, { env: {
6068
+ ...BLANKED_PROVIDER_ENV,
6069
+ TERM: "xterm-256color",
6070
+ OVERDECK_AGENT_ID: agentId,
6071
+ OVERDECK_ISSUE_ID: options.issueId,
6072
+ OVERDECK_SESSION_TYPE: role,
6073
+ OVERDECK_AGENT_STARTED_BY: startedBy,
6074
+ CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
6075
+ GIT_SEQUENCE_EDITOR: "false",
6076
+ ...flywheelEnv,
6077
+ ...providerEnv
6078
+ } }));
6079
+ if (kimiExistingSessionsBefore) {
6080
+ const { waitForNewKimiSessionAsync, writeKimiSessionId } = await import("./kimi-code-D_Ppt82c.js");
6081
+ const sessionId = await waitForNewKimiSessionAsync(join$1(homedir(), ".kimi-code"), options.workspace, kimiExistingSessionsBefore);
6082
+ if (sessionId) writeKimiSessionId(agentId, sessionId);
6083
+ else throw new Error(`kimi-code session capture timed out for ${agentId} — no new session directory appeared under the workspace bucket`);
6084
+ }
6085
+ };
6086
+ if (resolvedHarness === "kimi-code") {
6087
+ const { withKimiSessionCaptureLock } = await import("./kimi-code-D_Ppt82c.js");
6088
+ try {
6089
+ await withKimiSessionCaptureLock(join$1(homedir(), ".kimi-code"), options.workspace, launchAndCaptureKimiSession);
6090
+ } catch (err) {
6091
+ await Effect.runPromise(stopAgent(agentId)).catch(() => void 0);
6092
+ throw err;
6093
+ }
6094
+ } else await launchAndCaptureKimiSession();
5981
6095
  await acceptConsent?.();
5982
6096
  await saveAgentRuntimeState(agentId, {
5983
6097
  claudeSessionId: state.sessionId,
@@ -6033,7 +6147,7 @@ async function spawnAgentWithoutConsentClaim(options, acceptConsent) {
6033
6147
  const codexHomeForAgent = join$1(homedir(), ".overdeck", "agents", agentId, "codex-home");
6034
6148
  (async () => {
6035
6149
  try {
6036
- const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-o8FJwzmy.js");
6150
+ const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-B3n_rkwn.js");
6037
6151
  const rollout = await waitForCodexRollout(codexHomeForAgent, 12e4);
6038
6152
  if (rollout) {
6039
6153
  const threadId = extractThreadIdFromRollout(rollout);
@@ -6083,7 +6197,7 @@ function writeTaskCache(agentId, issueId) {
6083
6197
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
6084
6198
  }, null, 2));
6085
6199
  }
6086
- var execAsync$2;
6200
+ var execAsync$3;
6087
6201
  var init_spawn = __esmMin((() => {
6088
6202
  init_activity_logger();
6089
6203
  init_child_env();
@@ -6121,7 +6235,7 @@ var init_spawn = __esmMin((() => {
6121
6235
  init_auto_spawn_consent();
6122
6236
  init_provenance();
6123
6237
  init_registered_slot_spawn();
6124
- execAsync$2 = promisify$1(exec$1);
6238
+ execAsync$3 = promisify$1(exec$1);
6125
6239
  }));
6126
6240
  //#endregion
6127
6241
  //#region ../../lib/runtimes/ohmypi.ts
@@ -6298,7 +6412,7 @@ function walkJsonl(dir, out) {
6298
6412
  });
6299
6413
  }
6300
6414
  }
6301
- var execAsync$1, ACTIVE_HEARTBEAT_TTL_MS, SPAWN_READY_TIMEOUT_MS, OhmypiSpawnTimeout, OhmypiRuntimeSync;
6415
+ var execAsync$2, ACTIVE_HEARTBEAT_TTL_MS, SPAWN_READY_TIMEOUT_MS, OhmypiSpawnTimeout, OhmypiRuntimeSync;
6302
6416
  var init_ohmypi = __esmMin((() => {
6303
6417
  init_behavior();
6304
6418
  init_tmux();
@@ -6308,7 +6422,7 @@ var init_ohmypi = __esmMin((() => {
6308
6422
  init_ohmypi_fifo();
6309
6423
  init_errors();
6310
6424
  init_paths();
6311
- execAsync$1 = promisify(exec);
6425
+ execAsync$2 = promisify(exec);
6312
6426
  ACTIVE_HEARTBEAT_TTL_MS = 6e4;
6313
6427
  SPAWN_READY_TIMEOUT_MS = 12e4;
6314
6428
  OhmypiSpawnTimeout = class extends Error {
@@ -6427,12 +6541,12 @@ var init_ohmypi = __esmMin((() => {
6427
6541
  return;
6428
6542
  }
6429
6543
  try {
6430
- await execAsync$1(`tmux -L overdeck send-keys -t ${agentId} C-c 2>/dev/null || true`);
6544
+ await execAsync$2(`tmux -L overdeck send-keys -t ${agentId} C-c 2>/dev/null || true`);
6431
6545
  } catch {}
6432
6546
  try {
6433
- const { stdout } = await execAsync$1(`tmux -L overdeck list-panes -t ${shellQuote(agentId)} -F '#{pane_pid}' 2>/dev/null`);
6547
+ const { stdout } = await execAsync$2(`tmux -L overdeck list-panes -t ${shellQuote(agentId)} -F '#{pane_pid}' 2>/dev/null`);
6434
6548
  const pid = stdout.trim();
6435
- if (pid) await execAsync$1(`kill -TERM -- -${pid} 2>/dev/null || kill -TERM ${pid} 2>/dev/null || true`);
6549
+ if (pid) await execAsync$2(`kill -TERM -- -${pid} 2>/dev/null || kill -TERM ${pid} 2>/dev/null || true`);
6436
6550
  } catch {}
6437
6551
  if (await pollUntilSessionGone(agentId, 5e3)) {
6438
6552
  cleanupOhmypiTransientFiles(agentId);
@@ -6653,6 +6767,10 @@ function getLatestSessionIdSync(agentId) {
6653
6767
  const ohmypiSessionId = resolveLatestOhmypiSessionId(agentId);
6654
6768
  if (ohmypiSessionId) return ohmypiSessionId;
6655
6769
  }
6770
+ if (agentState?.harness && getHarnessBehavior(agentState.harness).sessionIdSource === "kimi-session-newest") try {
6771
+ const kimiSessionId = readFileSync(join$1(getAgentDir(agentId), "kimi-session-id"), "utf-8").trim();
6772
+ if (kimiSessionId) return kimiSessionId;
6773
+ } catch {}
6656
6774
  return null;
6657
6775
  }
6658
6776
  var getLatestSessionId;
@@ -6693,12 +6811,14 @@ var init_activity = __esmMin((() => {
6693
6811
  }));
6694
6812
  //#endregion
6695
6813
  //#region ../../lib/operator-interventions.ts
6814
+ /** PAN-1990 FR-15: additive workspaceId, populated when a workspace row exists for the issue. */
6696
6815
  function operatorInterventionEvent(input) {
6697
6816
  return {
6698
6817
  type: "operator.intervention",
6699
6818
  timestamp: input.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
6700
6819
  payload: {
6701
6820
  issueId: input.issueId,
6821
+ workspaceId: getWorkspaceForIssue(input.issueId)?.id,
6702
6822
  kind: input.kind,
6703
6823
  source: input.source
6704
6824
  }
@@ -6709,6 +6829,7 @@ async function appendOperatorInterventionEvent(input) {
6709
6829
  }
6710
6830
  var init_operator_interventions = __esmMin((() => {
6711
6831
  init_event_store();
6832
+ init_resolver();
6712
6833
  }));
6713
6834
  //#endregion
6714
6835
  //#region ../../lib/session-rotation.ts
@@ -6837,7 +6958,7 @@ function deliverWithOptionalKey(normalizedId, message, caller, deliveryMethod, d
6837
6958
  * at-most-once across the whole replay window.
6838
6959
  */
6839
6960
  async function resumeThenDeliverKeyed(normalizedId, message, caller, agentState, dedupKey) {
6840
- const { resumeAgent } = await import("./agents-ePFVoZbu.js");
6961
+ const { resumeAgent } = await import("./agents-IPSa5kzn.js");
6841
6962
  const result = await resumeAgent(normalizedId);
6842
6963
  if (!result.success) throw new Error(`Failed to auto-resume agent: ${result.error}`);
6843
6964
  const delivery = await deliverAgentMessage(normalizedId, message, `messageAgent:${caller}`, resolveAgentDeliveryMethod(agentState), { dedupKey });
@@ -6892,7 +7013,7 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6892
7013
  }
6893
7014
  console.log(`[agents] Auto-resuming suspended agent ${normalizedId} to deliver message`);
6894
7015
  if (opts.dedupKey !== void 0) return resumeThenDeliverKeyed(normalizedId, message, caller, agentState, opts.dedupKey);
6895
- const { resumeAgent } = await import("./agents-ePFVoZbu.js");
7016
+ const { resumeAgent } = await import("./agents-IPSa5kzn.js");
6896
7017
  const result = await resumeAgent(normalizedId, message);
6897
7018
  if (!result.success) throw new Error(`Failed to auto-resume agent: ${result.error}`);
6898
7019
  if (result.messageDelivered === false) throw new Error(`Agent resumed but ready signal did not fire — message not delivered. Feedback is in the mail queue.`);
@@ -6917,7 +7038,7 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6917
7038
  }
6918
7039
  console.log(`[agents] Auto-resuming stopped agent ${normalizedId} to deliver feedback (session exists: ${await Effect.runPromise(sessionExists(normalizedId))})`);
6919
7040
  if (opts.dedupKey !== void 0) return resumeThenDeliverKeyed(normalizedId, message, caller, agentState, opts.dedupKey);
6920
- const { resumeAgent } = await import("./agents-ePFVoZbu.js");
7041
+ const { resumeAgent } = await import("./agents-IPSa5kzn.js");
6921
7042
  const resumeResult = await resumeAgent(normalizedId, message);
6922
7043
  queueAgentMail(normalizedId, message, false);
6923
7044
  if (resumeResult.success && resumeResult.messageDelivered !== false) {
@@ -6961,7 +7082,7 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
6961
7082
  const resumeModel = agentState.model || "claude-sonnet-4-6";
6962
7083
  const fallbackHarness = agentState.harness ?? "claude-code";
6963
7084
  const harnessLaunch = await prepareHarnessLaunch(fallbackHarness);
6964
- const { assertWorkspaceStackHealthyForSpawn } = await import("./agents-ePFVoZbu.js");
7085
+ const { assertWorkspaceStackHealthyForSpawn } = await import("./agents-IPSa5kzn.js");
6965
7086
  await assertWorkspaceStackHealthyForSpawn(agentState.issueId || normalizedId.replace(/^agent-/, "").toUpperCase(), resumeRole, agentState.hostOverride === true, agentState.workspace);
6966
7087
  const fallbackPiFields = fallbackHarness === "ohmypi" ? await getOhmypiLauncherFields(normalizedId, resumeModel) : {};
6967
7088
  const fallbackCodexFields = fallbackHarness === "codex" ? getCodexLauncherFields(normalizedId, resumeModel, agentState.workspace, resumeRole) : {};
@@ -7044,12 +7165,12 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
7044
7165
  ...reason ? { reason } : {}
7045
7166
  };
7046
7167
  }
7047
- const { loadRemoteAgentState, sendToRemoteAgent } = await import("./remote-agents-CLZB3Coc.js");
7168
+ const { loadRemoteAgentState, sendToRemoteAgent } = await import("./remote-agents-BIIoc5pD.js");
7048
7169
  const remoteState = loadRemoteAgentState(normalizedId);
7049
7170
  if (remoteState && remoteState.vmName) {
7050
7171
  console.log(`[agents] Sending message to remote agent ${normalizedId} on ${remoteState.vmName}`);
7051
7172
  if (opts.dedupKey !== void 0) {
7052
- const { sendToRemoteAgentKeyed } = await import("./remote-agents-CLZB3Coc.js");
7173
+ const { sendToRemoteAgentKeyed } = await import("./remote-agents-BIIoc5pD.js");
7053
7174
  const remoteOutcome = await sendToRemoteAgentKeyed(normalizedId, remoteState.vmName, message, opts.dedupKey);
7054
7175
  queueAgentMail(normalizedId, message, false, opts.dedupKey);
7055
7176
  await appendTellInterventionForUserSource(normalizedId, caller);
@@ -7113,7 +7234,7 @@ async function messageAgent(agentId, message, caller = "internal", opts = {}) {
7113
7234
  if (panePids.length > 0 && !await hasAgentRuntimeInSubtree(panePids[0], expectedHarness)) {
7114
7235
  console.warn(`[agents] ${normalizedId} tmux session is a zombie (no ${expectedHarness} runtime) — attempting resume`);
7115
7236
  if (opts.dedupKey !== void 0) return resumeThenDeliverKeyed(normalizedId, message, caller, agentState, opts.dedupKey);
7116
- const { resumeAgent } = await import("./agents-ePFVoZbu.js");
7237
+ const { resumeAgent } = await import("./agents-IPSa5kzn.js");
7117
7238
  const resumeResult = await resumeAgent(normalizedId, message);
7118
7239
  if (resumeResult.success) {
7119
7240
  const delivered = resumeResult.messageDelivered !== false;
@@ -7328,7 +7449,7 @@ async function buildCompactRecoverySeed(agentId) {
7328
7449
  if (agentState?.workspace && sessionId) {
7329
7450
  const sessionFile = sessionFilePath(agentState.workspace, sessionId);
7330
7451
  try {
7331
- const [{ getConversationCompactionSettings }, { generateSmartSummary }] = await Promise.all([import("./conversation-compaction-BE3CNtHF.js"), import("./smart-compaction-8fA5k5XN.js")]);
7452
+ const [{ getConversationCompactionSettings }, { generateSmartSummary }] = await Promise.all([import("./conversation-compaction-5XuH6OBn.js"), import("./smart-compaction-DSTq-Wua.js")]);
7332
7453
  const settings = getConversationCompactionSettings();
7333
7454
  summary = (await Effect.runPromise(generateSmartSummary({
7334
7455
  jsonlPath: sessionFile,
@@ -7339,7 +7460,7 @@ async function buildCompactRecoverySeed(agentId) {
7339
7460
  } catch (err) {
7340
7461
  logAgentLifecycleSync(normalizedId, `compact-recovery smart summary failed (${err instanceof Error ? err.message : String(err)}); trying heuristic fallback`);
7341
7462
  try {
7342
- const { generateFallbackSummary } = await import("./summary-fork-BqgmgPDt.js");
7463
+ const { generateFallbackSummary } = await import("./summary-fork-B61fjRJn.js");
7343
7464
  summary = await Effect.runPromise(generateFallbackSummary(sessionFile));
7344
7465
  } catch (fallbackErr) {
7345
7466
  logAgentLifecycleSync(normalizedId, `compact-recovery fallback summary failed (${fallbackErr instanceof Error ? fallbackErr.message : String(fallbackErr)}); seeding with reseed instructions only`);
@@ -7586,6 +7707,17 @@ async function resumeAgent(agentId, message, opts) {
7586
7707
  messageDelivered = delivery.ok;
7587
7708
  if (delivery.ok && resumeMessage.redeliveringKickoff) markKickoffRedelivered(agentState);
7588
7709
  if (!delivery.ok) console.error(`[resumeAgent] Codex continue prompt did not land: ${delivery.failure ?? "unknown failure"}`);
7710
+ } else if (effectiveHarness === "kimi-code") {
7711
+ const delivery = await deliverInitialPromptWithRetry(normalizedId, effectiveMessage, "resumeAgent:kimi-code-continue");
7712
+ messageDelivered = delivery.ok;
7713
+ if (delivery.ok && resumeMessage.redeliveringKickoff) markKickoffRedelivered(agentState);
7714
+ if (!delivery.ok) {
7715
+ await Effect.runPromise(killSession(normalizedId));
7716
+ return {
7717
+ success: false,
7718
+ error: `Kimi Code continue prompt did not land: ${delivery.failure ?? "unknown failure"}`
7719
+ };
7720
+ }
7589
7721
  } else if (!shouldResumeSavedSession) {
7590
7722
  const delivery = await deliverInitialPromptWithRetry(normalizedId, effectiveMessage, "resumeAgent:compact-seed", resilientDeliveryMethod(agentState.deliveryMethod));
7591
7723
  messageDelivered = delivery.ok;
@@ -7730,16 +7862,790 @@ var init_graceful_restart = __esmMin((() => {
7730
7862
  GRACEFUL_RESTART_GRACE_MS = 6e4;
7731
7863
  }));
7732
7864
  //#endregion
7865
+ //#region ../../lib/agent-input-detection.ts
7866
+ function getPaneDetectionCacheKey(agentId, options) {
7867
+ return `${agentId}:${options.isPlanning === true ? "planning" : "agent"}:${options.lines ?? 90}`;
7868
+ }
7869
+ function sweepPaneDetectionCache(now = Date.now()) {
7870
+ for (const [key, entry] of paneDetectionCache) if (entry.expiresAt <= now) paneDetectionCache.delete(key);
7871
+ while (paneDetectionCache.size > MAX_PANE_DETECTION_CACHE_ENTRIES) {
7872
+ const oldestKey = paneDetectionCache.keys().next().value;
7873
+ if (!oldestKey) break;
7874
+ paneDetectionCache.delete(oldestKey);
7875
+ }
7876
+ }
7877
+ async function withPaneDetectionSlot(fn) {
7878
+ if (activePaneDetections >= MAX_CONCURRENT_PANE_DETECTIONS) await new Promise((resolve) => paneDetectionWaiters.push(resolve));
7879
+ activePaneDetections += 1;
7880
+ try {
7881
+ return await fn();
7882
+ } finally {
7883
+ activePaneDetections = Math.max(0, activePaneDetections - 1);
7884
+ paneDetectionWaiters.shift()?.();
7885
+ }
7886
+ }
7887
+ function cleanPaneLine(line) {
7888
+ return line.replace(ANSI_PATTERN, "").replace(/[\x00-\x1f\x7f]/g, "").replace(/\s+$/g, "");
7889
+ }
7890
+ function compactPrompt(prompt) {
7891
+ const compact = prompt.split("\n").map((line) => line.trim()).filter(Boolean).join("\n").trim();
7892
+ if (compact.length <= MAX_PROMPT_CHARS) return compact;
7893
+ return `${compact.slice(0, MAX_PROMPT_CHARS - 1)}…`;
7894
+ }
7895
+ function normalizeAwaitingInputPrompt(prompt) {
7896
+ return compactPrompt(prompt);
7897
+ }
7898
+ function snippetAround(lines, index, before = 8, after = 4) {
7899
+ const start = Math.max(0, index - before);
7900
+ const end = Math.min(lines.length, index + after + 1);
7901
+ return compactPrompt(lines.slice(start, end).join("\n"));
7902
+ }
7903
+ function lastIndexMatching(lines, predicate) {
7904
+ for (let i = lines.length - 1; i >= 0; i -= 1) if (predicate(lines[i], i)) return i;
7905
+ return -1;
7906
+ }
7907
+ function isRecentPromptIndex(lines, index) {
7908
+ if (index < 0) return false;
7909
+ return lines.length - index <= 25;
7910
+ }
7911
+ function isCurrentPromptIndex(lines, index, maxTrailingLines = 0) {
7912
+ if (index < 0) return false;
7913
+ return lines.length - index <= maxTrailingLines + 1;
7914
+ }
7915
+ /**
7916
+ * PAN-3068 — a harness footer hint line: key/action pairs separated by "·",
7917
+ * e.g. "Esc to cancel · Tab to amend · ctrl+e to explain". Every segment must
7918
+ * open with a key name, so real post-answer output ("● Bash(git status)") never
7919
+ * qualifies.
7920
+ */
7921
+ function looksLikeHarnessFooterHint(line) {
7922
+ const segments = line.split("·").map((segment) => segment.trim()).filter(Boolean);
7923
+ if (segments.length === 0) return false;
7924
+ return segments.every((segment) => /^(?:esc(?:ape)?|tab|enter|return|space|backspace|shift\+\S+|ctrl\+\S+|alt\+\S+|\?)\b/i.test(segment) || /^press\s+\S+/i.test(segment));
7925
+ }
7926
+ /**
7927
+ * PAN-3068 — the permission menu is still on screen when nothing but harness
7928
+ * footer chrome follows its final option. Claude Code renders "Esc to cancel ·
7929
+ * Tab to amend · ctrl+e to explain" below "3. No", so the old rule (the option
7930
+ * must be the literal last pane line) meant Claude permission prompts were
7931
+ * *never* detected — agents froze on a permission gate while the dashboard
7932
+ * reported them healthy and working. Real output below the menu means the
7933
+ * prompt was answered and scrolled, so it still clears.
7934
+ */
7935
+ function isPermissionMenuStillOnScreen(lines, menuEndIndex) {
7936
+ if (menuEndIndex < 0) return false;
7937
+ const trailing = lines.slice(menuEndIndex + 1);
7938
+ if (trailing.length > MAX_MENU_FOOTER_LINES) return false;
7939
+ return trailing.every(looksLikeHarnessFooterHint);
7940
+ }
7941
+ function findPermissionMenuEndIndex(lines, menuStartIndex) {
7942
+ if (menuStartIndex < 0) return -1;
7943
+ const end = Math.min(lines.length, menuStartIndex + 8);
7944
+ for (let i = menuStartIndex; i < end; i += 1) if (/\s*3\.\s*No\b/i.test(lines[i])) return i;
7945
+ return menuStartIndex;
7946
+ }
7947
+ function looksLikeClaudePermissionMenu(text) {
7948
+ return /(?:^|\n)\s*❯?\s*1\.\s*Yes\b/i.test(text) && /(?:^|\n)\s*2\.\s*Yes,?\s*(?:and\s*)?(?:allow|don't ask|always)/i.test(text) && /(?:^|\n)\s*3\.\s*No\b/i.test(text);
7949
+ }
7950
+ function looksLikePermissionText(text) {
7951
+ return /permission|allow(?:\s+this)?|tool use|bash command|mcp tool|do you want to proceed|do you want to continue/i.test(text);
7952
+ }
7953
+ function looksLikeGenericConfirmation(line) {
7954
+ return /(?:\?|:)\s*(?:\[[Yy]\/[Nn]\]|\[[Nn]\/[Yy]\]|\([Yy]\/[Nn]\)|\([Nn]\/[Yy]\)|\[y\/N\]|\[Y\/n\])\s*$/i.test(line) || /\b(?:continue|proceed|confirm|approve|allow|run|execute|overwrite|delete|remove)\b.*(?:\[[Yy]\/[Nn]\]|\([Yy]\/[Nn]\)|\[y\/N\]|\[Y\/n\])/i.test(line);
7955
+ }
7956
+ function looksLikePiPermission(text) {
7957
+ return /(?:permission|approval|approve|allow).{0,80}(?:required|request|prompt|action|command)/i.test(text) || /(?:allow|approve|run|execute)\s+(?:this\s+)?(?:command|tool|action)/i.test(text);
7958
+ }
7959
+ function looksLikePlanningDone(text) {
7960
+ return /planning finalized\s*[—-]\s*click done/i.test(text) || /click Done in the dashboard/i.test(text) || /planning (?:is )?complete.{0,120}(?:click|press|select) Done/i.test(text);
7961
+ }
7962
+ /**
7963
+ * PAN-1520 (covers #1197) — Claude Code session-resume dialog. Fires when an
7964
+ * agent is resumed via `claude --resume <session>` and a prior session is
7965
+ * still considered active or interrupted. The dialog blocks tool execution
7966
+ * until acknowledged. Conservative patterns — we want false-negatives over
7967
+ * false-positives, so we only match strings that clearly indicate a resume
7968
+ * choice point.
7969
+ */
7970
+ function looksLikeSessionResumeDialog(text) {
7971
+ return /this session (?:is|was)\s+(?:still\s+)?(?:active|interrupted|running)/i.test(text) || /resume (?:the\s+)?previous session/i.test(text) || /(?:continue|resume) (?:this\s+)?session\??.{0,40}(?:\[[Yy]\/[Nn]\]|\([Yy]\/[Nn]\)|press\s+enter)/i.test(text) || /press enter to (?:continue|resume)/i.test(text);
7972
+ }
7973
+ /**
7974
+ * PAN-1834 — Codex/gpt-5.5 rate-limit / model-switch modal. The harness shows a
7975
+ * choice between keeping the current model and switching to an alternative.
7976
+ * To avoid matching prose that merely mentions rate limits, require BOTH option
7977
+ * lines to be present near the bottom of the pane.
7978
+ */
7979
+ function looksLikeRateLimitModelSwitchModal(text) {
7980
+ return /keep current model/i.test(text) && /switch to\s+\S+/i.test(text);
7981
+ }
7982
+ /**
7983
+ * PAN-1690 — Codex TUI approval prompt header. Codex asks for approval with a
7984
+ * distinctive "Would you like to …?" prompt box (command run, edits, network/
7985
+ * host grants) followed by a numbered Yes/…/No menu. Unlike Claude's menu,
7986
+ * Codex renders option descriptions and a footer hint *below* "3. No", so the
7987
+ * trailing-line heuristics the Claude path relies on never fire — we key on the
7988
+ * header instead. Verb list pulled from the codex binary; see PAN-1690.
7989
+ */
7990
+ function looksLikeCodexApprovalHeader(line) {
7991
+ return /Would you like to (?:run the following command|grant these permissions?|make the following edits|allow|apply)\b/i.test(line);
7992
+ }
7993
+ function detectAwaitingInputFromPaneSync(pane, options = {}) {
7994
+ const lines = pane.split("\n").map(cleanPaneLine).filter((line) => line.trim().length > 0);
7995
+ if (lines.length === 0) return null;
7996
+ const recentText = lines.slice(-45).join("\n");
7997
+ if (looksLikeClaudePermissionMenu(recentText) && looksLikePermissionText(recentText)) {
7998
+ const menuIndex = lastIndexMatching(lines, (line) => /❯?\s*1\.\s*Yes\b/i.test(line));
7999
+ const menuEndIndex = findPermissionMenuEndIndex(lines, menuIndex);
8000
+ if (isRecentPromptIndex(lines, menuIndex) && isPermissionMenuStillOnScreen(lines, menuEndIndex)) return {
8001
+ reason: "tool_permission",
8002
+ prompt: snippetAround(lines, menuIndex, 10, 3)
8003
+ };
8004
+ }
8005
+ const codexHeaderIndex = lastIndexMatching(lines, looksLikeCodexApprovalHeader);
8006
+ if (codexHeaderIndex >= 0 && isRecentPromptIndex(lines, codexHeaderIndex)) {
8007
+ const optionIndex = lastIndexMatching(lines, (line) => /^[^\w]*1\.\s*Yes\b/i.test(line));
8008
+ if (optionIndex > codexHeaderIndex && lines.length - optionIndex <= 12) return {
8009
+ reason: "tool_permission",
8010
+ prompt: snippetAround(lines, codexHeaderIndex, 1, 14)
8011
+ };
8012
+ }
8013
+ const piIndex = lastIndexMatching(lines, (line) => looksLikePiPermission(line) || looksLikeGenericConfirmation(line));
8014
+ if (isRecentPromptIndex(lines, piIndex) && isCurrentPromptIndex(lines, piIndex)) {
8015
+ const snippet = snippetAround(lines, piIndex, 6, 2);
8016
+ return {
8017
+ reason: looksLikeGenericConfirmation(lines[piIndex]) ? "confirmation" : "tool_permission",
8018
+ prompt: snippet
8019
+ };
8020
+ }
8021
+ if (options.isPlanning && looksLikePlanningDone(recentText)) {
8022
+ const doneIndex = lastIndexMatching(lines, (line) => /done|planning/i.test(line));
8023
+ return {
8024
+ reason: "planning_done",
8025
+ prompt: snippetAround(lines, doneIndex >= 0 ? doneIndex : lines.length - 1, 8, 2)
8026
+ };
8027
+ }
8028
+ if (looksLikeSessionResumeDialog(recentText)) {
8029
+ const resumeIndex = lastIndexMatching(lines, (line) => looksLikeSessionResumeDialog(line));
8030
+ return {
8031
+ reason: "session_resume",
8032
+ prompt: snippetAround(lines, resumeIndex >= 0 ? resumeIndex : lines.length - 1, 8, 2)
8033
+ };
8034
+ }
8035
+ if (looksLikeRateLimitModelSwitchModal(recentText)) {
8036
+ const rateLimitIndex = lastIndexMatching(lines, (line) => /keep current model|switch to\s+\S+/i.test(line));
8037
+ if (isRecentPromptIndex(lines, rateLimitIndex)) return {
8038
+ reason: "rate_limit",
8039
+ prompt: snippetAround(lines, rateLimitIndex >= 0 ? rateLimitIndex : lines.length - 1, 8, 2)
8040
+ };
8041
+ }
8042
+ return null;
8043
+ }
8044
+ async function detectAwaitingInputForAgentPromise(agentId, options = {}) {
8045
+ const cacheEnabled = options.cache !== false;
8046
+ const cacheKey = getPaneDetectionCacheKey(agentId, options);
8047
+ const now = Date.now();
8048
+ if (cacheEnabled) {
8049
+ sweepPaneDetectionCache(now);
8050
+ const cached = paneDetectionCache.get(cacheKey);
8051
+ if (cached && cached.expiresAt > now) {
8052
+ paneDetectionCache.delete(cacheKey);
8053
+ paneDetectionCache.set(cacheKey, cached);
8054
+ return cached.detection;
8055
+ }
8056
+ const inFlight = paneDetectionInFlight.get(cacheKey);
8057
+ if (inFlight) return inFlight;
8058
+ }
8059
+ const detectionPromise = withPaneDetectionSlot(async () => {
8060
+ const detection = detectAwaitingInputFromPaneSync(await Effect.runPromise(capturePane(agentId, options.lines ?? 90)), options);
8061
+ if (cacheEnabled) {
8062
+ paneDetectionCache.set(cacheKey, {
8063
+ expiresAt: Date.now() + PANE_DETECTION_CACHE_TTL_MS,
8064
+ detection
8065
+ });
8066
+ sweepPaneDetectionCache();
8067
+ }
8068
+ return detection;
8069
+ });
8070
+ if (!cacheEnabled) return detectionPromise;
8071
+ paneDetectionInFlight.set(cacheKey, detectionPromise);
8072
+ try {
8073
+ return await detectionPromise;
8074
+ } finally {
8075
+ paneDetectionInFlight.delete(cacheKey);
8076
+ }
8077
+ }
8078
+ /**
8079
+ * PAN-1690 — parse a Codex approval prompt (as captured by the codex-aware
8080
+ * branch of detectAwaitingInputFromPaneSync) into its header, detail, and
8081
+ * numbered options, so the dashboard can render the menu and answer it without
8082
+ * the terminal. Returns null when the text doesn't contain a usable menu
8083
+ * (fewer than two numbered options). Option lines tolerate a leading selection
8084
+ * cursor (❯ › > etc.); the footer hint and other non-numbered lines are
8085
+ * naturally excluded.
8086
+ */
8087
+ function parseCodexApprovalPrompt(text) {
8088
+ const lines = text.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
8089
+ if (lines.length === 0) return null;
8090
+ const headerIndex = lines.findIndex((l) => looksLikeCodexApprovalHeader(l));
8091
+ if (headerIndex < 0) return null;
8092
+ const optionRe = /^[^\w]*(\d+)\.\s*(.+?)\s*$/;
8093
+ const options = [];
8094
+ const detailLines = [];
8095
+ let firstOptionSeen = false;
8096
+ for (let i = headerIndex + 1; i < lines.length; i += 1) {
8097
+ const m = optionRe.exec(lines[i]);
8098
+ if (m) {
8099
+ firstOptionSeen = true;
8100
+ options.push({
8101
+ number: Number(m[1]),
8102
+ label: m[2].trim()
8103
+ });
8104
+ } else if (!firstOptionSeen) detailLines.push(lines[i]);
8105
+ }
8106
+ if (options.length < 2) return null;
8107
+ return {
8108
+ header: lines[headerIndex],
8109
+ detail: detailLines.join("\n"),
8110
+ options
8111
+ };
8112
+ }
8113
+ var ANSI_PATTERN, MAX_PROMPT_CHARS, PANE_DETECTION_CACHE_TTL_MS, MAX_PANE_DETECTION_CACHE_ENTRIES, MAX_CONCURRENT_PANE_DETECTIONS, MAX_MENU_FOOTER_LINES, paneDetectionCache, paneDetectionInFlight, paneDetectionWaiters, activePaneDetections, detectAwaitingInputForAgent;
8114
+ var init_agent_input_detection = __esmMin((() => {
8115
+ init_tmux();
8116
+ init_errors();
8117
+ ANSI_PATTERN = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
8118
+ MAX_PROMPT_CHARS = 2e3;
8119
+ PANE_DETECTION_CACHE_TTL_MS = 1e4;
8120
+ MAX_PANE_DETECTION_CACHE_ENTRIES = 256;
8121
+ MAX_CONCURRENT_PANE_DETECTIONS = 4;
8122
+ MAX_MENU_FOOTER_LINES = 4;
8123
+ paneDetectionCache = /* @__PURE__ */ new Map();
8124
+ paneDetectionInFlight = /* @__PURE__ */ new Map();
8125
+ paneDetectionWaiters = [];
8126
+ activePaneDetections = 0;
8127
+ detectAwaitingInputForAgent = (agentId, options = {}) => Effect.tryPromise({
8128
+ try: () => detectAwaitingInputForAgentPromise(agentId, options),
8129
+ catch: (cause) => new TmuxError({
8130
+ command: "capture-pane",
8131
+ message: `failed to detect awaiting input for ${agentId}`,
8132
+ cause
8133
+ })
8134
+ });
8135
+ }));
8136
+ //#endregion
8137
+ //#region ../../lib/agent-enrichment.ts
8138
+ /**
8139
+ * Agent enrichment utilities (PAN-440 / PAN-1048)
8140
+ *
8141
+ * Shared functions for computing enrichment fields:
8142
+ * role, hasPendingQuestion, pendingQuestionCount, resolution, resolutionCount
8143
+ *
8144
+ * Used by both the legacy REST /api/agents endpoint and the new
8145
+ * AgentEnrichmentService background poller.
8146
+ *
8147
+ * PAN-1048: replaced the legacy `agentPhase` string with the role primitive —
8148
+ * the dashboard derives label/status from `role` + lifecycle state.
8149
+ */
8150
+ function appendPaneDetectionKind(detection, kinds) {
8151
+ if (detection?.reason === "session_resume" && !kinds.includes("sessionResume")) kinds.push("sessionResume");
8152
+ if (detection?.reason === "rate_limit" && !kinds.includes("rateLimit")) kinds.push("rateLimit");
8153
+ if (detection?.reason === "tool_permission" && !kinds.includes("permissionRequest")) kinds.push("permissionRequest");
8154
+ if ((detection?.reason === "user_question" || detection?.reason === "confirmation" || detection?.reason === "disambiguation" || detection?.reason === "planning_done") && !kinds.includes("askUserQuestion") && !kinds.includes("paneQuestion")) kinds.push("paneQuestion");
8155
+ }
8156
+ /**
8157
+ * PAN-3070 — the single predicate every "is this agent stuck?" surface consults.
8158
+ * Takes the detection fields rather than a whole enrichment so the REST listing,
8159
+ * the enrichment itself, and tests all judge from the same two values.
8160
+ */
8161
+ function isBlockedOnPendingInput(agent) {
8162
+ return agent.hasPendingQuestion === true && BLOCKING_AWAITING_INPUT_REASONS.has(agent.pendingQuestionReason ?? "");
8163
+ }
8164
+ function isOwnActiveSpecialist(role) {
8165
+ return role === "review" || role === "test" || role === "ship";
8166
+ }
8167
+ function getClaudeProjectDir(workspacePath) {
8168
+ return join$1(homedir(), ".claude", "projects", encodeClaudeProjectDir(workspacePath));
8169
+ }
8170
+ async function getActiveSessionPath(projectDir) {
8171
+ if (!existsSync(projectDir)) return null;
8172
+ try {
8173
+ const jsonlFiles = (await readdir$1(projectDir)).filter((f) => f.endsWith(".jsonl"));
8174
+ if (jsonlFiles.length === 0) return null;
8175
+ const withMtime = (await Promise.all(jsonlFiles.map(async (f) => {
8176
+ try {
8177
+ return {
8178
+ name: f,
8179
+ path: join$1(projectDir, f),
8180
+ mtime: (await stat$2(join$1(projectDir, f))).mtime.getTime()
8181
+ };
8182
+ } catch {
8183
+ return null;
8184
+ }
8185
+ }))).filter((x) => x !== null);
8186
+ if (withMtime.length === 0) return null;
8187
+ withMtime.sort((a, b) => b.mtime - a.mtime);
8188
+ return withMtime[0].path;
8189
+ } catch {
8190
+ return null;
8191
+ }
8192
+ }
8193
+ function getProjectPathByPrefix(issuePrefix) {
8194
+ const resolved = resolveProjectFromIssueSync(`${issuePrefix}-1`);
8195
+ if (resolved) return resolved.projectPath;
8196
+ const config = getGitHubConfig();
8197
+ if (config) {
8198
+ for (const { owner, repo, prefix } of config.repos) if ((prefix || repo.toUpperCase().replace(/-CLI$/, "").replace(/-/g, "")).toUpperCase() === issuePrefix.toUpperCase()) {
8199
+ const possiblePaths = [
8200
+ join$1(homedir(), "Projects", repo),
8201
+ join$1(homedir(), "Projects", repo.replace(/-cli$/, "")),
8202
+ join$1(homedir(), "Projects", owner, repo)
8203
+ ];
8204
+ for (const path of possiblePaths) if (existsSync(path)) return path;
8205
+ }
8206
+ }
8207
+ return join$1(homedir(), "Projects");
8208
+ }
8209
+ async function getAgentWorkspacePromise(agentId) {
8210
+ const workspace = getAgentStateSync(agentId)?.workspace;
8211
+ if (workspace) return workspace;
8212
+ try {
8213
+ const { stdout: paneCwd } = await execAsync$1(`tmux display-message -t ${agentId} -p '#{pane_current_path}' 2>/dev/null`, { encoding: "utf-8" });
8214
+ const trimmed = paneCwd.trim();
8215
+ if (trimmed && existsSync(trimmed)) return trimmed;
8216
+ } catch {}
8217
+ const isStrikeAgent = agentId.startsWith("strike-");
8218
+ const issueId = agentId.replace(/^(agent-|planning-|strike-)/, "").toUpperCase();
8219
+ const prefix = extractPrefixSync(issueId);
8220
+ if (!prefix) return null;
8221
+ try {
8222
+ const projectPath = getProjectPathByPrefix(prefix);
8223
+ const workspaceNames = isStrikeAgent ? [`feature-${issueId.toLowerCase()}-strike`, `feature-${issueId.toLowerCase()}`] : [`feature-${issueId.toLowerCase()}`];
8224
+ for (const workspaceName of workspaceNames) {
8225
+ const workspacePath = join$1(projectPath, "workspaces", workspaceName);
8226
+ if (existsSync(workspacePath)) return workspacePath;
8227
+ }
8228
+ return projectPath;
8229
+ } catch {
8230
+ return null;
8231
+ }
8232
+ }
8233
+ async function getAgentJsonlPathPromise(agentId) {
8234
+ const workspace = await Effect.runPromise(getAgentWorkspace(agentId));
8235
+ if (!workspace) return null;
8236
+ const projectDir = getClaudeProjectDir(workspace);
8237
+ const sessionId = getLatestSessionIdSync(agentId);
8238
+ if (sessionId) {
8239
+ const ownPath = join$1(projectDir, `${sessionId}.jsonl`);
8240
+ if (existsSync(ownPath)) return ownPath;
8241
+ }
8242
+ return await getActiveSessionPath(projectDir);
8243
+ }
8244
+ /**
8245
+ * Count outstanding AskUserQuestions across ALL of an agent's workspace JSONL
8246
+ * session files — not just the newest one. Claude Code rotates session files,
8247
+ * so an open AskUserQuestion can sit in a file that is not the most-recently-
8248
+ * modified. The complete-planning guard MUST be robust to that: scanning only
8249
+ * the active file let TIN-1 complete planning while the operator's question was
8250
+ * still open. Returns 0 only when no file has an unanswered AUQ.
8251
+ */
8252
+ async function countPendingAskUserQuestionsForAgentPromise(agentId) {
8253
+ const workspace = await Effect.runPromise(getAgentWorkspace(agentId));
8254
+ if (!workspace) return 0;
8255
+ const projectDir = getClaudeProjectDir(workspace);
8256
+ if (!existsSync(projectDir)) return 0;
8257
+ let files;
8258
+ try {
8259
+ files = (await readdir$1(projectDir)).filter((f) => f.endsWith(".jsonl"));
8260
+ } catch {
8261
+ return 0;
8262
+ }
8263
+ let total = 0;
8264
+ for (const f of files) try {
8265
+ const scan = await scanPendingInputsPromise(join$1(projectDir, f));
8266
+ total += scan.askUserQuestions.length;
8267
+ } catch {}
8268
+ return total;
8269
+ }
8270
+ /**
8271
+ * Count pending AskUserQuestions only in the current agent session generation.
8272
+ * A forced fresh start preserves historical JSONLs while replacing the agent
8273
+ * state directory, so an unpinned fallback transcript older than startedAt
8274
+ * belongs to the discarded generation and must not recreate the decision gate.
8275
+ */
8276
+ async function countPendingAskUserQuestionsForCurrentAgentSessionPromise(agentId) {
8277
+ const jsonlPath = await getAgentJsonlPathPromise(agentId);
8278
+ if (!jsonlPath) return 0;
8279
+ const currentSessionId = getLatestSessionIdSync(agentId);
8280
+ if (!(currentSessionId !== null && basename$1(jsonlPath) === `${currentSessionId}.jsonl`)) {
8281
+ const startedAtMs = Date.parse(getAgentStateSync(agentId)?.startedAt ?? "");
8282
+ if (Number.isFinite(startedAtMs)) try {
8283
+ if ((await stat$2(jsonlPath)).mtimeMs < startedAtMs) return 0;
8284
+ } catch {
8285
+ return 0;
8286
+ }
8287
+ }
8288
+ try {
8289
+ return (await scanPendingInputsPromise(jsonlPath)).askUserQuestions.length;
8290
+ } catch {
8291
+ return 0;
8292
+ }
8293
+ }
8294
+ /**
8295
+ * Read the last `maxBytes` from a file. Efficient for large JSONL files where
8296
+ * only recent entries (at the end) are relevant.
8297
+ */
8298
+ async function readFileTail(filePath, maxBytes) {
8299
+ try {
8300
+ const fileStat = await stat$2(filePath);
8301
+ const start = Math.max(0, fileStat.size - maxBytes);
8302
+ if (start === 0) return readFile$1(filePath, "utf-8");
8303
+ const { createReadStream } = await import("node:fs");
8304
+ return new Promise((resolve, reject) => {
8305
+ const stream = createReadStream(filePath, {
8306
+ start,
8307
+ encoding: "utf-8"
8308
+ });
8309
+ let data = "";
8310
+ stream.on("data", (chunk) => {
8311
+ data += chunk;
8312
+ });
8313
+ stream.on("end", () => resolve(data));
8314
+ stream.on("error", reject);
8315
+ });
8316
+ } catch {
8317
+ return "";
8318
+ }
8319
+ }
8320
+ function askUserQuestionDenySignalPresent(content) {
8321
+ const checkString = (text) => text.includes(ASK_USER_QUESTION_HOOK_DENY_MARKER) || text.includes(ASK_USER_QUESTION_HOOK_DENY_PHRASE);
8322
+ if (typeof content === "string") return checkString(content);
8323
+ if (Array.isArray(content)) return content.some((part) => {
8324
+ if (typeof part === "string") return checkString(part);
8325
+ if (part && typeof part === "object" && "text" in part) {
8326
+ const text = part.text;
8327
+ return typeof text === "string" && checkString(text);
8328
+ }
8329
+ return false;
8330
+ });
8331
+ return false;
8332
+ }
8333
+ function isAskUserQuestionHookDenyToolResult(item) {
8334
+ if (item.is_error !== true) return false;
8335
+ return askUserQuestionDenySignalPresent(item.content);
8336
+ }
8337
+ async function getPendingQuestionsPromise(jsonlPath) {
8338
+ return (await scanPendingInputsPromise(jsonlPath)).askUserQuestions;
8339
+ }
8340
+ /**
8341
+ * PAN-1520 — does this user-message entry carry operator text (i.e. an answer)
8342
+ * rather than just being a wrapper for a tool_result? When the hook denies an
8343
+ * AskUserQuestion the agent restates the question as plain text; the operator's
8344
+ * next user message — whether typed in the terminal, sent from the conversation
8345
+ * composer, or delivered by the answer-question route — is the actual answer.
8346
+ * The presence of that user-text turn after the deny is what resolves the AUQ.
8347
+ */
8348
+ function isUserTextEntry(entry) {
8349
+ if (!entry || typeof entry !== "object") return false;
8350
+ const e = entry;
8351
+ if (e.type !== "user") return false;
8352
+ const content = e.message?.content;
8353
+ if (typeof content === "string") return content.trim().length > 0;
8354
+ if (Array.isArray(content)) return content.some((item) => {
8355
+ if (!item || typeof item !== "object") return false;
8356
+ return item.type !== "tool_result";
8357
+ });
8358
+ return false;
8359
+ }
8360
+ async function scanPendingInputsPromise(jsonlPath) {
8361
+ if (!existsSync(jsonlPath)) return {
8362
+ askUserQuestions: [],
8363
+ enterPlanModeOpen: false,
8364
+ exitPlanModePending: false
8365
+ };
8366
+ try {
8367
+ const lines = (await readFileTail(jsonlPath, 512e3)).split("\n").filter((line) => line.trim());
8368
+ const askToolCalls = /* @__PURE__ */ new Map();
8369
+ const askAnswered = /* @__PURE__ */ new Set();
8370
+ const askDeniedAwaitingUser = /* @__PURE__ */ new Set();
8371
+ const exitPlanModeIds = /* @__PURE__ */ new Set();
8372
+ const exitPlanModeAnswered = /* @__PURE__ */ new Set();
8373
+ const exitPlanModeCalls = /* @__PURE__ */ new Map();
8374
+ let pendingExitPlanId;
8375
+ const enterPlanModeIds = /* @__PURE__ */ new Set();
8376
+ const exitPlanModeFiredAfterEnter = /* @__PURE__ */ new Set();
8377
+ for (const line of lines) try {
8378
+ const entry = JSON.parse(line);
8379
+ if (isUserTextEntry(entry)) {
8380
+ for (const id of askDeniedAwaitingUser) askAnswered.add(id);
8381
+ askDeniedAwaitingUser.clear();
8382
+ }
8383
+ const messageContent = entry.message?.content;
8384
+ if (!Array.isArray(messageContent)) continue;
8385
+ for (const item of messageContent) {
8386
+ if (item.type === "tool_use") {
8387
+ if (item.name === "AskUserQuestion" && typeof item.id === "string") askToolCalls.set(item.id, {
8388
+ toolId: item.id,
8389
+ timestamp: entry.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
8390
+ questions: item.input?.questions || []
8391
+ });
8392
+ else if (item.name === "ExitPlanMode" && typeof item.id === "string") {
8393
+ exitPlanModeIds.add(item.id);
8394
+ exitPlanModeFiredAfterEnter.add(item.id);
8395
+ const planText = typeof item.input?.plan === "string" ? item.input.plan : "";
8396
+ exitPlanModeCalls.set(item.id, {
8397
+ timestamp: entry.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
8398
+ plan: planText
8399
+ });
8400
+ pendingExitPlanId = item.id;
8401
+ } else if (item.name === "EnterPlanMode" && typeof item.id === "string") enterPlanModeIds.add(item.id);
8402
+ }
8403
+ if (item.type === "tool_result" && typeof item.tool_use_id === "string") {
8404
+ if (askToolCalls.has(item.tool_use_id)) if (isAskUserQuestionHookDenyToolResult(item)) askDeniedAwaitingUser.add(item.tool_use_id);
8405
+ else {
8406
+ askAnswered.add(item.tool_use_id);
8407
+ askDeniedAwaitingUser.delete(item.tool_use_id);
8408
+ }
8409
+ if (exitPlanModeIds.has(item.tool_use_id)) exitPlanModeAnswered.add(item.tool_use_id);
8410
+ }
8411
+ }
8412
+ } catch {}
8413
+ const askUserQuestions = Array.from(askToolCalls.entries()).filter(([id]) => !askAnswered.has(id)).map(([, question]) => question);
8414
+ const exitPlanModePending = Array.from(exitPlanModeIds).some((id) => !exitPlanModeAnswered.has(id));
8415
+ const pendingCall = pendingExitPlanId && !exitPlanModeAnswered.has(pendingExitPlanId) ? exitPlanModeCalls.get(pendingExitPlanId) : void 0;
8416
+ const pendingProposedPlan = pendingCall ? {
8417
+ toolUseId: pendingExitPlanId,
8418
+ askedAt: pendingCall.timestamp,
8419
+ plan: pendingCall.plan
8420
+ } : void 0;
8421
+ return {
8422
+ askUserQuestions,
8423
+ enterPlanModeOpen: enterPlanModeIds.size > 0 && exitPlanModeFiredAfterEnter.size === 0,
8424
+ exitPlanModePending,
8425
+ ...pendingProposedPlan ? { pendingProposedPlan } : {}
8426
+ };
8427
+ } catch {
8428
+ return {
8429
+ askUserQuestions: [],
8430
+ enterPlanModeOpen: false,
8431
+ exitPlanModePending: false
8432
+ };
8433
+ }
8434
+ }
8435
+ async function getAgentPendingQuestionsPromise(agentId) {
8436
+ const jsonlPath = await Effect.runPromise(getAgentJsonlPath(agentId));
8437
+ if (!jsonlPath) return [];
8438
+ return [...await Effect.runPromise(getPendingQuestions(jsonlPath))];
8439
+ }
8440
+ async function getAgentJsonlMtimePromise(agentId) {
8441
+ const jsonlPath = await Effect.runPromise(getAgentJsonlPath(agentId));
8442
+ if (!jsonlPath || !existsSync(jsonlPath)) return null;
8443
+ try {
8444
+ return (await stat$2(jsonlPath)).mtime.getTime();
8445
+ } catch {
8446
+ return null;
8447
+ }
8448
+ }
8449
+ async function computeAgentEnrichmentPromise(agentId, startedAt, hasActiveSpecialist, cachedScan) {
8450
+ const isPlanning = agentId.startsWith("planning-");
8451
+ const stateRole = getAgentStateSync(agentId)?.role;
8452
+ const role = stateRole === "plan" || stateRole === "work" || stateRole === "review" || stateRole === "test" || stateRole === "ship" || stateRole === "flywheel" ? stateRole : isPlanning ? "plan" : void 0;
8453
+ const runtimeState = await Effect.runPromise(getAgentRuntimeState(agentId));
8454
+ let scan = EMPTY_PENDING_INPUTS_SCAN;
8455
+ if (cachedScan) scan = cachedScan;
8456
+ else {
8457
+ const jsonlPath = await Effect.runPromise(getAgentJsonlPath(agentId));
8458
+ if (jsonlPath) scan = await scanPendingInputsPromise(jsonlPath);
8459
+ }
8460
+ let pendingQuestions = [...scan.askUserQuestions];
8461
+ const enterPlanModeOpen = scan.enterPlanModeOpen;
8462
+ const exitPlanModePending = scan.exitPlanModePending;
8463
+ if (pendingQuestions.length > 0 && startedAt) {
8464
+ const agentStartTime = new Date(startedAt).getTime();
8465
+ pendingQuestions = pendingQuestions.filter((q) => {
8466
+ const qTime = new Date(q.timestamp).getTime();
8467
+ return !isNaN(qTime) && qTime >= agentStartTime;
8468
+ });
8469
+ }
8470
+ const questionDetection = pendingQuestions.length > 0 ? {
8471
+ reason: "user_question",
8472
+ prompt: normalizeAwaitingInputPrompt(pendingQuestions[0]?.questions.map((q) => q.question).filter(Boolean).join("\n") || "Agent is waiting for a user answer")
8473
+ } : null;
8474
+ const runtimeDetection = runtimeState?.state === "waiting-on-human" ? {
8475
+ reason: runtimeState.waitingReason || "other",
8476
+ prompt: normalizeAwaitingInputPrompt(runtimeState.waitingNotification || "Agent is waiting for human input")
8477
+ } : null;
8478
+ const paneDetection = !questionDetection && !runtimeDetection ? await Effect.runPromise(detectAwaitingInputForAgent(agentId, { isPlanning })) : null;
8479
+ const fallbackDetection = runtimeState?.resolution === "needs_input" ? {
8480
+ reason: "other",
8481
+ prompt: normalizeAwaitingInputPrompt("Agent stopped because it needs human input or hit a blocker")
8482
+ } : null;
8483
+ const turnEndedWaiting = (role === "plan" || agentId.startsWith("conv-")) && runtimeState?.state === "idle";
8484
+ const turnEndedDetection = turnEndedWaiting ? {
8485
+ reason: "other",
8486
+ prompt: normalizeAwaitingInputPrompt("Agent finished its turn and is waiting for your reply")
8487
+ } : null;
8488
+ const detection = questionDetection ?? runtimeDetection ?? paneDetection ?? fallbackDetection ?? turnEndedDetection;
8489
+ const isSpecialistSuppressed = hasActiveSpecialist === true && !isOwnActiveSpecialist(role);
8490
+ const hasBlockingPaneDetection = paneDetection !== null && BLOCKING_AWAITING_INPUT_REASONS.has(paneDetection.reason);
8491
+ const shouldSuppressPendingInput = isSpecialistSuppressed && !hasBlockingPaneDetection;
8492
+ const hasPendingQuestion = !shouldSuppressPendingInput && detection !== null;
8493
+ const pendingInputKinds = [];
8494
+ let pendingAskUserQuestion;
8495
+ if (!isSpecialistSuppressed) {
8496
+ if (pendingQuestions.length > 0) {
8497
+ pendingInputKinds.push("askUserQuestion");
8498
+ const first = pendingQuestions[0];
8499
+ pendingAskUserQuestion = {
8500
+ toolUseId: first.toolId,
8501
+ askedAt: first.timestamp,
8502
+ questions: first.questions.map((q) => ({
8503
+ question: q.question,
8504
+ header: q.header,
8505
+ multiSelect: q.multiSelect,
8506
+ options: q.options.map((o) => ({
8507
+ label: o.label,
8508
+ description: o.description
8509
+ }))
8510
+ }))
8511
+ };
8512
+ }
8513
+ if (exitPlanModePending) pendingInputKinds.push("exitPlanMode");
8514
+ if (enterPlanModeOpen && !exitPlanModePending) pendingInputKinds.push("enterPlanMode");
8515
+ if (turnEndedWaiting && pendingInputKinds.length === 0) pendingInputKinds.push("agentTurnEnded");
8516
+ }
8517
+ if (!shouldSuppressPendingInput) appendPaneDetectionKind(detection, pendingInputKinds);
8518
+ return {
8519
+ role,
8520
+ hasPendingQuestion,
8521
+ pendingQuestionCount: shouldSuppressPendingInput ? 0 : pendingQuestions.length > 0 ? pendingQuestions.length : isBlockedOnPendingInput({
8522
+ hasPendingQuestion,
8523
+ pendingQuestionReason: detection?.reason
8524
+ }) ? 1 : 0,
8525
+ pendingQuestionPrompt: shouldSuppressPendingInput ? void 0 : detection?.prompt,
8526
+ pendingQuestionReason: shouldSuppressPendingInput ? void 0 : detection?.reason,
8527
+ pendingInputCount: pendingInputKinds.length,
8528
+ pendingInputKinds,
8529
+ pendingAskUserQuestion,
8530
+ pendingProposedPlan: isSpecialistSuppressed ? void 0 : scan.pendingProposedPlan,
8531
+ resolution: isBlockedOnPendingInput({
8532
+ hasPendingQuestion,
8533
+ pendingQuestionReason: detection?.reason
8534
+ }) ? "needs_input" : runtimeState?.resolution || "working",
8535
+ resolutionCount: runtimeState?.resolutionCount || 0,
8536
+ jsonlScan: scan
8537
+ };
8538
+ }
8539
+ var execAsync$1, BLOCKING_AWAITING_INPUT_REASONS, countPendingAskUserQuestionsForAgent, countPendingAskUserQuestionsForCurrentAgentSession, ASK_USER_QUESTION_HOOK_DENY_MARKER, ASK_USER_QUESTION_HOOK_DENY_PHRASE, EMPTY_PENDING_INPUTS_SCAN, computeAgentEnrichment, getAgentWorkspace, getAgentJsonlPath, getAgentJsonlMtime, getPendingQuestions, getAgentPendingQuestions;
8540
+ var init_agent_enrichment = __esmMin((() => {
8541
+ init_paths();
8542
+ init_errors();
8543
+ init_agent_state();
8544
+ init_runtime_state();
8545
+ init_agent_input_detection();
8546
+ init_projects();
8547
+ init_tracker_config();
8548
+ init_issue_id();
8549
+ init_activity();
8550
+ execAsync$1 = promisify$1(exec$1);
8551
+ BLOCKING_AWAITING_INPUT_REASONS = new Set([
8552
+ "tool_permission",
8553
+ "user_question",
8554
+ "disambiguation",
8555
+ "confirmation",
8556
+ "planning_done",
8557
+ "session_resume",
8558
+ "rate_limit"
8559
+ ]);
8560
+ countPendingAskUserQuestionsForAgent = (agentId) => Effect.promise(() => countPendingAskUserQuestionsForAgentPromise(agentId));
8561
+ countPendingAskUserQuestionsForCurrentAgentSession = (agentId) => Effect.promise(() => countPendingAskUserQuestionsForCurrentAgentSessionPromise(agentId));
8562
+ ASK_USER_QUESTION_HOOK_DENY_MARKER = "PAN-1520";
8563
+ ASK_USER_QUESTION_HOOK_DENY_PHRASE = "surfaced to the operator";
8564
+ EMPTY_PENDING_INPUTS_SCAN = Object.freeze({
8565
+ askUserQuestions: [],
8566
+ enterPlanModeOpen: false,
8567
+ exitPlanModePending: false
8568
+ });
8569
+ computeAgentEnrichment = (agentId, startedAt, hasActiveSpecialist, cachedScan) => Effect.tryPromise({
8570
+ try: () => computeAgentEnrichmentPromise(agentId, startedAt, hasActiveSpecialist, cachedScan),
8571
+ catch: (cause) => new FsError({
8572
+ path: getAgentDir(agentId),
8573
+ operation: "computeAgentEnrichment",
8574
+ cause
8575
+ })
8576
+ });
8577
+ getAgentWorkspace = (agentId) => Effect.promise(() => getAgentWorkspacePromise(agentId));
8578
+ getAgentJsonlPath = (agentId) => Effect.promise(() => getAgentJsonlPathPromise(agentId));
8579
+ getAgentJsonlMtime = (agentId) => Effect.promise(() => getAgentJsonlMtimePromise(agentId));
8580
+ getPendingQuestions = (jsonlPath) => Effect.promise(() => getPendingQuestionsPromise(jsonlPath));
8581
+ getAgentPendingQuestions = (agentId) => Effect.promise(() => getAgentPendingQuestionsPromise(agentId));
8582
+ }));
8583
+ //#endregion
8584
+ //#region ../../lib/agents/pending-decision-gate.ts
8585
+ async function detectPendingOperatorDecision(agentId, deps = {}) {
8586
+ const sessionExists$1 = deps.sessionExists ?? ((id) => Effect.runPromise(sessionExists(id)));
8587
+ const detectAwaitingInputForAgent$1 = deps.detectAwaitingInputForAgent ?? ((id) => Effect.runPromise(detectAwaitingInputForAgent(id)));
8588
+ const countPendingAskUserQuestionsForCurrentAgentSession$1 = deps.countPendingAskUserQuestionsForCurrentAgentSession ?? ((id) => Effect.runPromise(countPendingAskUserQuestionsForCurrentAgentSession(id)));
8589
+ const warn = deps.warn ?? console.warn;
8590
+ let liveSession = false;
8591
+ try {
8592
+ liveSession = await sessionExists$1(agentId);
8593
+ } catch (error) {
8594
+ if (!(error instanceof TmuxError)) throw error;
8595
+ warn(`[agents] Pending operator decision pane check failed open for ${agentId}: ${error.message}`);
8596
+ }
8597
+ if (liveSession) try {
8598
+ const detection = await detectAwaitingInputForAgent$1(agentId);
8599
+ if (detection && DESTRUCTIVE_RECOVERY_BLOCKING_REASONS.has(detection.reason)) return {
8600
+ source: "pane",
8601
+ reason: detection.reason,
8602
+ prompt: detection.prompt
8603
+ };
8604
+ } catch (error) {
8605
+ if (!(error instanceof TmuxError)) throw error;
8606
+ warn(`[agents] Pending operator decision pane check failed open for ${agentId}: ${error.message}`);
8607
+ }
8608
+ if (await countPendingAskUserQuestionsForCurrentAgentSession$1(agentId) > 0) return {
8609
+ source: "jsonl-auq",
8610
+ reason: "ask_user_question"
8611
+ };
8612
+ return null;
8613
+ }
8614
+ var DESTRUCTIVE_RECOVERY_BLOCKING_REASONS;
8615
+ var init_pending_decision_gate = __esmMin((() => {
8616
+ init_agent_enrichment();
8617
+ init_agent_input_detection();
8618
+ init_errors();
8619
+ init_tmux();
8620
+ DESTRUCTIVE_RECOVERY_BLOCKING_REASONS = new Set([
8621
+ "tool_permission",
8622
+ "user_question",
8623
+ "disambiguation",
8624
+ "confirmation",
8625
+ "planning_done",
8626
+ "session_resume"
8627
+ ]);
8628
+ }));
8629
+ //#endregion
7733
8630
  //#region ../../lib/agents/recovery.ts
7734
8631
  function resolveRecoveryResumeSessionId(agentId, harness) {
7735
- if (harness !== "codex" && harness !== "acp") return void 0;
8632
+ if (harness !== "codex" && harness !== "acp" && harness !== "kimi-code") return void 0;
7736
8633
  return getLatestSessionIdSync(agentId) ?? void 0;
7737
8634
  }
7738
- async function restartAgent(agentId, opts = {}) {
8635
+ async function restartAgent(agentId, opts = {}, deps = {}) {
7739
8636
  const normalizedId = normalizeAgentId(agentId);
7740
- const { graceful = true, model: rawNewModel, harness: newHarness, message } = opts;
8637
+ const { graceful = true, model: rawNewModel, harness: newHarness, message, force = false } = opts;
7741
8638
  const newModel = normalizeModelOverrideSync(rawNewModel);
7742
- const agentState = getAgentStateSync(normalizedId);
8639
+ const readAgentState = deps.getAgentStateSync ?? getAgentStateSync;
8640
+ const detectPendingDecision = deps.detectPendingOperatorDecision ?? detectPendingOperatorDecision;
8641
+ const logLifecycle = deps.logAgentLifecycleSync ?? logAgentLifecycleSync;
8642
+ const assertWorkspaceHealthy = deps.assertWorkspaceStackHealthyForSpawn ?? assertWorkspaceStackHealthyForSpawn;
8643
+ const resolveRestartHarness = deps.resolveHarness ?? resolveHarness;
8644
+ const prepareRestartHarness = deps.prepareHarnessLaunch ?? prepareHarnessLaunch;
8645
+ const restartSessionExists = deps.sessionExists ?? ((id) => Effect.runPromise(sessionExists(id)));
8646
+ const sendRestartWarning = deps.sendGracefulRestartWarning ?? sendGracefulRestartWarning;
8647
+ const stopRestartAgent = deps.stopAgent ?? ((id) => Effect.runPromise(stopAgent(id)));
8648
+ const agentState = readAgentState(normalizedId);
7743
8649
  if (!agentState) return {
7744
8650
  success: false,
7745
8651
  error: `Agent ${normalizedId} not found`
@@ -7747,36 +8653,57 @@ async function restartAgent(agentId, opts = {}) {
7747
8653
  const gateDecision = decideResumeGate(getAgentResumeGateBlockReason(agentState), "operator-start");
7748
8654
  if (gateDecision.decision === "block") {
7749
8655
  const reason = `Cannot restart ${normalizedId}: ${gateDecision.reason}. Clear the gate before restarting.`;
7750
- logAgentLifecycleSync(normalizedId, `restartAgent BLOCKED: ${reason}`);
8656
+ logLifecycle(normalizedId, `restartAgent BLOCKED: ${reason}`);
7751
8657
  return {
7752
8658
  success: false,
7753
8659
  error: reason
7754
8660
  };
7755
8661
  }
8662
+ const checkPendingDecision = async () => {
8663
+ if (force) return null;
8664
+ const pendingDecision = await detectPendingDecision(normalizedId);
8665
+ if (!pendingDecision) return null;
8666
+ const reason = `Agent ${normalizedId} is waiting on an operator decision (${pendingDecision.reason.replaceAll("_", " ")}). Answer it with 'pan answer ${agentState.issueId || normalizedId.replace(/^agent-/, "").toUpperCase()}' or open the Decisions panel; pass force to discard it deliberately.`;
8667
+ logLifecycle(normalizedId, `restartAgent BLOCKED: ${reason}`);
8668
+ return {
8669
+ success: false,
8670
+ error: reason,
8671
+ code: "pending-operator-decision",
8672
+ pendingDecision
8673
+ };
8674
+ };
8675
+ const initialPendingDecision = await checkPendingDecision();
8676
+ if (initialPendingDecision) return initialPendingDecision;
7756
8677
  if (!agentState.workspace || !existsSync(agentState.workspace)) return {
7757
8678
  success: false,
7758
8679
  error: `Agent workspace missing: ${agentState.workspace}`
7759
8680
  };
7760
- logAgentLifecycleSync(normalizedId, `restartAgent called (graceful=${graceful}, model=${newModel || "unchanged"}, harness=${newHarness || "unchanged"})`);
8681
+ logLifecycle(normalizedId, `restartAgent called (graceful=${graceful}, model=${newModel || "unchanged"}, harness=${newHarness || "unchanged"})`);
7761
8682
  try {
7762
- await assertWorkspaceStackHealthyForSpawn(agentState.issueId || normalizedId.replace(/^agent-/, "").toUpperCase(), agentState.role ?? "work", agentState.hostOverride === true, agentState.workspace);
8683
+ await assertWorkspaceHealthy(agentState.issueId || normalizedId.replace(/^agent-/, "").toUpperCase(), agentState.role ?? "work", agentState.hostOverride === true, agentState.workspace);
7763
8684
  } catch (error) {
7764
8685
  const reason = error instanceof Error ? error.message : String(error);
7765
- logAgentLifecycleSync(normalizedId, `restartAgent BLOCKED: ${reason}`);
8686
+ logLifecycle(normalizedId, `restartAgent BLOCKED: ${reason}`);
7766
8687
  return {
7767
8688
  success: false,
7768
8689
  error: reason
7769
8690
  };
7770
8691
  }
7771
8692
  const effectiveModel = newModel || requireModelOverrideSync(agentState.model || "claude-sonnet-4-6");
7772
- const effectiveHarness = await resolveHarness({
8693
+ const effectiveHarness = await resolveRestartHarness({
7773
8694
  explicit: newHarness ?? agentState.harness,
7774
8695
  role: agentState.role,
7775
8696
  model: effectiveModel
7776
8697
  });
7777
- const harnessLaunch = await prepareHarnessLaunch(effectiveHarness);
7778
- if (graceful && await Effect.runPromise(sessionExists(normalizedId))) await sendGracefulRestartWarning(normalizedId, agentState.harness, agentState.workspace);
7779
- await Effect.runPromise(stopAgent(normalizedId));
8698
+ const harnessLaunch = await prepareRestartHarness(effectiveHarness);
8699
+ if (graceful && await restartSessionExists(normalizedId)) {
8700
+ const warningPendingDecision = await checkPendingDecision();
8701
+ if (warningPendingDecision) return warningPendingDecision;
8702
+ await sendRestartWarning(normalizedId, agentState.harness, agentState.workspace);
8703
+ }
8704
+ const stopPendingDecision = await checkPendingDecision();
8705
+ if (stopPendingDecision) return stopPendingDecision;
8706
+ await stopRestartAgent(normalizedId);
7780
8707
  if (newModel && newModel !== agentState.model) agentState.model = newModel;
7781
8708
  agentState.harness = effectiveHarness;
7782
8709
  agentState.status = "starting";
@@ -7800,16 +8727,40 @@ async function restartAgent(agentId, opts = {}) {
7800
8727
  const launcherScript = join$1(getAgentDir(normalizedId), "launcher.sh");
7801
8728
  await writeLauncherScriptAtomic(launcherScript, launcherContent);
7802
8729
  const claudeCmd = `bash ${launcherScript}`;
7803
- await Effect.runPromise(createSession(normalizedId, agentState.workspace, claudeCmd, { env: {
7804
- ...BLANKED_PROVIDER_ENV,
7805
- TERM: "xterm-256color",
7806
- OVERDECK_AGENT_ID: normalizedId,
7807
- OVERDECK_ISSUE_ID: agentState.issueId || "",
7808
- OVERDECK_SESSION_TYPE: agentState.role,
7809
- CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
7810
- GIT_SEQUENCE_EDITOR: "false",
7811
- ...providerEnv
7812
- } }));
8730
+ const launchAndCaptureKimiSession = async () => {
8731
+ let kimiExistingSessionsBefore;
8732
+ if (effectiveHarness === "kimi-code") {
8733
+ try {
8734
+ unlinkSync(join$1(getAgentDir(normalizedId), "kimi-session-id"));
8735
+ } catch {}
8736
+ try {
8737
+ const { kimiSessionsRoot } = await import("./kimi-code-D_Ppt82c.js");
8738
+ kimiExistingSessionsBefore = new Set(await readdir$1(kimiSessionsRoot(join$1(homedir(), ".kimi-code"), agentState.workspace)));
8739
+ } catch {
8740
+ kimiExistingSessionsBefore = /* @__PURE__ */ new Set();
8741
+ }
8742
+ }
8743
+ await Effect.runPromise(createSession(normalizedId, agentState.workspace, claudeCmd, { env: {
8744
+ ...BLANKED_PROVIDER_ENV,
8745
+ TERM: "xterm-256color",
8746
+ OVERDECK_AGENT_ID: normalizedId,
8747
+ OVERDECK_ISSUE_ID: agentState.issueId || "",
8748
+ OVERDECK_SESSION_TYPE: agentState.role,
8749
+ CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
8750
+ GIT_SEQUENCE_EDITOR: "false",
8751
+ ...providerEnv
8752
+ } }));
8753
+ if (kimiExistingSessionsBefore) {
8754
+ const { waitForNewKimiSessionAsync, writeKimiSessionId } = await import("./kimi-code-D_Ppt82c.js");
8755
+ const sessionId = await waitForNewKimiSessionAsync(join$1(homedir(), ".kimi-code"), agentState.workspace, kimiExistingSessionsBefore);
8756
+ if (!sessionId) throw new Error(`kimi-code session capture timed out after fresh relaunch for ${normalizedId} — no new session directory appeared under the workspace bucket`);
8757
+ writeKimiSessionId(normalizedId, sessionId);
8758
+ }
8759
+ };
8760
+ if (effectiveHarness === "kimi-code") {
8761
+ const { withKimiSessionCaptureLock } = await import("./kimi-code-D_Ppt82c.js");
8762
+ await withKimiSessionCaptureLock(join$1(homedir(), ".kimi-code"), agentState.workspace, launchAndCaptureKimiSession);
8763
+ } else await launchAndCaptureKimiSession();
7813
8764
  const prompt = message || buildResumeContinueMessage(agentState);
7814
8765
  if (effectiveHarness === "ohmypi") try {
7815
8766
  await writeOhmypiAgentPrompt(normalizedId, prompt);
@@ -7820,7 +8771,7 @@ async function restartAgent(agentId, opts = {}) {
7820
8771
  else {
7821
8772
  if (!await waitForPromptReady(normalizedId, effectiveHarness, 30)) throw new Error(`${getHarnessBehavior(effectiveHarness).displayName} did not become ready within 30s for ${normalizedId}`);
7822
8773
  await new Promise((r) => setTimeout(r, 500));
7823
- if (effectiveHarness === "codex" || effectiveHarness === "acp") {
8774
+ if (effectiveHarness === "codex" || effectiveHarness === "acp" || effectiveHarness === "kimi-code") {
7824
8775
  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`);
7825
8776
  } else await Effect.runPromise(sendKeys(normalizedId, prompt));
7826
8777
  }
@@ -7830,12 +8781,12 @@ async function restartAgent(agentId, opts = {}) {
7830
8781
  state: "active",
7831
8782
  lastActivity: (/* @__PURE__ */ new Date()).toISOString()
7832
8783
  });
7833
- logAgentLifecycleSync(normalizedId, `restartAgent SUCCESS: model=${effectiveModel}`);
8784
+ logLifecycle(normalizedId, `restartAgent SUCCESS: model=${effectiveModel}`);
7834
8785
  return { success: true };
7835
8786
  } catch (error) {
7836
8787
  const msg = error instanceof Error ? error.message : String(error);
7837
8788
  await Effect.runPromise(stopAgent(normalizedId)).catch(() => void 0);
7838
- logAgentLifecycleSync(normalizedId, `restartAgent FAILED: ${msg}`);
8789
+ logLifecycle(normalizedId, `restartAgent FAILED: ${msg}`);
7839
8790
  return {
7840
8791
  success: false,
7841
8792
  error: `Failed to restart agent: ${msg}`
@@ -7878,6 +8829,13 @@ async function recoverAgent(agentId, opts = {}) {
7878
8829
  logAgentLifecycleSync(normalizedId, `recoverAgent BLOCKED: Cannot recover ${normalizedId}: ${gateDecision.reason}. Clear the gate before recovering.`);
7879
8830
  return null;
7880
8831
  }
8832
+ if (!opts.force) {
8833
+ const pendingDecision = await detectPendingOperatorDecision(normalizedId);
8834
+ if (pendingDecision) {
8835
+ logAgentLifecycleSync(normalizedId, `recoverAgent BLOCKED: pending operator decision (${pendingDecision.reason})`);
8836
+ return null;
8837
+ }
8838
+ }
7881
8839
  const modelOverride = normalizeModelOverrideSync(opts.modelOverride);
7882
8840
  if (modelOverride) {
7883
8841
  state.model = modelOverride;
@@ -7997,6 +8955,64 @@ async function recoverAgent(agentId, opts = {}) {
7997
8955
  logAgentLifecycleSync(normalizedId, `recoverAgent SUCCESS: recoveryCount=${health.recoveryCount} (acp)`);
7998
8956
  return state;
7999
8957
  }
8958
+ if (recoveryHarness === "kimi-code") {
8959
+ const resumeSessionId = resolveRecoveryResumeSessionId(normalizedId, recoveryHarness);
8960
+ const { launcherContent, providerEnv: kimiProviderEnv } = await buildAgentLaunchConfig({
8961
+ agentId: normalizedId,
8962
+ model: state.model,
8963
+ workspace: state.workspace,
8964
+ role: recoveryRole,
8965
+ isPlanning: recoveryRole === "plan",
8966
+ ...resumeSessionId ? {
8967
+ spawnMode: "resume",
8968
+ resumeSessionId
8969
+ } : {},
8970
+ harness: "kimi-code",
8971
+ harnessBinaryPath: harnessLaunch.binaryPath,
8972
+ extraEnvExports: [harnessLaunch.pathExport]
8973
+ });
8974
+ const launcherScript = join$1(getAgentDir(normalizedId), "launcher.sh");
8975
+ await writeLauncherScriptAtomic(launcherScript, launcherContent);
8976
+ const launchAndCaptureKimiSession = async () => {
8977
+ let kimiExistingSessionsBefore;
8978
+ if (!resumeSessionId) try {
8979
+ const { kimiSessionsRoot } = await import("./kimi-code-D_Ppt82c.js");
8980
+ kimiExistingSessionsBefore = new Set(await readdir$1(kimiSessionsRoot(join$1(homedir(), ".kimi-code"), state.workspace)));
8981
+ } catch {
8982
+ kimiExistingSessionsBefore = /* @__PURE__ */ new Set();
8983
+ }
8984
+ await Effect.runPromise(createSession(normalizedId, state.workspace, `bash ${launcherScript}`, { env: {
8985
+ ...BLANKED_PROVIDER_ENV,
8986
+ OVERDECK_AGENT_ID: normalizedId,
8987
+ OVERDECK_ISSUE_ID: state.issueId || "",
8988
+ OVERDECK_SESSION_TYPE: recoveryRole,
8989
+ CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
8990
+ ...kimiProviderEnv
8991
+ } }));
8992
+ if (kimiExistingSessionsBefore) {
8993
+ const { waitForNewKimiSessionAsync, writeKimiSessionId } = await import("./kimi-code-D_Ppt82c.js");
8994
+ const sessionId = await waitForNewKimiSessionAsync(join$1(homedir(), ".kimi-code"), state.workspace, kimiExistingSessionsBefore);
8995
+ if (sessionId) writeKimiSessionId(normalizedId, sessionId);
8996
+ else throw new Error(`kimi-code session capture timed out after fresh relaunch for ${normalizedId} — no new session directory appeared under the workspace bucket`);
8997
+ }
8998
+ };
8999
+ const { withKimiSessionCaptureLock } = await import("./kimi-code-D_Ppt82c.js");
9000
+ try {
9001
+ await withKimiSessionCaptureLock(join$1(homedir(), ".kimi-code"), state.workspace, launchAndCaptureKimiSession);
9002
+ } catch (err) {
9003
+ await Effect.runPromise(stopAgent(normalizedId)).catch(() => void 0);
9004
+ throw err;
9005
+ }
9006
+ const delivery = await deliverInitialPromptWithRetry(normalizedId, recoveryPrompt, "recoverAgent:kimi-code-recovery-prompt");
9007
+ if (!delivery.ok) {
9008
+ await Effect.runPromise(stopAgent(normalizedId));
9009
+ throw new Error(`Kimi Code recovery prompt delivery failed for ${normalizedId}: ${delivery.failure ?? "unknown failure"}`);
9010
+ }
9011
+ markAgentRunning(state);
9012
+ saveAgentStateSync(state);
9013
+ logAgentLifecycleSync(normalizedId, `recoverAgent SUCCESS: recoveryCount=${health.recoveryCount} (kimi-code)`);
9014
+ return state;
9015
+ }
8000
9016
  const recoveryCodexFields = recoveryHarness === "codex" ? getCodexLauncherFields(normalizedId, state.model, state.workspace, recoveryRole) : {};
8001
9017
  const recoveryLauncherContent = generateLauncherScriptSync({
8002
9018
  role: recoveryRole,
@@ -8103,6 +9119,7 @@ var init_recovery = __esmMin((() => {
8103
9119
  init_agent_state();
8104
9120
  init_delivery();
8105
9121
  init_identity();
9122
+ init_pending_decision_gate();
8106
9123
  init_queries();
8107
9124
  init_provider_env();
8108
9125
  init_runtime_state();
@@ -8627,13 +9644,14 @@ function extractTracedFrText(prdMarkdown, traces) {
8627
9644
  return sections.length > 0 ? sections.join("\n\n") : void 0;
8628
9645
  }
8629
9646
  /**
8630
- * Read the Overdeck-managed PRD draft for an issue
8631
- * (<projectRoot>/.pan/drafts/<ISSUE>.md, falling back to the lowercase
8632
- * filename). Returns undefined when no draft exists.
9647
+ * Read the Overdeck-managed PRD draft for an issue through the
9648
+ * state-branch-aware path authority, falling back to the lowercase filename.
9649
+ * Returns undefined when no draft exists.
8633
9650
  */
8634
9651
  async function loadPrdDraft(projectRoot, issueId) {
9652
+ const draftsDir = getProjectPanPaths(projectRoot).draftsDir;
8635
9653
  for (const name of [`${issueId.toUpperCase()}.md`, `${issueId.toLowerCase()}.md`]) try {
8636
- return await readFile(join(projectRoot, ".pan", "drafts", name), "utf-8");
9654
+ return await readFile(join(draftsDir, name), "utf-8");
8637
9655
  } catch {}
8638
9656
  }
8639
9657
  /**
@@ -8727,6 +9745,7 @@ async function deliverCommitForReview(options) {
8727
9745
  var SUPERVISOR_SUB_ROLE, execFileAsync$4;
8728
9746
  var init_tier_supervisor = __esmMin((() => {
8729
9747
  init_git_utils();
9748
+ init_paths$1();
8730
9749
  init_delivery();
8731
9750
  init_spawn_prep();
8732
9751
  init_spawn();
@@ -9686,7 +10705,7 @@ var init_runtime_census = __esmMin((() => {
9686
10705
  ]);
9687
10706
  runtimeCensusService = createRuntimeCensusService({
9688
10707
  listPanes: async () => {
9689
- const { listAllPaneRecords } = await import("./tmux-Ctk6RV5l.js");
10708
+ const { listAllPaneRecords } = await import("./tmux-Cjpx8L8u.js");
9690
10709
  return Effect.runPromise(listAllPaneRecords());
9691
10710
  },
9692
10711
  readProcesses: readRuntimeProcessTable
@@ -9840,6 +10859,6 @@ var init_queries = __esmMin((() => {
9840
10859
  });
9841
10860
  }));
9842
10861
  //#endregion
9843
- export { operatorInterventionEvent as $, getAgentDir as $n, providerDefaultHarnessSync as $t, spawnTierSupervisor as A, getProviderExportsForModel as An, resolvePtySupervisorScriptPath as Ar, AmbiguousKeyedDeliveryError as At, detectCrashedAgents as B, dismissDevChannelsDialog as Bn, saveAgentRuntimeState 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_token as Dr, getCachedMemoryVerdict as Dt, deliverCommitForReview as E, buildCavemanExports as En, init_resume_contract as Er, workResumeSlotsAvailable as Et, init_tier_escalation as F, init_openai_auth as Fn, waitForAgentIdle as Fr, deliverResumeMessageWithTranscriptConfirmation as Ft, resumeAgent as G, SESSION_EXITED_BEFORE_KICKOFF as Gn, init_codex_auth as Gr, assertWorkspaceStackHealthyForSpawn as Gt, restartAgent as H, init_supervisor_channels as Hn, init_agent_runtime as Hr, BRIDGE_TOKEN_HEADER as Ht, init_slot_reconcile as I, buildDefaultResumeContinueMessage as In, waitForReadySignal as Ir, init_delivery as It, isContextOverflowTail as J, clearAgentPausedSync as Jn, parseOhmypiSessionCostResultSync as Jr, init_spawn_prep as Jt, init_context_overflow as K, __testInternals as Kn, paneShowsCodexAuthBurn as Kr, buildAgentLaunchConfig as Kt, listSlotAssignments as L, buildResumeContinueMessage as Ln, getAgentRuntimeState as Lr, resilientDeliveryMethod as Lt, broadcastCommit as M, init_provider_health as Mn, isQualifiedAgentId as Mr, deliverAgentMessage as Mt, init_tier_feed as N, validateProviderHealth as Nn, normalizeAgentId as Nr, deliverAgentPermissionDecision as Nt, loadPrdDraft as O, determineModel as On, writePtyToken as Or, init_memory_verdict_cache as Ot, decideEscalation as P, getOpenAIAuthStatus as Pn, resolveAgentTargetSync as Pr, deliverInitialPromptWithRetry as Pt, init_operator_interventions as Q, decideResumeGate as Qn, init_staffing as Qt, reconcileSlotState as R, decideChannelsForWorkAgent as Rn, getAgentRuntimeStateSync 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, buildResumeContract as Tr, tryReserveSwarmSlot as Tt, buildCompactRecoverySeed as U, writeChannelsBridgeMcpConfig as Un, applyCodexAuthBurnFlag as Ur, init_bridge_token as Ut, recoverAgent as V, hasCompletionMarkerForAgent as Vn, getAgentRuntimeSnapshot as Vr, probeTranscriptSince as Vt, init_resume as W, GOVERNOR_SLOT_PAUSE_REASON_PREFIX as Wn, checkCodexAuthStatus 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, clearReadySignal as jr, SocketPostStatusError as jt, shouldSupervise as k, getProviderEnvForModel as kn, init_pty_supervisor_locate 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, init_ohmypi_parser as qr, 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, init_runtime_state as zr, captureTranscriptUserRecordSnapshot as zt };
10862
+ export { scanPendingInputsPromise as $, buildDefaultResumeContinueMessage as $n, waitForReadySignal as $r, resilientDeliveryMethod as $t, spawnTierSupervisor as A, init_runtime_command as An, recordAgentFailureSync as Ar, countRunningAgents as At, detectCrashedAgents as B, materializeAcpContextFile as Bn, init_agent_record_sync as Br, tryReserveSwarmSlot as Bt, replayCrashedStandingAgent as C, getAcpLauncherFields as Cn, isAgentTroubled as Cr, init_ohmypi as Ct, init_tier_supervisor as D, getOhmypiLauncherFields as Dn, markAgentStoppedState as Dr, init_termination as Dt, deliverCommitForReview as E, getKimiCodeLauncherFields as En, markAgentRunningState as Er, spawnRun as Et, init_tier_escalation as F, init_pi_fifo as Fn, setAgentPaused as Fr, init_concurrency as Ft, computeAgentEnrichment as G, determineModel as Gn, writePtyToken as Gr, AmbiguousKeyedDeliveryError as Gt, restartAgent as H, init_claude_auth as Hn, buildResumeContract as Hr, getCachedMemoryVerdict as Ht, init_slot_reconcile as I, piFifoPaths as In, setAgentPausedSync as Ir, releaseAdvancingSlot as It, getAgentJsonlPath as J, getProviderTmuxFlags as Jn, clearReadySignal as Jr, deliverAgentPermissionDecision as Jt, countPendingAskUserQuestionsForAgent as K, getProviderEnvForModel as Kn, init_pty_supervisor_locate as Kr, SocketPostStatusError as Kt, listSlotAssignments as L, init_ohmypi_fifo as Ln, setAgentYieldedSync as Lr, releaseSwarmSlot as Lt, broadcastCommit as M, roleAgentDefinitionPath as Mn, resetAgentFailureCount as Mr, describeRunningAgents as Mt, init_tier_feed as N, waitForAcpHostReady as Nn, saveAgentState as Nr, emergencyBrake as Nt, loadPrdDraft as O, getProviderAuthMode as On, markAgentTroubled as Or, stopAgent as Ot, decideEscalation as P, waitForPromptReady as Pn, saveAgentStateSync as Pr, getConcurrencyLimits as Pt, isBlockedOnPendingInput as Q, init_openai_auth as Qn, waitForAgentIdle as Qr, keyedSupervisorFailureKind as Qt, reconcileSlotState as R, ohmypiFifoPaths as Rn, wipeAgentStateDirs as Rr, resetPatrolDispatchBudget as Rt, contextWindowForModel as S, describeOhmypiSpawnFailure as Sn, isAgentPaused as Sr, createOhmypiRuntimeSync as St, shouldReplayCompactAtTierRunBoundary as T, getCodexLauncherFields as Tn, markAgentRunning as Tr, spawnAgent as Tt, detectPendingOperatorDecision as U, buildCavemanExports as Un, init_resume_contract as Ur, init_memory_verdict_cache as Ut, recoverAgent as V, getClaudeAuthStatus as Vn, readAgentHarnessModelRecordSync as Vr, workResumeSlotsAvailable as Vt, init_pending_decision_gate as W, buildSpawnEnvForModel as Wn, init_pty_token as Wr, setCachedMemoryVerdict as Wt, getAgentWorkspace as X, validateProviderHealth as Xn, normalizeAgentId as Xr, deliverResumeMessageWithTranscriptConfirmation as Xt, getAgentPendingQuestions as Y, init_provider_health as Yn, isQualifiedAgentId as Yr, deliverInitialPromptWithRetry as Yt, init_agent_enrichment as Z, getOpenAIAuthStatus as Zn, resolveAgentTargetSync as Zr, init_delivery as Zt, init_linux as _, resolveIssueWorkModel as _n, getAgentResumeGateBlockReason as _r, getActivity as _t, listRunningAgentsSync as a, init_agent_runtime as ai, init_bridge_token as an, init_supervisor_channels as ar, buildCompactRecoverySeed as at, init_agents as b, resolveTier as bn, getAgentStateSync as br, getSessionId as bt, getRuntimeCensus as c, init_codex_auth as ci, buildAgentLaunchConfig as cn, SESSION_EXITED_BEFORE_KICKOFF as cr, init_context_overflow as ct, panePidsForSession as d, parseOhmypiSessionCostResultSync as di, retrieveSpawnTimeMemoryContext as dn, clearAgentPausedSync as dr, init_messaging as dt, getAgentRuntimeState as ei, setAgentDeliveryMethod as en, buildResumeContinueMessage as er, detectAwaitingInputForAgent as et, refreshRuntimeCensus as f, transitionIssueToInProgress as fn, clearAgentTroubled as fr, messageAgent as ft, LINUX_MEMORY_PRESSURE_DEFAULTS as g, resolveImplicitStaffing as gn, getAgentDir as gr, appendActivity as gt, init_collector as h, providerDefaultHarnessSync as hn, decideResumeGate as hr, operatorInterventionEvent as ht, listRunningAgents as i, getAgentRuntimeSnapshot as ii, BRIDGE_TOKEN_HEADER as in, hasCompletionMarkerForAgent as ir, parseCodexApprovalPrompt as it, supervisorAgentId as j, injectPiConversationMemory as jn, recordStartupSessionExit as jr, countRunningSwarmSlotsForIssue as jt, shouldSupervise as k, getRoleRuntimeBaseCommand as kn, recordAgentFailure as kr, stopAgentSync as kt, getRuntimeCensusSnapshot as l, paneShowsCodexAuthBurn as li, defaultRunWorkspace as ln, __testInternals as lr, isContextOverflowError as lt, createHostHealthCollector as m, init_staffing as mn, clearYieldForResumeSync as mr, init_operator_interventions as mt, init_queries as n, init_runtime_state as ni, init_transcript_landing as nn, decideSupervisorForWorkAgent as nr, init_agent_input_detection as nt, warnOnBareNumericIssueIds as o, applyCodexAuthBurnFlag as oi, writeBridgeTokenSync as on, writeChannelsBridgeMcpConfig as or, init_resume as ot, runtimeCensusHasHarnessProcess as p, transitionIssueToInReview as pn, clearAgentTroubledSync as pr, messageAgentWithOutcome as pt, getAgentJsonlMtime as q, getProviderExportsForModel as qn, resolvePtySupervisorScriptPath as qr, deliverAgentMessage as qt, listAgentStates as r, saveAgentRuntimeState as ri, probeTranscriptSince as rn, dismissDevChannelsDialog as rr, normalizeAwaitingInputPrompt as rt, descendantPidsForSession as s, checkCodexAuthStatus as si, assertWorkspaceStackHealthyForSpawn as sn, GOVERNOR_SLOT_PAUSE_REASON_PREFIX as sr, resumeAgent as st, dropLegacyAgentStatesMissingRoleAsync as t, getAgentRuntimeStateSync as ti, captureTranscriptUserRecordSnapshot as tn, decideChannelsForWorkAgent as tr, detectAwaitingInputFromPaneSync as tt, init_runtime_census as u, init_ohmypi_parser as ui, init_spawn_prep as un, clearAgentPaused as ur, isContextOverflowTail as ut, DARWIN_MEMORY_PRESSURE_DEFAULTS as v, resolveStaffing as vn, getAgentState as vr, getLatestSessionId as vt, replayStandingAgent as w, getAgentRuntimeBaseCommand as wn, isRole as wr, init_spawn as wt, compactAtTierRunBoundary as x, OHMYPI_AGENT_READY_TIMEOUT_SECONDS as xn, init_agent_state as xr, saveSessionId as xt, init_darwin as y, init_resolve_tier as yn, getAgentStateFilePath as yr, getLatestSessionIdSync as yt, autoRecoverAgents as z, init_context as zn, writeAgentStateJsonSync as zr, tryReserveAdvancingSlot as zt };
9844
10863
 
9845
- //# sourceMappingURL=queries-C-MUZaIy.js.map
10864
+ //# sourceMappingURL=queries-DVpl1vsU.js.map