@overdeck/desktop 0.49.1 → 0.49.2

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 (497) hide show
  1. package/package.json +1 -1
  2. package/server/{acceptance-criteria-Crw-xSJ3.js → acceptance-criteria-CHtDkHEL.js} +2 -2
  3. package/server/{active-dashboard-bundle-CLwfD-Om.js → active-dashboard-bundle-Byh6sP-q.js} +2 -2
  4. package/server/{activity-logger-BAVLrkR7.js → activity-logger-BWZhVphb.js} +22 -4
  5. package/server/activity-logger-Ck8qoluj.js +3 -0
  6. package/server/{advancing-selfheal-BQiJ7mIH.js → advancing-selfheal-65W4yUQi.js} +6 -6
  7. package/server/{agent-gc-5E0lgxI1.js → agent-gc-BNUudFnt.js} +10 -10
  8. package/server/agent-idle-ONBssBN_.js +745 -0
  9. package/server/{agent-state-Bb3UUxQm.js → agent-state-BJhGIJZe.js} +421 -135
  10. package/server/agent-state-CM8iVw5B.js +3 -0
  11. package/server/{agent-state-service-BFbttwRA.js → agent-state-service-CiIuwzIs.js} +5 -5
  12. package/server/{agent-state-service-keg-x1bT.js → agent-state-service-CzHfoqKQ.js} +1 -1
  13. package/server/agents-DpCuoF65.js +3 -0
  14. package/server/{agents-CqQJW75N.js → agents-jXgqpHca.js} +8 -8
  15. package/server/archive-planning-BW4MKNI7.js +2 -0
  16. package/server/{archive-planning-BwEhu9Oq.js → archive-planning-CGkU6UeL.js} +20 -135
  17. package/server/{artifact-index-jobs-C6Lg2rKm.js → artifact-index-jobs-Ck4NRRkY.js} +3 -3
  18. package/server/{assemble-DyTp2gSB.js → assemble-CyvEBmmq.js} +28 -9
  19. package/server/{auto-spawn-consent-BDfe4qz0.js → auto-spawn-consent-Dc4mtM-B.js} +8 -7
  20. package/server/{backlog-auto-trigger-DuOGpdDW.js → backlog-auto-trigger-CCEpr4YT.js} +3 -3
  21. package/server/{behavior-Bitko0mD.js → behavior-BiCQzqyT.js} +3 -3
  22. package/server/{bridge-pool-patrol-DiHEd13O.js → bridge-pool-patrol-Ce8rNPym.js} +2 -2
  23. package/server/{briefing-freshness-CDJcmHHZ.js → briefing-freshness-e_OEYZEe.js} +2 -2
  24. package/server/{build-info-DTX8JwVP.js → build-info-BRw4QlYO.js} +3 -3
  25. package/server/build-info-Bj2vQEMh.js +2 -0
  26. package/server/{checkpoint-manager-CKg1tn34.js → checkpoint-manager-CKr42Usw.js} +1 -1
  27. package/server/{checkpoint-manager-BlOOdzLF.js → checkpoint-manager-DOwRGFff.js} +26 -9
  28. package/server/checkpoint-worker.js +1 -1
  29. package/server/{checkpoints-DRALkfDS.js → checkpoints-Cb6CWT4S.js} +1 -1
  30. package/server/{checkpoints-BGfl0cHM.js → checkpoints-Cszp_0Np.js} +2 -2
  31. package/server/{claude-hooks-provision-B_tv3wzE.js → claude-hooks-provision-C5JHpxTS.js} +1 -1
  32. package/server/{claude-hooks-provision-BlGv6twJ.js → claude-hooks-provision-Cer2eFfj.js} +2 -2
  33. package/server/{claude-permissions-aHgDcZi5.js → claude-permissions-Bc5kjX1q.js} +2 -2
  34. package/server/{claude-settings-overlay-CYOvFE3A.js → claude-settings-overlay-C7rWsnya.js} +1 -1
  35. package/server/{claude-settings-overlay-T2LWLteV.js → claude-settings-overlay-m-VVZej1.js} +2 -2
  36. package/server/cli-BRuzUT_I.js +2 -0
  37. package/server/{cli-Do8UpLoI.js → cli-BmczsfD6.js} +11 -11
  38. package/server/{cliproxy-CX6jHRDP.js → cliproxy-BpYpkogS.js} +52 -17
  39. package/server/cliproxy-_yUU0HRY.js +3 -0
  40. package/server/{close-issue-J0_eWYT1.js → close-issue-CxvRD0UI.js} +5 -5
  41. package/server/{closed-issue-reaper-bFppuk6F.js → closed-issue-reaper-nMLRi5de.js} +13 -12
  42. package/server/{closed-issue-reaper-Cl2h9AfT.js → closed-issue-reaper-omOcUDBl.js} +1 -1
  43. package/server/{codex-icapA4om.js → codex-DZhFfcWu.js} +1 -1
  44. package/server/{codex-OOea7lXs.js → codex-KaSKE-R3.js} +16 -10
  45. package/server/{compaction-continuation-D5voR1ME.js → compaction-continuation-Bjfi70G-.js} +3 -3
  46. package/server/{config-Cjleh3_U.js → config-CH1AqqIQ.js} +1 -1
  47. package/server/{config-DC75T4Mr.js → config-Doq_tF-f.js} +2 -2
  48. package/server/{config-tucKBCCc.js → config-ZGjvuR6J.js} +2 -2
  49. package/server/{config-yaml-BwOEANMr.js → config-yaml-D9nfpEx1.js} +33 -8
  50. package/server/{conflict-gate-DlpWCMd7.js → conflict-gate-D4XCtrm2.js} +1 -1
  51. package/server/{conflict-gate-D2L1kZeL.js → conflict-gate-DcUTY4Gb.js} +4 -4
  52. package/server/{context-layers-CSPGc2Hb.js → context-layers-BBTKP-Y4.js} +3 -3
  53. package/server/context-layers-BGj2Y9l3.js +4 -0
  54. package/server/{continue-U3Af0jUq.js → continue-i7Revg8D.js} +3 -3
  55. package/server/{control-settings-5k6ixdFW.js → control-settings-BMoDHY1G.js} +6 -6
  56. package/server/{conversation-compaction-CSpVpxN6.js → conversation-compaction-D4VOmF7p.js} +8 -8
  57. package/server/{conversation-compaction-Ciit9O6k.js → conversation-compaction-DzIjYMfg.js} +1 -1
  58. package/server/{conversation-service-BxrB5lUT.js → conversation-service-CzZUJFEx.js} +1 -1
  59. package/server/{conversation-service-BteE4ELK.js → conversation-service-tQCIbBVZ.js} +6 -6
  60. package/server/{conversations-DhwxsOru.js → conversations-C75EFFjf.js} +12 -7
  61. package/server/conversations-bFDaD5YN.js +3 -0
  62. package/server/{cost-Bnf9NUC5.js → cost-BCWEkvro.js} +3 -3
  63. package/server/{cost-CQKI6OCu.js → cost-CiIwxH1D.js} +2 -2
  64. package/server/{cost-sync-B-ADeXKY.js → cost-sync-DOkdE_yB.js} +3 -3
  65. package/server/{dag-DI9LaK_q.js → dag-BPc74hwj.js} +6 -19
  66. package/server/{dangerous-git-ops-akhA3iyF.js → dangerous-git-ops-By9iguTP.js} +1 -1
  67. package/server/dashboard-db-worker.js +7 -7
  68. package/server/{deacon-TPYssFYt.js → deacon-B24dNzr8.js} +1774 -171
  69. package/server/deacon-CzSZMtb-.js +4 -0
  70. package/server/{deacon-canonical-state-DFYymrDw.js → deacon-canonical-state-CkvxRPck.js} +3 -3
  71. package/server/{deacon-event-client-Te5v10-b.js → deacon-event-client-BYIQBu0T.js} +1 -1
  72. package/server/{deacon-event-client-BKOL4AcL.js → deacon-event-client-Do6Z2gKl.js} +2 -2
  73. package/server/{deacon-nudge-log-BtlTWgWu.js → deacon-nudge-log-CzM9JA9t.js} +1 -1
  74. package/server/{deacon-pending-lifecycle-DVHjOLje.js → deacon-pending-lifecycle-BObEdT-L.js} +3 -3
  75. package/server/deacon.js +11 -11
  76. package/server/dead-end-trip-6V_CwveT.js +2 -0
  77. package/server/{dead-end-trip-P0IF1O0E.js → dead-end-trip-CnVmjnya.js} +3 -3
  78. package/server/delivery-gyce0vQ7.js +3 -0
  79. package/server/{deploy-patrol-BXjlvoV3.js → deploy-patrol-CEwwEYDM.js} +8 -8
  80. package/server/deploy-queue-CjLErpgw.js +2 -0
  81. package/server/{deploy-queue-o7shYg1j.js → deploy-queue-r96ojDI3.js} +2 -2
  82. package/server/{deploy-window-CNT6fOff.js → deploy-window-D_3hhfxt.js} +4 -4
  83. package/server/{deploy-window-BMk5_oX6.js → deploy-window-DeJK8mTK.js} +1 -1
  84. package/server/{dev-supervisor-SR1CLOAK.js → dev-supervisor-DZWwpENk.js} +2 -2
  85. package/server/{devcontainer-renderer-enMmNDFa.js → devcontainer-renderer-d-9dCV_2.js} +3 -3
  86. package/server/{dist-CPTO_zMR.js → dist-DsLAsFSh.js} +1 -1
  87. package/server/dist-fCA6y2bH.js +3 -0
  88. package/server/{docker-B7qUZptz.js → docker-B2mUBzGk.js} +3 -3
  89. package/server/{docker-KR3zSFKY.js → docker-CRPHBylA.js} +1 -1
  90. package/server/{dod-gK835UMf.js → dod-DWtilRLx.js} +1 -1
  91. package/server/{done-preflight-CksRvh49.js → done-preflight-BDVdWed5.js} +1 -1
  92. package/server/{done-preflight-Bk8aExAL.js → done-preflight-D4ukUf-S.js} +5 -5
  93. package/server/{driver-CmsY2RLl.js → driver-BtcFz-qu.js} +14 -3
  94. package/server/{durable-review-pipeline-DgYHucN2.js → durable-review-pipeline-B3OS2_He.js} +11 -2
  95. package/server/durable-review-pipeline-CaCbEJSt.js +3 -0
  96. package/server/{ensure-devcontainer-ojerEqQg.js → ensure-devcontainer-BUeBRjmm.js} +4 -4
  97. package/server/{ensure-devcontainer-BQ4YizSH.js → ensure-devcontainer-rGSh0JHK.js} +1 -1
  98. package/server/{esm-shims-1htPASWs.js → esm-shims-oAaKIa-a.js} +1 -1
  99. package/server/{event-store-D7qcJXuZ.js → event-store-BCSgMubf.js} +5 -5
  100. package/server/{event-store-BgEjNsvk.js → event-store-Db4w4YIY.js} +1 -1
  101. package/server/{event-store-provider-BKvk2rDj.js → event-store-provider-DlSQND3V.js} +1 -1
  102. package/server/{events-BIKGJZOT.js → events-B6zioJA_.js} +3 -3
  103. package/server/{dist-src-BM9eudEd.js → factory-BrdqXBeK.js} +714 -2
  104. package/server/{feature-registry-storage-ewNSIVsQ.js → feature-registry-storage-zh3ZXW6f.js} +3 -3
  105. package/server/{features-CGopJXdU.js → features-BGntOWdy.js} +2 -2
  106. package/server/{feedback-stuck-retirement-B8-fX7NA.js → feedback-stuck-retirement-DpA5u1kt.js} +2 -2
  107. package/server/{feedback-target-Ci6N5p4G.js → feedback-target-D7GxdUYG.js} +10 -10
  108. package/server/{feedback-target-CkyLYohm.js → feedback-target-Ddqk93NF.js} +1 -1
  109. package/server/{feedback-writer-D4ULO4qG.js → feedback-writer-C1gCLFmp.js} +5 -5
  110. package/server/{feedback-writer-DfuVjvH0.js → feedback-writer-CH2846DP.js} +1 -1
  111. package/server/{flywheel-C7yek87O.js → flywheel-CjW2L7BS.js} +79 -29
  112. package/server/{flywheel-DXI_WITn.js → flywheel-HJt7QdWP.js} +1 -1
  113. package/server/{flywheel-merge-order-C5m5bYBc.js → flywheel-merge-order-4fNRN2F2.js} +1 -1
  114. package/server/{flywheel-merge-order-CXfU4M6l.js → flywheel-merge-order-D_yyAlND.js} +7 -7
  115. package/server/{flywheel-BwYPDlhK.js → flywheel-v1cCOBx-.js} +14 -14
  116. package/server/{forge-DYX9sKzG.js → forge-RVTCK_5X.js} +2 -2
  117. package/server/forge-bvak6vXJ.js +2 -0
  118. package/server/{from-DAdMxC29.js → from-BnLgKYvw.js} +1 -1
  119. package/server/{fs-lock-cw25uO_E.js → fs-lock-C7J-ugIf.js} +2 -2
  120. package/server/{fts-operations-D_rzLxX5.js → fts-operations-CU0B5WUx.js} +3 -3
  121. package/server/git-info-BSrI9owC.js +148 -0
  122. package/server/{git-utils-Y0zG25ez.js → git-utils-CsKV0Dis.js} +1 -1
  123. package/server/{git-utils-DV4B9TRl.js → git-utils-DW8-jIUJ.js} +4 -4
  124. package/server/{github-app-4UX8VIr8.js → github-app-7ywLhuZO.js} +2 -2
  125. package/server/{github-app-C33lDk9Z.js → github-app-Oi5hdn1n.js} +1 -1
  126. package/server/{github-client-nPj5ckZO.js → github-client-Cy0fSj1a.js} +1 -1
  127. package/server/{github-client-DkJVR908.js → github-client-DAbuXLuk.js} +3 -3
  128. package/server/{github-pr-lookup-C9Vokb0W.js → github-pr-lookup-Dhh3ec1V.js} +2 -2
  129. package/server/{harness-binary-BgXYDo2Z.js → harness-binary-tMmgJfC1.js} +2 -2
  130. package/server/{harness-resolve-1NZcVx7n.js → harness-resolve-DusNpVEe.js} +4 -4
  131. package/server/{health-events-jMfxrElt.js → health-events-BYDZ9n2i.js} +1 -1
  132. package/server/{health-events-DlX_FVAB.js → health-events-DNw9Mzw9.js} +2 -2
  133. package/server/{hooks-W3REcb3h.js → hooks-B4wj32l2.js} +1 -1
  134. package/server/{hooks-NQ19vvlB.js → hooks-BjBjxqNh.js} +2 -2
  135. package/server/{hume-BFkid2PO.js → hume-BP9YbxaE.js} +2 -2
  136. package/server/hume-TYTb6fDU.js +3 -0
  137. package/server/{identity-Bwh6VGeL.js → identity-C23uY8dZ.js} +3 -3
  138. package/server/{idle-stack-reaper-BeU_KxWx.js → idle-stack-reaper-BSxb1bln.js} +4 -4
  139. package/server/{idle-stack-reaper-CHtCNpvd.js → idle-stack-reaper-Bw0rU9GC.js} +1 -1
  140. package/server/{in-flight-guard-pcwXKLGz.js → in-flight-guard-DuxabAHT.js} +1 -1
  141. package/server/{infra-KTp9KV9u.js → infra-CHIvOb9q.js} +30 -7
  142. package/server/{injection-67YyU6SC.js → injection-BYUt8ml1.js} +8 -8
  143. package/server/{injection-BxbZKPDh.js → injection-BviePcm3.js} +1 -1
  144. package/server/inspect-agent-JFEaYTRa.js +2 -0
  145. package/server/{inspect-agent-VHSihlb7.js → inspect-agent-sV_19NxZ.js} +12 -12
  146. package/server/{internal-token-B-z-sGBH.js → internal-token-BOtIRJU7.js} +1 -1
  147. package/server/{internal-token-zY75jrRJ.js → internal-token-DoVzb4b7.js} +2 -2
  148. package/server/{io-DfvO2xyh.js → io-DKrWd3gX.js} +5 -5
  149. package/server/{issue-closed-dvEWKO7Q.js → issue-closed-6RQsAjDX.js} +7 -7
  150. package/server/{issue-lifecycle-3N8XF7lP.js → issue-lifecycle-D9nLErvS.js} +206 -29
  151. package/server/{issue-lifecycle-BI6jAfp8.js → issue-lifecycle-DOPVv7xz.js} +1 -1
  152. package/server/{issue-service-singleton-BN_2MXp4.js → issue-service-singleton-B2xy-IS9.js} +124 -11
  153. package/server/{issue-service-singleton-CL6hESX2.js → issue-service-singleton-CvgNAWqK.js} +1 -1
  154. package/server/issue-title-fallback-DTSCQVu0.js +120 -0
  155. package/server/{issues-CkvUoAnq.js → issues-e_Ck1Ln2.js} +2 -2
  156. package/server/{jsonl-parser-CrEb2PWr.js → jsonl-parser-DqxVCZ1k.js} +3 -3
  157. package/server/jsonl-resolver-07OS3qOr.js +324 -0
  158. package/server/{kimi-code-C26gmGxM.js → kimi-code-BjtAHIz1.js} +14 -12
  159. package/server/{kimi-code-DoMoGqIu.js → kimi-code-vtXl2DR5.js} +1 -1
  160. package/server/{kimi-parser-Dmhy3UlR.js → kimi-parser-B1lgy2Vt.js} +2 -2
  161. package/server/{label-cleanup-X2lWfghH.js → label-cleanup-D2zUMasf.js} +3 -3
  162. package/server/{lifecycle-Bg44O-9x.js → lifecycle-0NOEzomy.js} +2 -2
  163. package/server/{lifecycle-B0rL38D3.js → lifecycle-DaCovZwn.js} +6 -6
  164. package/server/{lifecycle-io-CCBpRv5m.js → lifecycle-io-6WL46dsB.js} +5 -5
  165. package/server/{lifecycle-io-DQDU0apV.js → lifecycle-io-BBMTaP7S.js} +1 -1
  166. package/server/{linear-client-B0cIkTs4.js → linear-client-7fQThJTc.js} +3 -3
  167. package/server/{linear-client-6V2E-DSa.js → linear-client-BTGApNLo.js} +1 -1
  168. package/server/{linear-mcp-auth-LCo9AWUd.js → linear-mcp-auth-B8pYRsiU.js} +1 -1
  169. package/server/{linear-mcp-auth-Dsu9Io9r.js → linear-mcp-auth-Nk5s3L9M.js} +5 -5
  170. package/server/memory-fts-worker.js +1 -1
  171. package/server/{memory-governor-A4O6vI9d.js → memory-governor-Cqvbusr4.js} +14 -14
  172. package/server/{memory-pressure-patrol-BWlWywmA.js → memory-pressure-patrol-DPb8foam.js} +5 -5
  173. package/server/{merge-BGWcBxku.js → merge-BB_bjJ9a.js} +1 -1
  174. package/server/{merge-vz80RvSE.js → merge-FZ78_cEz.js} +3 -3
  175. package/server/{merge-agent-GWhmnxFk.js → merge-agent-B3jRrlS1.js} +37 -33
  176. package/server/{merge-agent-BRSz26Oh.js → merge-agent-BuoC_PRZ.js} +2 -2
  177. package/server/{merge-batch-CFMEtTxv.js → merge-batch-B8bVjFWS.js} +1 -1
  178. package/server/{merge-completeness-CP347umA.js → merge-completeness-DQt7Qa7i.js} +4 -4
  179. package/server/{merge-completeness-7ajHAIR-.js → merge-completeness-DkdabVch.js} +1 -1
  180. package/server/merge-ops-DabXHp2i.js +2 -0
  181. package/server/merge-rebase-CXq0qsgR.js +2 -0
  182. package/server/{merge-rebase-C5htyEEH.js → merge-rebase-qq40s91P.js} +2 -2
  183. package/server/{merge-set-DsGW8fmc.js → merge-set-BTNYvxM3.js} +1 -1
  184. package/server/{merge-set-eiE2nC6C.js → merge-set-BmRRflt0.js} +4 -4
  185. package/server/{merge-sync-CM2-myXu.js → merge-sync-0m2Q087q.js} +1 -1
  186. package/server/{merge-sync-Ct0-cxMX.js → merge-sync-CJpOa0cZ.js} +2 -2
  187. package/server/{merge-train-deps-LXHGK61n.js → merge-train-deps-CH5Mr3vN.js} +4 -4
  188. package/server/{merge-train-BOu3fN7O.js → merge-train-iwKqjtCF.js} +4 -4
  189. package/server/{merge-verification-BRp08IzI.js → merge-verification-JJc5GC2t.js} +6 -6
  190. package/server/{merged-docker-cleanup-worker-CwldDjHV.js → merged-docker-cleanup-worker-BOqWA373.js} +4 -4
  191. package/server/{merged-docker-cleanup-worker-C8eGn78a.js → merged-docker-cleanup-worker-CrhTdxZV.js} +1 -1
  192. package/server/messaging-nuwStbdQ.js +3 -0
  193. package/server/{multipart-parser-OAuW7824.js → multipart-parser-DxuW_rZV.js} +2 -2
  194. package/server/{no-resume-mode-MWI6pnrK.js → no-resume-mode-xuYLFhLw.js} +1 -1
  195. package/server/node_modules/.package-lock.json +11 -11
  196. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/AGENTS.md +14 -0
  197. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/CLAUDE.md +14 -0
  198. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/README.md +10 -3
  199. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/40_sql/10_basics.ts +175 -0
  200. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/40_sql/index.md +6 -0
  201. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/51_http-server/10_basics.ts +3 -1
  202. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/51_http-server/20_testing.ts +100 -0
  203. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/51_http-server/fixtures/api/Users.ts +30 -14
  204. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/51_http-server/fixtures/domain/User.ts +15 -6
  205. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/51_http-server/fixtures/server/Authorization.ts +11 -10
  206. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/51_http-server/fixtures/server/Users/http.ts +41 -32
  207. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/51_http-server/fixtures/server/Users.ts +141 -20
  208. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/ai-docs/src/70_cli/10_basics.ts +27 -3
  209. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.d.ts.map +1 -1
  210. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js +10 -9
  211. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js.map +1 -1
  212. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeSocketServer.js +4 -4
  213. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeSocketServer.js.map +1 -1
  214. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeStream.d.ts.map +1 -1
  215. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeStream.js +10 -4
  216. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeStream.js.map +1 -1
  217. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/internal/nodeChildProcessSpawner.d.ts +4 -0
  218. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/internal/nodeChildProcessSpawner.d.ts.map +1 -0
  219. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/internal/nodeChildProcessSpawner.js +10 -0
  220. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/internal/nodeChildProcessSpawner.js.map +1 -0
  221. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/package.json +4 -4
  222. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/src/NodeChildProcessSpawner.ts +16 -11
  223. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/src/NodeSocketServer.ts +4 -4
  224. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/src/NodeStream.ts +10 -4
  225. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/src/internal/nodeChildProcessSpawner.ts +16 -0
  226. package/server/node_modules/ansi-regex/index.js +3 -2
  227. package/server/node_modules/ansi-regex/package.json +1 -1
  228. package/server/node_modules/gaxios/build/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  229. package/server/node_modules/gaxios/build/esm/tsconfig.tsbuildinfo +1 -1
  230. package/server/node_modules/gaxios/package.json +3 -3
  231. package/server/{orphan-proposed-reconciler-cV3URUqk.js → orphan-proposed-reconciler-Dmk0kO_p.js} +24 -23
  232. package/server/{orphan-proposed-reconciler-BAE5AZ_e.js → orphan-proposed-reconciler-gf4TxfZb.js} +2 -2
  233. package/server/package-lock.json +12 -12
  234. package/server/package.json +1 -1
  235. package/server/{pan-dir-DDd91kMb.js → pan-dir-BMda7tQj.js} +5 -5
  236. package/server/{deacon-merge-BOGFEV8_.js → parked-residue-BiHb8cD7.js} +150 -35
  237. package/server/{paths-CRLnDgcI.js → paths-DEe9j-kw.js} +2 -2
  238. package/server/{pending-lifecycle-claim-CYgMiDAP.js → pending-lifecycle-claim-J5uIIJPu.js} +2 -2
  239. package/server/{pickup-BjJsSX12.js → pickup-D1UbSDPd.js} +1 -1
  240. package/server/{pipeline-agent-reader-BLc43dVJ.js → pipeline-agent-reader-D-6okryb.js} +5 -5
  241. package/server/{pipeline-membership-5qlRz5Qg.js → pipeline-membership-CCbgBzNC.js} +1 -1
  242. package/server/{pipeline-membership-BHZp_ShY.js → pipeline-membership-PGX3Pe8V.js} +1 -1
  243. package/server/{pipeline-membership-gather-CGFY1v-y.js → pipeline-membership-gather-BK4dzh0X.js} +17 -12
  244. package/server/{pipeline-membership-gather-WhRc1yke.js → pipeline-membership-gather-BRhU7XPx.js} +1 -1
  245. package/server/{pipeline-notifier-BmsLWM_2.js → pipeline-notifier-BNAV9kpa.js} +2 -2
  246. package/server/{pipeline-notifier-C4fZ2ito.js → pipeline-notifier-DvHLaXKb.js} +1 -1
  247. package/server/{post-merge-lifecycle-worker-KK1RTKRE.js → post-merge-lifecycle-worker-DAWgzXQA.js} +3 -3
  248. package/server/{post-merge-state-_Lj3LDLh.js → post-merge-state-DC2_0t12.js} +4 -4
  249. package/server/prd-locations-BbAvqQmT.js +124 -0
  250. package/server/{project-pipelines-CCkebHOu.js → project-pipelines-By_5WcT4.js} +2 -2
  251. package/server/{project-repos-B4MK48j4.js → project-repos--QeCg7yQ.js} +29 -3
  252. package/server/project-repos-3bI6t4fO.js +3 -0
  253. package/server/project-resource-refresh-queue-BaZC79S3.js +2 -0
  254. package/server/project-resource-refresh-queue-x-K9mvpP.js +865 -0
  255. package/server/{projects-DvPEAP18.js → projects-LftaVK99.js} +1 -1
  256. package/server/{prompts-BiS5I2tZ.js → prompts-BotGu-6W.js} +2 -2
  257. package/server/{providers-DrfK0Ip8.js → providers-BL1I66sM.js} +7 -7
  258. package/server/providers-Dqgz3MY5.js +3 -0
  259. package/server/public/assets/{chunk-BO2N2NFS-GtVe_o56.js → chunk-BO2N2NFS-D5Fz5jND.js} +4 -4
  260. package/server/public/assets/{diagram-OG6HWLK6-BvhcYYHc.js → diagram-OG6HWLK6-Eux0gWFq.js} +1 -1
  261. package/server/public/assets/{dist-D0ryefak.js → dist-C3zShwhA.js} +1 -1
  262. package/server/public/assets/{dist-CSmUXazd.js → dist-D-JX_u7m.js} +3 -3
  263. package/server/public/assets/{ganttDiagram-6RSMTGT7-BXA51DzM.js → ganttDiagram-6RSMTGT7-UH3aweia.js} +1 -1
  264. package/server/public/assets/{highlighted-body-OFNGDK62-mlV4EpWt.js → highlighted-body-OFNGDK62-ccIQ-WXS.js} +1 -1
  265. package/server/public/assets/index-2wV4ipy_.css +1 -0
  266. package/server/public/assets/index-BTVcdPve.js +860 -0
  267. package/server/public/assets/{linear-BPE7oswm.js → linear-Cnnu4YQy.js} +1 -1
  268. package/server/public/assets/mermaid-GHXKKRXX-Bjto8iJh.js +1 -0
  269. package/server/public/assets/{pieDiagram-4H26LBE5-BguGGV3S.js → pieDiagram-4H26LBE5-BD8-Tye6.js} +1 -1
  270. package/server/public/assets/{prod-aKDYUrXQ.js → prod-Ca6aKMts.js} +4 -4
  271. package/server/public/assets/{quadrantDiagram-W4KKPZXB-Bx3i4B6H.js → quadrantDiagram-W4KKPZXB-BmSrVyFD.js} +1 -1
  272. package/server/public/assets/{sankeyDiagram-5OEKKPKP-B5vuLjA4.js → sankeyDiagram-5OEKKPKP-CEGy8Das.js} +1 -1
  273. package/server/public/assets/{xychartDiagram-2RQKCTM6-HPlpkqsN.js → xychartDiagram-2RQKCTM6-VnQ8iY8s.js} +1 -1
  274. package/server/public/index.html +2 -2
  275. package/server/{pull-requests-BcHIsFJv.js → pull-requests-Cp_FDT8-.js} +3 -3
  276. package/server/pull-requests-jVGcVq5G.js +2 -0
  277. package/server/rally-CxhVgIQ6.js +3 -0
  278. package/server/{rally-api-ShZ4kvn0.js → rally-api-CqAIJ8RX.js} +2 -2
  279. package/server/{rally-api-u_vkr5c_.js → rally-api-Ij1Zt0NI.js} +1 -1
  280. package/server/{rally-B1OMtzch.js → rally-bQpBzUNf.js} +3 -3
  281. package/server/{rally-client-DgZvUZqX.js → rally-client-CN5vh4Ac.js} +1 -1
  282. package/server/{rally-client-D6Feq1Ka.js → rally-client-qKbCNRVW.js} +5 -5
  283. package/server/{reap-terminal-sessions-CRfiXLY0.js → reap-terminal-sessions-BaDSNR-k.js} +2 -2
  284. package/server/{reap-terminal-sessions-D7f3zSE9.js → reap-terminal-sessions-DgEIKMhH.js} +2 -2
  285. package/server/{rebuild-stack-DKxOnkpE.js → rebuild-stack-BNOMVh7C.js} +7 -7
  286. package/server/{rebuild-stack-CCwKHZb6.js → rebuild-stack-DrMyA_mA.js} +2 -2
  287. package/server/{reconstruct-cache-BP8UIKt7.js → reconstruct-cache-mxIYCnqs.js} +7 -7
  288. package/server/{record-By-wp6pg.js → record-Ug18Cp4V.js} +1 -1
  289. package/server/{record-update-ByGtIlUK.js → record-update-WyhsREoH.js} +1 -1
  290. package/server/{record-update-D23jPU6b.js → record-update-dBGxL9OC.js} +8 -6
  291. package/server/{recovery-trip-C4dTl8DO.js → recovery-trip-BKLrL6NX.js} +43 -10
  292. package/server/{recovery-trip-qloOYOFz.js → recovery-trip-wFAixKsg.js} +1 -1
  293. package/server/{release-engine-Crc0Tjx-.js → release-engine-D9gaCBn9.js} +5 -5
  294. package/server/{release-set-DDXwbIK7.js → release-set-DPHHzEGx.js} +3 -3
  295. package/server/{remote-CBpLi4Yy.js → remote-BU6ONLpv.js} +3 -3
  296. package/server/{remote-oEMfXlwT.js → remote-BUEeUic6.js} +3 -3
  297. package/server/{remote-agents-DQVGZVQ9.js → remote-agents-BVtASiOF.js} +1 -1
  298. package/server/{remote-agents-Bgtc2nOO.js → remote-agents-CSaTLi3u.js} +6 -6
  299. package/server/{remote-completion-DxUJ5HKR.js → remote-completion-CBV3b9TI.js} +13 -13
  300. package/server/{resolver-C8rooxoz.js → resolver-DvSMXty7.js} +31 -8
  301. package/server/{resolver-CuAULbLs.js → resolver-gxv97jsQ.js} +2 -2
  302. package/server/resume-DvHuF-bm.js +3 -0
  303. package/server/review-agent-DgkUPRx0.js +3 -0
  304. package/server/{review-agent-7C2w5CzU.js → review-agent-esZ0QXdY.js} +43 -55
  305. package/server/{review-artifacts-BJeEfm2r.js → review-artifacts-DGGEobLp.js} +6 -6
  306. package/server/{review-convoy-liveness-DfF9eXjI.js → review-convoy-liveness-DmO8dIBH.js} +20 -11
  307. package/server/{review-run-recovery-7BKt2Es0.js → review-run-recovery-Ct0q7FkE.js} +3 -3
  308. package/server/{review-run-recovery-ZjuDTNhZ.js → review-run-recovery-DHiiw7d8.js} +1 -1
  309. package/server/{review-status-CUnjjOUu.js → review-status-C_kQeeX0.js} +1 -1
  310. package/server/{review-status-emit-Cg4tOb8U.js → review-status-emit-BZz1Y_22.js} +3 -3
  311. package/server/{review-status-enrichment-D-rQshu6.js → review-status-enrichment-BWH0XW_m.js} +3 -3
  312. package/server/{review-status-source-DSn0glLa.js → review-status-source-D2PCWS6E.js} +1 -1
  313. package/server/{review-status-source-Ct912fv_.js → review-status-source-Jq0BXmn3.js} +1 -1
  314. package/server/{review-status-sync-B7V_Gg51.js → review-status-sync-2C9lk85r.js} +2 -2
  315. package/server/{review-status-sync-YthpOH_q.js → review-status-sync-Bq00Loey.js} +1 -1
  316. package/server/{review-status-DBnR5t4z.js → review-status-yOGD2MuK.js} +86 -27
  317. package/server/{review-verdict-feedback-DqXTuJk8.js → review-verdict-feedback-Brjaxoda.js} +1 -1
  318. package/server/{review-verdict-feedback-C-dBon_-.js → review-verdict-feedback-CE_tr2iQ.js} +8 -8
  319. package/server/{review-verdict-writer-jldSh3Bm.js → review-verdict-writer-CD-4kDVx.js} +1 -1
  320. package/server/{review-verdict-writer-CKaJWp75.js → review-verdict-writer-Ca2V7QSY.js} +7 -7
  321. package/server/{rollup-DZwH4CLs.js → rollup--g9ik1XQ.js} +1 -1
  322. package/server/{rollup-QCwYcBdP.js → rollup-B6g9Nr6L.js} +8 -8
  323. package/server/{scanner-2aHeLC3W.js → scanner-YxIv-fG1.js} +8 -8
  324. package/server/{search-DwHYaj66.js → search-DqMN4__-.js} +2 -2
  325. package/server/{secret-redaction-B5G1xZ3k.js → secret-redaction-DLZ-VqHq.js} +1 -1
  326. package/server/{sequence-io-POKWdusG.js → sequence-io--b3_PsWq.js} +4 -4
  327. package/server/{sequencer-agent-DS00KHVm.js → sequencer-agent-CqouKVZG.js} +6 -6
  328. package/server/server.js +1115 -1269
  329. package/server/{service-BLb_CyPL.js → service-CEp-3iow.js} +64 -63
  330. package/server/{session-fork-DcTzVwex.js → session-fork-GtoeCh2H.js} +2 -2
  331. package/server/{settings-Clw8UVNs.js → settings-CLQcdkoD.js} +2 -2
  332. package/server/{settings-B9-H2K_E.js → settings-Ch2pCVtt.js} +3 -3
  333. package/server/settings-DhtPDmmI.js +2 -0
  334. package/server/{shadow-engineering-C6oO_PiR.js → shadow-engineering-BxiFrIKv.js} +3 -3
  335. package/server/{shadow-state-CEGrrECe.js → shadow-state-CSA1vtxr.js} +2 -2
  336. package/server/{shadow-state-e7250VUx.js → shadow-state-nGhCNXT2.js} +1 -1
  337. package/server/{shadow-utils-xFk2Wusb.js → shadow-utils-7q5QDmMj.js} +2 -2
  338. package/server/{ship-log-7BnQHuKU.js → ship-log-ie0A_SqV.js} +1 -1
  339. package/server/{ship-record-CwUX6Afo.js → ship-record-BM3oVvnL.js} +7 -7
  340. package/server/{ship-record-BgUPnpT0.js → ship-record-DHWH1hLz.js} +1 -1
  341. package/server/{ship-status-Ce3_3edi.js → ship-status-BEkddXMT.js} +2 -2
  342. package/server/{smart-compaction-BmfIi3oL.js → smart-compaction-BkzjVpWL.js} +1 -1
  343. package/server/{smart-compaction-Dy0gw1VH.js → smart-compaction-D0TE1lBD.js} +7 -7
  344. package/server/{spawn-planning-session-nH3b4Drz.js → spawn-planning-session-CkGweSCC.js} +19 -19
  345. package/server/{spawn-planning-session-CfhxRJoY.js → spawn-planning-session-s406rw1N.js} +2 -2
  346. package/server/{specialist-completion-CC1XJbTx.js → specialist-completion-CTAjwH5j.js} +1 -1
  347. package/server/{specialist-context-cHwpcXSh.js → specialist-context-CKasRfYu.js} +5 -5
  348. package/server/{specialist-handoff-logger-GqnGSYoJ.js → specialist-handoff-logger-DrjrOmmn.js} +2 -2
  349. package/server/{specialist-logs-5OTnrV91.js → specialist-logs-Du6quZ0_.js} +3 -3
  350. package/server/{specialists-xXcJHAyg.js → specialists-B-4zyE4Y.js} +1 -1
  351. package/server/{specialists-8LcQi9Np.js → specialists-CuDWiNdB.js} +21 -272
  352. package/server/{specialists-DocAK-7A.js → specialists-b0dMMjWq.js} +148 -685
  353. package/server/specialists-registry-1y6Rt_F1.js +3 -0
  354. package/server/specialists-registry-BYjs04iK.js +277 -0
  355. package/server/specialists-x-kPMhrL.js +4 -0
  356. package/server/specs-IYsFlM-L.js +3 -0
  357. package/server/{src-DudQNYVw.js → src-CY2Wl8IX.js} +337 -6
  358. package/server/{src-C2TAxwki.js → src-CZsPs61V.js} +6 -6
  359. package/server/{src-DUVvEA8Q.js → src-DeQwpuh6.js} +3 -3
  360. package/server/{stack-health-DKT4ySnA.js → stack-health-BQFSJc0l.js} +3 -3
  361. package/server/{stack-health-CbyiYS9H.js → stack-health-ypIKtkbE.js} +1 -1
  362. package/server/{stale-task-claims-PzFee70R.js → stale-task-claims-C2e1zdMT.js} +5 -5
  363. package/server/{staleness-BjOAq9-d.js → staleness-CRDK6LFG.js} +1 -1
  364. package/server/{staleness-D8UTEXV5.js → staleness-Fzx_3_Hr.js} +1 -1
  365. package/server/{stall-sweeper-DOyIfeLR.js → stall-sweeper-QNk4h9m6.js} +8 -8
  366. package/server/{state-home-DhAZlk5k.js → state-home-DdG8erBI.js} +2 -2
  367. package/server/{state-mapping-BVSs84bO.js → state-mapping-D2yC81Vy.js} +1 -1
  368. package/server/{state-migrate-CJKEwpB0.js → state-migrate-C6H3jfHE.js} +6 -6
  369. package/server/{state-mirror-Do7pag7W.js → state-mirror-DF4Lfxm0.js} +3 -3
  370. package/server/stuck-remediation-BDa_tXgB.js +774 -0
  371. package/server/stuck-remediation-BVNd9txd.js +2 -0
  372. package/server/{substrate-bug-weights-service-BTNjHBnl.js → substrate-bug-weights-service-BbbCZEtJ.js} +3 -3
  373. package/server/{summary-fork-CZ88rhVx.js → summary-fork-BvcW6bq0.js} +113 -30
  374. package/server/{summary-fork-CvB7Oyq9.js → summary-fork-DIQmtOuV.js} +2 -2
  375. package/server/supervisor/{pane-composer-BaLLspSj.js → pane-composer-CoiVkGIt.js} +8 -1
  376. package/server/supervisor/{paths-D6XUcR_g.js → paths-DTGbtcaP.js} +8 -4
  377. package/server/supervisor/pty-supervisor.js +3 -3
  378. package/server/supervisor/{pty-token-DjjHxoCq.js → pty-token-GVqnvU3U.js} +2 -2
  379. package/server/{supervisor-D4v0WfiQ.js → supervisor-D3jC2c7A.js} +4 -4
  380. package/server/supervisor-v0cYN2Vp.js +2 -0
  381. package/server/{swarm-readiness-D8R-LWX5.js → swarm-readiness-CMWAQuWM.js} +3 -3
  382. package/server/{synthesis-verdict-B6wvLGcA.js → synthesis-verdict-C-pJOPsn.js} +1 -1
  383. package/server/{synthesis-verdict-N5Z11pg7.js → synthesis-verdict-DVlrLF9A.js} +2 -2
  384. package/server/{system-prerequisites-BbGZ_WHF.js → system-prerequisites-QKtIYXI2.js} +2 -2
  385. package/server/{teardown-workspace-CYend-KY.js → teardown-workspace-cJea1OLo.js} +16 -16
  386. package/server/{test-agent-queue-BUtWhNcc.js → test-agent-queue-C5DI_gWX.js} +6 -6
  387. package/server/{test-verdict-BWm3hgDj.js → test-verdict-C7kmd2_Y.js} +1 -1
  388. package/server/{test-verdict-BWtRmdiR.js → test-verdict-DUbDHqeD.js} +2 -2
  389. package/server/{tldr-daemon-CneJ24eL.js → tldr-daemon-BNQHwblU.js} +1 -1
  390. package/server/{tldr-daemon-CMVBT4kT.js → tldr-daemon-CO08YlfQ.js} +2 -2
  391. package/server/tmux-B8zsqD_6.js +4 -0
  392. package/server/{tmux-BqXzRuaH.js → tmux-DWEc4Ld9.js} +91 -19
  393. package/server/{token-CO3INKbh.js → token-Bez-qCB2.js} +2 -2
  394. package/server/{token-util-DyJJyX_B.js → token-util-Crcay9j_.js} +1 -1
  395. package/server/token-util-DfUS3Lpp.js +3 -0
  396. package/server/{tracker-config-DVzhaUxO.js → tracker-config-CJzPhSHv.js} +2 -2
  397. package/server/{tracker-utils-xnVJVrrO.js → tracker-utils-DJAOAuMN.js} +2 -2
  398. package/server/{traefik-connect-A5k54mCv.js → traefik-connect-D3H5I6b9.js} +1 -1
  399. package/server/{tunnel-DauSR-rs.js → tunnel-BSdKnW0U.js} +1 -1
  400. package/server/{tunnel-CwOnS-PB.js → tunnel-Cr3ctqxp.js} +3 -3
  401. package/server/{typed-errors-B-gfU2RB.js → typed-errors-CZ3GFBvo.js} +1 -1
  402. package/server/{typed-errors-DzC4zXbI.js → typed-errors-DXqf3RnP.js} +1 -1
  403. package/server/{types-DjpLVpsj.js → types-fzBp9cYi.js} +1 -1
  404. package/server/{types-DbxY2QB6.js → types-pLpbsNto.js} +1 -1
  405. package/server/{uat-failure-feedback-BVqsWlrr.js → uat-failure-feedback-IZQ-J8jt.js} +5 -5
  406. package/server/{uat-promote-verification-DmG097QS.js → uat-promote-verification-DXApKcc2.js} +5 -5
  407. package/server/{uat-train-COSy-vEX.js → uat-train-CycEzpbE.js} +1 -1
  408. package/server/{uat-train-DVUNW03P.js → uat-train-IIZlz7r3.js} +0 -0
  409. package/server/{validate-Dvv83iBx.js → validate-Ur4xH5bN.js} +3 -3
  410. package/server/{validation-BdCjzWLN.js → validation-CHovCoTT.js} +1 -1
  411. package/server/{validation-DlHafKzu.js → validation-Dr6V4PXx.js} +9 -6
  412. package/server/{verification-artifact-CaSbxUVg.js → verification-artifact-D3viYe_t.js} +1 -1
  413. package/server/{verification-artifact-0Zku8N-W.js → verification-artifact-k5Ftpg0c.js} +1 -1
  414. package/server/{verification-runner-C6wdZda2.js → verification-runner-BuqGwm2t.js} +1 -1
  415. package/server/{verification-runner-DwP2fUEF.js → verification-runner-Dl13mmsI.js} +53 -27
  416. package/server/{vtt-parser-luerJpYT.js → vtt-parser-BSnAB-Og.js} +1 -1
  417. package/server/work-agent-prompt-CJJ4tXci.js +3 -0
  418. package/server/{work-agent-prompt--9AWNYwZ.js → work-agent-prompt-CioeOuM4.js} +14 -14
  419. package/server/{work-agent-start-BNQO65W7.js → work-agent-start-B65Gqn9N.js} +2 -2
  420. package/server/{work-agent-start-DkzseQFl.js → work-agent-start-Ct1HVh6z.js} +1 -1
  421. package/server/{workflows-BYwR2aIN.js → workflows-AgFul1xc.js} +114 -41
  422. package/server/workflows-CfHm8lVd.js +2 -0
  423. package/server/{workspace-B-QJa3Ps.js → workspace-Cu3XlMXt.js} +1 -1
  424. package/server/{workspace-iTnTycOB.js → workspace-Cy4sDd3q.js} +3 -3
  425. package/server/{workspace-anchor-drift-DTt6h2Em.js → workspace-anchor-drift-BI0Hz6zI.js} +1 -1
  426. package/server/{workspace-anchor-drift-CHiGg8iu.js → workspace-anchor-drift-CMaqvizr.js} +4 -4
  427. package/server/{workspace-config-D0CavVtz.js → workspace-config-DRYDO7Zr.js} +1 -1
  428. package/server/{workspace-manager-W1OnbvU5.js → workspace-manager-CgovxDrO.js} +17 -17
  429. package/server/{workspace-manager-5BKPV6SY.js → workspace-manager-jfkKAEuO.js} +1 -1
  430. package/server/{workspace-metadata-tbbevEmP.js → workspace-metadata-BDqXzGGK.js} +1 -1
  431. package/server/{workspace-metadata-dJhXvZGQ.js → workspace-metadata-BNzODIv6.js} +2 -2
  432. package/server/{workspaces-BlpbOPZ7.js → workspaces-BJdPqx_J.js} +131 -127
  433. package/sync-sources/dev-skills/pan-style-guide/SKILL.md +90 -15
  434. package/sync-sources/hooks/linear-mcp-auth-hook +6 -1
  435. package/sync-sources/rules/handoff-isolate-cwd.md +4 -4
  436. package/sync-sources/rules/pan-handoff-focus-limit.md +12 -5
  437. package/sync-sources/rules/ste-writing.md +17 -0
  438. package/sync-sources/rules/work-agents-via-pan.md +2 -1
  439. package/sync-sources/rules/writing-style.md +3 -2
  440. package/sync-sources/skills/{skill-creator → claude-skill-creator}/SKILL.md +1 -1
  441. package/sync-sources/skills/{skill-creator → claude-skill-creator}/scripts/init_skill.py +1 -1
  442. package/sync-sources/skills/{skill-creator → claude-skill-creator}/scripts/package_skill.py +1 -1
  443. package/sync-sources/skills/pan-gauntlet-loop/SKILL.md +182 -0
  444. package/sync-sources/skills/pan-gauntlet-loop/assets/PROMPT.template.md +92 -0
  445. package/sync-sources/skills/pan-gauntlet-loop/assets/REFERENCE-BAR.template.md +53 -0
  446. package/sync-sources/skills/pan-gauntlet-loop/assets/STYLE.template.md +41 -0
  447. package/sync-sources/skills/pan-gauntlet-loop/assets/gauntlet-index.html +237 -0
  448. package/sync-sources/skills/pan-gauntlet-loop/references/domains.md +106 -0
  449. package/sync-sources/skills/pan-gauntlet-loop/references/lessons.md +60 -0
  450. package/sync-sources/skills/pan-handoff/SKILL.md +13 -6
  451. package/sync-sources/skills/pan-help/SKILL.md +1 -1
  452. package/sync-sources/skills/pan-peer-review/SKILL.md +3 -3
  453. package/sync-sources/skills/pan-restart/SKILL.md +6 -3
  454. package/sync-sources/skills/pan-start/SKILL.md +3 -0
  455. package/sync-sources/skills/pan-swarm/SKILL.md +32 -44
  456. package/sync-sources/skills/pan-sync/SKILL.md +1 -1
  457. package/server/activity-logger-BejO16Am.js +0 -3
  458. package/server/agent-state-DH_-Jkua.js +0 -3
  459. package/server/agents-megfmQHM.js +0 -3
  460. package/server/archive-planning-C-H9cM_J.js +0 -2
  461. package/server/build-info-PQlh_Rhb.js +0 -2
  462. package/server/cli-TaZspPHS.js +0 -2
  463. package/server/cliproxy-36ncAXlu.js +0 -3
  464. package/server/context-layers-CF6zHws4.js +0 -4
  465. package/server/conversations-AnGJ5rtX.js +0 -3
  466. package/server/deacon-BEH-IY0v.js +0 -5
  467. package/server/deacon-swarm-BHX-kR1b.js +0 -2
  468. package/server/deacon-swarm-BiLfNm_v.js +0 -1522
  469. package/server/dead-end-trip-BWpDg1Qd.js +0 -2
  470. package/server/delivery-cJM6zRjJ.js +0 -3
  471. package/server/deploy-queue-CmVBZEja.js +0 -2
  472. package/server/dist-VKBfkdi7.js +0 -3
  473. package/server/durable-review-pipeline-DgcVCYDL.js +0 -3
  474. package/server/factory-D4V2wd_V.js +0 -717
  475. package/server/forge-CrP1L3i6.js +0 -2
  476. package/server/hume-1ubD_6O7.js +0 -3
  477. package/server/inspect-agent-CfxERkNt.js +0 -2
  478. package/server/merge-ops-DtHx17Vd.js +0 -2
  479. package/server/merge-rebase-BvB4UuNS.js +0 -2
  480. package/server/project-repos-BJiShUsN.js +0 -3
  481. package/server/providers-CStNGwze.js +0 -3
  482. package/server/public/assets/index-BFEwfmqX.js +0 -860
  483. package/server/public/assets/index-_USwyTAT.css +0 -1
  484. package/server/public/assets/mermaid-GHXKKRXX-Dsln95SK.js +0 -1
  485. package/server/pull-requests-C1Cqp2yo.js +0 -2
  486. package/server/rally-CjayjUIl.js +0 -3
  487. package/server/resume-D7JuMCRQ.js +0 -3
  488. package/server/review-agent-BUNTVJK2.js +0 -2
  489. package/server/settings-DBWB1gsG.js +0 -2
  490. package/server/specialists-D8gsOCwh.js +0 -3
  491. package/server/specs-BqkrRnU9.js +0 -3
  492. package/server/stuck-remediation-Di5JYkoo.js +0 -1164
  493. package/server/stuck-remediation-TNM1VhZb.js +0 -2
  494. package/server/supervisor-DX8VsPnb.js +0 -2
  495. package/server/tmux-CqNapnrr.js +0 -4
  496. package/server/token-util-Bu8bPF9f.js +0 -3
  497. package/server/workflows-Cf4LAnhg.js +0 -2
package/server/server.js CHANGED
@@ -1,120 +1,121 @@
1
1
  import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM, r as __exportAll, t as __commonJSMin } from "./rolldown-runtime-DNCzzKnI.js";
2
- import { $n as canUseHarnessSync, $t as findProjectByPathSync, A as validateTieredExecutionConfig, Ai as getDocsIndexPath, An as resolveProjectKeyForCwdAsync, Ar as getModelEffortLevelsSync, Bi as sessionFilePath, Ci as SYNC_SOURCES, Cn as registerProjectSync, Cr as computeModelOrigin, Ct as flushAllPendingAutoCommits, D as resolveTieredExecutionBlock, Di as encodeClaudeProjectDir, Dn as resolveProjectFromIssue, Dr as MODEL_CAPABILITIES, E as init_tier_table, En as resolveInfraRepo, Er as resolveModel, Fi as init_paths, Gn as init_issue_id, Gr as ROLE_EFFORTS, Hn as validateVersionSyncConfig, Ht as init_state_read_home, Ii as isDeploymentGenerationRoot, In as setProjectMergeTrain, Jt as PROJECTS_CONFIG_FILE, Kt as init_project_key, Li as isDevMode, Mr as init_model_capabilities, Ni as getLegacyHome, Nr as modelSupportsImagesSync, O as resolveTieredExecutionEnabled, Oi as getDocsBudgetStatePath, On as resolveProjectFromIssueSync, Or as MODEL_DEPRECATIONS, Pi as getOverdeckHome, Pn as setProjectAutoMergeDefault, Pr as resolveModelIdSync, Qn as require_dist$1, Ri as packageRoot, Rn as setProjectSwarmPolicy, Sr as DEFAULT_WORKHORSES, T as TieredExecutionConfigError, Ti as activeDeploymentRepoRoot, Tt as init_auto_commit, Ur as COMPLIANCE_MODES, Ut as resolveStateReadHomeAsync, Wn as extractPrefixSync, Wr as PARENT_MODEL_REF, Wt as resolveStateReadHomeSync, Xn as init_projects_config_write, Y as init_record, Yr as FsError, Yt as ProjectRenameError, Zn as updateProjectsConfigText, Zr as GitHubApiError, Zt as extractTeamPrefix, _ as mergeConfigs, _n as listProjectsAsync, _r as getDashScopeUpstreamBaseUrl, ar as UnknownModelError, b as mergeTtsDaemonConfigs, bn as loadProjectsConfigSync, br as init_registry, c as init_load, cr as getKimiAnthropicBaseUrl, d as isTldrEnabledSync, dr as init_providers, f as loadConfigNoMigration, fi as CLAUDE_DIR, fn as init_projects, g as jsYaml, gi as OVERDECK_HOME, gn as listProjects, h as init_js_yaml, hi as LOGS_DIR, hn as invalidateProjectsConfigCache, i as getConversationsConfig, ii as TrackerError, ji as getDocsTelemetryPath, jn as resolveProjectPath, jr as hasModelCapabilitySync, ki as getDocsDisableStatePath, m as updateConversationsConfig, n as clearConfigCache, ni as ProcessSpawnError, o as getGlobalConfigPath, oi as init_errors, on as getProjectSync, p as loadConfigSync, q as getIssueWorkspacePath, qn as parseIssueIdSync, qt as projectKey, r as getConversationSearchConfigSync, rn as getIssuePrefix, s as getOpenInEditorCommand, sr as getBuiltInDefaultHarness, t as init_config_yaml, tn as findProjectByTeamSync, tr as init_harness_policy, tt as readIssueRecordSync, ur as getProviderForModelSync, v as getDefaultDocsConfig, vn as listProjectsSync, vr as init_openai_compatible_proxy, wn as renameProject, wt as flushAutoCommits, x as DEFAULT_CONFIG$1, xr as DEFAULT_ROLES, y as getDefaultTtsDaemonConfig, yr as defaultBackgroundAiFeatures } from "./config-yaml-BwOEANMr.js";
3
- import { i as shouldRefuseHostDashboardPort, n as isNonPrimaryCheckoutRoot, r as readHostDashboardApiPort, t as getDashboardIdentity } from "./identity-Bwh6VGeL.js";
4
- import { $ as resolvePolicy, A as handleConversationSwitchModel, At as validateOrigin$1, B as waitForTmuxSession$1, C as conversationNeedsRunningRepair, Ct as rejectUnauthorizedDashboardRequest, D as handleConversationRestartAll, Dt as waitForSessionRespawn, E as handleConversationDelete, Et as isRespawnPending, F as spawnConversationSession, Ft as jsonStringResponse, G as extractConversationAttachmentPaths, H as cleanupOrphanedConversationAttachments, I as startConversationModelBackfill, J as isManagedConversationAttachmentPath, K as getConversationAttachmentsRoot, L as stopConversationRuntime, M as resolveAllowedHarness, Mt as httpHandler, N as resolveRegisteredProject, Nt as getDefaultCwd, O as handleConversationResume, Ot as getHeaderFromMap, P as shouldReportUnresolvedLiveSession, Pt as jsonResponse, Q as handleComposerCommandMessage, R as tmuxSessionExists, S as validateConversationControlAckOrigin, St as hasDashboardInternalToken, T as handleConversationCreate, Tt as rejectUnsafeDashboardMutationRequest, U as cleanupUnreferencedConversationAttachments, V as cleanupConversationAttachments, W as ensureConversationAttachmentDir, X as runInBatches, Y as removeConversationAttachment, Z as composerCommandResultHttpStatus, _ as handleConversationPlanAction, _t as resolveJsonlPath, a as agentsRouteLayer, at as isInternalAgentRequest, b as pickDeliverAs, bt as dashboardCsrfToken, c as answerSessionPaneChoice, ct as resolveConversationGitInfo, d as deliverConversationViaControlChannel, et as ComposerCommandParseError, f as handleConversationAbort, ft as readLauncherPinnedSessionId, g as handleConversationDeliveryMethod, gt as resolveCodexRolloutPath, h as handleConversationControlAck, ht as resolveClaudeSessionId, it as invalidateAgentsCache, j as isInsideGitWorkTree, jt as validateOriginHeaders, k as handleConversationStop, kt as isTrustedOriginForHost, l as captureSessionPaneChoice, m as handleConversationCompact, mt as resolveAgentHarness, nt as composerCommandConfirmationFromBody, o as saveAgentStateAndEmitEvent, ot as resolveRequestedStartedBy, p as handleConversationCodexApproval, pt as resolveAcpTranscriptPath, q as hasConversationAttachment, rt as evaluateSpawnGuardrails, s as saveAgentStateAndEmitEventProgram, st as resolveAgentGitInfo, t as specialistsRouteLayer, tt as ComposerCommandConfirmationError, u as codexConversationPendingInput, ut as panCliInvocation, v as handleConversationThinkingLevel, vt as resolveKimiWirePath, w as conversationSessionAliveFromState, wt as rejectUnauthorizedDashboardSessionMintRequest, x as resolveConversationDeliveryMethod, xt as dashboardSessionCookieHeader, y as isPiControlChannelHarness, yt as resolvePiSessionPath, z as waitForPiTuiReady } from "./specialists-DocAK-7A.js";
5
- import { h as loadConfigSync$1, p as init_config, s as getDashboardApiUrlSync } from "./config-tucKBCCc.js";
6
- import { a as emitActivityEntrySync, c as init_activity_logger, o as emitActivityTtsSync, s as emitDashboardLifecycleSync } from "./activity-logger-BAVLrkR7.js";
7
- import { A as init_paths$1, O as OVERDECK_MIGRATION_PATH, f as init_infra, i as DbLive, k as getOverdeckDatabasePath, u as TmuxLive } from "./infra-KTp9KV9u.js";
8
- import { n as openDatabase, t as init_driver } from "./driver-CmsY2RLl.js";
9
- import { a as updateIssueRecord, i as init_record_update, r as clearRecordPipelineClosedOutSync } from "./record-update-D23jPU6b.js";
10
- import { A as listSessionNames, B as sessionExists, C as isHarnessProcessAlive, F as resizeWindow, K as deliveryVerifyLine, L as sendKeys, R as sendKeysAsync, S as init_tmux, T as killSession, a as capturePaneText, at as buildChildEnvSync, l as ensureManagedTmuxContextOnce, nt as init_ui_theme, o as createSession, ot as buildChildEnvWithoutTmuxSync, r as capturePane, rt as setUiTheme, st as init_child_env, t as buildTmuxArgs, w as isPaneDead, x as getWindowDimensions } from "./tmux-BqXzRuaH.js";
11
- import { a as getWorkspaceForIssue, c as listProjectTargets, f as resolveWorkspaceForCwd, i as getWorkspaceById, l as listProjects$1, o as init_resolver, s as listPinnedDocs, u as listWorkspaces } from "./resolver-CuAULbLs.js";
12
- import { a as init_event_store, i as initEventStore, n as getEventStore } from "./event-store-D7qcJXuZ.js";
13
- import { A as AgentRuntimeSnapshot, C as FlywheelStatus, E as SystemHealthSnapshot, M as ReviewStatusSnapshot, O as MemoryObservation, S as FlywheelRunId, T as DomainEvent, b as PanRpcGroup, j as AgentSnapshot, l as ContextLayerSaveRequest, n as COMPOSER_COMMAND_MANIFEST, p as FlywheelStats, r as compareIssueIds, s as getHarnessBehavior, t as init_src, u as ContextPreviewRequest, w as EDITORS, x as WS_METHODS, y as PanRpcError } from "./src-DudQNYVw.js";
14
- import { a as EventStoreServiceLive, c as activityEntriesFromStoredEvents, d as toAgentStatus, f as toRole, i as EventStoreService, n as IssueLifecycleLive, o as ReadModelService, s as ReadModelServiceLive, t as IssueLifecycle, u as toAgentResolution } from "./issue-lifecycle-3N8XF7lP.js";
15
- import { c as init_agents, g as logAgentLifecycleSync, h as init_persistent_logger, n as AgentsResolverLive, u as listAllAgentsSync } from "./agents-CqQJW75N.js";
16
- import { c as resolveMemoryRoot, d as resolveRagRunsFile, i as init_paths$2, l as resolveObservationsFile, m as resolveWorkspaceMemoryRoot, r as ensureParentDir, s as resolveMemoryBase, t as assertMemorySafeSegment } from "./paths-CRLnDgcI.js";
17
- import { i as recordBriefingSessionStart, n as ensureSessionContextBriefingFile, r as init_briefing_freshness, t as appendFreshBriefingUpdate } from "./briefing-freshness-CDJcmHHZ.js";
18
- import { n as listFeatureRegistryEntries, t as init_feature_registry_storage } from "./feature-registry-storage-ewNSIVsQ.js";
19
- import { a as diffAgainstMain, c as diffCheckpoints, d as diffPatchSinceCommit, f as findCommitAtTime, l as diffFilesAgainstHead, m as listCheckpoints, o as diffAgainstMainFiles, s as diffCheckpointFiles, t as captureCheckpoint, u as diffPatchFilesAgainstHead } from "./checkpoint-manager-BlOOdzLF.js";
20
- import { Ai as init_agent_runtime_mirror, B as waitForReadySignal, Bt as init_operator_interventions, Cn as refreshRuntimeCensus, Cr as resolveImplicitStaffing, Di as init_agent_record_sync, Dt as detectAwaitingInputFromPaneSync, Et as detectAwaitingInputForAgent, Fr as getProviderAuthMode, G as init_agents$1, H as getAgentRuntimeStateSync, In as init_concurrency, L as normalizeAgentId, Lt as init_messaging, O as saveAgentStateSync, Oi as readAgentHarnessModelRecordSync, Ot as init_agent_input_detection, Pn as emergencyBrake, Q as init_tier_supervisor, Rt as messageAgent, Sn as panePidsForSession, Sr as init_staffing, St as init_agent_enrichment, Tt as scanPendingInputsPromise, V as getAgentRuntimeState, Vt as operatorInterventionEvent, Xn as deliverAgentMessage, Xr as init_claude_auth, Yr as getClaudeAuthStatus, Z as deliverCommitForReview, _t as countPendingAskUserQuestionsForAgent, ai as getOpenAIAuthStatus, ar as init_transcript_landing, bn as getRuntimeCensusSnapshot, cn as listAgentStates, dr as checkCodexAuthStatus, ei as getProviderEnvForModel, f as getAgentState, fr as init_codex_auth, gt as computeAgentEnrichment, ir as captureTranscriptUserRecordSnapshot, ln as listRunningAgents, m as getAgentStateSync, nt as supervisorAgentId, oi as init_openai_auth, or as probeTranscriptSince, sn as init_queries, u as getAgentDir, un as listRunningAgentsSync, vt as getAgentJsonlMtime, wn as runtimeCensusHasHarnessProcess, wt as isInteractiveRoleAgent, xn as init_runtime_census, yn as getRuntimeCensus, zr as injectPiConversationMemory } from "./agent-state-Bb3UUxQm.js";
21
- import { t as init_behavior } from "./behavior-Bitko0mD.js";
22
- import { a as getCostForIssueAggregateSync, c as getDailyTrendsSync, d as init_cost_sync, l as getModelRollupSync, n as getBackgroundCostBySourceSync, p as queryCostEventsSync, r as getCavemanExperimentDataSync, s as getCostsByIssueSync, u as getTodayCostSync } from "./cost-sync-B-ADeXKY.js";
23
- import { a as generateHealthSummary, c as CostDoorLive, d as CostWriter, l as CostResolver, n as readCloisterStateFile, o as getAgentHealth, s as getAgentsNeedingAttention, t as getCloisterService, u as CostResolverLive } from "./service-BLb_CyPL.js";
24
- import { n as isBackgroundFeatureEnabled, t as init_features } from "./features-CGopJXdU.js";
25
- import { i as init_settings, r as getMemoryWorkerConcurrency, t as areMemoryObservationsEnabled } from "./settings-B9-H2K_E.js";
26
- import { i as updateMemoryHealth, n as extractWithProviderPolicy, r as init_health, t as init_providers$1 } from "./providers-DrfK0Ip8.js";
27
- import { C as restartCliproxy, S as readPidFile, T as stopCliproxy, b as isCliproxyInstalled, d as getCliproxyAuthDir, o as bridgeCodexAuthToCliproxy, v as init_cliproxy, w as startCliproxy, x as isCliproxyRunning, y as installCliproxy } from "./cliproxy-CX6jHRDP.js";
28
- import { i as ensureInternalTokenSync, o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-zY75jrRJ.js";
29
- import { $ as updateConversationCost, A as isAgentConversationName, B as recordConversationHandoff, C as getConversationByTmuxSession, D as importLegacyConversation, F as markConversationActive, I as markConversationEnded, J as setConversationProjectKey, L as markConversationRunning, M as listArchivedConversationsWithEnrichment, N as listConversations, O as incrementForkRetryCount, P as listFavoritedIds, Q as unarchiveConversation, S as getConversationByName, T as getStuckForks, U as setClearedToConvId, V as removeFavorite, W as setConversationClaudeSessionId, X as setForkRequest, Y as setFavorite, Z as setImportedConversationLinks, _ as canRefineTitle, b as getConversationByClaudeSessionId, ct as aggregateDiscoveredSessionCostBy, gt as getDiscoveredSessionById, h as archiveConversation, k as init_conversations, mt as findDiscoveredSessions, nt as updateConversationTitle, rt as updateForkStatus, st as aggregateDiscoveredSessionCost, tt as updateConversationForkFallbackReason, ut as countDiscoveredSessions, v as canReplaceTitle, vt as getDiscoveredSessionBySessionId, w as getConversationLedgerCosts, x as getConversationById, xt as init_discovered_sessions, y as createConversation, yt as getDiscoveredStats } from "./conversations-DhwxsOru.js";
30
- import { C as generateLauncherScriptSync, D as normalizeModelOverrideSync, E as init_model_validation, O as requireModelOverrideSync, T as MODEL_ID_PATTERN, w as init_launcher_generator } from "./auto-spawn-consent-BDfe4qz0.js";
31
- import { a as init_claude_permissions, r as getClaudePermissionFlagsStringSync } from "./claude-permissions-aHgDcZi5.js";
32
- import { C as ensureProjectLayer, E as init_layers, I as workspaceContextFile, N as resolveProjectContextFile, P as resolveWorkspaceContextFile, S as codexGlobalContextFile, T as globalContextFile$1, b as validateTemplate, c as init_render, d as userContentOutsideRegion, i as workspaceContextWithoutProjectLayer, r as init_assemble, s as hasManagedRegion, v as init_harness, y as renderForHarness } from "./assemble-DyTp2gSB.js";
33
- import { l as init_codex, s as findRolloutPath } from "./codex-OOea7lXs.js";
34
- import { i as prepareHarnessLaunch, r as init_harness_binary } from "./harness-binary-BgXYDo2Z.js";
35
- import { D as setSetting, E as setMergeTrainEnabled, S as setFlywheelAutoPickupBacklog, T as setLastCleanShutdownAt, b as setDeaconGloballyPausedSync, c as init_control_settings, d as isDeaconGloballyPausedSync, f as isFlywheelAutoPickupBacklog, g as setBootReconciliationDecision, h as isMergeTrainEnabled, l as isCloisterSpawnsPausedSync, m as isFlywheelRequireUatBeforeMerge, n as FLYWHEEL_GLOBAL_PAUSE_KEY, p as isFlywheelGloballyPaused, r as getBootReconciliationState, s as getSetting, t as FLYWHEEL_ACTIVE_RUN_ID_KEY, v as setCloisterSpawnsPausedSync, w as setFlywheelRequireUatBeforeMerge } from "./control-settings-5k6ixdFW.js";
36
- import { r as init_factory, t as createTracker } from "./factory-D4V2wd_V.js";
37
- import { n as init_review_status_source, t as classifyAdvancingSessionLifecycle } from "./review-status-source-Ct912fv_.js";
38
- import { a as PAN_DIRNAME, d as PENDING_PROMOTION_FILENAME, f as WORKSPACE_RUNTIME_DIRNAME, i as PAN_CONTINUE_FILENAME, m as init_types, p as asPanSpecDocument } from "./types-DbxY2QB6.js";
39
- import { C as init_specs, D as writeSpecDocument, N as getProjectPanPaths, O as writeSpecForIssue, P as init_paths$3, S as findSpecByIssue, a as findWorkspaceDraftPlan, b as subItemsOf, c as isPlanningComplete, d as readPlan, h as readWorkspacePlanSync, m as readWorkspacePlan, r as findPlan, s as init_io, y as init_types$1 } from "./io-DfvO2xyh.js";
40
- import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-1NZcVx7n.js";
41
- import { a as loadCloisterConfigSync, o as saveCloisterConfigSync, r as init_config$1, s as shouldAutoStart } from "./config-DC75T4Mr.js";
42
- import { a as init_state_home, c as isStateMigrated, i as ensureStateWorktree, r as clearStateMigrationCache, s as inspectStateMigration } from "./state-home-DhAZlk5k.js";
43
- import { i as checkPrdGateSync, s as promoteWorkspacePrdDraft, t as init_pan_dir } from "./pan-dir-DDd91kMb.js";
44
- import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-CCBpRv5m.js";
45
- import { a as init_tracker_config, i as initTrackerConfigCache, n as getLinearApiKey, r as getRallyConfig, t as getGitHubConfig } from "./tracker-config-DVzhaUxO.js";
46
- import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-D8R-LWX5.js";
47
- import { n as AgentStateServiceLive } from "./agent-state-service-BFbttwRA.js";
48
- import { i as PlanEmpty, l as WorkspaceCreateError, n as AgentStartError, s as TrackerApiError, t as AgentAlreadyRunning, u as WorkspaceNotFound } from "./typed-errors-DzC4zXbI.js";
49
- import { r as LinearClientOptionalLive, t as LinearClient } from "./linear-client-B0cIkTs4.js";
50
- import { r as GitHubClientOptionalLive, t as GitHubClient } from "./github-client-DkJVR908.js";
51
- import { r as RallyClientOptionalLive, t as RallyClient } from "./rally-client-D6Feq1Ka.js";
52
- import { n as resolveGitHubIssueSync, r as resolveTrackerTypeSync, t as init_tracker_utils } from "./tracker-utils-xnVJVrrO.js";
53
- import { a as startSharedIssueService, c as parseIntegerHeader, i as issue_service_singleton_exports, n as init_issue_service_singleton, o as CacheService, s as init_cache_service, t as getSharedIssueService } from "./issue-service-singleton-BN_2MXp4.js";
54
- import { a as setPipelineHandlerSync, t as init_pipeline_notifier } from "./pipeline-notifier-BmsLWM_2.js";
55
- import { a as getMergeBlockerReconcileCandidates, l as init_review_status_sync } from "./review-status-sync-B7V_Gg51.js";
56
- import { S as requeueToPending, T as transitionToMerging, _ as markMerged, c as init_merge_sync, f as listActiveAutoMerges, g as markFailed, h as markBlocked, i as getActionableAutoMerge, j as listUatGenerationsSync, l as isFlywheelGloballyPaused$1, m as listProblemAutoMerges, n as countActionableAutoMerges, p as listDuePendingAutoMerges, t as cancelPending, v as markMergingBlocked, w as scheduleAutoMergeWithResult } from "./merge-sync-Ct0-cxMX.js";
57
- import { C as setReviewStatus, F as init_install_id, I as init_config$2, L as resolveTelemetryEnabled, M as init_service, N as synchronizeAnalyticsServices, P as getOrCreateInstallId, R as telemetryEnvironmentForcesOff, _ as markWorkspaceStuck, a as clearStuckMergeStatuses, c as fixStuckCommentedReviews, d as getReviewStatusSync, h as loadReviewStatuses, i as clearReviewStatus, j as getAnalyticsService, l as fixStuckReadyForMerge, m as loadReadyForMergeFlags, p as init_review_status, u as getReviewStatus, w as setReviewStatusSync } from "./review-status-DBnR5t4z.js";
58
- import { a as clearQueryExpansionCache, i as resolveKnowledgeBundleRoot, n as init_injection, o as init_query_expansion, r as injectPromptTimeMemory } from "./injection-67YyU6SC.js";
59
- import { a as init_fts_db, i as closeMemoryFtsDatabases, n as init_search, o as runMemoryFtsStatement, s as runMemoryFtsTransaction, t as buildMatchQuery } from "./search-DwHYaj66.js";
60
- import { n as require_auth_errors, r as require_token_error, t as require_token_util } from "./token-util-DyJJyX_B.js";
61
- import { A as createSettledTtlPromiseCache, D as init_advisory_checks, E as verifyAppCanMerge, M as withConcurrencyLimit, O as isAdvisoryCheckName, d as getPullRequestState, f as init_github_app, j as init_concurrency$1, k as createPromiseConcurrencyLimiter, l as getMergeBackendStatus, p as isGitHubAppConfigured } from "./github-app-4UX8VIr8.js";
62
- import { C as getWorkspacePathForIssue, E as stopAgentOutputService, S as resolveIssueHeadlineCost, T as startAgentOutputService, _ as getCostsForIssueSync, b as processPendingFeedbackDeliveries, d as resumeQueuedMerges, f as syncWalFromAllProjects, g as migrateAllSessionsSync, h as reclassifyUnknownCostEventsSync, l as internalEventsRouteLayer, m as reconcilePiTranscripts, p as reconcile$1, t as workspacesRouteLayer, u as eventsRouteLayer, v as rebuildCacheSync, w as retainAgentOutputInterest, x as getCachedRunningAgents, y as syncCacheSync } from "./workspaces-BlpbOPZ7.js";
63
- import { S as parseAcpConversationMessages, _ as isOhmypiSessionFile, a as contextUsageFromParseResult, b as parseCodexConversationMessages, c as parseEntireConversation, d as init_kimi_conversation_parser, f as parseKimiConversationMessages, g as init_ohmypi_conversation_parser, h as parsePiConversationMessages, i as computeContextUsage, l as parseFromLastCompactBoundary, m as isPiSessionFile, n as gateSnapshotEmission, o as summarizeConversationActivity, p as init_pi_conversation_parser, r as watchConversation, s as parseConversationMessages, t as init_conversation_service, v as parseOhmypiConversationMessages, x as init_acp_conversation_parser, y as init_codex_conversation_parser } from "./conversation-service-BteE4ELK.js";
64
- import { a as enrichSessions, c as searchSessions, i as CostThresholdError, l as embed, n as getSessionsFeedFacets, o as embedSessions, r as listSessionsFeed, s as parseRelativeTime, t as scan } from "./scanner-2aHeLC3W.js";
65
- import { c as tailEventsSync, n as deduplicateEventsSync, s as readEventsSync } from "./events-BIKGJZOT.js";
66
- import { n as recordBackgroundAiCost, t as init_cost } from "./cost-Bnf9NUC5.js";
67
- import { a as getByIssueId, i as parseFlywheelStatsWindow, n as derivePipelineRunStatsInputs, o as markFixed, r as computeFlywheelStats, s as upsert, t as listSubstrateBugWeights } from "./substrate-bug-weights-service-BTNjHBnl.js";
68
- import { n as writeSequenceMd, t as parseSequenceMd } from "./sequence-io-POKWdusG.js";
69
- import { _ as normalizeGate, d as computeEpicGroups, f as computeLanes, h as init_pickup, l as classifyIssue, m as computeWaves, p as computeStats, u as computeCohort, v as selectNeedsPlanning } from "./pickup-BjJsSX12.js";
70
- import { C as readCurrentLatestFlywheelStatus, D as writeFlywheelLaunchMetadata, E as subscribeLatestFlywheelStatus, F as setItemRequirements, G as liveOrderIssueLookup, H as getBook, I as setSettings, L as setStatus, M as moveItem, N as removeItem, O as writeLatestFlywheelStatus, P as renameBook, R as backlogCandidates, S as nextFlywheelRunId, T as resolveLiveFlywheelRunId, U as getBookAsync, W as listBooks, a as isFlywheelDevcontainerRuntime, b as isFlywheelRunId, f as spawnFlywheelAgent, g as abortFlywheelRun, j as createBook, k as addItems, p as buildClassifyLookups, s as loadResumeSessionId, t as FLYWHEEL_ORCHESTRATOR_AGENT_ID, u as saveResumeSessionId, v as getFlywheelRunDetail, w as readFlywheelLaunchMetadata, x as listFlywheelRuns, z as computeBookProgress } from "./flywheel-C7yek87O.js";
71
- import { a as getResourceStacks, c as getCurrentDockerStats, f as getSystemHealthEvidenceSnapshot, g as classifyAgentHealth, h as startSmeeProcessSync, l as getAcceptedSystemHealthSnapshot, m as isSmeeConfiguredSync, o as formatUptime, s as getContainerHistory, u as getDeployStaleness } from "./memory-governor-A4O6vI9d.js";
72
- import { D as detectPlatform, E as validateFeatureName, O as init_platform, S as init_worktree_ops, _ as updateWorkspaceLayout, b as readWorkspaceIdentity, c as installGitHooksInDir, d as init_writer, f as relocateWorkspace, g as unarchiveWorkspace, h as touchWorkspaceAccessed, l as archiveWorkspace, m as setWorkspaceRunCommand, p as setWorkspaceFavorite, s as init_git_hooks, u as createWorkspace, v as upsertProjectFromConfig, x as writeWorkspaceIdentity, y as init_identity_record } from "./workspace-manager-W1OnbvU5.js";
73
- import { n as init_workspace_config, t as getDefaultWorkspaceConfigSync } from "./workspace-config-D0CavVtz.js";
74
- import { B as cleanupClosedIssueAgentDirectories, F as setAgentStatusChangedNotifier, I as setAgentStoppedNotifier, J as isBootReconciliationCandidate, K as extendBootReconciliationGrace, L as setMergeReadyNotifier, O as loadConfig, X as startBootReconciliation, Y as listBootReconciliationCandidates, ht as paneShowsClaudeBootBlockingScreen, k as loadState, n as applyBootReconciliationDecision, q as isAutoResumableRole, r as assessDeaconPatrolFreshness, x as getDeaconLogs } from "./deacon-TPYssFYt.js";
75
- import { s as getRuntimeForAgent } from "./stuck-remediation-Di5JYkoo.js";
76
- import { a as getShadowState, s as init_shadow_state } from "./shadow-state-CEGrrECe.js";
77
- import { n as init_issue_closed, t as clearIssueClosedCache } from "./issue-closed-dvEWKO7Q.js";
78
- import { r as parseArtifactRef } from "./forge-DYX9sKzG.js";
79
- import "./deacon-merge-BOGFEV8_.js";
80
- import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-D4ULO4qG.js";
81
- import { V as getReviewerSessionName, t as init_specialists } from "./specialists-8LcQi9Np.js";
82
- import { c as findPrdAnywhereSync, l as readPrdContent, s as findDraftPrd } from "./archive-planning-BwEhu9Oq.js";
83
- import { b as resolveSwarmPolicy } from "./deacon-swarm-BiLfNm_v.js";
84
- import { i as resolveBootGates, r as formatBootGateState } from "./no-resume-mode-MWI6pnrK.js";
85
- import { t as createInFlightGuard } from "./in-flight-guard-pcwXKLGz.js";
86
- import { A as removeIssueParkedLabel, C as applyIssueParkedLabel, D as init_label_ops, E as applyIssueVetoedLabel, M as removeIssueReleasedLabel, N as removeIssueVetoedLabel, O as removeIssueBlocksMainLabel, S as applyIssueObjectionLabel, T as applyIssueReleasedLabel, a as gatherProjectLensSignals, g as parseIssueIdFromTextSync, h as init_resource_utils, j as removeIssueReadyLabel, k as removeIssueObjectionLabel, n as PipelineMembershipUnavailableError, s as init_pipeline_membership_gather, u as listOpenPullRequestsSnapshot, w as applyIssueReadyLabel, x as applyIssueBlocksMainLabel } from "./pipeline-membership-gather-CGFY1v-y.js";
87
- import { a as spawnPlanningSession, r as resolveAutoSpawnOnFinalize } from "./spawn-planning-session-nH3b4Drz.js";
88
- import { r as computeMergeQueueFromCandidates, s as listEligibleCandidatesByProject } from "./flywheel-merge-order-CXfU4M6l.js";
89
- import { n as init_pipeline_membership, r as resolvePipelineMembership } from "./pipeline-membership-BHZp_ShY.js";
90
- import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-dJhXvZGQ.js";
91
- import { d as killRemoteAgent, m as loadRemoteAgentState, o as getRemoteAgentOutput, r as checkRemoteSpendCap, s as init_remote_agents, v as sendToRemoteAgent, y as spawnRemoteAgent } from "./remote-agents-Bgtc2nOO.js";
92
- import { r as spawnInspectAgent } from "./inspect-agent-VHSihlb7.js";
93
- import { r as lookupPullRequestNumberForBranch, t as githubPrLookupSource } from "./github-pr-lookup-C9Vokb0W.js";
94
- import { a as fetchIssuePullRequestDiff, c as getCachedIssuePrTabResponse, i as fetchIssuePullRequestDetails, l as getIssuePrTabCacheGeneration, n as fetchIssueCheckRuns, r as fetchIssuePullRequest, s as bumpIssuePrTabCacheGeneration, u as setCachedIssuePrTabResponse } from "./pull-requests-BcHIsFJv.js";
95
- import { n as DOD_ROWS } from "./dod-gK835UMf.js";
96
- import { n as resolveParkedPopulation, r as summarizeParked } from "./resolver-C8rooxoz.js";
97
- import { a as readCurrentStatus, l as maybeTriggerStatusRollup, s as readRecentObservations, u as writePendingTurn } from "./rollup-QCwYcBdP.js";
98
- import { r as isExtendedReviewEnabled } from "./review-agent-7C2w5CzU.js";
99
- import { n as getTldrDaemonServiceSync, r as init_tldr_daemon } from "./tldr-daemon-CMVBT4kT.js";
100
- import { S as ensureSyncGitQuiescent, x as listGitOperationsSync } from "./merge-agent-GWhmnxFk.js";
101
- import { t as readVerificationArtifact } from "./verification-artifact-0Zku8N-W.js";
102
- import { t as getAgentCommandSync } from "./settings-Clw8UVNs.js";
103
- import { r as isRemoteAvailable, t as createFlyProviderFromConfig } from "./remote-CBpLi4Yy.js";
104
- import { n as init_claude_settings_overlay, t as detectProviderEnvConflicts } from "./claude-settings-overlay-T2LWLteV.js";
105
- import { _ as init_transcript_adapter, a as generateFallbackSummary, c as handoffPreconditionFallbackReason, d as prependFallbackFocus, f as requestHandoffFromAgent, g as getTranscriptAdapter, i as copySessionFromCompactBoundary, l as init_summary_fork, o as generateSummaryForFork, p as reserveSummaryForkSession, r as authorHandoffExternal, s as handoffFailureReason, u as logHandoffFallback } from "./summary-fork-CZ88rhVx.js";
106
- import { a as init_conversation_compaction, c as shouldInterceptManualCompact, n as compactConversationNative, o as isCompacting } from "./conversation-compaction-CSpVpxN6.js";
107
- import { n as loadShipRecords, r as publicShipStatus, t as aggregateGenerationShipStatus } from "./ship-status-Ce3_3edi.js";
108
- import { t as init_context_layers } from "./context-layers-CSPGc2Hb.js";
109
- import { a as appendLinearMcpAuthHealthyEvent, r as appendLinearMcpAuthCallbackRelayedEvent, u as resolveLinearMcpAuthIntervention } from "./linear-mcp-auth-Dsu9Io9r.js";
110
- import { i as getMergeBlockersPayload, n as hasOrderIssuePrd, r as validateBookForStart, t as createOrderPrdLookup } from "./validate-Dvv83iBx.js";
111
- import { i as spawnSequencerAgent, n as clearFinishedSequencerRun, r as getSequencerRunStatus, t as SEQUENCER_AGENT_ID } from "./sequencer-agent-DS00KHVm.js";
112
- import { n as sameCanonicalReviewStatus, t as emitReviewStatusChanged } from "./review-status-emit-Cg4tOb8U.js";
113
- import "./supervisor-D4v0WfiQ.js";
114
- import { l as startUatTrainReconciler, u as stopUatTrainReconciler } from "./uat-train-DVUNW03P.js";
115
- import { n as settlePendingLifecycleClaim, t as claimPendingLifecycleFile } from "./pending-lifecycle-claim-CYgMiDAP.js";
116
- import { i as listTranscriptCheckpoints, r as getTranscriptCheckpoint$1 } from "./checkpoints-BGfl0cHM.js";
117
- import { r as readPendingDeploy } from "./deploy-queue-o7shYg1j.js";
2
+ import { $n as updateProjectsConfigText, $r as GitHubApiError, $t as findProjectByPathSync, A as validateTieredExecutionConfig, An as resolveProjectKeyForCwdAsync, Ar as MODEL_DEPRECATIONS, Bi as isDevMode, Cn as registerProjectSync, Cr as DEFAULT_ROLES, Ct as flushAllPendingAutoCommits, D as resolveTieredExecutionBlock, Di as activeDeploymentRepoRoot, Dn as resolveProjectFromIssue, E as init_tier_table, En as resolveInfraRepo, Fr as modelSupportsImagesSync, Gr as COMPLIANCE_MODES, Hn as validateVersionSyncConfig, Ht as init_state_read_home, Ii as getLegacyHome, In as setProjectMergeTrain, Ir as resolveModelIdSync, Jt as PROJECTS_CONFIG_FILE, Kn as extractPrefixSync, Kr as PARENT_MODEL_REF, Kt as init_project_key, Li as getOverdeckHome, Mi as getDocsDisableStatePath, Mr as getModelEffortLevelsSync, Ni as getDocsIndexPath, Nr as hasModelCapabilitySync, O as resolveTieredExecutionEnabled, On as resolveProjectFromIssueSync, Or as resolveModel, Pi as getDocsTelemetryPath, Pn as setProjectAutoMergeDefault, Pr as init_model_capabilities, Qn as init_projects_config_write, Ri as init_paths, Rn as setProjectSwarmPolicy, Sr as init_registry, T as TieredExecutionConfigError, Ti as SYNC_SOURCES, Tr as computeModelOrigin, Tt as init_auto_commit, Ui as sessionFilePath, Un as init_projects_cache_events, Ut as resolveStateReadHomeAsync, Vi as packageRoot, Wn as subscribeProjectsConfigInvalidation, Wt as resolveStateReadHomeSync, Y as init_record, Yn as parseIssueIdSync, Yt as ProjectRenameError, Zr as FsError, Zt as extractTeamPrefix, _ as mergeConfigs, _i as LOGS_DIR, _n as listProjectsAsync, b as mergeTtsDaemonConfigs, bn as loadProjectsConfigSync, br as init_openai_compatible_proxy, c as init_load, ci as init_errors, d as isTldrEnabledSync, er as require_dist$1, f as loadConfigNoMigration, fn as init_projects, fr as getProviderForModelSync, g as jsYaml, gn as listProjects, h as init_js_yaml, hn as invalidateProjectsConfigCache, i as getConversationsConfig, ii as ProcessSpawnError, ji as getDocsBudgetStatePath, jn as resolveProjectPath, ki as encodeClaudeProjectDir, kr as MODEL_CAPABILITIES, lr as getBuiltInDefaultHarness, m as updateConversationsConfig, mi as CLAUDE_DIR, n as clearConfigCache, o as getGlobalConfigPath, oi as TrackerError, on as getProjectSync, p as loadConfigSync, pr as init_providers, q as getIssueWorkspacePath, qn as init_issue_id, qr as ROLE_EFFORTS, qt as projectKey, r as getConversationSearchConfigSync, rn as getIssuePrefix, rr as init_harness_policy, s as getOpenInEditorCommand, sr as UnknownModelError, t as init_config_yaml, tn as findProjectByTeamSync, tr as canUseHarnessSync, tt as readIssueRecordSync, ur as getKimiAnthropicBaseUrl, v as getDefaultDocsConfig, vi as OVERDECK_HOME, vn as listProjectsSync, wn as renameProject, wr as DEFAULT_WORKHORSES, wt as flushAutoCommits, x as DEFAULT_CONFIG$1, xr as defaultBackgroundAiFeatures, y as getDefaultTtsDaemonConfig, yr as getDashScopeUpstreamBaseUrl, zi as isDeploymentGenerationRoot } from "./config-yaml-D9nfpEx1.js";
3
+ import { i as shouldRefuseHostDashboardPort, n as isNonPrimaryCheckoutRoot, r as readHostDashboardApiPort, t as getDashboardIdentity } from "./identity-C23uY8dZ.js";
4
+ import { $ as ComposerCommandParseError, A as isInsideGitWorkTree, B as cleanupConversationAttachments, C as handleConversationClearForkState, Ct as jsonResponse, D as handleConversationResume, E as handleConversationRestartAll, F as startConversationModelBackfill, G as getConversationAttachmentsRoot, H as cleanupUnreferencedConversationAttachments, I as stopConversationRuntime, J as removeConversationAttachment, K as hasConversationAttachment, L as tmuxSessionExists, M as resolveRegisteredProject, N as shouldReportUnresolvedLiveSession, O as handleConversationStop, P as spawnConversationSession, Q as resolvePolicy, R as waitForPiTuiReady, S as conversationSessionAliveFromState, St as getDefaultCwd, T as handleConversationDelete, U as ensureConversationAttachmentDir, V as cleanupOrphanedConversationAttachments, W as extractConversationAttachmentPaths, X as composerCommandResultHttpStatus, Y as runInBatches, Z as handleComposerCommandMessage, _ as isPiControlChannelHarness, _t as getHeaderFromMap, a as agentsRouteLayer, at as resolveRequestedStartedBy, b as validateConversationControlAckOrigin, bt as validateOriginHeaders, c as codexConversationPendingInput, d as handleConversationCodexApproval, dt as hasDashboardInternalToken, et as ComposerCommandConfirmationError, f as handleConversationCompact, ft as rejectUnauthorizedDashboardRequest, g as handleConversationThinkingLevel, gt as waitForSessionRespawn, h as handleConversationPlanAction, ht as isRespawnPending, it as isInternalAgentRequest, j as resolveAllowedHarness, k as handleConversationSwitchModel, l as deliverConversationViaControlChannel, lt as dashboardCsrfToken, m as handleConversationDeliveryMethod, mt as rejectUnsafeDashboardMutationRequest, nt as evaluateSpawnGuardrails, o as saveAgentStateAndEmitEvent, p as handleConversationControlAck, pt as rejectUnauthorizedDashboardSessionMintRequest, q as isManagedConversationAttachmentPath, rt as invalidateAgentsCache, s as saveAgentStateAndEmitEventProgram, st as panCliInvocation, t as specialistsRouteLayer, tt as composerCommandConfirmationFromBody, u as handleConversationAbort, ut as dashboardSessionCookieHeader, v as pickDeliverAs, vt as isTrustedOriginForHost, w as handleConversationCreate, wt as jsonStringResponse, x as conversationNeedsRunningRepair, xt as httpHandler, y as resolveConversationDeliveryMethod, yt as validateOrigin$1, z as waitForTmuxSession$1 } from "./specialists-b0dMMjWq.js";
5
+ import { h as loadConfigSync$1, p as init_config, s as getDashboardApiUrlSync } from "./config-ZGjvuR6J.js";
6
+ import { c as emitDashboardLifecycleSync, l as init_activity_logger, o as emitActivityEntrySync, s as emitActivityTtsSync, t as appendDomainEventAsync } from "./activity-logger-BWZhVphb.js";
7
+ import { A as init_paths$1, O as OVERDECK_MIGRATION_PATH, f as init_infra, i as DbLive, k as getOverdeckDatabasePath, u as TmuxLive } from "./infra-CHIvOb9q.js";
8
+ import { n as openDatabase, t as init_driver } from "./driver-BtcFz-qu.js";
9
+ import { a as updateIssueRecord, i as init_record_update, r as clearRecordPipelineClosedOutSync } from "./record-update-dBGxL9OC.js";
10
+ import { B as sendKeys, C as init_tmux, E as killSession, L as resizeWindow, S as getWindowDimensions, T as isPaneDead, U as sessionExists, V as sendKeysAsync, X as deliveryVerifyLine, Y as activeComposerRegion, Z as init_pane_composer, a as capturePaneText, dt as init_child_env, j as listSessionNames, lt as buildChildEnvSync, o as capturePaneViewport, ot as init_ui_theme, r as capturePane, s as createSession, st as setUiTheme, t as buildTmuxArgs, u as ensureManagedTmuxContextOnce, ut as buildChildEnvWithoutTmuxSync, w as isHarnessProcessAlive } from "./tmux-DWEc4Ld9.js";
11
+ import { a as getWorkspaceForIssue, c as listProjectTargets, f as resolveWorkspaceForCwd, i as getWorkspaceById, l as listProjects$1, o as init_resolver, s as listPinnedDocs, u as listWorkspaces } from "./resolver-gxv97jsQ.js";
12
+ import { a as init_event_store, i as initEventStore, n as getEventStore } from "./event-store-BCSgMubf.js";
13
+ import { A as AgentRuntimeSnapshot, C as FlywheelStatus, E as SystemHealthSnapshot, M as ReviewStatusSnapshot, O as MemoryObservation, S as FlywheelRunId, T as DomainEvent, b as PanRpcGroup, j as AgentSnapshot, l as ContextLayerSaveRequest, n as COMPOSER_COMMAND_MANIFEST, p as FlywheelStats, r as compareIssueIds, s as getHarnessBehavior, t as init_src, u as ContextPreviewRequest, w as EDITORS, x as WS_METHODS, y as PanRpcError } from "./src-CY2Wl8IX.js";
14
+ import { a as EventStoreServiceLive, c as ReadModelService, f as toAgentResolution, i as EventStoreService, l as ReadModelServiceLive, m as toRole, n as IssueLifecycleLive, o as startProjectCiRefillAfterProjectionReady, p as toAgentStatus, s as resolveDefaultBranchHead, t as IssueLifecycle, u as activityEntriesFromStoredEvents } from "./issue-lifecycle-D9nLErvS.js";
15
+ import { c as init_agents, g as logAgentLifecycleSync, h as init_persistent_logger, n as AgentsResolverLive, u as listAllAgentsSync } from "./agents-jXgqpHca.js";
16
+ import { c as resolveMemoryRoot, d as resolveRagRunsFile, i as init_paths$2, l as resolveObservationsFile, m as resolveWorkspaceMemoryRoot, r as ensureParentDir, s as resolveMemoryBase, t as assertMemorySafeSegment } from "./paths-DEe9j-kw.js";
17
+ import { i as recordBriefingSessionStart, n as ensureSessionContextBriefingFile, r as init_briefing_freshness, t as appendFreshBriefingUpdate } from "./briefing-freshness-e_OEYZEe.js";
18
+ import { n as listFeatureRegistryEntries, t as init_feature_registry_storage } from "./feature-registry-storage-zh3ZXW6f.js";
19
+ import { a as diffAgainstMain, c as diffCheckpoints, d as diffPatchSinceCommit, f as findCommitAtTime, h as listCheckpoints, l as diffFilesAgainstHead, o as diffAgainstMainFiles, s as diffCheckpointFiles, t as captureCheckpoint, u as diffPatchFilesAgainstHead } from "./checkpoint-manager-DOwRGFff.js";
20
+ import { $ as deliverCommitForReview, A as saveAgentStateSync, An as init_runtime_census, At as init_agent_input_detection, Dt as scanPendingInputsPromise, Et as isInteractiveRoleAgent, Gn as init_concurrency, H as waitForReadySignal, Ht as init_messaging, Ii as init_agent_record_sync, It as answerSessionPaneChoice, Jr as injectPiConversationMemory, Kt as init_operator_interventions, Li as readAgentHarnessModelRecordSync, Lt as captureSessionPaneChoice, Mn as refreshRuntimeCensus, Mr as resolveImplicitStaffing, Nn as runtimeCensusHasHarnessProcess, On as getRuntimeCensus, Ot as detectAwaitingInputForAgent, Rt as init_session_pane_choice, U as getAgentRuntimeState, Un as emergencyBrake, Ut as messageAgent, W as getAgentRuntimeStateSync, Wr as getProviderAuthMode, _n as listAgentStates, ai as init_claude_auth, ar as deliverAgentMessage, br as checkCodexAuthStatus, bt as getAgentJsonlMtime, et as init_tier_supervisor, f as getAgentDir, g as getAgentStateSync, gn as init_queries, hi as init_openai_auth, hr as probeTranscriptSince, ii as getClaudeAuthStatus, it as supervisorAgentId, jn as panePidsForSession, jr as init_staffing, kn as getRuntimeCensusSnapshot, kt as detectAwaitingInputFromPaneSync, li as getProviderEnvForModel, m as getAgentState, mi as getOpenAIAuthStatus, mr as init_transcript_landing, pr as captureTranscriptUserRecordSnapshot, q as init_agents$1, qt as operatorInterventionEvent, vn as listRunningAgents, vt as computeAgentEnrichment, wt as init_agent_enrichment, xr as init_codex_auth, yn as listRunningAgentsSync, yt as countPendingAskUserQuestionsForAgent, z as normalizeAgentId, zi as init_agent_runtime_mirror } from "./agent-state-BJhGIJZe.js";
21
+ import { t as init_behavior } from "./behavior-BiCQzqyT.js";
22
+ import { a as getCostForIssueAggregateSync, c as getDailyTrendsSync, d as init_cost_sync, l as getModelRollupSync, n as getBackgroundCostBySourceSync, p as queryCostEventsSync, r as getCavemanExperimentDataSync, s as getCostsByIssueSync, u as getTodayCostSync } from "./cost-sync-DOkdE_yB.js";
23
+ import { a as generateHealthSummary, c as CostDoorLive, d as CostWriter, l as CostResolver, n as readCloisterStateFile, o as getAgentHealth, s as getAgentsNeedingAttention, t as getCloisterService, u as CostResolverLive } from "./service-CEp-3iow.js";
24
+ import { n as isBackgroundFeatureEnabled, t as init_features } from "./features-BGntOWdy.js";
25
+ import { i as init_settings, r as getMemoryWorkerConcurrency, t as areMemoryObservationsEnabled } from "./settings-Ch2pCVtt.js";
26
+ import { i as updateMemoryHealth, n as extractWithProviderPolicy, r as init_health, t as init_providers$1 } from "./providers-BL1I66sM.js";
27
+ import { C as isCliproxyRunning, D as restartCliproxy, E as readPidFile, O as startCliproxy, S as isCliproxyInstalled, b as init_cliproxy, k as stopCliproxy, o as bridgeCodexAuthToCliproxy, p as getCliproxyAuthDir, x as installCliproxy } from "./cliproxy-BpYpkogS.js";
28
+ import { i as ensureInternalTokenSync, o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-DoVzb4b7.js";
29
+ import { $ as unarchiveConversation, A as init_conversations, C as getConversationByName, E as getStuckForks, F as listFavoritedIds, G as setConversationClaudeSessionId, H as removeFavorite, I as markConversationActive, L as markConversationEnded, N as listArchivedConversationsWithEnrichment, O as importLegacyConversation, P as listConversations, Q as setImportedConversationLinks, R as markConversationRunning, S as getConversationById, St as init_discovered_sessions, T as getConversationLedgerCosts, V as recordConversationHandoff, W as setClearedToConvId, X as setFavorite, Y as setConversationProjectKey, Z as setForkRequest, _ as canRefineTitle, _t as getDiscoveredSessionById, b as createConversation, bt as getDiscoveredStats, ct as aggregateDiscoveredSessionCost, dt as countDiscoveredSessions, et as updateConversationCost, h as archiveConversation, ht as findDiscoveredSessions, it as updateForkStatus, j as isAgentConversationName, k as incrementForkRetryCount, lt as aggregateDiscoveredSessionCostBy, nt as updateConversationForkFallbackReason, rt as updateConversationTitle, v as canReplaceTitle, w as getConversationByTmuxSession, x as getConversationByClaudeSessionId, yt as getDiscoveredSessionBySessionId } from "./conversations-C75EFFjf.js";
30
+ import { C as generateLauncherScriptSync, D as normalizeModelOverrideSync, E as init_model_validation, O as requireModelOverrideSync, T as MODEL_ID_PATTERN, w as init_launcher_generator } from "./auto-spawn-consent-Dc4mtM-B.js";
31
+ import { a as init_claude_permissions, r as getClaudePermissionFlagsStringSync } from "./claude-permissions-Bc5kjX1q.js";
32
+ import { C as codexGlobalContextFile, D as init_layers, E as globalContextFile$1, F as resolveWorkspaceContextFile, L as workspaceContextFile, P as resolveProjectContextFile, b as renderForHarness, c as hasManagedRegion, f as userContentOutsideRegion, i as workspaceContextWithoutProjectLayer, l as init_render, r as init_assemble, s as configDisabledRuleNames, w as ensureProjectLayer, x as validateTemplate, y as init_harness } from "./assemble-CyvEBmmq.js";
33
+ import { l as init_codex, s as findRolloutPath } from "./codex-KaSKE-R3.js";
34
+ import { i as prepareHarnessLaunch, r as init_harness_binary } from "./harness-binary-tMmgJfC1.js";
35
+ import { D as setSetting, E as setMergeTrainEnabled, S as setFlywheelAutoPickupBacklog, T as setLastCleanShutdownAt, b as setDeaconGloballyPausedSync, c as init_control_settings, d as isDeaconGloballyPausedSync, f as isFlywheelAutoPickupBacklog, g as setBootReconciliationDecision, h as isMergeTrainEnabled, l as isCloisterSpawnsPausedSync, m as isFlywheelRequireUatBeforeMerge, n as FLYWHEEL_GLOBAL_PAUSE_KEY, p as isFlywheelGloballyPaused, r as getBootReconciliationState, s as getSetting, t as FLYWHEEL_ACTIVE_RUN_ID_KEY, v as setCloisterSpawnsPausedSync, w as setFlywheelRequireUatBeforeMerge } from "./control-settings-BMoDHY1G.js";
36
+ import { n as init_review_status_source, t as classifyAdvancingSessionLifecycle } from "./review-status-source-Jq0BXmn3.js";
37
+ import { a as PAN_DIRNAME, d as PENDING_PROMOTION_FILENAME, f as WORKSPACE_RUNTIME_DIRNAME, i as PAN_CONTINUE_FILENAME, m as init_types, p as asPanSpecDocument } from "./types-pLpbsNto.js";
38
+ import { C as init_specs, D as writeSpecDocument, N as getProjectPanPaths, O as writeSpecForIssue, P as init_paths$3, S as findSpecByIssue, a as findWorkspaceDraftPlan, b as subItemsOf, c as isPlanningComplete, d as readPlan, h as readWorkspacePlanSync, m as readWorkspacePlan, r as findPlan, s as init_io, y as init_types$1 } from "./io-DKrWd3gX.js";
39
+ import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-DusNpVEe.js";
40
+ import { a as loadCloisterConfigSync, o as saveCloisterConfigSync, r as init_config$1, s as shouldAutoStart } from "./config-Doq_tF-f.js";
41
+ import { a as init_state_home, c as isStateMigrated, i as ensureStateWorktree, r as clearStateMigrationCache, s as inspectStateMigration } from "./state-home-DdG8erBI.js";
42
+ import { i as checkPrdGateSync, s as promoteWorkspacePrdDraft, t as init_pan_dir } from "./pan-dir-BMda7tQj.js";
43
+ import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-6WL46dsB.js";
44
+ import { a as init_tracker_config, i as initTrackerConfigCache, n as getLinearApiKey, r as getRallyConfig, t as getGitHubConfig } from "./tracker-config-CJzPhSHv.js";
45
+ import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-CMWAQuWM.js";
46
+ import { n as AgentStateServiceLive } from "./agent-state-service-CiIuwzIs.js";
47
+ import { i as PlanEmpty, l as WorkspaceCreateError, n as AgentStartError, s as TrackerApiError, t as AgentAlreadyRunning, u as WorkspaceNotFound } from "./typed-errors-DXqf3RnP.js";
48
+ import { r as LinearClientOptionalLive, t as LinearClient } from "./linear-client-7fQThJTc.js";
49
+ import { r as GitHubClientOptionalLive, t as GitHubClient } from "./github-client-DAbuXLuk.js";
50
+ import { r as RallyClientOptionalLive, t as RallyClient } from "./rally-client-qKbCNRVW.js";
51
+ import { n as resolveGitHubIssueSync, r as resolveTrackerTypeSync, t as init_tracker_utils } from "./tracker-utils-DJAOAuMN.js";
52
+ import { a as startSharedIssueService, c as parseIntegerHeader, i as issue_service_singleton_exports, n as init_issue_service_singleton, o as CacheService, s as init_cache_service, t as getSharedIssueService } from "./issue-service-singleton-B2xy-IS9.js";
53
+ import { a as setPipelineHandlerSync, t as init_pipeline_notifier } from "./pipeline-notifier-BNAV9kpa.js";
54
+ import { a as getMergeBlockerReconcileCandidates, l as init_review_status_sync } from "./review-status-sync-2C9lk85r.js";
55
+ import { S as requeueToPending, T as transitionToMerging, _ as markMerged, c as init_merge_sync, f as listActiveAutoMerges, g as markFailed, h as markBlocked, i as getActionableAutoMerge, j as listUatGenerationsSync, l as isFlywheelGloballyPaused$1, m as listProblemAutoMerges, n as countActionableAutoMerges, p as listDuePendingAutoMerges, t as cancelPending, v as markMergingBlocked, w as scheduleAutoMergeWithResult } from "./merge-sync-CJpOa0cZ.js";
56
+ import { C as setReviewStatus, F as init_install_id, I as init_config$2, L as resolveTelemetryEnabled, M as init_service, N as synchronizeAnalyticsServices, P as getOrCreateInstallId, R as telemetryEnvironmentForcesOff, _ as markWorkspaceStuck, a as clearStuckMergeStatuses, c as fixStuckCommentedReviews, d as getReviewStatusSync, h as loadReviewStatuses, i as clearReviewStatus, j as getAnalyticsService, l as fixStuckReadyForMerge, p as init_review_status, u as getReviewStatus, w as setReviewStatusSync } from "./review-status-yOGD2MuK.js";
57
+ import { a as clearQueryExpansionCache, i as resolveKnowledgeBundleRoot, n as init_injection, o as init_query_expansion, r as injectPromptTimeMemory } from "./injection-BYUt8ml1.js";
58
+ import { a as init_fts_db, i as closeMemoryFtsDatabases, n as init_search, o as runMemoryFtsStatement, s as runMemoryFtsTransaction, t as buildMatchQuery } from "./search-DqMN4__-.js";
59
+ import { n as require_auth_errors, r as require_token_error, t as require_token_util } from "./token-util-Crcay9j_.js";
60
+ import { D as init_advisory_checks, E as verifyAppCanMerge, M as withConcurrencyLimit, O as isAdvisoryCheckName, d as getPullRequestState, f as init_github_app, j as init_concurrency$1, l as getMergeBackendStatus, p as isGitHubAppConfigured } from "./github-app-7ywLhuZO.js";
61
+ import { C as resolveIssueHeadlineCost, D as stopAgentOutputService, E as startAgentOutputService, S as getCachedRunningAgents, T as retainAgentOutputInterest, _ as migrateAllSessionsSync, b as syncCacheSync, d as eventsRouteLayer, f as resumeQueuedMerges, g as reclassifyUnknownCostEventsSync, h as reconcilePiTranscripts, m as reconcile$1, p as syncWalFromAllProjects, t as workspacesRouteLayer, u as internalEventsRouteLayer, v as getCostsForIssueSync, w as getWorkspacePathForIssue, x as processPendingFeedbackDeliveries, y as rebuildCacheSync } from "./workspaces-BJdPqx_J.js";
62
+ import { S as parseAcpConversationMessages, _ as isOhmypiSessionFile, a as contextUsageFromParseResult, b as parseCodexConversationMessages, c as parseEntireConversation, d as init_kimi_conversation_parser, f as parseKimiConversationMessages, g as init_ohmypi_conversation_parser, h as parsePiConversationMessages, i as computeContextUsage, l as parseFromLastCompactBoundary, m as isPiSessionFile, n as gateSnapshotEmission, o as summarizeConversationActivity, p as init_pi_conversation_parser, r as watchConversation, s as parseConversationMessages, t as init_conversation_service, v as parseOhmypiConversationMessages, x as init_acp_conversation_parser, y as init_codex_conversation_parser } from "./conversation-service-tQCIbBVZ.js";
63
+ import { a as resolveClaudeSessionId, c as resolveKimiWirePath, i as resolveAgentHarness, l as resolvePiSessionPath, n as readLauncherPinnedSessionId, o as resolveCodexRolloutPath, r as resolveAcpTranscriptPath, s as resolveJsonlPath, t as init_jsonl_resolver } from "./jsonl-resolver-07OS3qOr.js";
64
+ import { a as enrichSessions, c as searchSessions, i as CostThresholdError, l as embed, n as getSessionsFeedFacets, o as embedSessions, r as listSessionsFeed, s as parseRelativeTime, t as scan } from "./scanner-YxIv-fG1.js";
65
+ import { c as tailEventsSync, n as deduplicateEventsSync, s as readEventsSync } from "./events-B6zioJA_.js";
66
+ import { n as recordBackgroundAiCost, t as init_cost } from "./cost-BCWEkvro.js";
67
+ import { a as getByIssueId, i as parseFlywheelStatsWindow, n as derivePipelineRunStatsInputs, o as markFixed, r as computeFlywheelStats, s as upsert, t as listSubstrateBugWeights } from "./substrate-bug-weights-service-BbbCZEtJ.js";
68
+ import { n as writeSequenceMd, t as parseSequenceMd } from "./sequence-io--b3_PsWq.js";
69
+ import { _ as normalizeGate, d as computeEpicGroups, f as computeLanes, h as init_pickup, l as classifyIssue, m as computeWaves, p as computeStats, u as computeCohort, v as selectNeedsPlanning } from "./pickup-D1UbSDPd.js";
70
+ import { C as readCurrentLatestFlywheelStatus, D as writeFlywheelLaunchMetadata, E as subscribeLatestFlywheelStatus, F as setItemRequirements, G as liveOrderIssueLookup, H as getBook, I as setSettings, K as normalizeOrderIssueId, L as setStatus, M as moveItem, N as removeItem, O as writeLatestFlywheelStatus, P as renameBook, R as backlogCandidates, S as nextFlywheelRunId, T as resolveLiveFlywheelRunId, U as getBookAsync, W as listBooks, a as isFlywheelDevcontainerRuntime, b as isFlywheelRunId, f as spawnFlywheelAgent, g as abortFlywheelRun, j as createBook, k as addItems, p as buildClassifyLookups, s as loadResumeSessionId, t as FLYWHEEL_ORCHESTRATOR_AGENT_ID, u as saveResumeSessionId, v as getFlywheelRunDetail, w as readFlywheelLaunchMetadata, x as listFlywheelRuns, z as computeBookProgress } from "./flywheel-CjW2L7BS.js";
71
+ import { n as resolveConversationGitInfo } from "./git-info-BSrI9owC.js";
72
+ import { a as getResourceStacks, c as getCurrentDockerStats, f as getSystemHealthEvidenceSnapshot, g as classifyAgentHealth, h as startSmeeProcessSync, l as getAcceptedSystemHealthSnapshot, m as isSmeeConfiguredSync, o as formatUptime, s as getContainerHistory, u as getDeployStaleness } from "./memory-governor-Cqvbusr4.js";
73
+ import { D as detectPlatform, E as validateFeatureName, O as init_platform, S as init_worktree_ops, _ as updateWorkspaceLayout, b as readWorkspaceIdentity, c as installGitHooksInDir, d as init_writer, f as relocateWorkspace, g as unarchiveWorkspace, h as touchWorkspaceAccessed, l as archiveWorkspace, m as setWorkspaceRunCommand, p as setWorkspaceFavorite, s as init_git_hooks, u as createWorkspace, v as upsertProjectFromConfig, x as writeWorkspaceIdentity, y as init_identity_record } from "./workspace-manager-CgovxDrO.js";
74
+ import { n as init_workspace_config, t as getDefaultWorkspaceConfigSync } from "./workspace-config-DRYDO7Zr.js";
75
+ import { B as cleanupClosedIssueAgentDirectories, F as setAgentStatusChangedNotifier, I as setAgentStoppedNotifier, J as isBootReconciliationCandidate, K as extendBootReconciliationGrace, L as setMergeReadyNotifier, O as loadConfig, X as startBootReconciliation, Y as listBootReconciliationCandidates, Z as resolveSwarmPolicy, gt as paneShowsClaudeBootBlockingScreen, k as loadState, n as applyBootReconciliationDecision, q as isAutoResumableRole, r as assessDeaconPatrolFreshness, x as getDeaconLogs } from "./deacon-B24dNzr8.js";
76
+ import { i as getRuntimeForAgent } from "./agent-idle-ONBssBN_.js";
77
+ import { a as getShadowState, s as init_shadow_state } from "./shadow-state-CSA1vtxr.js";
78
+ import { n as init_issue_closed, t as clearIssueClosedCache } from "./issue-closed-6RQsAjDX.js";
79
+ import { r as parseArtifactRef } from "./forge-RVTCK_5X.js";
80
+ import "./parked-residue-BiHb8cD7.js";
81
+ import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-C1gCLFmp.js";
82
+ import { t as init_specialists } from "./specialists-CuDWiNdB.js";
83
+ import { a as getReviewerSessionName } from "./specialists-registry-BYjs04iK.js";
84
+ import { a as readPrdContent, r as findPrdAnywhereSync } from "./prd-locations-BbAvqQmT.js";
85
+ import { i as resolveBootGates, r as formatBootGateState } from "./no-resume-mode-xuYLFhLw.js";
86
+ import { t as createInFlightGuard } from "./in-flight-guard-DuxabAHT.js";
87
+ import { A as removeIssueParkedLabel, C as applyIssueParkedLabel, D as init_label_ops, E as applyIssueVetoedLabel, M as removeIssueReleasedLabel, N as removeIssueVetoedLabel, O as removeIssueBlocksMainLabel, S as applyIssueObjectionLabel, T as applyIssueReleasedLabel, g as parseIssueIdFromTextSync, h as init_resource_utils, j as removeIssueReadyLabel, k as removeIssueObjectionLabel, w as applyIssueReadyLabel, x as applyIssueBlocksMainLabel } from "./pipeline-membership-gather-BK4dzh0X.js";
88
+ import { a as spawnPlanningSession, r as resolveAutoSpawnOnFinalize } from "./spawn-planning-session-CkGweSCC.js";
89
+ import { r as computeMergeQueueFromCandidates, s as listEligibleCandidatesByProject } from "./flywheel-merge-order-D_yyAlND.js";
90
+ import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-BNzODIv6.js";
91
+ import { d as killRemoteAgent, m as loadRemoteAgentState, o as getRemoteAgentOutput, r as checkRemoteSpendCap, s as init_remote_agents, v as sendToRemoteAgent, y as spawnRemoteAgent } from "./remote-agents-CSaTLi3u.js";
92
+ import { _ as refreshMembershipSnapshotsForProjects, a as enqueueProjectsResourceRefresh, c as startProjectResourceConvergence, d as getCachedResourceAllocatedIssues, f as getResourceDetailIdentifiers, g as readPipelineMembershipSnapshotsForProjects, h as sanitizeResourceAllocatedIssues, l as stopProjectResourceRefreshQueue, m as isDiscoverableAgentSession, o as getProjectResourceRefreshQueueState, p as groupResourceAllocatedIssuesByProject, u as whenProjectResourceRefreshIdle, v as summarizePipelineMembership, y as unavailablePipelineMembership } from "./project-resource-refresh-queue-x-K9mvpP.js";
93
+ import { r as spawnInspectAgent } from "./inspect-agent-sV_19NxZ.js";
94
+ import { r as lookupPullRequestNumberForBranch, t as githubPrLookupSource } from "./github-pr-lookup-Dhh3ec1V.js";
95
+ import { a as fetchIssuePullRequestDiff, c as getCachedIssuePrTabResponse, i as fetchIssuePullRequestDetails, l as getIssuePrTabCacheGeneration, n as fetchIssueCheckRuns, r as fetchIssuePullRequest, s as bumpIssuePrTabCacheGeneration, u as setCachedIssuePrTabResponse } from "./pull-requests-Cp_FDT8-.js";
96
+ import { n as DOD_ROWS } from "./dod-DWtilRLx.js";
97
+ import { n as resolveParkedPopulation, r as summarizeParked } from "./resolver-DvSMXty7.js";
98
+ import { a as readCurrentStatus, l as maybeTriggerStatusRollup, s as readRecentObservations, u as writePendingTurn } from "./rollup-B6g9Nr6L.js";
99
+ import { r as isExtendedReviewEnabled } from "./review-agent-esZ0QXdY.js";
100
+ import { n as getTldrDaemonServiceSync, r as init_tldr_daemon } from "./tldr-daemon-CO08YlfQ.js";
101
+ import { S as ensureSyncGitQuiescent, x as listGitOperationsSync } from "./merge-agent-B3jRrlS1.js";
102
+ import { t as readVerificationArtifact } from "./verification-artifact-k5Ftpg0c.js";
103
+ import { t as getAgentCommandSync } from "./settings-CLQcdkoD.js";
104
+ import { r as isRemoteAvailable, t as createFlyProviderFromConfig } from "./remote-BU6ONLpv.js";
105
+ import { n as init_claude_settings_overlay, t as detectProviderEnvConflicts } from "./claude-settings-overlay-m-VVZej1.js";
106
+ import { _ as init_transcript_adapter, a as generateFallbackSummary, c as handoffPreconditionFallbackReason, d as prependFallbackFocus, f as requestHandoffFromAgent, g as getTranscriptAdapter, i as copySessionFromCompactBoundary, l as init_summary_fork, o as generateSummaryForFork, p as reserveSummaryForkSession, r as authorHandoffExternal, s as handoffFailureReason, u as logHandoffFallback } from "./summary-fork-BvcW6bq0.js";
107
+ import { a as init_conversation_compaction, c as shouldInterceptManualCompact, n as compactConversationNative, o as isCompacting } from "./conversation-compaction-D4VOmF7p.js";
108
+ import { n as loadShipRecords, r as publicShipStatus, t as aggregateGenerationShipStatus } from "./ship-status-BEkddXMT.js";
109
+ import { t as init_context_layers } from "./context-layers-BBTKP-Y4.js";
110
+ import { a as appendLinearMcpAuthHealthyEvent, r as appendLinearMcpAuthCallbackRelayedEvent, u as resolveLinearMcpAuthIntervention } from "./linear-mcp-auth-Nk5s3L9M.js";
111
+ import { i as getMergeBlockersPayload, n as hasOrderIssuePrd, r as validateBookForStart, t as createOrderPrdLookup } from "./validate-Ur4xH5bN.js";
112
+ import { i as spawnSequencerAgent, n as clearFinishedSequencerRun, r as getSequencerRunStatus, t as SEQUENCER_AGENT_ID } from "./sequencer-agent-CqouKVZG.js";
113
+ import { n as sameCanonicalReviewStatus, t as emitReviewStatusChanged } from "./review-status-emit-BZz1Y_22.js";
114
+ import "./supervisor-D3jC2c7A.js";
115
+ import { l as startUatTrainReconciler, u as stopUatTrainReconciler } from "./uat-train-IIZlz7r3.js";
116
+ import { n as settlePendingLifecycleClaim, t as claimPendingLifecycleFile } from "./pending-lifecycle-claim-J5uIIJPu.js";
117
+ import { i as listTranscriptCheckpoints, r as getTranscriptCheckpoint$1 } from "./checkpoints-Cszp_0Np.js";
118
+ import { r as readPendingDeploy } from "./deploy-queue-r96ojDI3.js";
118
119
  import { createRequire } from "node:module";
119
120
  import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, posix, relative, resolve, sep, win32 } from "node:path";
120
121
  import { Cause, Context, Data, Duration, Effect, Exit, Fiber, FileSystem, Layer, Option, Path, Queue, Result, Schedule, Schema, Stream } from "effect";
@@ -404,6 +405,7 @@ init_harness_policy();
404
405
  var import_dist = /* @__PURE__ */ __toESM(require_dist$1(), 1);
405
406
  init_projects_config_write();
406
407
  init_issue_id();
408
+ init_projects_cache_events();
407
409
  init_projects();
408
410
  init_project_key();
409
411
  init_state_read_home();
@@ -419,6 +421,7 @@ init_paths$1();
419
421
  init_driver();
420
422
  init_record_update();
421
423
  init_ui_theme();
424
+ init_pane_composer();
422
425
  init_infra();
423
426
  init_persistent_logger();
424
427
  init_agents();
@@ -721,7 +724,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
721
724
  if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
722
725
  const plan = readWorkspacePlanSync(workspacePath);
723
726
  if (!plan || plan.plan.items.length === 0) throw new PlanEmpty({ id: issueId });
724
- const { getAgentState, spawnAgent, normalizeAgentId } = await import("./agents-megfmQHM.js");
727
+ const { getAgentState, spawnAgent, normalizeAgentId } = await import("./agents-DpCuoF65.js");
725
728
  const normalizedId = normalizeAgentId(issueId);
726
729
  if ((await Effect.runPromise(getAgentState(normalizedId)))?.status === "running") throw new AgentAlreadyRunning({ id: issueId });
727
730
  return {
@@ -753,7 +756,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
753
756
  const { workspacePath, projectPath, issue } = opts;
754
757
  if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
755
758
  const sessionName = opts.sessionName ?? `planning-${issueId.toLowerCase()}`;
756
- const { spawnPlanningSession } = await import("./spawn-planning-session-CfhxRJoY.js");
759
+ const { spawnPlanningSession } = await import("./spawn-planning-session-s406rw1N.js");
757
760
  const result = await spawnPlanningSession({
758
761
  issue: {
759
762
  id: issue.id,
@@ -787,14 +790,14 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
787
790
  }),
788
791
  kill: (agentId) => Effect.tryPromise({
789
792
  try: async () => {
790
- const { stopAgent } = await import("./agents-megfmQHM.js");
793
+ const { stopAgent } = await import("./agents-DpCuoF65.js");
791
794
  await Effect.runPromise(stopAgent(agentId));
792
795
  },
793
796
  catch: () => void 0
794
797
  }).pipe(Effect.ignore),
795
798
  message: (agentId, msg) => Effect.tryPromise({
796
799
  try: async () => {
797
- const { messageAgent } = await import("./agents-megfmQHM.js");
800
+ const { messageAgent } = await import("./agents-DpCuoF65.js");
798
801
  await messageAgent(agentId, msg);
799
802
  },
800
803
  catch: (err) => new AgentStartError({
@@ -805,8 +808,8 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
805
808
  }),
806
809
  deepWipe: (issueId, opts) => Effect.tryPromise({
807
810
  try: async () => {
808
- const { deepWipe } = await import("./workflows-Cf4LAnhg.js");
809
- const { resolveProjectFromIssueSync } = await import("./projects-DvPEAP18.js");
811
+ const { deepWipe } = await import("./workflows-CfHm8lVd.js");
812
+ const { resolveProjectFromIssueSync } = await import("./projects-LftaVK99.js");
810
813
  const project = resolveProjectFromIssueSync(issueId);
811
814
  const projectPath = project?.projectPath ?? process.cwd();
812
815
  await Effect.runPromise(deepWipe({
@@ -865,8 +868,8 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
865
868
  const { workspacePath, branch } = getWorkspacePath(issueId);
866
869
  const issueLower = issueId.toLowerCase();
867
870
  if (existsSync$1(workspacePath)) return workspacePath;
868
- const { createWorkspace } = await import("./workspace-manager-5BKPV6SY.js");
869
- const { loadProjectsConfigSync } = await import("./projects-DvPEAP18.js");
871
+ const { createWorkspace } = await import("./workspace-manager-jfkKAEuO.js");
872
+ const { loadProjectsConfigSync } = await import("./projects-LftaVK99.js");
870
873
  const { projects } = loadProjectsConfigSync();
871
874
  const project = resolveProjectFromIssueSync(issueId);
872
875
  if (!project) throw new WorkspaceCreateError({
@@ -901,7 +904,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
901
904
  const { workspacePath } = getWorkspacePath(issueId);
902
905
  const issueLower = issueId.toLowerCase();
903
906
  if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
904
- const { removeWorkspace } = await import("./workspace-manager-5BKPV6SY.js");
907
+ const { removeWorkspace } = await import("./workspace-manager-jfkKAEuO.js");
905
908
  const project = resolveProjectFromIssueSync(issueId);
906
909
  if (!project) throw new WorkspaceCreateError({
907
910
  id: issueId,
@@ -932,7 +935,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
932
935
  try: async () => {
933
936
  const { workspacePath } = getWorkspacePath(issueId);
934
937
  const issueLower = issueId.toLowerCase();
935
- const { stopWorkspaceDocker } = await import("./workspace-manager-5BKPV6SY.js");
938
+ const { stopWorkspaceDocker } = await import("./workspace-manager-jfkKAEuO.js");
936
939
  await Effect.runPromise(stopWorkspaceDocker(workspacePath, issueLower));
937
940
  },
938
941
  catch: () => void 0
@@ -1001,7 +1004,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
1001
1004
  join(workspacePath, ".devcontainer", "docker-compose.devcontainer.yml")
1002
1005
  ];
1003
1006
  if (!composePaths.find((p) => existsSync$1(p))) {
1004
- const { ensureDevcontainerSync } = await import("./ensure-devcontainer-BQ4YizSH.js");
1007
+ const { ensureDevcontainerSync } = await import("./ensure-devcontainer-rGSh0JHK.js");
1005
1008
  const ensure = ensureDevcontainerSync({
1006
1009
  workspacePath,
1007
1010
  issueId
@@ -4870,7 +4873,7 @@ init_cliproxy();
4870
4873
  init_tmux();
4871
4874
  const reauthSessions = /* @__PURE__ */ new Map();
4872
4875
  const SESSION_MAX_AGE_MS = 3600 * 1e3;
4873
- const readJsonBody$21 = Effect.gen(function* () {
4876
+ const readJsonBody$22 = Effect.gen(function* () {
4874
4877
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
4875
4878
  return text ? JSON.parse(text) : {};
4876
4879
  });
@@ -4978,7 +4981,7 @@ const postCodexReauthRoute = HttpRouter.add("POST", "/api/settings/codex-reauth"
4978
4981
  const postCodexReauthStatusRoute = HttpRouter.add("POST", "/api/settings/codex-reauth/status", httpHandler(Effect.gen(function* () {
4979
4982
  const originError = rejectInvalidOrigin$1(yield* HttpServerRequest.HttpServerRequest);
4980
4983
  if (originError) return originError;
4981
- const body = yield* readJsonBody$21;
4984
+ const body = yield* readJsonBody$22;
4982
4985
  const sessionName = typeof body.session === "string" ? body.session : "";
4983
4986
  const token = typeof body.token === "string" ? body.token : "";
4984
4987
  const session = getLiveReauthSession(sessionName);
@@ -17270,7 +17273,7 @@ var require_get_vercel_oidc_token = /* @__PURE__ */ __commonJSMin(((exports, mod
17270
17273
  err = error;
17271
17274
  }
17272
17275
  try {
17273
- const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await import("./token-util-Bu8bPF9f.js").then((m) => /* @__PURE__ */ __toESM(m.default)), await import("./token-CO3INKbh.js").then((m) => /* @__PURE__ */ __toESM(m.default))]);
17276
+ const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await import("./token-util-DfUS3Lpp.js").then((m) => /* @__PURE__ */ __toESM(m.default)), await import("./token-Bez-qCB2.js").then((m) => /* @__PURE__ */ __toESM(m.default))]);
17274
17277
  if (!token || isExpired(getTokenPayload(token), options?.expirationBufferMs)) {
17275
17278
  await refreshToken(options);
17276
17279
  token = getVercelOidcTokenSync();
@@ -29587,7 +29590,7 @@ var GoogleCloudTranscription = class {
29587
29590
  }
29588
29591
  async start(apiKey, model) {
29589
29592
  try {
29590
- const { SpeechClient } = await import("./src-C2TAxwki.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1)).then((module) => module.v1p1beta1 ?? module.v1);
29593
+ const { SpeechClient } = await import("./src-CZsPs61V.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1)).then((module) => module.v1p1beta1 ?? module.v1);
29591
29594
  if (this.closed) return;
29592
29595
  const stream = new SpeechClient({ apiKey }).streamingRecognize({
29593
29596
  config: {
@@ -29851,7 +29854,7 @@ const DEFAULT_VOICE_SETTINGS = {
29851
29854
  model: "gpt-4.1-mini"
29852
29855
  }
29853
29856
  };
29854
- const readJsonBody$20 = Effect.gen(function* () {
29857
+ const readJsonBody$21 = Effect.gen(function* () {
29855
29858
  const request = yield* HttpServerRequest.HttpServerRequest;
29856
29859
  const contentLength = Number(request.headers["content-length"] ?? 0);
29857
29860
  if (Number.isFinite(contentLength) && contentLength > MAX_VOICE_SETTINGS_BODY_BYTES) return {
@@ -29974,7 +29977,7 @@ const getVoiceSettingsRoute = HttpRouter.add("GET", "/api/voice/settings", httpH
29974
29977
  const putVoiceSettingsRoute = HttpRouter.add("PUT", "/api/voice/settings", httpHandler(Effect.gen(function* () {
29975
29978
  const originError = requireTrustedOrigin$2(yield* HttpServerRequest.HttpServerRequest);
29976
29979
  if (originError) return originError;
29977
- const parsed = yield* readJsonBody$20;
29980
+ const parsed = yield* readJsonBody$21;
29978
29981
  if (!parsed.ok) return jsonResponse({ error: parsed.error }, { status: 413 });
29979
29982
  const body = parsed.body;
29980
29983
  if (!isVoiceSettings(body)) return jsonResponse({ error: "Invalid voice settings payload" }, { status: 400 });
@@ -30268,12 +30271,16 @@ function streamAgentOutput(eventStore, agentId) {
30268
30271
  }
30269
30272
  //#endregion
30270
30273
  //#region services/dashboard-db-task.ts
30274
+ init_agent_input_detection();
30275
+ init_tracker_config();
30276
+ init_agent_enrichment();
30271
30277
  init_acp_conversation_parser();
30272
30278
  init_codex_conversation_parser();
30273
30279
  init_ohmypi_conversation_parser();
30274
30280
  init_pi_conversation_parser();
30275
30281
  init_kimi_conversation_parser();
30276
30282
  init_conversation_service();
30283
+ init_jsonl_resolver();
30277
30284
  init_control_settings();
30278
30285
  const MAX_PENDING_JOBS = 32;
30279
30286
  const SEMANTIC_SEARCH_TIMEOUT_MS = Number.parseInt(process.env["OVERDECK_SEMANTIC_SEARCH_TIMEOUT_MS"] ?? "15000", 10);
@@ -30414,15 +30421,15 @@ async function runInline$1(operation, payload, onProgress) {
30414
30421
  });
30415
30422
  }
30416
30423
  case "getArtifactBySlug": {
30417
- const { getArtifactBySlugJob } = await import("./artifact-index-jobs-C6Lg2rKm.js");
30424
+ const { getArtifactBySlugJob } = await import("./artifact-index-jobs-Ck4NRRkY.js");
30418
30425
  return getArtifactBySlugJob(payload);
30419
30426
  }
30420
30427
  case "listArtifactsForWorkspaceOrIssue": {
30421
- const { listArtifactsForWorkspaceOrIssueJob } = await import("./artifact-index-jobs-C6Lg2rKm.js");
30428
+ const { listArtifactsForWorkspaceOrIssueJob } = await import("./artifact-index-jobs-Ck4NRRkY.js");
30422
30429
  return listArtifactsForWorkspaceOrIssueJob(payload);
30423
30430
  }
30424
30431
  case "unshareArtifactBySlug": {
30425
- const { unshareArtifactBySlugJob } = await import("./artifact-index-jobs-C6Lg2rKm.js");
30432
+ const { unshareArtifactBySlugJob } = await import("./artifact-index-jobs-Ck4NRRkY.js");
30426
30433
  return unshareArtifactBySlugJob(payload);
30427
30434
  }
30428
30435
  }
@@ -31533,6 +31540,7 @@ const PanRpcLayer = PanRpcGroup.toLayer(Effect.gen(function* () {
31533
31540
  }), (unsubscribe) => Effect.sync(() => unsubscribe()))),
31534
31541
  [WS_METHODS.subscribeIssueEvents]: (input) => {
31535
31542
  console.log(`[ws-rpc] subscribeIssueEvents invoked issueId=${input.issueId}`);
31543
+ import("./issue-service-singleton-CvgNAWqK.js").then(({ getSharedIssueService }) => getSharedIssueService().backfillIssue(input.issueId)).catch(() => {});
31536
31544
  return eventStore.streamEvents.pipe(Stream.filter(shouldBroadcastDashboardEvent), Stream.map(storedToDomainEvent), Stream.filter(passesDomainEventSchema), Stream.mapEffect((event) => getCachedAgentIssueLookup(readModel).pipe(Effect.map((lookup) => filterDomainEventForIssue(event, input.issueId, lookup)))), Stream.filter((event) => event !== null));
31537
31545
  },
31538
31546
  [WS_METHODS.subscribeTerminal]: (input) => terminalService.streamSession(input.sessionName, input.cols, input.rows),
@@ -31848,9 +31856,6 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
31848
31856
  init_internal_token();
31849
31857
  init_state_home();
31850
31858
  init_pan_dir();
31851
- init_agent_input_detection();
31852
- init_tracker_config();
31853
- init_agent_enrichment();
31854
31859
  init_tracker_utils();
31855
31860
  init_cache_service();
31856
31861
  init_pipeline_notifier();
@@ -32204,781 +32209,8 @@ function assertPlanQuality(doc, options = {}) {
32204
32209
  return issues;
32205
32210
  }
32206
32211
  //#endregion
32207
- //#region services/resource-discovery-shared.ts
32208
- init_conversations();
32209
- init_runtime_census();
32210
- const execFileAsync$20 = promisify(execFile);
32211
- async function loadTrackerIssues() {
32212
- const map = /* @__PURE__ */ new Map();
32213
- try {
32214
- const { getSharedIssueService } = await import("./issue-service-singleton-CL6hESX2.js");
32215
- const issues = (await getSharedIssueService()).getIssues();
32216
- for (const issue of issues) if (issue.identifier) map.set(issue.identifier.toUpperCase(), issue);
32217
- } catch {}
32218
- return map;
32219
- }
32220
- async function loadDockerContainers() {
32221
- try {
32222
- const { stdout } = await execFileAsync$20("docker", [
32223
- "ps",
32224
- "--format",
32225
- "{{.Names}}"
32226
- ], {
32227
- encoding: "utf-8",
32228
- timeout: 5e3
32229
- });
32230
- return stdout.split("\n").map((line) => line.trim()).filter(Boolean);
32231
- } catch {
32232
- return [];
32233
- }
32234
- }
32235
- async function loadActiveRemoteAgentStates() {
32236
- try {
32237
- const { listActiveRemoteAgentStates } = await import("./remote-agents-DQVGZVQ9.js");
32238
- return listActiveRemoteAgentStates();
32239
- } catch {
32240
- return [];
32241
- }
32242
- }
32243
- async function captureSharedResourceSignals() {
32244
- const [trackerIssues, runtimeCensus, dockerContainers, remoteAgentStates] = await Promise.all([
32245
- loadTrackerIssues(),
32246
- getRuntimeCensus(),
32247
- loadDockerContainers(),
32248
- loadActiveRemoteAgentStates()
32249
- ]);
32250
- const tmuxSessions = [...runtimeCensus.sessionNames];
32251
- let conversations = [];
32252
- try {
32253
- conversations = listConversations();
32254
- } catch {}
32255
- return {
32256
- trackerIssues,
32257
- tmuxSessions,
32258
- dockerContainers,
32259
- conversations,
32260
- remoteAgentStates
32261
- };
32262
- }
32263
- //#endregion
32264
- //#region review-status.ts
32265
- init_factory();
32266
- init_concurrency$1();
32267
- init_advisory_checks();
32268
- init_github_app();
32269
- init_resource_utils();
32270
- init_pipeline_membership_gather();
32271
- init_pipeline_membership();
32272
- //#endregion
32273
- //#region services/issue-title-fallback.ts
32274
- /**
32275
- * Titles for issues that have aged out of the tracker sync window.
32276
- *
32277
- * The resource tree surfaces any issue that still owns local resources
32278
- * (workspaces, agent sessions, records, planning artifacts) — including
32279
- * issues closed long ago, which the shared issue service no longer syncs.
32280
- * Without a tracker row, discovery falls back to the bare identifier as the
32281
- * row title, so the tree renders "MIN-852 — MIN-852" (PAN-3337).
32282
- *
32283
- * Resolve those titles per issue on demand through the tracker's own
32284
- * getIssue door. Successes are memoized for the process lifetime (titles of
32285
- * closed issues do not churn); failures are memoized briefly so a broken or
32286
- * unconfigured tracker cannot be hammered by the discovery refresh loop.
32287
- */
32288
- const FAILURE_RETRY_MS = 600 * 1e3;
32289
- const LOOKUP_TIMEOUT = "10 seconds";
32290
- /** Per-pass cap so one discovery pass cannot fan out unbounded tracker calls. */
32291
- const MAX_LOOKUPS_PER_PASS = 8;
32292
- const resolvedTitles = /* @__PURE__ */ new Map();
32293
- const failedLookupsAt = /* @__PURE__ */ new Map();
32294
- const inFlight$3 = /* @__PURE__ */ new Map();
32295
- async function lookupTitle(issueId) {
32296
- const trackerType = resolveTrackerTypeSync(issueId);
32297
- if (!trackerType) return null;
32298
- const tracker = createTracker({ type: trackerType });
32299
- const title = (await Effect.runPromise(tracker.getIssue(issueId).pipe(Effect.timeout(LOOKUP_TIMEOUT)))).title?.trim();
32300
- return title && title.toUpperCase() !== issueId.toUpperCase() ? title : null;
32301
- }
32302
- /**
32303
- * Resolve titles for issues the tracker snapshot missed. Returns only the
32304
- * identifiers that resolved to a real title (memoized or freshly fetched).
32305
- */
32306
- async function resolveMissingIssueTitles(issueIds) {
32307
- const result = /* @__PURE__ */ new Map();
32308
- const toFetch = [];
32309
- const now = Date.now();
32310
- for (const raw of issueIds) {
32311
- const issueId = raw.toUpperCase();
32312
- const memoized = resolvedTitles.get(issueId);
32313
- if (memoized) {
32314
- result.set(issueId, memoized);
32315
- continue;
32316
- }
32317
- const failedAt = failedLookupsAt.get(issueId);
32318
- if (failedAt !== void 0 && now - failedAt < FAILURE_RETRY_MS) continue;
32319
- if (toFetch.length < MAX_LOOKUPS_PER_PASS) toFetch.push(issueId);
32320
- }
32321
- await Promise.all(toFetch.map(async (issueId) => {
32322
- let pending = inFlight$3.get(issueId);
32323
- if (!pending) {
32324
- pending = lookupTitle(issueId).catch(() => null).finally(() => inFlight$3.delete(issueId));
32325
- inFlight$3.set(issueId, pending);
32326
- }
32327
- const title = await pending;
32328
- if (title) {
32329
- resolvedTitles.set(issueId, title);
32330
- failedLookupsAt.delete(issueId);
32331
- result.set(issueId, title);
32332
- } else failedLookupsAt.set(issueId, Date.now());
32333
- }));
32334
- return result;
32335
- }
32336
- //#endregion
32337
- //#region services/pipeline-membership.ts
32338
- const PIPELINE_MEMBERSHIP_TTL_MS = 3e4;
32339
- function createPipelineMembershipService(deps = {
32340
- gather: gatherProjectLensSignals,
32341
- now: () => Date.now()
32342
- }) {
32343
- const cachedGather = createSettledTtlPromiseCache(PIPELINE_MEMBERSHIP_TTL_MS, deps.now);
32344
- const service = async (project) => cachedGather(project.path, () => deps.gather(project).then((signals) => signals.map(resolvePipelineMembership)));
32345
- service.invalidate = (projectPath) => cachedGather.invalidate(projectPath);
32346
- return service;
32347
- }
32348
- const getProjectPipelineMembership = createPipelineMembershipService();
32349
- const membershipSnapshots = /* @__PURE__ */ new Map();
32350
- const scheduleMembershipRefresh = createPromiseConcurrencyLimiter(3);
32351
- function refreshMembershipSnapshot(project, snapshot, getMembership, now) {
32352
- if (snapshot.refresh) return snapshot.refresh;
32353
- snapshot.refresh = scheduleMembershipRefresh(() => getMembership(project)).then((value) => {
32354
- snapshot.value = value;
32355
- snapshot.refreshedAt = now();
32356
- snapshot.lastError = void 0;
32357
- snapshot.lastErrorReason = void 0;
32358
- snapshot.lastErrorAt = void 0;
32359
- }).catch((error) => {
32360
- snapshot.lastError = error instanceof Error ? error.message : String(error);
32361
- snapshot.lastErrorReason = error instanceof PipelineMembershipUnavailableError ? error.reason : "gather_failed";
32362
- snapshot.lastErrorAt = now();
32363
- console.warn(`[pipeline-membership] refresh failed for ${project.name ?? project.path}; keeping last-good snapshot:`, snapshot.lastError);
32364
- }).finally(() => {
32365
- snapshot.refresh = void 0;
32366
- });
32367
- return snapshot.refresh;
32368
- }
32369
- /** Read the latest successful snapshots without scheduling tracker or git work. */
32370
- function readPipelineMembershipSnapshotsForProjects(projects) {
32371
- return projects.map((project) => {
32372
- const snapshot = membershipSnapshots.get(project.path);
32373
- if (snapshot?.refreshedAt) return {
32374
- project,
32375
- memberships: snapshot.value
32376
- };
32377
- return {
32378
- project,
32379
- error: /* @__PURE__ */ new Error(snapshot?.lastError ? `Pipeline membership refresh failed: ${snapshot.lastError}` : "Pipeline membership snapshot is loading"),
32380
- unavailableReason: snapshot?.lastErrorReason
32381
- };
32382
- });
32383
- }
32384
- /**
32385
- * PAN-2893 — event-driven refresh. Invalidate the per-project TTL cache and
32386
- * force a snapshot re-gather NOW for the given projects, so agent lifecycle
32387
- * changes reach membership consumers without waiting out the 5-minute TTL.
32388
- * Refresh failures keep the last good snapshot (same policy as TTL refreshes).
32389
- */
32390
- async function refreshMembershipSnapshotsForProjects(projects, getMembership = getProjectPipelineMembership, now = () => Date.now()) {
32391
- await Promise.all(projects.map(async (project) => {
32392
- getMembership.invalidate(project.path);
32393
- const snapshot = membershipSnapshots.get(project.path) ?? {
32394
- value: [],
32395
- refreshedAt: 0
32396
- };
32397
- membershipSnapshots.set(project.path, snapshot);
32398
- const inFlight = snapshot.refresh;
32399
- if (inFlight) {
32400
- await inFlight;
32401
- getMembership.invalidate(project.path);
32402
- }
32403
- await refreshMembershipSnapshot(project, snapshot, getMembership, now);
32404
- }));
32405
- }
32406
- function summarizePipelineMembership(membership) {
32407
- return {
32408
- available: true,
32409
- inPipeline: membership.inPipeline,
32410
- bucket: membership.bucket,
32411
- labelDrift: membership.labelDrift
32412
- };
32413
- }
32414
- function unavailablePipelineMembership() {
32415
- return {
32416
- available: false,
32417
- inPipeline: false,
32418
- bucket: "clean_terminal",
32419
- labelDrift: null
32420
- };
32421
- }
32422
- //#endregion
32423
- //#region services/resource-discovery.ts
32424
- init_src();
32425
- init_projects();
32426
- init_pipeline_membership();
32427
- init_pipeline_membership_gather();
32428
- const execFileAsync$19 = promisify(execFile);
32429
- const RECENT_ACTIVITY_WINDOW_MS = 5e3;
32430
- const projectResourceSnapshots = /* @__PURE__ */ new Map();
32431
- let cachedResourceIssues = null;
32432
- let cachedDetailedResourceIssues = null;
32433
- function projectPrefixes(project) {
32434
- const prefixes = /* @__PURE__ */ new Set();
32435
- if (project.config.issue_prefix) prefixes.add(project.config.issue_prefix.toUpperCase());
32436
- for (const prefix of project.config.issue_prefixes ?? []) prefixes.add(prefix.toUpperCase());
32437
- if (prefixes.size === 0) prefixes.add(project.key.toUpperCase().replace(/-/g, ""));
32438
- return [...prefixes];
32439
- }
32440
- function deriveStateLabel(issue, hasTmux, hasFreshHeartbeat, membership) {
32441
- const trackerState = issue.trackerState ?? "";
32442
- if (membership?.bucket === "post_merge_limbo") return "Merged — Needs Close-Out";
32443
- if (membership?.lenses.L3_issueOpen === false) return hasTmux ? "Closed" : "Done";
32444
- if (issue.readyForMerge) return "In Review";
32445
- if (trackerState === "done" || trackerState === "closed" || trackerState === "canceled") return hasTmux ? "Closed" : "Done";
32446
- if (trackerState === "in_review") return "In Review";
32447
- if (trackerState === "in_progress") return "In Progress";
32448
- if (hasTmux && (issue.agentStatus === "active" || hasFreshHeartbeat)) return "In Progress";
32449
- if (issue.agentStatus === "suspended") return "Suspended";
32450
- if (issue.hasPrd && !issue.hasState) return "Planning";
32451
- if (issue.hasState) return "Has Context";
32452
- if (issue.resourceSources.has("workspace") || issue.resourceSources.has("branch")) return "Allocated";
32453
- return "Idle";
32454
- }
32455
- function sortPullRequests(prs) {
32456
- return [...prs].sort((a, b) => {
32457
- if (a.isDraft !== b.isDraft) return a.isDraft ? 1 : -1;
32458
- return a.number - b.number;
32459
- });
32460
- }
32461
- function summarizeResourceDetails(details) {
32462
- return {
32463
- hasWorkspace: details.workspacePath !== null,
32464
- localBranchCount: details.localBranches.length,
32465
- remoteBranchCount: details.remoteBranches.length,
32466
- tmuxSessionCount: details.tmuxSessions.length,
32467
- prs: sortPullRequests(details.prs).map((pr) => ({
32468
- number: pr.number,
32469
- title: pr.title,
32470
- url: pr.url,
32471
- state: pr.state,
32472
- isDraft: pr.isDraft
32473
- })),
32474
- hasXbrief: details.xbriefPath !== null,
32475
- hasTasks: details.tasksPath !== null,
32476
- hasPrd: details.prdPath !== null,
32477
- dockerContainerCount: details.dockerContainers.length,
32478
- actualBranch: details.actualBranch,
32479
- branchDrifted: details.branchDrifted,
32480
- branchAheadOfMain: details.branchAheadOfMain,
32481
- workspaceMissing: details.workspaceMissing,
32482
- remoteAgent: details.remoteAgent,
32483
- conversations: details.conversations.map((conv) => ({
32484
- id: conv.id,
32485
- name: conv.name,
32486
- title: conv.title,
32487
- status: conv.status
32488
- }))
32489
- };
32490
- }
32491
- function summarizeResourceDetailIdentifiers(details) {
32492
- return {
32493
- workspacePaths: details.workspacePath ? [details.workspacePath] : [],
32494
- localBranchNames: [...details.localBranches].sort(),
32495
- remoteBranchNames: [...details.remoteBranches].sort(),
32496
- tmuxSessionNames: [...details.tmuxSessions].sort(),
32497
- prs: sortPullRequests(details.prs).map((pr) => ({
32498
- number: pr.number,
32499
- title: pr.title,
32500
- state: pr.state,
32501
- isDraft: pr.isDraft
32502
- })),
32503
- dockerContainerNames: [...details.dockerContainers].sort()
32504
- };
32505
- }
32506
- function hasRecentActivity(lastActivity) {
32507
- return lastActivity !== null && Number.isFinite(lastActivity) && Date.now() - lastActivity < RECENT_ACTIVITY_WINDOW_MS;
32508
- }
32509
- function isLiveResource(issue) {
32510
- return issue.resourceDetails.remoteAgent !== null || issue.resourceDetails.tmuxSessions.length > 0 || issue.resourceDetails.dockerContainers.length > 0 || hasOpenPr(issue);
32511
- }
32512
- function isActiveTrackerState(state) {
32513
- return state === "in_progress" || state === "in_review" || state === "started";
32514
- }
32515
- function isTerminalTrackerState(state) {
32516
- return state === "closed" || state === "done" || state === "canceled" || state === "completed";
32517
- }
32518
- function hasOpenPr(issue) {
32519
- return issue.resourceDetails.prs.some((pr) => pr.state === "OPEN" || pr.state === "open");
32520
- }
32521
- function shouldLoadReviewStatus(issue) {
32522
- return issue.resourceSources.size > 0 && (!isTerminalTrackerState(issue.trackerState) || hasOpenPr(issue)) && (isLiveResource(issue) || isActiveTrackerState(issue.trackerState) && issue.branch != null);
32523
- }
32524
- /**
32525
- * tmux session-name prefixes that map a session to its issue in the Command Deck
32526
- * tree. `strike-` MUST be included (PAN-1682): strike sessions are named
32527
- * `strike-<issue>` and a strike issue is typically `todo` (not an active tracker
32528
- * state), so without registering the tmux resource the issue is filtered out of
32529
- * the tree entirely. Keep this list in sync with the agent-session prefixes the
32530
- * dashboard recognizes elsewhere (e.g. routes/agents.ts).
32531
- */
32532
- const DISCOVERABLE_SESSION_PREFIXES = [
32533
- "agent-",
32534
- "planning-",
32535
- "specialist-",
32536
- "review-",
32537
- "strike-"
32538
- ];
32539
- function isDiscoverableAgentSession(sessionName) {
32540
- return DISCOVERABLE_SESSION_PREFIXES.some((prefix) => sessionName.startsWith(prefix));
32541
- }
32542
- async function loadOpenPullRequests(projects) {
32543
- const pullRequests = /* @__PURE__ */ new Map();
32544
- await Promise.all(projects.map(async (project) => {
32545
- if (!project.config.github_repo) return;
32546
- const [owner, repo] = project.config.github_repo.split("/");
32547
- if (!owner || !repo) return;
32548
- try {
32549
- const prs = await listOpenPullRequestsSnapshot(owner, repo);
32550
- for (const row of prs) {
32551
- if (row.number === void 0 || row.title === void 0 || row.url === void 0 || row.state === void 0 || row.isDraft === void 0 || row.baseRefName === void 0) continue;
32552
- const pr = {
32553
- number: row.number,
32554
- title: row.title,
32555
- url: row.url,
32556
- state: row.state,
32557
- isDraft: row.isDraft,
32558
- headRefName: row.headRefName,
32559
- baseRefName: row.baseRefName
32560
- };
32561
- const issueId = parseIssueIdFromTextSync(pr.headRefName);
32562
- if (!issueId) continue;
32563
- const existing = pullRequests.get(issueId) ?? [];
32564
- existing.push(pr);
32565
- pullRequests.set(issueId, existing);
32566
- }
32567
- } catch {}
32568
- }));
32569
- for (const [issueId, prs] of pullRequests) pullRequests.set(issueId, sortPullRequests(prs));
32570
- return pullRequests;
32571
- }
32572
- const PROJECT_BRANCH_PATTERNS = [
32573
- "refs/heads/feature/*",
32574
- "refs/remotes/origin/feature/*",
32575
- "refs/heads/bypass/*",
32576
- "refs/remotes/origin/bypass/*"
32577
- ];
32578
- async function loadProjectBranchSnapshot(projectPath) {
32579
- const run = (extraArgs = []) => execFileAsync$19("git", [
32580
- "for-each-ref",
32581
- "--format=%(refname:short)",
32582
- ...extraArgs,
32583
- ...PROJECT_BRANCH_PATTERNS
32584
- ], {
32585
- cwd: projectPath,
32586
- encoding: "utf-8",
32587
- timeout: 1e4
32588
- }).catch(() => ({ stdout: "" }));
32589
- const [allRefs, unmergedRefs] = await Promise.all([run(), run(["--no-merged=main"])]);
32590
- const branches = allRefs.stdout.split("\n").map((line) => line.trim()).filter(Boolean);
32591
- const ahead = new Set(unmergedRefs.stdout.split("\n").map((line) => line.trim()).filter(Boolean));
32592
- return {
32593
- local: branches.filter((branch) => !branch.startsWith("origin/")),
32594
- remote: branches.filter((branch) => branch.startsWith("origin/")),
32595
- ahead
32596
- };
32597
- }
32598
- async function scanWorkspace(workspacesDir, workspaceName) {
32599
- const workspacePath = join(workspacesDir, workspaceName);
32600
- const projectRoot = join(workspacesDir, "..");
32601
- const workspaceEntries = new Set(await readdir(workspacePath).catch(() => []));
32602
- const panEntries = workspaceEntries.has(".pan") ? new Set(await readdir(join(workspacePath, PAN_DIRNAME)).catch(() => [])) : /* @__PURE__ */ new Set();
32603
- const issueMatch = workspaceName.match(/^feature-([a-z]+-\d+)$/i);
32604
- const issueId = issueMatch ? issueMatch[1].toUpperCase() : null;
32605
- const specEntry = issueId ? await Effect.runPromise(findSpecByIssue(projectRoot, issueId)).catch(() => null) : null;
32606
- const xbriefPath = specEntry ? specEntry.path : null;
32607
- let xbriefMtime = null;
32608
- if (xbriefPath) try {
32609
- xbriefMtime = (await stat(xbriefPath)).mtimeMs;
32610
- } catch {
32611
- xbriefMtime = null;
32612
- }
32613
- return {
32614
- workspacePath,
32615
- hasPlanning: workspaceEntries.has(PAN_DIRNAME),
32616
- hasPrd: panEntries.has("prd.md"),
32617
- hasState: panEntries.has(PAN_CONTINUE_FILENAME),
32618
- hasXbrief: xbriefPath !== null,
32619
- xbriefPath,
32620
- xbriefMtime,
32621
- hasTasks: xbriefPath !== null
32622
- };
32623
- }
32624
- async function computeResourceAllocatedIssues(projectConfigs, sharedSignals) {
32625
- const registeredProjects = listProjectsSync();
32626
- const projects = projectConfigs.map((config) => registeredProjects.find((entry) => entry.config.path === config.path) ?? {
32627
- key: config.name ?? config.path,
32628
- config
32629
- });
32630
- const { trackerIssues, tmuxSessions, dockerContainers, conversations, remoteAgentStates } = sharedSignals ?? await captureSharedResourceSignals();
32631
- const pullRequests = await loadOpenPullRequests(projects);
32632
- const issueMap = /* @__PURE__ */ new Map();
32633
- const projectByPrefix = /* @__PURE__ */ new Map();
32634
- for (const project of projects) for (const prefix of projectPrefixes(project)) projectByPrefix.set(prefix, project);
32635
- const projectRefFromResolved = (resolvedProject) => projects.find((project) => project.key === resolvedProject.projectKey || project.config.path === resolvedProject.projectPath) ?? null;
32636
- const resolveProjectRef = (issueId, preferredProject) => {
32637
- if (preferredProject) return preferredProject;
32638
- const resolvedProject = resolveProjectFromIssueSync(issueId);
32639
- if (resolvedProject) {
32640
- const project = projectRefFromResolved(resolvedProject);
32641
- if (project) return project;
32642
- }
32643
- const prefix = issueId.toUpperCase().match(/^([A-Z]+)-\d+$/)?.[1] ?? "";
32644
- return projectByPrefix.get(prefix) ?? null;
32645
- };
32646
- const ensureIssue = (issueId, preferredProject) => {
32647
- const upper = issueId.toUpperCase();
32648
- const existing = issueMap.get(upper);
32649
- if (existing) return existing;
32650
- const resolved = resolveProjectRef(upper, preferredProject);
32651
- if (!resolved) return null;
32652
- const tracker = trackerIssues.get(upper);
32653
- const created = {
32654
- issueId: upper,
32655
- title: tracker?.title?.trim() || upper,
32656
- projectName: resolved.config.name ?? resolved.key,
32657
- branch: `feature/${upper.toLowerCase()}`,
32658
- trackerState: typeof tracker?.state === "string" ? tracker.state : null,
32659
- rawTrackerState: tracker?.rawTrackerState,
32660
- isRally: tracker?.source === "rally",
32661
- hasPlanning: false,
32662
- hasPrd: false,
32663
- hasState: false,
32664
- isShadow: false,
32665
- agentStatus: null,
32666
- readyForMerge: false,
32667
- lastActivity: null,
32668
- resourceSources: /* @__PURE__ */ new Set(),
32669
- resourceDetails: {
32670
- tmuxSessions: [],
32671
- workspacePath: null,
32672
- localBranches: [],
32673
- remoteBranches: [],
32674
- prs: [],
32675
- xbriefPath: null,
32676
- xbriefMtime: null,
32677
- tasksPath: null,
32678
- prdPath: null,
32679
- dockerContainers: [],
32680
- actualBranch: null,
32681
- branchDrifted: false,
32682
- branchAheadOfMain: false,
32683
- workspaceMissing: false,
32684
- remoteAgent: null,
32685
- conversations: []
32686
- },
32687
- taskTotals: null
32688
- };
32689
- issueMap.set(upper, created);
32690
- return created;
32691
- };
32692
- for (const [issueId, tracker] of trackerIssues) {
32693
- const issue = ensureIssue(issueId);
32694
- if (!issue) continue;
32695
- issue.title = tracker.title?.trim() || issue.title;
32696
- issue.trackerState = typeof tracker.state === "string" ? tracker.state : issue.trackerState;
32697
- issue.rawTrackerState = tracker.rawTrackerState ?? issue.rawTrackerState;
32698
- issue.isRally = tracker.source === "rally";
32699
- issue.resourceSources.add("tracker");
32700
- }
32701
- for (const sessionName of tmuxSessions) {
32702
- if (!isDiscoverableAgentSession(sessionName)) continue;
32703
- const issueId = parseIssueIdFromTextSync(sessionName);
32704
- if (!issueId) continue;
32705
- const issue = ensureIssue(issueId);
32706
- if (!issue) continue;
32707
- issue.resourceSources.add("tmux");
32708
- if (!issue.resourceDetails.tmuxSessions.includes(sessionName)) issue.resourceDetails.tmuxSessions.push(sessionName);
32709
- }
32710
- for (const conv of conversations) {
32711
- if (!conv.issueId || conv.archivedAt) continue;
32712
- const issue = ensureIssue(conv.issueId);
32713
- if (!issue) continue;
32714
- issue.resourceSources.add("conversation");
32715
- issue.resourceDetails.conversations.push({
32716
- id: conv.id,
32717
- name: conv.name,
32718
- title: conv.title,
32719
- status: conv.status,
32720
- tmuxSession: conv.tmuxSession
32721
- });
32722
- }
32723
- for (const remoteState of remoteAgentStates) {
32724
- const issue = ensureIssue(remoteState.issueId);
32725
- if (!issue) continue;
32726
- issue.resourceSources.add("remote-agent");
32727
- issue.resourceDetails.remoteAgent = {
32728
- vmName: remoteState.vmName,
32729
- status: remoteState.status,
32730
- model: remoteState.model,
32731
- startedAt: remoteState.startedAt
32732
- };
32733
- if (!issue.agentStatus) issue.agentStatus = "active";
32734
- }
32735
- for (const containerName of dockerContainers) {
32736
- const issueId = parseIssueIdFromTextSync(containerName.replace(/feature\//g, "feature-"));
32737
- if (!issueId) continue;
32738
- const issue = ensureIssue(issueId);
32739
- if (!issue) continue;
32740
- issue.resourceSources.add("docker");
32741
- issue.resourceDetails.dockerContainers.push(containerName);
32742
- }
32743
- await Promise.all(projects.map(async (project) => {
32744
- const projectPath = project.config.path;
32745
- const workspacesDir = join(projectPath, "workspaces");
32746
- const resolverRows = listWorkspaces({
32747
- projectId: project.key,
32748
- kind: "issue"
32749
- });
32750
- const [workspaceCandidates, branches] = await Promise.all([resolverRows.length > 0 ? Promise.resolve(resolverRows.map((row) => ({
32751
- name: basename(row.path),
32752
- issueId: (row.issueId ?? basename(row.path).replace(/^feature-/, "")).toUpperCase()
32753
- }))) : readdir(workspacesDir, { withFileTypes: true }).then((entries) => entries.filter((entry) => entry.isDirectory() && entry.name.startsWith("feature-")).map((entry) => ({
32754
- name: entry.name,
32755
- issueId: entry.name.replace(/^feature-/, "").toUpperCase()
32756
- }))).catch(() => []), loadProjectBranchSnapshot(projectPath)]);
32757
- await Promise.all(workspaceCandidates.map(async ({ name, issueId }) => {
32758
- const issue = ensureIssue(issueId, project);
32759
- if (!issue) return;
32760
- const workspace = await scanWorkspace(workspacesDir, name);
32761
- issue.resourceSources.add("workspace");
32762
- issue.resourceDetails.workspacePath = workspace.workspacePath;
32763
- issue.hasPlanning = workspace.hasPlanning;
32764
- issue.hasPrd = workspace.hasPrd;
32765
- issue.hasState = workspace.hasState;
32766
- if (workspace.xbriefPath) {
32767
- issue.resourceSources.add("vbrief");
32768
- issue.resourceDetails.xbriefPath = workspace.xbriefPath;
32769
- issue.resourceDetails.xbriefMtime = workspace.xbriefMtime;
32770
- }
32771
- if (workspace.hasTasks) {
32772
- issue.resourceSources.add("tasks");
32773
- issue.resourceDetails.tasksPath = join(workspace.workspacePath, ".tasks");
32774
- }
32775
- const gitInfo = await resolveAgentGitInfo(workspace.workspacePath, issue.branch);
32776
- issue.resourceDetails.actualBranch = gitInfo.actualBranch;
32777
- issue.resourceDetails.branchDrifted = gitInfo.branchDrifted;
32778
- issue.resourceDetails.workspaceMissing = gitInfo.workspaceMissing;
32779
- }));
32780
- for (const [branch, key] of [...branches.local.map((b) => [b, "localBranches"]), ...branches.remote.map((b) => [b, "remoteBranches"])]) {
32781
- const issueId = parseIssueIdFromTextSync(branch);
32782
- if (!issueId) continue;
32783
- const issue = ensureIssue(issueId, project);
32784
- if (!issue) continue;
32785
- issue.resourceSources.add("branch");
32786
- if (!issue.resourceDetails[key].includes(branch)) issue.resourceDetails[key].push(branch);
32787
- if (branches.ahead.has(branch)) issue.resourceDetails.branchAheadOfMain = true;
32788
- }
32789
- }));
32790
- for (const [issueId, prs] of pullRequests) {
32791
- const issue = ensureIssue(issueId);
32792
- if (!issue) continue;
32793
- issue.resourceSources.add("pr");
32794
- issue.resourceDetails.prs = prs;
32795
- const bestTitle = prs.find((pr) => !pr.isDraft)?.title ?? prs[0]?.title;
32796
- issue.title = issue.title === issue.issueId && bestTitle ? bestTitle : issue.title;
32797
- }
32798
- await Promise.all([...issueMap.values()].map(async (issue) => {
32799
- if (issue.resourceDetails.tmuxSessions.length === 0) return;
32800
- const states = (await Promise.all(issue.resourceDetails.tmuxSessions.map((sessionName) => Effect.runPromise(getAgentRuntimeState(sessionName)).catch(() => null)))).filter((state) => state !== null);
32801
- if (states.length === 0) return;
32802
- issue.agentStatus = (states.find((state) => state.state === "active") ?? states.reduce((a, b) => Date.parse(a.lastActivity) >= Date.parse(b.lastActivity) ? a : b)).state;
32803
- const lastActivity = Math.max(...states.map((state) => Date.parse(state.lastActivity)).filter(Number.isFinite));
32804
- issue.lastActivity = Number.isFinite(lastActivity) ? lastActivity : null;
32805
- }));
32806
- const reviewStatusIssueIds = [...issueMap.values()].filter(shouldLoadReviewStatus).map((issue) => issue.issueId);
32807
- if (reviewStatusIssueIds.length > 0) {
32808
- const readyForMergeFlags = loadReadyForMergeFlags(reviewStatusIssueIds);
32809
- for (const issue of issueMap.values()) issue.readyForMerge = readyForMergeFlags.get(issue.issueId) ?? false;
32810
- }
32811
- const memberships = /* @__PURE__ */ new Map();
32812
- const unavailableProjects = /* @__PURE__ */ new Set();
32813
- const projectMemberships = readPipelineMembershipSnapshotsForProjects(projects.map((project) => project.config));
32814
- for (const result of projectMemberships) {
32815
- if (result.error) unavailableProjects.add(result.project.name);
32816
- for (const membership of result.memberships ?? []) {
32817
- ensureIssue(membership.issueId);
32818
- memberships.set(membership.issueId, membership);
32819
- }
32820
- }
32821
- await Promise.all([...issueMap.values()].map(async (issue) => {
32822
- const project = resolveProjectRef(issue.issueId);
32823
- if (!project) return;
32824
- const draft = await Effect.runPromise(findDraftPrd(project.config.path, issue.issueId)).catch(() => null);
32825
- if (!draft) return;
32826
- issue.resourceSources.add("prd");
32827
- issue.resourceDetails.prdPath = draft.path;
32828
- issue.hasPrd = true;
32829
- }));
32830
- const untitledIssueIds = [...issueMap.values()].filter((issue) => issue.resourceSources.size > 0 && issue.title === issue.issueId).map((issue) => issue.issueId);
32831
- if (untitledIssueIds.length > 0) {
32832
- const fallbackTitles = await resolveMissingIssueTitles(untitledIssueIds).catch(() => /* @__PURE__ */ new Map());
32833
- for (const issue of issueMap.values()) {
32834
- const title = fallbackTitles.get(issue.issueId);
32835
- if (title && issue.title === issue.issueId) issue.title = title;
32836
- }
32837
- }
32838
- return [...issueMap.values()].filter((issue) => issue.resourceSources.size > 0).filter((issue) => {
32839
- const membership = memberships.get(issue.issueId);
32840
- return membership?.inPipeline === true || membership?.bucket === "clean_terminal" && isLiveResource(issue) || !membership && unavailableProjects.has(issue.projectName) && isLiveResource(issue);
32841
- }).map((issue) => {
32842
- const membership = memberships.get(issue.issueId);
32843
- const hasTmux = issue.resourceDetails.tmuxSessions.length > 0;
32844
- const hasRecentHeartbeat = hasRecentActivity(issue.lastActivity);
32845
- const stateLabel = deriveStateLabel(issue, hasTmux, hasRecentHeartbeat, membership);
32846
- const isRemoteRunning = issue.resourceDetails.remoteAgent?.status === "running" || issue.resourceDetails.remoteAgent?.status === "starting";
32847
- const status = hasTmux && (issue.agentStatus === "active" || hasRecentHeartbeat) || isRemoteRunning ? "running" : issue.hasState ? "has_state" : "idle";
32848
- return {
32849
- issueId: issue.issueId,
32850
- title: issue.title,
32851
- projectName: issue.projectName,
32852
- branch: issue.branch,
32853
- status,
32854
- stateLabel,
32855
- agentStatus: issue.agentStatus,
32856
- hasPlanning: issue.hasPlanning,
32857
- hasPrd: issue.hasPrd,
32858
- hasState: issue.hasState,
32859
- isShadow: issue.isShadow,
32860
- isRally: issue.isRally,
32861
- childCount: trackerIssues.get(issue.issueId)?.totalChildCount,
32862
- completedCount: trackerIssues.get(issue.issueId)?.completedChildCount,
32863
- inProgressCount: trackerIssues.get(issue.issueId)?.inProgressChildCount,
32864
- readyForMerge: issue.readyForMerge,
32865
- rawTrackerState: issue.rawTrackerState,
32866
- resourceSources: new Set([...issue.resourceSources].sort()),
32867
- resourceDetails: issue.resourceDetails,
32868
- taskTotals: issue.taskTotals,
32869
- pipelineBucket: membership?.bucket,
32870
- specOnlyPlanned: membership ? membership.bucket === "planned_backlog" && membership.reasons.includes("open issue with an xBRIEF spec but no branch/PR — planned work whose plan encodes code paths that age; needs starting or re-planning") : void 0,
32871
- resourceDrift: membership ? !membership.inPipeline : void 0
32872
- };
32873
- }).sort((a, b) => compareIssueIds(a.issueId, b.issueId));
32874
- }
32875
- function toPublicResourceIssue(issue) {
32876
- return {
32877
- ...issue,
32878
- resourceSources: [...issue.resourceSources],
32879
- resourceDetails: summarizeResourceDetails(issue.resourceDetails)
32880
- };
32881
- }
32882
- function rebuildCombinedResourceSnapshot() {
32883
- const detailed = [...projectResourceSnapshots.values()].flatMap((snapshot) => snapshot.detailed).sort((a, b) => compareIssueIds(a.issueId, b.issueId));
32884
- const publicIssues = detailed.map(toPublicResourceIssue);
32885
- cachedDetailedResourceIssues = detailed;
32886
- cachedResourceIssues = {
32887
- value: publicIssues,
32888
- computedAt: Math.max(0, ...[...projectResourceSnapshots.values()].map((snapshot) => snapshot.computedAt))
32889
- };
32890
- return publicIssues;
32891
- }
32892
- function publishProjectResourceSnapshot(project, issues) {
32893
- projectResourceSnapshots.set(project.path, {
32894
- detailed: issues,
32895
- public: issues.map(toPublicResourceIssue),
32896
- computedAt: Date.now()
32897
- });
32898
- rebuildCombinedResourceSnapshot();
32899
- }
32900
- /** Refresh only the requested projects, capturing fleet-wide signals once for the batch. */
32901
- async function refreshResourceAllocatedProjects(projects, options = {}) {
32902
- if (projects.length === 0) return cachedResourceIssues?.value ?? [];
32903
- const sharedSignals = await captureSharedResourceSignals();
32904
- const failures = [];
32905
- for (const project of projects) try {
32906
- if (options.refreshMembership !== false) await refreshMembershipSnapshotsForProjects([project]);
32907
- publishProjectResourceSnapshot(project, await computeResourceAllocatedIssues([project], sharedSignals));
32908
- } catch (error) {
32909
- const failure = error instanceof Error ? error : new Error(String(error));
32910
- failures.push(failure);
32911
- console.warn(`[resource-discovery] refresh failed for ${project.name ?? project.path}; keeping last-good snapshot:`, failure.message);
32912
- }
32913
- if (failures.length > 0) throw new AggregateError(failures, `${failures.length} project resource refresh(es) failed`);
32914
- return cachedResourceIssues?.value ?? [];
32915
- }
32916
- async function getCachedResourceAllocatedIssues() {
32917
- return cachedResourceIssues?.value ?? [];
32918
- }
32919
- function sanitizeResourceAllocatedIssues(issues) {
32920
- return issues.map((issue) => ({
32921
- ...issue,
32922
- resourceDetails: {
32923
- hasWorkspace: issue.resourceDetails.hasWorkspace,
32924
- localBranchCount: issue.resourceDetails.localBranchCount,
32925
- remoteBranchCount: issue.resourceDetails.remoteBranchCount,
32926
- tmuxSessionCount: issue.resourceDetails.tmuxSessionCount,
32927
- prs: issue.resourceDetails.prs.map((pr) => ({
32928
- number: pr.number,
32929
- title: pr.title,
32930
- state: pr.state,
32931
- isDraft: pr.isDraft
32932
- })),
32933
- hasXbrief: issue.resourceDetails.hasXbrief,
32934
- hasTasks: issue.resourceDetails.hasTasks,
32935
- hasPrd: issue.resourceDetails.hasPrd,
32936
- dockerContainerCount: issue.resourceDetails.dockerContainerCount,
32937
- actualBranch: issue.resourceDetails.actualBranch,
32938
- branchDrifted: issue.resourceDetails.branchDrifted,
32939
- branchAheadOfMain: issue.resourceDetails.branchAheadOfMain,
32940
- workspaceMissing: issue.resourceDetails.workspaceMissing,
32941
- remoteAgent: issue.resourceDetails.remoteAgent ?? null,
32942
- conversations: issue.resourceDetails.conversations.map((conv) => ({
32943
- id: conv.id,
32944
- name: conv.name,
32945
- title: conv.title,
32946
- status: conv.status
32947
- }))
32948
- }
32949
- }));
32950
- }
32951
- function toPublicResourceDetailIdentifiers(details) {
32952
- return summarizeResourceDetailIdentifiers(details);
32953
- }
32954
- async function getResourceDetailIdentifiers(issueId) {
32955
- const normalizedIssueId = issueId.toUpperCase();
32956
- const cachedMatch = cachedDetailedResourceIssues?.find((entry) => entry.issueId === normalizedIssueId);
32957
- return cachedMatch ? toPublicResourceDetailIdentifiers(cachedMatch.resourceDetails) : null;
32958
- }
32959
- function groupResourceAllocatedIssuesByProject(issues) {
32960
- const projectTree = /* @__PURE__ */ new Map();
32961
- for (const issue of issues) {
32962
- const existing = projectTree.get(issue.projectName);
32963
- if (existing) {
32964
- existing.features.push(issue);
32965
- continue;
32966
- }
32967
- projectTree.set(issue.projectName, {
32968
- name: issue.projectName,
32969
- path: issue.projectName,
32970
- features: [issue]
32971
- });
32972
- }
32973
- return [...projectTree.values()].map((project) => ({
32974
- ...project,
32975
- features: project.features.sort((a, b) => compareIssueIds(a.issueId, b.issueId))
32976
- })).sort((a, b) => a.name.localeCompare(b.name));
32977
- }
32978
- //#endregion
32979
32212
  //#region ../../lib/overdeck/issue-reads.ts
32980
32213
  init_projects();
32981
- init_tracker_utils();
32982
32214
  init_io();
32983
32215
  function isGitHubIssue$6(issueId) {
32984
32216
  const resolved = resolveGitHubIssueSync(issueId);
@@ -33271,10 +32503,7 @@ function getIssueResourceDetails(rawId) {
33271
32503
  //#endregion
33272
32504
  //#region ../../lib/overdeck/planning-promotion.ts
33273
32505
  init_tracker_config();
33274
- init_agents$1();
33275
- init_pan_dir();
33276
32506
  init_projects();
33277
- init_review_status();
33278
32507
  init_remote_agents();
33279
32508
  init_tracker_utils();
33280
32509
  init_tmux();
@@ -34105,7 +33334,7 @@ async function closeIssuePullRequest(issueId, reason = "Canceled via Overdeck")
34105
33334
  timeout: 15e3
34106
33335
  });
34107
33336
  try {
34108
- const { setReviewStatusSync } = await import("./review-status-CUnjjOUu.js");
33337
+ const { setReviewStatusSync } = await import("./review-status-C_kQeeX0.js");
34109
33338
  setReviewStatusSync(issueId.toUpperCase(), { prUrl: void 0 });
34110
33339
  } catch {}
34111
33340
  return [`Closed PR #${prNumber} on ${githubCheck.owner}/${githubCheck.repo}`];
@@ -34159,7 +33388,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
34159
33388
  const { ctx, projectConfig } = buildLifecycleContext(id, getIssueDataService$8().getIssueSource(id) ?? void 0);
34160
33389
  const deleteWorkspace = opts.deleteWorkspace ?? true;
34161
33390
  cleanupLog.push(...await closeIssuePullRequest(id, mode === "cancel" ? "Canceled via Overdeck" : "Reset to Todo via Overdeck"));
34162
- const { resetToTodo, cancelIssueWorkflow } = await import("./lifecycle-B0rL38D3.js");
33391
+ const { resetToTodo, cancelIssueWorkflow } = await import("./lifecycle-DaCovZwn.js");
34163
33392
  const workflow = mode === "cancel" ? cancelIssueWorkflow : resetToTodo;
34164
33393
  const result = await Effect.runPromise(workflow(ctx, {
34165
33394
  deleteWorkspace,
@@ -34174,7 +33403,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
34174
33403
  }));
34175
33404
  cleanupLog.push(...result.steps.flatMap((step) => step.details || [step.error].filter(Boolean)));
34176
33405
  if (mode === "cancel") try {
34177
- const { transitionXBriefOnMain } = await import("./lifecycle-io-DQDU0apV.js");
33406
+ const { transitionXBriefOnMain } = await import("./lifecycle-io-BBMTaP7S.js");
34178
33407
  const tx = await Effect.runPromise(transitionXBriefOnMain(ctx.projectPath, id, "cancelled", "cancelled", `scope: cancel ${id.toUpperCase()} xBRIEF`));
34179
33408
  if (tx.moved) cleanupLog.push(`xBRIEF moved ${tx.fromDir} → cancelled`);
34180
33409
  if (tx.committed) cleanupLog.push(`Committed xBRIEF cancellation on main`);
@@ -34182,8 +33411,8 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
34182
33411
  cleanupLog.push(`xBRIEF cancel transition failed (non-fatal): ${err?.message ?? err}`);
34183
33412
  }
34184
33413
  try {
34185
- const { killAllReviewerSessions } = await import("./review-agent-BUNTVJK2.js");
34186
- const { resolveProjectFromIssueSync } = await import("./projects-DvPEAP18.js");
33414
+ const { killAllReviewerSessions } = await import("./review-agent-DgkUPRx0.js");
33415
+ const { resolveProjectFromIssueSync } = await import("./projects-LftaVK99.js");
34187
33416
  const projectKey = resolveProjectFromIssueSync(id)?.projectKey;
34188
33417
  if (projectKey) {
34189
33418
  const { killed } = await Effect.runPromise(killAllReviewerSessions(projectKey, id.toUpperCase()));
@@ -34197,7 +33426,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
34197
33426
  cleanupLog.push("Cleared review status");
34198
33427
  } catch {}
34199
33428
  try {
34200
- const { resetPostMergeState } = await import("./merge-agent-BRSz26Oh.js");
33429
+ const { resetPostMergeState } = await import("./merge-agent-BuoC_PRZ.js");
34201
33430
  resetPostMergeState(id);
34202
33431
  resetPostMergeState(id.toUpperCase());
34203
33432
  cleanupLog.push("Cleared merge state");
@@ -34217,7 +33446,7 @@ function closeIssueTransition(options) {
34217
33446
  const { issueId, body, eventStore } = options;
34218
33447
  const { reason } = body;
34219
33448
  const projectPath = getProjectPath$3(void 0, extractPrefixSync(issueId) ?? issueId.split("-")[0]);
34220
- const { close: closeWorkflow } = yield* Effect.promise(() => import("./lifecycle-B0rL38D3.js"));
33449
+ const { close: closeWorkflow } = yield* Effect.promise(() => import("./lifecycle-DaCovZwn.js"));
34221
33450
  const githubCheck = isGitHubIssue$4(issueId);
34222
33451
  const issueDataService = getIssueDataService$8();
34223
33452
  const issueSource = issueDataService.getIssueSource(issueId);
@@ -34484,7 +33713,7 @@ function reopenIssueTransition(options) {
34484
33713
  else clearReviewStatus(id.toUpperCase());
34485
33714
  } catch {}
34486
33715
  try {
34487
- const { resetPostMergeState } = await import("./merge-agent-BRSz26Oh.js");
33716
+ const { resetPostMergeState } = await import("./merge-agent-BuoC_PRZ.js");
34488
33717
  resetPostMergeState(id);
34489
33718
  resetPostMergeState(id.toUpperCase());
34490
33719
  } catch {}
@@ -34548,7 +33777,7 @@ function moveIssueStatus(options) {
34548
33777
  "done"
34549
33778
  ];
34550
33779
  if (!targetStatus || !validStatuses.includes(targetStatus)) return jsonResponse({ error: `Invalid targetStatus. Must be one of: ${validStatuses.join(", ")}` }, { status: 400 });
34551
- const { updateShadowState } = yield* Effect.promise(() => import("./shadow-state-e7250VUx.js"));
33780
+ const { updateShadowState } = yield* Effect.promise(() => import("./shadow-state-nGhCNXT2.js"));
34552
33781
  const issueState = {
34553
33782
  backlog: "open",
34554
33783
  todo: "open",
@@ -34611,7 +33840,6 @@ function moveIssueStatus(options) {
34611
33840
  init_issue_service_singleton();
34612
33841
  init_issue_id();
34613
33842
  init_agents$1();
34614
- init_resolver();
34615
33843
  init_writer();
34616
33844
  const execAsync$8 = promisify(exec);
34617
33845
  /**
@@ -34792,7 +34020,7 @@ async function copySettingsToWorkspace(id) {
34792
34020
  success: false,
34793
34021
  error: "Workspace not found"
34794
34022
  }, { status: 404 });
34795
- const { copyOverdeckSettingsToWorkspaceSync } = await import("./workspace-manager-5BKPV6SY.js");
34023
+ const { copyOverdeckSettingsToWorkspaceSync } = await import("./workspace-manager-jfkKAEuO.js");
34796
34024
  const result = copyOverdeckSettingsToWorkspaceSync(workspacePath);
34797
34025
  return jsonResponse({
34798
34026
  success: result.errors.length === 0 || result.copied.length > 0,
@@ -34802,8 +34030,11 @@ async function copySettingsToWorkspace(id) {
34802
34030
  }
34803
34031
  //#endregion
34804
34032
  //#region ../../lib/overdeck/task-generation.ts
34033
+ init_concurrency$1();
34805
34034
  init_identity_record();
34806
34035
  init_shadow_state();
34036
+ init_advisory_checks();
34037
+ init_github_app();
34807
34038
  init_io();
34808
34039
  function buildChildStoriesFromRally(children) {
34809
34040
  return children.map((c) => ({
@@ -35295,7 +34526,7 @@ function restartFromPlan(options) {
35295
34526
  });
35296
34527
  const resetResult = yield* Effect.promise(async () => {
35297
34528
  try {
35298
- const { runGitResetHard } = await import("./dangerous-git-ops-akhA3iyF.js");
34529
+ const { runGitResetHard } = await import("./dangerous-git-ops-By9iguTP.js");
35299
34530
  async function findPlanningCommit(grep, label) {
35300
34531
  try {
35301
34532
  const { stdout } = await execAsync$7(`git log --grep="${grep.replace(/"/g, "\\\"")}" --format=%H -1`, {
@@ -35648,7 +34879,6 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
35648
34879
  //#region ../../lib/overdeck/issue-close-out.ts
35649
34880
  init_issue_service_singleton();
35650
34881
  init_tracker_config();
35651
- init_concurrency$1();
35652
34882
  init_agents$1();
35653
34883
  init_projects();
35654
34884
  init_tracker_utils();
@@ -35743,7 +34973,7 @@ function closeOutIssue(id, opts = {}) {
35743
34973
  }
35744
34974
  const closeOutResult = yield* Effect.promise(async () => {
35745
34975
  try {
35746
- const { closeOut } = await import("./lifecycle-B0rL38D3.js");
34976
+ const { closeOut } = await import("./lifecycle-DaCovZwn.js");
35747
34977
  return {
35748
34978
  ok: true,
35749
34979
  result: await Effect.runPromise(closeOut(ctx, {
@@ -35833,7 +35063,7 @@ function bulkCloseOut(body) {
35833
35063
  const invalidIds = issueIds.filter((id) => !isValidIssueId(id));
35834
35064
  if (invalidIds.length > 0) return jsonResponse({ error: `Invalid issue ID format: ${invalidIds.join(", ")}` }, { status: 400 });
35835
35065
  const eventStore = yield* EventStoreService;
35836
- const { closeOut } = yield* Effect.promise(() => import("./lifecycle-B0rL38D3.js"));
35066
+ const { closeOut } = yield* Effect.promise(() => import("./lifecycle-DaCovZwn.js"));
35837
35067
  const issueDataService = getIssueDataService$5();
35838
35068
  const tasks = [];
35839
35069
  const agentChecks = yield* withConcurrencyLimit(issueIds.map((id) => Effect.promise(async () => {
@@ -36000,7 +35230,7 @@ const execFileAsync$15 = promisify(execFile);
36000
35230
  function getIssueDataService$4() {
36001
35231
  return getSharedIssueService();
36002
35232
  }
36003
- const readJsonBody$19 = Effect.gen(function* () {
35233
+ const readJsonBody$20 = Effect.gen(function* () {
36004
35234
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
36005
35235
  try {
36006
35236
  return text ? JSON.parse(text) : {};
@@ -36058,8 +35288,8 @@ const getIssueShipLogRoute = HttpRouter.add("GET", "/api/issues/:id/ship-log", h
36058
35288
  const id = (yield* HttpRouter.params)["id"] ?? "";
36059
35289
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36060
35290
  return yield* Effect.promise(async () => {
36061
- const { getShipLog } = await import("./ship-log-7BnQHuKU.js");
36062
- const { getReviewStatusSync } = await import("./review-status-CUnjjOUu.js");
35291
+ const { getShipLog } = await import("./ship-log-ie0A_SqV.js");
35292
+ const { getReviewStatusSync } = await import("./review-status-C_kQeeX0.js");
36063
35293
  const log = getShipLog(id);
36064
35294
  const rs = getReviewStatusSync(id);
36065
35295
  return jsonResponse({
@@ -36074,8 +35304,8 @@ const getIssueVerificationRoute = HttpRouter.add("GET", "/api/issues/:id/verific
36074
35304
  const id = (yield* HttpRouter.params)["id"] ?? "";
36075
35305
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36076
35306
  return yield* Effect.promise(async () => {
36077
- const { readVerificationArtifact } = await import("./verification-artifact-CaSbxUVg.js");
36078
- const { getReviewStatusSync } = await import("./review-status-CUnjjOUu.js");
35307
+ const { readVerificationArtifact } = await import("./verification-artifact-D3viYe_t.js");
35308
+ const { getReviewStatusSync } = await import("./review-status-C_kQeeX0.js");
36079
35309
  const { join } = await import("node:path");
36080
35310
  const resolved = resolveProjectFromIssueSync(id);
36081
35311
  const workspacePath = resolved ? join(resolved.projectPath, "workspaces", `feature-${id.toLowerCase()}`) : null;
@@ -36093,7 +35323,7 @@ const postIssueCloseRoute = HttpRouter.add("POST", "/api/issues/:issueId/close",
36093
35323
  if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36094
35324
  return yield* closeIssueTransition({
36095
35325
  issueId,
36096
- body: yield* readJsonBody$19,
35326
+ body: yield* readJsonBody$20,
36097
35327
  eventStore: yield* EventStoreService
36098
35328
  });
36099
35329
  })));
@@ -36101,7 +35331,7 @@ const postIssueStartPlanningRoute = HttpRouter.add("POST", "/api/issues/:id/star
36101
35331
  const request = yield* HttpServerRequest.HttpServerRequest;
36102
35332
  const id = (yield* HttpRouter.params)["id"] ?? "";
36103
35333
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36104
- const body = yield* readJsonBody$19;
35334
+ const body = yield* readJsonBody$20;
36105
35335
  const eventStore = yield* EventStoreService;
36106
35336
  const linear = yield* LinearClient;
36107
35337
  const github = yield* GitHubClient;
@@ -36129,7 +35359,7 @@ const postIssueAbortPlanningRoute = HttpRouter.add("POST", "/api/issues/:id/abor
36129
35359
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36130
35360
  return yield* abortPlanningForIssue({
36131
35361
  id,
36132
- body: yield* readJsonBody$19,
35362
+ body: yield* readJsonBody$20,
36133
35363
  lifecycle: yield* IssueLifecycle,
36134
35364
  linear: yield* LinearClient,
36135
35365
  eventStore: yield* EventStoreService
@@ -36139,7 +35369,7 @@ const postIssueCompletePlanningRoute = HttpRouter.add("POST", "/api/issues/:id/c
36139
35369
  const request = yield* HttpServerRequest.HttpServerRequest;
36140
35370
  const id = (yield* HttpRouter.params)["id"] ?? "";
36141
35371
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36142
- const body = yield* readJsonBody$19;
35372
+ const body = yield* readJsonBody$20;
36143
35373
  const eventStore = yield* EventStoreService;
36144
35374
  const linear = yield* LinearClient;
36145
35375
  const lifecycle = yield* IssueLifecycle;
@@ -36165,7 +35395,7 @@ const postIssueResetRoute = HttpRouter.add("POST", "/api/issues/:id/reset", http
36165
35395
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36166
35396
  return yield* resetIssueTransition({
36167
35397
  id,
36168
- body: yield* readJsonBody$19,
35398
+ body: yield* readJsonBody$20,
36169
35399
  eventStore: yield* EventStoreService
36170
35400
  });
36171
35401
  })));
@@ -36189,7 +35419,7 @@ const postIssueCancelRoute = HttpRouter.add("POST", "/api/issues/:id/cancel", ht
36189
35419
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36190
35420
  return yield* cancelIssueTransition({
36191
35421
  id,
36192
- body: yield* readJsonBody$19,
35422
+ body: yield* readJsonBody$20,
36193
35423
  eventStore: yield* EventStoreService
36194
35424
  });
36195
35425
  })));
@@ -36200,7 +35430,7 @@ const postIssueReopenRoute = HttpRouter.add("POST", "/api/issues/:id/reopen", ht
36200
35430
  if (authError) return authError;
36201
35431
  return yield* reopenIssueTransition({
36202
35432
  id,
36203
- body: yield* readJsonBody$19,
35433
+ body: yield* readJsonBody$20,
36204
35434
  lifecycle: yield* IssueLifecycle,
36205
35435
  linear: yield* LinearClient,
36206
35436
  eventStore: yield* EventStoreService
@@ -36220,7 +35450,7 @@ const postIssueMoveStatusRoute = HttpRouter.add("POST", "/api/issues/:id/move-st
36220
35450
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
36221
35451
  return yield* moveIssueStatus({
36222
35452
  id,
36223
- body: yield* readJsonBody$19,
35453
+ body: yield* readJsonBody$20,
36224
35454
  eventStore: yield* EventStoreService,
36225
35455
  lifecycle: yield* IssueLifecycle
36226
35456
  });
@@ -36232,7 +35462,7 @@ const postIssueCleanupWorkspaceRoute = HttpRouter.add("POST", "/api/issues/:id/c
36232
35462
  })));
36233
35463
  const postIssueDeepWipeRoute = HttpRouter.add("POST", "/api/issues/:id/deep-wipe", httpHandler(Effect.gen(function* () {
36234
35464
  const id = (yield* HttpRouter.params)["id"] ?? "";
36235
- const body = yield* readJsonBody$19;
35465
+ const body = yield* readJsonBody$20;
36236
35466
  const eventStore = yield* EventStoreService;
36237
35467
  return yield* Effect.promise(() => deepWipeIssue(id, body, eventStore));
36238
35468
  })));
@@ -36293,7 +35523,7 @@ const postIssueTaskInspectRoute = HttpRouter.add("POST", "/api/issues/:id/tasks/
36293
35523
  return yield* inspectIssueTask({
36294
35524
  id: (params["id"] ?? "").toUpperCase(),
36295
35525
  itemId: params["itemId"] ?? "",
36296
- body: yield* readJsonBody$19
35526
+ body: yield* readJsonBody$20
36297
35527
  });
36298
35528
  })));
36299
35529
  const getIssuePlanningStateRoute = HttpRouter.add("GET", "/api/issues/:id/planning-state", httpHandler(Effect.gen(function* () {
@@ -37271,7 +36501,7 @@ async function readMemoryPhase(workspace) {
37271
36501
  * `!== false` default then read as "apply the mutation" instead of rejecting
37272
36502
  * the request.
37273
36503
  */
37274
- const readJsonBody$18 = Effect.gen(function* () {
36504
+ const readJsonBody$19 = Effect.gen(function* () {
37275
36505
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
37276
36506
  if (!text) return {};
37277
36507
  try {
@@ -37329,14 +36559,14 @@ const getWorkspaceRegistryProjectTargetsRoute = HttpRouter.add("GET", "/api/work
37329
36559
  const postWorkspaceRegistryResolveRoute = HttpRouter.add("POST", "/api/workspace-registry/resolve", httpHandler(Effect.gen(function* () {
37330
36560
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
37331
36561
  if (authError) return authError;
37332
- const body = yield* readJsonBody$18;
36562
+ const body = yield* readJsonBody$19;
37333
36563
  if (body === void 0) return jsonResponse({ error: "Malformed JSON body" }, { status: 400 });
37334
36564
  return jsonResponse(yield* Effect.promise(() => resolveWorkspaceCreateIntent(toCreateInput(body))));
37335
36565
  })));
37336
36566
  const postWorkspaceRegistryCreateRoute = HttpRouter.add("POST", "/api/workspace-registry", httpHandler(Effect.gen(function* () {
37337
36567
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
37338
36568
  if (authError) return authError;
37339
- const body = yield* readJsonBody$18;
36569
+ const body = yield* readJsonBody$19;
37340
36570
  if (body === void 0) return jsonResponse({ error: "Malformed JSON body" }, { status: 400 });
37341
36571
  const intent = yield* Effect.promise(() => resolveWorkspaceCreateIntent({
37342
36572
  ...toCreateInput(body),
@@ -37358,7 +36588,7 @@ const postWorkspaceRegistryRelocateRoute = HttpRouter.add("POST", "/api/workspac
37358
36588
  if (authError) return authError;
37359
36589
  const id = (yield* HttpRouter.params)["id"] ?? "";
37360
36590
  if (!getWorkspaceById(id)) return jsonResponse({ error: `Workspace not found: ${id}` }, { status: 404 });
37361
- const body = yield* readJsonBody$18;
36591
+ const body = yield* readJsonBody$19;
37362
36592
  if (body === void 0) return jsonResponse({ error: "Malformed JSON body" }, { status: 400 });
37363
36593
  if (typeof body.path !== "string" || !body.path) return jsonResponse({ error: "path is required" }, { status: 400 });
37364
36594
  const failure = yield* Effect.promise(() => relocateWorkspace(id, body.path, { force: body.force === true }).then(() => null).catch((err) => err instanceof Error ? err.message : String(err)));
@@ -37547,7 +36777,7 @@ const putWorkspaceRegistryRunCommandRoute = HttpRouter.add("PUT", "/api/workspac
37547
36777
  const id = (yield* HttpRouter.params)["id"] ?? "";
37548
36778
  const workspace = getWorkspaceById(id);
37549
36779
  if (!workspace) return jsonResponse({ error: `Workspace not found: ${id}` }, { status: 404 });
37550
- const body = yield* readJsonBody$18;
36780
+ const body = yield* readJsonBody$19;
37551
36781
  if (body === void 0) return jsonResponse({ error: "Malformed JSON body" }, { status: 400 });
37552
36782
  if (body.command !== null && typeof body.command !== "string") return jsonResponse({ error: "command must be a string or null" }, { status: 400 });
37553
36783
  const trimmed = typeof body.command === "string" ? body.command.trim() : null;
@@ -37600,7 +36830,7 @@ const postWorkspaceRegistryOpenRoute = HttpRouter.add("POST", "/api/workspace-re
37600
36830
  const id = (yield* HttpRouter.params)["id"] ?? "";
37601
36831
  const workspace = getWorkspaceById(id);
37602
36832
  if (!workspace) return jsonResponse({ error: `Workspace not found: ${id}` }, { status: 404 });
37603
- const body = yield* readJsonBody$18;
36833
+ const body = yield* readJsonBody$19;
37604
36834
  if (body === void 0) return jsonResponse({ error: "Malformed JSON body" }, { status: 400 });
37605
36835
  const target = body.target;
37606
36836
  if (target !== "file-manager" && target !== "editor") return jsonResponse({ error: "target must be 'file-manager' or 'editor'" }, { status: 400 });
@@ -37636,7 +36866,7 @@ const postWorkspaceRegistryArchiveRoute = HttpRouter.add("POST", "/api/workspace
37636
36866
  const id = (yield* HttpRouter.params)["id"] ?? "";
37637
36867
  const workspace = getWorkspaceById(id);
37638
36868
  if (!workspace) return jsonResponse({ error: `Workspace not found: ${id}` }, { status: 404 });
37639
- const body = yield* readJsonBody$18;
36869
+ const body = yield* readJsonBody$19;
37640
36870
  if (body === void 0) return jsonResponse({ error: "Malformed JSON body" }, { status: 400 });
37641
36871
  if (body.archived === false) unarchiveWorkspace(id);
37642
36872
  else yield* Effect.promise(() => archiveWorkspace(id));
@@ -37648,7 +36878,7 @@ const postWorkspaceRegistryFavoriteRoute = HttpRouter.add("POST", "/api/workspac
37648
36878
  const id = (yield* HttpRouter.params)["id"] ?? "";
37649
36879
  const workspace = getWorkspaceById(id);
37650
36880
  if (!workspace) return jsonResponse({ error: `Workspace not found: ${id}` }, { status: 404 });
37651
- const body = yield* readJsonBody$18;
36881
+ const body = yield* readJsonBody$19;
37652
36882
  if (body === void 0) return jsonResponse({ error: "Malformed JSON body" }, { status: 400 });
37653
36883
  setWorkspaceFavorite(id, body.favorite !== false);
37654
36884
  return jsonResponse(toListRow(getWorkspaceById(id) ?? workspace));
@@ -37659,7 +36889,7 @@ const putWorkspaceRegistryLayoutRoute = HttpRouter.add("PUT", "/api/workspace-re
37659
36889
  const id = (yield* HttpRouter.params)["id"] ?? "";
37660
36890
  const workspace = getWorkspaceById(id);
37661
36891
  if (!workspace) return jsonResponse({ error: `Workspace not found: ${id}` }, { status: 404 });
37662
- const body = yield* readJsonBody$18;
36892
+ const body = yield* readJsonBody$19;
37663
36893
  if (body === void 0) return jsonResponse({ error: "Malformed JSON body" }, { status: 400 });
37664
36894
  if (body.layout === void 0) return jsonResponse({ error: "layout is required" }, { status: 400 });
37665
36895
  updateWorkspaceLayout(id, JSON.stringify(body.layout));
@@ -38202,7 +37432,7 @@ function reloadDurableCloisterConfig(deps = {}) {
38202
37432
  */
38203
37433
  init_config$1();
38204
37434
  init_agents$1();
38205
- const readJsonBody$17 = Effect.gen(function* () {
37435
+ const readJsonBody$18 = Effect.gen(function* () {
38206
37436
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
38207
37437
  try {
38208
37438
  return text ? JSON.parse(text) : {};
@@ -38305,7 +37535,7 @@ const getCloisterConfigRoute = HttpRouter.add("GET", "/api/cloister/config", htt
38305
37535
  catch: (err) => new Error(err instanceof Error ? err.message : String(err))
38306
37536
  })));
38307
37537
  const putCloisterConfigRoute = HttpRouter.add("PUT", "/api/cloister/config", httpHandler(Effect.gen(function* () {
38308
- const updates = yield* readJsonBody$17;
37538
+ const updates = yield* readJsonBody$18;
38309
37539
  yield* Effect.try({
38310
37540
  try: () => {
38311
37541
  saveCloisterConfigSync(updates);
@@ -39669,7 +38899,7 @@ const getStackTeardownEstimateRoute = HttpRouter.add("GET", "/api/resources/stac
39669
38899
  })));
39670
38900
  const postStackTeardownRoute = HttpRouter.add("POST", "/api/resources/stacks/:issueId/teardown", httpHandler(Effect.gen(function* () {
39671
38901
  const params = yield* HttpRouter.params;
39672
- const body = yield* readJsonBody$16;
38902
+ const body = yield* readJsonBody$17;
39673
38903
  return yield* postStackTeardownEffect(params["issueId"] ?? "", body);
39674
38904
  })));
39675
38905
  function getStackTeardownEstimateEffect(issue) {
@@ -39843,7 +39073,7 @@ function lines(value) {
39843
39073
  function isDockerIdentifier(value) {
39844
39074
  return /^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/.test(value);
39845
39075
  }
39846
- const readJsonBody$16 = Effect.gen(function* () {
39076
+ const readJsonBody$17 = Effect.gen(function* () {
39847
39077
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
39848
39078
  try {
39849
39079
  return text ? JSON.parse(text) : {};
@@ -41101,6 +40331,7 @@ function normalizeAgentStatus(status) {
41101
40331
  */
41102
40332
  init_agents$1();
41103
40333
  init_specialists();
40334
+ init_jsonl_resolver();
41104
40335
  init_tmux();
41105
40336
  const CONVOY_REVIEWER_ROLES = [
41106
40337
  "correctness",
@@ -41253,12 +40484,14 @@ async function buildReviewerNodes(opts) {
41253
40484
  if (!isExtendedReviewEnabled(opts.issueId)) return [];
41254
40485
  const agentsRoot = opts.agentsDirOverride ?? join(homedir$1(), ".overdeck", "agents");
41255
40486
  const latestReviewRunDir = await findLatestReviewRunDir(opts.workspacePath, opts.issueId);
41256
- return await Promise.all(CONVOY_REVIEWER_ROLES.map(async (role) => {
40487
+ return (await Promise.all(CONVOY_REVIEWER_ROLES.map(async (role) => {
41257
40488
  const sessionId = getReviewerSessionName(role, opts.projectKey, opts.issueId);
41258
40489
  const isLive = opts.tmuxSessionNames.has(sessionId);
41259
40490
  const roundMetadata = await readReviewerRounds(sessionId, agentsRoot);
40491
+ const hasStateRow = existsSync$1(join(agentsRoot, sessionId, "state.json"));
41260
40492
  const jsonlPath = await resolveJsonlPath(sessionId, opts.workspacePath ?? opts.projectPath, { agentsDirOverride: opts.agentsDirOverride });
41261
40493
  const latestRunOutputExists = latestReviewRunDir ? existsSync$1(join(latestReviewRunDir, `${role}.md`)) : false;
40494
+ if (!(isLive || hasStateRow || roundMetadata !== void 0 || jsonlPath !== null || latestRunOutputExists)) return null;
41262
40495
  const inProgressThisRound = isLive && latestReviewRunDir !== null && !latestRunOutputExists;
41263
40496
  const isWarmIdle = isLive && existsSync$1(join(agentsRoot, sessionId, "reviewer-signaled"));
41264
40497
  const latestRoundDone = roundMetadata?.latestStatus === "completed" || roundMetadata?.latestStatus === "failed";
@@ -41296,7 +40529,7 @@ async function buildReviewerNodes(opts) {
41296
40529
  };
41297
40530
  if (roundMetadata) node.roundMetadata = roundMetadata;
41298
40531
  return node;
41299
- }));
40532
+ }))).filter((node) => node !== null);
41300
40533
  }
41301
40534
  //#endregion
41302
40535
  //#region routes/command-deck.ts
@@ -41320,6 +40553,7 @@ init_issue_id();
41320
40553
  init_tracker_config();
41321
40554
  init_config_yaml();
41322
40555
  init_issue_service_singleton();
40556
+ init_jsonl_resolver();
41323
40557
  init_types();
41324
40558
  init_io();
41325
40559
  const execAsync$5 = promisify(exec);
@@ -41376,7 +40610,7 @@ function getProjectPath$1(issuePrefix) {
41376
40610
  }
41377
40611
  return setProjectPathCache(issuePrefix, join(homedir$1(), "Projects"));
41378
40612
  }
41379
- const readJsonBody$15 = Effect.gen(function* () {
40613
+ const readJsonBody$16 = Effect.gen(function* () {
41380
40614
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
41381
40615
  try {
41382
40616
  return text ? JSON.parse(text) : {};
@@ -42070,7 +41304,7 @@ Be specific: reference actual file names, function names, requirement text, disc
42070
41304
  const { command: cliCmd, args: cliArgs } = getAgentCommandSync(statusModelId);
42071
41305
  const modelFlag = cliArgs.length > 0 ? ` ${cliArgs.join(" ")}` : "";
42072
41306
  const promptFile = join(planningDir, ".status-review-prompt.tmp");
42073
- const { getProviderForModelSync, getProviderEnvSync } = await import("./providers-CStNGwze.js");
41307
+ const { getProviderForModelSync, getProviderEnvSync } = await import("./providers-Dqgz3MY5.js");
42074
41308
  let providerEnvStr = "";
42075
41309
  let providerEnv = {};
42076
41310
  const statusProvider = getProviderForModelSync(statusModelId);
@@ -42145,7 +41379,7 @@ ${issueContext ? `## Issue Tracker Data\n${issueContext}\n` : ""}---
42145
41379
  }
42146
41380
  const postMissionControlUploadRoute = HttpRouter.add("POST", "/api/command-deck/planning/:issueId/upload", httpHandler(Effect.gen(function* () {
42147
41381
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
42148
- const { type, filename, content } = yield* readJsonBody$15;
41382
+ const { type, filename, content } = yield* readJsonBody$16;
42149
41383
  const issueLower = issueId.toLowerCase();
42150
41384
  const issuePrefix = extractPrefixSync(issueId) ?? issueId.split("-")[0];
42151
41385
  if (!type || !filename || !content) return jsonResponse({ error: "type, filename, and content are required" }, { status: 400 });
@@ -42153,7 +41387,7 @@ const postMissionControlUploadRoute = HttpRouter.add("POST", "/api/command-deck/
42153
41387
  let safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "-");
42154
41388
  let processedContent = content;
42155
41389
  if (safeName.endsWith(".vtt")) {
42156
- const { vttToMarkdown } = yield* Effect.promise(() => import("./vtt-parser-luerJpYT.js"));
41390
+ const { vttToMarkdown } = yield* Effect.promise(() => import("./vtt-parser-BSnAB-Og.js"));
42157
41391
  processedContent = vttToMarkdown(content);
42158
41392
  safeName = safeName.replace(/\.vtt$/, ".md");
42159
41393
  }
@@ -42174,7 +41408,7 @@ const postMissionControlUploadRoute = HttpRouter.add("POST", "/api/command-deck/
42174
41408
  const postMissionControlSyncDiscussionsRoute = HttpRouter.add("POST", "/api/command-deck/planning/:issueId/sync-discussions", httpHandler(Effect.gen(function* () {
42175
41409
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
42176
41410
  if (!parseIssueIdSync(issueId)) return jsonResponse({ error: "Invalid issue id: " + issueId }, { status: 400 });
42177
- const body = yield* readJsonBody$15;
41411
+ const body = yield* readJsonBody$16;
42178
41412
  const linear = yield* LinearClient;
42179
41413
  const { tracker } = body;
42180
41414
  const issueLower = issueId.toLowerCase();
@@ -42320,7 +41554,7 @@ const postMissionControlSyncDiscussionsRoute = HttpRouter.add("POST", "/api/comm
42320
41554
  })));
42321
41555
  const postMissionControlPlanningInitRoute = HttpRouter.add("POST", "/api/command-deck/planning/:issueId/init", httpHandler(Effect.gen(function* () {
42322
41556
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
42323
- const body = yield* readJsonBody$15;
41557
+ const body = yield* readJsonBody$16;
42324
41558
  const eventStore = yield* EventStoreService;
42325
41559
  const { shadow } = body;
42326
41560
  const issueLower = issueId.toLowerCase();
@@ -42404,7 +41638,7 @@ async function listRemoteWorkspaceMetadata() {
42404
41638
  }
42405
41639
  return workspaces;
42406
41640
  }
42407
- const readJsonBody$14 = Effect.gen(function* () {
41641
+ const readJsonBody$15 = Effect.gen(function* () {
42408
41642
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
42409
41643
  try {
42410
41644
  return text ? JSON.parse(text) : {};
@@ -42519,7 +41753,7 @@ const stopRemoteWorkspaceRoute = HttpRouter.add("POST", "/api/remote/workspaces/
42519
41753
  })));
42520
41754
  const startRemoteAgentRoute = HttpRouter.add("POST", "/api/remote/workspaces/:issueId/agent/start", httpHandler(Effect.gen(function* () {
42521
41755
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
42522
- const body = yield* readJsonBody$14;
41756
+ const body = yield* readJsonBody$15;
42523
41757
  const eventStore = yield* EventStoreService;
42524
41758
  const { prompt, model } = body;
42525
41759
  const metadata = yield* Effect.promise(() => loadRemoteWorkspaceMetadata(issueId));
@@ -42584,7 +41818,7 @@ const getRemoteAgentOutputRoute = HttpRouter.add("GET", "/api/remote/workspaces/
42584
41818
  })));
42585
41819
  const tellRemoteAgentRoute = HttpRouter.add("POST", "/api/remote/workspaces/:issueId/agent/tell", httpHandler(Effect.gen(function* () {
42586
41820
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
42587
- const { message } = yield* readJsonBody$14;
41821
+ const { message } = yield* readJsonBody$15;
42588
41822
  if (!message) return jsonResponse({ error: "Message is required" }, { status: 400 });
42589
41823
  const metadata = yield* Effect.promise(() => loadRemoteWorkspaceMetadata(issueId));
42590
41824
  if (!metadata) return jsonResponse({ error: "Remote workspace not found" }, { status: 404 });
@@ -45274,7 +44508,7 @@ function consumeReindexConfirmationNonce(nonce, estimatedUsd) {
45274
44508
  reindexConfirmationNonces.delete(nonce);
45275
44509
  return !!entry && entry.expiresAt > Date.now() && Math.abs(entry.estimatedUsd - estimatedUsd) < 1e-6;
45276
44510
  }
45277
- const readJsonBody$13 = Effect.gen(function* () {
44511
+ const readJsonBody$14 = Effect.gen(function* () {
45278
44512
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
45279
44513
  try {
45280
44514
  return text ? JSON.parse(text) : {};
@@ -45351,7 +44585,7 @@ const getOpenAIAuthRoute = HttpRouter.add("GET", "/api/settings/openai-auth", ht
45351
44585
  return jsonResponse(yield* getOpenAIAuthStatus());
45352
44586
  })));
45353
44587
  const postTestApiKeyRoute = HttpRouter.add("POST", "/api/settings/test-api-key", httpHandler(Effect.gen(function* () {
45354
- const { provider, apiKey, model } = yield* readJsonBody$13;
44588
+ const { provider, apiKey, model } = yield* readJsonBody$14;
45355
44589
  if (!provider || !apiKey) return jsonResponse({ error: "Provider and apiKey are required" }, { status: 400 });
45356
44590
  return yield* Effect.promise(async () => {
45357
44591
  let success = false;
@@ -45661,7 +44895,7 @@ const postTestApiKeyRoute = HttpRouter.add("POST", "/api/settings/test-api-key",
45661
44895
  });
45662
44896
  })));
45663
44897
  const postValidateApiKeyRoute = HttpRouter.add("POST", "/api/settings/validate-api-key", httpHandler(Effect.gen(function* () {
45664
- const { provider, apiKey } = yield* readJsonBody$13;
44898
+ const { provider, apiKey } = yield* readJsonBody$14;
45665
44899
  if (!provider || !apiKey) return jsonResponse({ error: "Provider and apiKey are required" }, { status: 400 });
45666
44900
  if (![
45667
44901
  "openai",
@@ -45897,7 +45131,7 @@ const getConversationSearchReindexEstimateRoute = HttpRouter.add("GET", "/api/se
45897
45131
  const postConversationSearchReindexRoute = HttpRouter.add("POST", "/api/settings/conversation-search/reindex", httpHandler(Effect.gen(function* () {
45898
45132
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
45899
45133
  if (authError) return authError;
45900
- const body = yield* readJsonBody$13;
45134
+ const body = yield* readJsonBody$14;
45901
45135
  return yield* Effect.promise(async () => {
45902
45136
  if (activeConversationSearchReindex) return jsonResponse({ error: "Conversation search reindex already in progress" }, { status: 409 });
45903
45137
  const job = (async () => {
@@ -45947,7 +45181,7 @@ const getConversationSearchReindexProgressRoute = HttpRouter.add("GET", "/api/se
45947
45181
  return jsonResponse(conversationReindexProgress);
45948
45182
  })));
45949
45183
  const putSettingsRoute = HttpRouter.add("PUT", "/api/settings", httpHandler(Effect.gen(function* () {
45950
- const body = yield* readJsonBody$13;
45184
+ const body = yield* readJsonBody$14;
45951
45185
  return yield* Effect.promise(async () => {
45952
45186
  try {
45953
45187
  const newSettings = body;
@@ -45968,7 +45202,7 @@ const putSettingsRoute = HttpRouter.add("PUT", "/api/settings", httpHandler(Effe
45968
45202
  });
45969
45203
  })));
45970
45204
  const putUiThemeRoute = HttpRouter.add("PUT", "/api/settings/ui-theme", httpHandler(Effect.gen(function* () {
45971
- const body = yield* readJsonBody$13;
45205
+ const body = yield* readJsonBody$14;
45972
45206
  return yield* Effect.promise(async () => {
45973
45207
  const theme = body?.theme;
45974
45208
  if (theme !== "light" && theme !== "dark") return jsonResponse({ error: "theme must be 'light' or 'dark'" }, { status: 400 });
@@ -45979,7 +45213,7 @@ const putUiThemeRoute = HttpRouter.add("PUT", "/api/settings/ui-theme", httpHand
45979
45213
  const putDesignLanguageRoute = HttpRouter.add("PUT", "/api/settings/design-language", httpHandler(Effect.gen(function* () {
45980
45214
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
45981
45215
  if (authError) return authError;
45982
- const body = yield* readJsonBody$13;
45216
+ const body = yield* readJsonBody$14;
45983
45217
  return yield* Effect.promise(async () => {
45984
45218
  const theme = body?.theme;
45985
45219
  if (theme !== "ledger" && theme !== "broadsheet") return jsonResponse({ error: "theme must be 'ledger' or 'broadsheet'" }, { status: 400 });
@@ -45994,7 +45228,7 @@ const getOpenRouterModelsRoute = HttpRouter.add("GET", "/api/settings/openrouter
45994
45228
  });
45995
45229
  })));
45996
45230
  const putOpenRouterFavoritesRoute = HttpRouter.add("PUT", "/api/settings/openrouter/favorites", httpHandler(Effect.gen(function* () {
45997
- const { favorites } = yield* readJsonBody$13;
45231
+ const { favorites } = yield* readJsonBody$14;
45998
45232
  if (!Array.isArray(favorites)) return jsonResponse({ error: "favorites must be an array of model IDs" }, { status: 400 });
45999
45233
  const modelIds = favorites.filter((f) => typeof f === "string");
46000
45234
  return yield* Effect.promise(async () => {
@@ -46010,7 +45244,7 @@ const putOpenRouterFavoritesRoute = HttpRouter.add("PUT", "/api/settings/openrou
46010
45244
  });
46011
45245
  })));
46012
45246
  const putOpenRouterApiKeyRoute = HttpRouter.add("PUT", "/api/settings/openrouter/api-key", httpHandler(Effect.gen(function* () {
46013
- const { apiKey } = yield* readJsonBody$13;
45247
+ const { apiKey } = yield* readJsonBody$14;
46014
45248
  if (apiKey !== void 0 && typeof apiKey !== "string") return jsonResponse({ error: "apiKey must be a string when provided" }, { status: 400 });
46015
45249
  return yield* Effect.promise(async () => {
46016
45250
  try {
@@ -46025,7 +45259,7 @@ const putOpenRouterApiKeyRoute = HttpRouter.add("PUT", "/api/settings/openrouter
46025
45259
  });
46026
45260
  })));
46027
45261
  const postOpenRouterTestKeyRoute = HttpRouter.add("POST", "/api/settings/openrouter/test-key", httpHandler(Effect.gen(function* () {
46028
- const { apiKey } = yield* readJsonBody$13;
45262
+ const { apiKey } = yield* readJsonBody$14;
46029
45263
  if (!apiKey) return jsonResponse({ error: "apiKey is required" }, { status: 400 });
46030
45264
  return jsonResponse(yield* (yield* OpenRouterService).validateApiKey(apiKey));
46031
45265
  })));
@@ -46076,7 +45310,7 @@ const getLegacyImportPreviewRoute = HttpRouter.add("GET", "/api/settings/legacy-
46076
45310
  const postLegacyImportRoute = HttpRouter.add("POST", "/api/settings/legacy-import/conversations", httpHandler(Effect.gen(function* () {
46077
45311
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
46078
45312
  if (authError) return authError;
46079
- const body = yield* readJsonBody$13;
45313
+ const body = yield* readJsonBody$14;
46080
45314
  return yield* Effect.try({
46081
45315
  try: () => {
46082
45316
  const { path, names } = body;
@@ -46088,7 +45322,7 @@ const postLegacyImportRoute = HttpRouter.add("POST", "/api/settings/legacy-impor
46088
45322
  const settingsRouteLayer = Layer.mergeAll(getSettingsRoute, getAvailableModelsRoute, getOptimalDefaultsRoute, getMiniMaxDefaultsRoute, getClaudeAuthRoute, getOpenAIAuthRoute, postTestApiKeyRoute, postValidateApiKeyRoute, getConversationSearchStatusRoute, getConversationSearchReindexEstimateRoute, postConversationSearchReindexRoute, getConversationSearchReindexProgressRoute, putSettingsRoute, putUiThemeRoute, putDesignLanguageRoute, getOpenRouterModelsRoute, putOpenRouterFavoritesRoute, putOpenRouterApiKeyRoute, postOpenRouterTestKeyRoute, getHarnessPolicyRoute, getProviderEnvConflictsRoute, getLegacyImportPreviewRoute, postLegacyImportRoute);
46089
45323
  //#endregion
46090
45324
  //#region routes/autopreso.ts
46091
- const readJsonBody$12 = Effect.gen(function* () {
45325
+ const readJsonBody$13 = Effect.gen(function* () {
46092
45326
  const request = yield* HttpServerRequest.HttpServerRequest;
46093
45327
  const contentLength = Number(request.headers["content-length"] ?? 0);
46094
45328
  if (Number.isFinite(contentLength) && contentLength > 256e3) return {
@@ -46119,7 +45353,7 @@ function requireTrustedOrigin$1(request) {
46119
45353
  const startRoute = HttpRouter.add("POST", "/api/autopreso/start", httpHandler(Effect.gen(function* () {
46120
45354
  const originError = requireTrustedOrigin$1(yield* HttpServerRequest.HttpServerRequest);
46121
45355
  if (originError) return originError;
46122
- const parsed = yield* readJsonBody$12;
45356
+ const parsed = yield* readJsonBody$13;
46123
45357
  if (!parsed.ok) return jsonResponse({ error: parsed.error }, { status: 413 });
46124
45358
  const elements = readElementLikes(parsed.body);
46125
45359
  const validation = validateAutoPresoCanvasElements(elements);
@@ -46317,7 +45551,7 @@ const metricsRouteLayer = Layer.mergeAll(getMetricsSummaryRoute, getMetricsCosts
46317
45551
  //#region routes/boot-reconciliation.ts
46318
45552
  init_tmux();
46319
45553
  init_control_settings();
46320
- const readJsonBody$11 = Effect.gen(function* () {
45554
+ const readJsonBody$12 = Effect.gen(function* () {
46321
45555
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
46322
45556
  try {
46323
45557
  return text ? JSON.parse(text) : {};
@@ -46392,7 +45626,7 @@ function parsePerAgentMap(value) {
46392
45626
  return parsed;
46393
45627
  }
46394
45628
  const postBootReconciliationDecisionRoute = HttpRouter.add("POST", "/api/boot-reconciliation/decision", httpHandler(Effect.gen(function* () {
46395
- const body = yield* readJsonBody$11;
45629
+ const body = yield* readJsonBody$12;
46396
45630
  if (!isBootReconciliationDecision(body.decision)) return jsonResponse({
46397
45631
  ok: false,
46398
45632
  error: "Body must include decision resume_all, hold_all, or per_agent"
@@ -46489,7 +45723,7 @@ function getGitHubLocalPaths() {
46489
45723
  }
46490
45724
  return out;
46491
45725
  }
46492
- const readJsonBody$10 = Effect.gen(function* () {
45726
+ const readJsonBody$11 = Effect.gen(function* () {
46493
45727
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
46494
45728
  try {
46495
45729
  return text ? JSON.parse(text) : {};
@@ -46501,7 +45735,7 @@ const readJsonBody$10 = Effect.gen(function* () {
46501
45735
  //#region routes/misc/project-mappings.ts
46502
45736
  const getProjectMappingsRoute = HttpRouter.add("GET", "/api/project-mappings", httpHandler(Effect.promise(() => getProjectMappings().then((m) => jsonResponse(m)))));
46503
45737
  const putProjectMappingsRoute = HttpRouter.add("PUT", "/api/project-mappings", Effect.gen(function* () {
46504
- const mappings = yield* readJsonBody$10;
45738
+ const mappings = yield* readJsonBody$11;
46505
45739
  if (!Array.isArray(mappings)) return jsonResponse({ error: "Expected array of mappings" }, { status: 400 });
46506
45740
  yield* Effect.promise(() => saveProjectMappings(mappings));
46507
45741
  return jsonResponse({
@@ -46510,7 +45744,7 @@ const putProjectMappingsRoute = HttpRouter.add("PUT", "/api/project-mappings", E
46510
45744
  });
46511
45745
  }));
46512
45746
  const postProjectMappingsRoute = HttpRouter.add("POST", "/api/project-mappings", Effect.gen(function* () {
46513
- const { linearProjectId, linearProjectName, linearPrefix, localPath } = yield* readJsonBody$10;
45747
+ const { linearProjectId, linearProjectName, linearPrefix, localPath } = yield* readJsonBody$11;
46514
45748
  if (!linearProjectId || !localPath) return jsonResponse({ error: "linearProjectId and localPath required" }, { status: 400 });
46515
45749
  return yield* Effect.promise(async () => {
46516
45750
  try {
@@ -46617,14 +45851,14 @@ const getTrackerStatusRoute = HttpRouter.add("GET", "/api/tracker-status", Effec
46617
45851
  }
46618
45852
  }));
46619
45853
  const postRallyValidateRoute = HttpRouter.add("POST", "/api/rally/validate", Effect.gen(function* () {
46620
- const { apiKey, server, workspace, project } = yield* readJsonBody$10;
45854
+ const { apiKey, server, workspace, project } = yield* readJsonBody$11;
46621
45855
  if (!apiKey) return jsonResponse({
46622
45856
  valid: false,
46623
45857
  error: "API key is required"
46624
45858
  }, { status: 400 });
46625
45859
  return yield* Effect.promise(async () => {
46626
45860
  try {
46627
- const { RallyRestApi } = await import("./rally-api-u_vkr5c_.js");
45861
+ const { RallyRestApi } = await import("./rally-api-Ij1Zt0NI.js");
46628
45862
  const api = new RallyRestApi({
46629
45863
  apiKey,
46630
45864
  server: server || "https://rally1.rallydev.com"
@@ -46965,7 +46199,7 @@ const getDeaconPauseRoute = HttpRouter.add("GET", "/api/deacon/pause", Effect.tr
46965
46199
  * Persists to `app_settings` so the flag survives dashboard restarts.
46966
46200
  */
46967
46201
  const postDeaconPauseRoute = HttpRouter.add("POST", "/api/deacon/pause", httpHandler(Effect.gen(function* () {
46968
- const body = yield* readJsonBody$10;
46202
+ const body = yield* readJsonBody$11;
46969
46203
  if (typeof body.paused !== "boolean") return jsonResponse({ error: "Body must include { paused: boolean }" }, { status: 400 });
46970
46204
  setDeaconGloballyPausedSync(body.paused);
46971
46205
  console.log(`[deacon] Global pause flag set to ${body.paused}`);
@@ -47008,7 +46242,7 @@ const getPlanningStatusRoute = HttpRouter.add("GET", "/api/planning/:issueId/sta
47008
46242
  const remoteState = loadRemoteAgentState(sessionName);
47009
46243
  const isRemote = !!remoteState;
47010
46244
  const vmName = remoteState?.vmName ?? "";
47011
- const { getAgentStateSync } = await import("./agents-megfmQHM.js");
46245
+ const { getAgentStateSync } = await import("./agents-DpCuoF65.js");
47012
46246
  const agentStarting = getAgentStateSync(sessionName)?.status === "starting";
47013
46247
  let tmuxSessionAlive = false;
47014
46248
  if (!isRemote) try {
@@ -47060,7 +46294,7 @@ const postPlanningMessageRoute = HttpRouter.add("POST", "/api/planning/:issueId/
47060
46294
  const issueId = new URL(request.url, "http://localhost").pathname.split("/")[3] || "";
47061
46295
  const sessionName = `planning-${issueId.toLowerCase()}`;
47062
46296
  const issueLower = issueId.toLowerCase();
47063
- const { message } = yield* readJsonBody$10;
46297
+ const { message } = yield* readJsonBody$11;
47064
46298
  const eventStore = yield* EventStoreService;
47065
46299
  if (!message) return jsonResponse({ error: "Message required" }, { status: 400 });
47066
46300
  return yield* Effect.promise(async () => {
@@ -47152,7 +46386,7 @@ Continue the PLANNING session. Do NOT implement anything.
47152
46386
  const agentCwd = workspacePath;
47153
46387
  const harnessLaunch = await prepareHarnessLaunch("claude-code");
47154
46388
  if (existsSync$1(outputFile)) await rename(outputFile, join(planningDir, `output-${Date.now()}.jsonl`));
47155
- const { getAgentCommandSync } = await import("./settings-DBWB1gsG.js");
46389
+ const { getAgentCommandSync } = await import("./settings-DhtPDmmI.js");
47156
46390
  let msgPlanningModel = "claude-sonnet-5";
47157
46391
  try {
47158
46392
  msgPlanningModel = resolveModel("plan", void 0, loadConfigSync().config);
@@ -47275,7 +46509,7 @@ async function getIndexStats(rootPath, isMain) {
47275
46509
  }
47276
46510
  const getTldrStatusRoute = HttpRouter.add("GET", "/api/services/tldr/status", Effect.promise(async () => {
47277
46511
  try {
47278
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CneJ24eL.js");
46512
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-BNQHwblU.js");
47279
46513
  const projectRoot = process.cwd();
47280
46514
  const venvPath = join(projectRoot, ".venv");
47281
46515
  const results = [];
@@ -47320,7 +46554,7 @@ const getTldrStatusRoute = HttpRouter.add("GET", "/api/services/tldr/status", Ef
47320
46554
  }));
47321
46555
  const postTldrStartRoute = HttpRouter.add("POST", "/api/services/tldr/start", Effect.promise(async () => {
47322
46556
  try {
47323
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CneJ24eL.js");
46557
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-BNQHwblU.js");
47324
46558
  const projectRoot = process.cwd();
47325
46559
  const venvPath = join(projectRoot, ".venv");
47326
46560
  if (!existsSync$1(venvPath)) return jsonResponse({ error: "No .venv found in project root" }, { status: 404 });
@@ -47337,7 +46571,7 @@ const postTldrStartRoute = HttpRouter.add("POST", "/api/services/tldr/start", Ef
47337
46571
  }));
47338
46572
  const postTldrStopRoute = HttpRouter.add("POST", "/api/services/tldr/stop", Effect.promise(async () => {
47339
46573
  try {
47340
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CneJ24eL.js");
46574
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-BNQHwblU.js");
47341
46575
  const projectRoot = process.cwd();
47342
46576
  const venvPath = join(projectRoot, ".venv");
47343
46577
  if (!existsSync$1(venvPath)) return jsonResponse({ error: "No .venv found in project root" }, { status: 404 });
@@ -47354,7 +46588,7 @@ const postTldrStopRoute = HttpRouter.add("POST", "/api/services/tldr/stop", Effe
47354
46588
  }));
47355
46589
  const postTldrReloadRoute = HttpRouter.add("POST", "/api/services/tldr/reload", Effect.promise(async () => {
47356
46590
  try {
47357
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CneJ24eL.js");
46591
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-BNQHwblU.js");
47358
46592
  const enabled = isTldrEnabledSync();
47359
46593
  const projectRoot = process.cwd();
47360
46594
  const targets = [];
@@ -47401,6 +46635,458 @@ const postTldrReloadRoute = HttpRouter.add("POST", "/api/services/tldr/reload",
47401
46635
  }));
47402
46636
  const tldrRouteLayer = Layer.mergeAll(getTldrStatusRoute, postTldrStartRoute, postTldrStopRoute, postTldrReloadRoute);
47403
46637
  //#endregion
46638
+ //#region services/restart-gate.ts
46639
+ /**
46640
+ * Restart Gate (PAN-3729) — operator approval for voluntary dashboard restarts.
46641
+ *
46642
+ * A *voluntary* restart is one a requester asks for: the post-merge deploy
46643
+ * script, `pan reload`, or bare `pan restart`. An *involuntary* restart (crash
46644
+ * recovery, watchdog respawn, the supervisor's own `POST /restart-dashboard`)
46645
+ * is never gated — gating it would deadlock the mechanism an approved restart
46646
+ * uses to actually restart.
46647
+ *
46648
+ * Requesters register through `POST /api/restart-gate/requests` every 5s and
46649
+ * block until the operator approves. One approval opens one *epoch*: the
46650
+ * snapshot of request ids taken at approval. Exactly one requester in that
46651
+ * epoch *claims* the restart; every other member is *satisfied* by it once the
46652
+ * fresh server boots.
46653
+ *
46654
+ * ── Doors ──────────────────────────────────────────────────────────────────
46655
+ * This module is the ONE read door and the ONE write door for gate state. No
46656
+ * route handler, CLI, or script reads or writes `restart-gate.json` directly.
46657
+ * The gate is runtime-plane state — the same plane as
46658
+ * `~/.overdeck/dashboard-restarting.json` — so it is NOT canonical, NOT
46659
+ * mirrored to git, and NOT persisted to the event log. It is a single JSON
46660
+ * file that survives exactly one restart, which is all the protocol needs.
46661
+ *
46662
+ * ── Expiry rules ───────────────────────────────────────────────────────────
46663
+ * - A pending request not refreshed for 20s expires (a poll IS the refresh).
46664
+ * - A claim not completed within 5 minutes lapses; the epoch falls back to
46665
+ * `approved` and the next poller may claim it. This covers a claimant that
46666
+ * died between claiming and restarting.
46667
+ * - An unclaimed epoch whose members have ALL expired is dropped, so the gate
46668
+ * cannot wedge in `approved` forever with nobody left to claim it. This is
46669
+ * the post-approval twin of "approve when every request has already expired
46670
+ * → clear the gate, restart nothing". That drop records `lastOutcome` on the
46671
+ * projection for 15s so the banner can say the approval restarted nothing
46672
+ * instead of silently vanishing (PAN-3731).
46673
+ * - Satisfied ids are served to polls for 10 minutes after boot, then pruned.
46674
+ */
46675
+ init_paths();
46676
+ /** A pending request not refreshed within this window expires. */
46677
+ const REQUEST_TTL_MS = 2e4;
46678
+ /** A claim not completed within this window lapses back to `approved`. */
46679
+ const CLAIM_LAPSE_MS = 5 * 6e4;
46680
+ /** Satisfied requester ids are served to late polls for this long. */
46681
+ const SATISFIED_TTL_MS = 10 * 6e4;
46682
+ /** How often the server prunes expired requests so the banner self-clears. */
46683
+ const SWEEP_INTERVAL_MS = 5e3;
46684
+ const RESTART_GATE_FILE = join(OVERDECK_HOME, "restart-gate.json");
46685
+ function emptyRestartGateState() {
46686
+ return {
46687
+ version: 1,
46688
+ pending: [],
46689
+ epoch: null,
46690
+ satisfied: []
46691
+ };
46692
+ }
46693
+ function millis(iso) {
46694
+ const parsed = Date.parse(iso);
46695
+ return Number.isFinite(parsed) ? parsed : 0;
46696
+ }
46697
+ /** True while the epoch's claim is held and has not lapsed. */
46698
+ function hasLiveClaim(epoch, nowMs) {
46699
+ if (!epoch?.claimedBy || !epoch.claimedAt) return false;
46700
+ return nowMs - millis(epoch.claimedAt) < CLAIM_LAPSE_MS;
46701
+ }
46702
+ /**
46703
+ * Drops everything the clock has invalidated. Called on EVERY read and every
46704
+ * mutation, so a caller never has to remember to prune first.
46705
+ */
46706
+ function pruneRestartGateState(state, nowMs) {
46707
+ const pending = state.pending.filter((request) => nowMs - millis(request.lastSeenAt) < REQUEST_TTL_MS);
46708
+ const satisfied = state.satisfied.filter((entry) => nowMs - millis(entry.satisfiedAt) < SATISFIED_TTL_MS);
46709
+ let lastOutcome = state.lastOutcome;
46710
+ if (lastOutcome && nowMs - millis(lastOutcome.at) >= 15e3) lastOutcome = void 0;
46711
+ let epoch = state.epoch;
46712
+ if (epoch && !hasLiveClaim(epoch, nowMs)) {
46713
+ const livePending = new Set(pending.map((request) => request.requesterId));
46714
+ if (!epoch.requesterIds.some((id) => livePending.has(id))) {
46715
+ epoch = null;
46716
+ lastOutcome = {
46717
+ type: "pruned-unclaimed",
46718
+ at: new Date(nowMs).toISOString()
46719
+ };
46720
+ }
46721
+ }
46722
+ return {
46723
+ version: state.version,
46724
+ pending,
46725
+ satisfied,
46726
+ epoch,
46727
+ ...lastOutcome === void 0 ? {} : { lastOutcome }
46728
+ };
46729
+ }
46730
+ /** The single place gate status is derived — used by every read and mutation. */
46731
+ function deriveRestartGateStatus(state, nowMs) {
46732
+ if (state.epoch) return hasLiveClaim(state.epoch, nowMs) ? "claimed" : "approved";
46733
+ return state.pending.length > 0 ? "pending" : "idle";
46734
+ }
46735
+ /** The operator-facing projection — identical to the `GET /api/restart-gate` body. */
46736
+ function toRestartGateSnapshot(state, nowMs) {
46737
+ return {
46738
+ status: deriveRestartGateStatus(state, nowMs),
46739
+ pending: state.pending.map((request) => ({
46740
+ requesterId: request.requesterId,
46741
+ kind: request.kind,
46742
+ reason: request.reason,
46743
+ ...request.builtSha === void 0 ? {} : { builtSha: request.builtSha },
46744
+ requestedAt: request.requestedAt
46745
+ })),
46746
+ ...state.lastOutcome === void 0 ? {} : { lastOutcome: state.lastOutcome }
46747
+ };
46748
+ }
46749
+ /**
46750
+ * Upsert + poll + TTL refresh in one step.
46751
+ *
46752
+ * A requester already marked satisfied is answered without being re-added:
46753
+ * its restart happened, so it must exit rather than start a new cycle.
46754
+ */
46755
+ function upsertRestartRequest(state, input, nowMs) {
46756
+ const pruned = pruneRestartGateState(state, nowMs);
46757
+ const nowIso = new Date(nowMs).toISOString();
46758
+ if (pruned.satisfied.some((entry) => entry.requesterId === input.requesterId)) return {
46759
+ state: pruned,
46760
+ result: {
46761
+ status: "satisfied",
46762
+ mayClaim: false,
46763
+ pendingCount: pruned.pending.length
46764
+ }
46765
+ };
46766
+ const existing = pruned.pending.find((request) => request.requesterId === input.requesterId);
46767
+ const upserted = {
46768
+ requesterId: input.requesterId,
46769
+ kind: input.kind,
46770
+ reason: input.reason,
46771
+ ...input.builtSha === void 0 ? {} : { builtSha: input.builtSha },
46772
+ requestedAt: existing?.requestedAt ?? nowIso,
46773
+ lastSeenAt: nowIso
46774
+ };
46775
+ const pending = existing ? pruned.pending.map((request) => request.requesterId === input.requesterId ? upserted : request) : [...pruned.pending, upserted];
46776
+ const next = {
46777
+ ...pruned,
46778
+ pending
46779
+ };
46780
+ const gateStatus = deriveRestartGateStatus(next, nowMs);
46781
+ if (!(next.epoch?.requesterIds.includes(input.requesterId) ?? false)) return {
46782
+ state: next,
46783
+ result: {
46784
+ status: "pending",
46785
+ mayClaim: false,
46786
+ pendingCount: pending.length
46787
+ }
46788
+ };
46789
+ if (gateStatus === "claimed") return {
46790
+ state: next,
46791
+ result: {
46792
+ status: "claimed",
46793
+ mayClaim: next.epoch?.claimedBy === input.requesterId,
46794
+ pendingCount: pending.length
46795
+ }
46796
+ };
46797
+ return {
46798
+ state: next,
46799
+ result: {
46800
+ status: "approved",
46801
+ mayClaim: true,
46802
+ pendingCount: pending.length
46803
+ }
46804
+ };
46805
+ }
46806
+ /**
46807
+ * Operator approval. Opens one epoch over every live request.
46808
+ *
46809
+ * When every request has already expired there is nothing to restart for, so
46810
+ * the gate is simply cleared — approving must never trigger a bare restart.
46811
+ * Re-approving an open epoch is a no-op so a double-click cannot widen it.
46812
+ */
46813
+ function approveRestartGate(state, nowMs) {
46814
+ const pruned = pruneRestartGateState(state, nowMs);
46815
+ if (pruned.epoch) return {
46816
+ state: pruned,
46817
+ result: {
46818
+ approved: true,
46819
+ pendingCount: pruned.pending.length
46820
+ }
46821
+ };
46822
+ if (pruned.pending.length === 0) return {
46823
+ state: {
46824
+ ...pruned,
46825
+ epoch: null
46826
+ },
46827
+ result: {
46828
+ approved: true,
46829
+ pendingCount: 0
46830
+ }
46831
+ };
46832
+ const nowIso = new Date(nowMs).toISOString();
46833
+ const epoch = {
46834
+ id: `epoch-${nowMs}`,
46835
+ requesterIds: pruned.pending.map((request) => request.requesterId),
46836
+ approvedAt: nowIso
46837
+ };
46838
+ return {
46839
+ state: {
46840
+ ...pruned,
46841
+ epoch
46842
+ },
46843
+ result: {
46844
+ approved: true,
46845
+ pendingCount: pruned.pending.length
46846
+ }
46847
+ };
46848
+ }
46849
+ /**
46850
+ * Grant the exclusive right to perform the restart.
46851
+ *
46852
+ * Atomic by construction: the state transition is synchronous, so two
46853
+ * concurrent claims are serialized by the event loop and exactly one wins.
46854
+ * A claimant re-claiming its own live claim is granted again, so a retry after
46855
+ * a dropped response is safe.
46856
+ */
46857
+ function claimRestartGate(state, requesterId, nowMs) {
46858
+ const pruned = pruneRestartGateState(state, nowMs);
46859
+ const epoch = pruned.epoch;
46860
+ if (!epoch || !epoch.requesterIds.includes(requesterId)) return {
46861
+ state: pruned,
46862
+ result: {
46863
+ granted: false,
46864
+ status: deriveRestartGateStatus(pruned, nowMs)
46865
+ }
46866
+ };
46867
+ if (hasLiveClaim(epoch, nowMs) && epoch.claimedBy !== requesterId) return {
46868
+ state: pruned,
46869
+ result: {
46870
+ granted: false,
46871
+ status: "claimed"
46872
+ }
46873
+ };
46874
+ const claimed = {
46875
+ ...epoch,
46876
+ claimedBy: requesterId,
46877
+ claimedAt: new Date(nowMs).toISOString()
46878
+ };
46879
+ return {
46880
+ state: {
46881
+ ...pruned,
46882
+ epoch: claimed
46883
+ },
46884
+ result: {
46885
+ granted: true,
46886
+ status: "claimed"
46887
+ }
46888
+ };
46889
+ }
46890
+ /**
46891
+ * The dashboard's own restart button is implicit approval (PAN-3729 §2.4).
46892
+ *
46893
+ * Every live request is folded into an epoch claimed by the UI, so the boot
46894
+ * that follows marks them satisfied and unblocks the requesters instead of
46895
+ * leaving them waiting for an approval that already happened.
46896
+ */
46897
+ function satisfyRestartGateForDirectRestart(state, nowMs, claimedBy) {
46898
+ const pruned = pruneRestartGateState(state, nowMs);
46899
+ const nowIso = new Date(nowMs).toISOString();
46900
+ return {
46901
+ ...pruned,
46902
+ epoch: {
46903
+ id: `epoch-${nowMs}`,
46904
+ requesterIds: pruned.pending.map((request) => request.requesterId),
46905
+ approvedAt: nowIso,
46906
+ claimedBy,
46907
+ claimedAt: nowIso
46908
+ }
46909
+ };
46910
+ }
46911
+ /**
46912
+ * Boot-time epoch resolution: this process starting IS the restart completing.
46913
+ *
46914
+ * A persisted epoch in `claimed` state means the previous server died to
46915
+ * perform an approved restart, so every member of that epoch got what it asked
46916
+ * for. An approved-but-unclaimed epoch is left alone — nobody performed a
46917
+ * restart for it, so its members keep waiting and can still claim.
46918
+ */
46919
+ function resolveRestartGateBoot(state, nowMs) {
46920
+ if (!state.epoch?.claimedBy) return {
46921
+ state: pruneRestartGateState(state, nowMs),
46922
+ satisfiedIds: []
46923
+ };
46924
+ const satisfiedAt = new Date(nowMs).toISOString();
46925
+ const satisfiedIds = state.epoch.requesterIds;
46926
+ const satisfied = [...state.satisfied.filter((entry) => !satisfiedIds.includes(entry.requesterId)), ...satisfiedIds.map((requesterId) => ({
46927
+ requesterId,
46928
+ satisfiedAt
46929
+ }))];
46930
+ return {
46931
+ state: pruneRestartGateState({
46932
+ ...state,
46933
+ pending: [],
46934
+ epoch: null,
46935
+ satisfied
46936
+ }, nowMs),
46937
+ satisfiedIds
46938
+ };
46939
+ }
46940
+ function emitThroughEventStore(snapshot) {
46941
+ (async () => {
46942
+ try {
46943
+ const { getEventStore } = await import("./event-store-Db4w4YIY.js");
46944
+ getEventStore().emitOnly({
46945
+ type: "restart_gate.changed",
46946
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
46947
+ payload: snapshot
46948
+ });
46949
+ } catch {}
46950
+ })();
46951
+ }
46952
+ function createRestartGate(deps = {}) {
46953
+ const filePath = deps.filePath ?? RESTART_GATE_FILE;
46954
+ const now = deps.now ?? (() => Date.now());
46955
+ const emit = deps.emit ?? emitThroughEventStore;
46956
+ let state = null;
46957
+ let loading = null;
46958
+ let writing = Promise.resolve();
46959
+ let lastPublished = null;
46960
+ async function loadState() {
46961
+ let parsed;
46962
+ try {
46963
+ const raw = await readFile(filePath, "utf-8");
46964
+ const candidate = JSON.parse(raw);
46965
+ parsed = {
46966
+ version: 1,
46967
+ pending: Array.isArray(candidate.pending) ? candidate.pending : [],
46968
+ epoch: candidate.epoch ?? null,
46969
+ satisfied: Array.isArray(candidate.satisfied) ? candidate.satisfied : [],
46970
+ ...candidate.lastOutcome === void 0 ? {} : { lastOutcome: candidate.lastOutcome }
46971
+ };
46972
+ } catch {
46973
+ parsed = emptyRestartGateState();
46974
+ }
46975
+ const resolved = resolveRestartGateBoot(parsed, now());
46976
+ state = resolved.state;
46977
+ if (resolved.satisfiedIds.length > 0) {
46978
+ console.log(`[restart-gate] Boot completed an approved restart — satisfied ${resolved.satisfiedIds.length} request(s): ${resolved.satisfiedIds.join(", ")}`);
46979
+ await persist();
46980
+ }
46981
+ }
46982
+ function ensureLoaded() {
46983
+ if (!loading) loading = loadState();
46984
+ return loading;
46985
+ }
46986
+ /** Atomic tmp+rename so a crash mid-write cannot leave a truncated gate. */
46987
+ async function persist() {
46988
+ const current = state;
46989
+ if (!current) return;
46990
+ const body = JSON.stringify(current, null, 2);
46991
+ writing = writing.then(async () => {
46992
+ try {
46993
+ await mkdir(dirname(filePath), { recursive: true });
46994
+ const tmp = `${filePath}.tmp`;
46995
+ await writeFile(tmp, body, "utf-8");
46996
+ await rename(tmp, filePath);
46997
+ } catch (error) {
46998
+ console.error("[restart-gate] Failed to persist gate state:", error);
46999
+ }
47000
+ });
47001
+ await writing;
47002
+ }
47003
+ function publish() {
47004
+ const snapshot = toRestartGateSnapshot(state ?? emptyRestartGateState(), now());
47005
+ const serialized = JSON.stringify(snapshot);
47006
+ if (serialized !== lastPublished) {
47007
+ lastPublished = serialized;
47008
+ emit(snapshot);
47009
+ }
47010
+ return snapshot;
47011
+ }
47012
+ async function mutate(apply) {
47013
+ await ensureLoaded();
47014
+ const { state: next, result } = apply(state ?? emptyRestartGateState(), now());
47015
+ state = next;
47016
+ await persist();
47017
+ publish();
47018
+ return result;
47019
+ }
47020
+ return {
47021
+ request: (input) => mutate((current, nowMs) => upsertRestartRequest(current, input, nowMs)),
47022
+ claim: (requesterId) => mutate((current, nowMs) => claimRestartGate(current, requesterId, nowMs)),
47023
+ approve: () => mutate((current, nowMs) => approveRestartGate(current, nowMs)),
47024
+ read: async () => {
47025
+ await ensureLoaded();
47026
+ state = pruneRestartGateState(state ?? emptyRestartGateState(), now());
47027
+ return publish();
47028
+ },
47029
+ satisfyForDirectRestart: (claimedBy) => mutate((current, nowMs) => ({
47030
+ state: satisfyRestartGateForDirectRestart(current, nowMs, claimedBy),
47031
+ result: void 0
47032
+ })),
47033
+ sweep: async () => {
47034
+ await ensureLoaded();
47035
+ const before = state ?? emptyRestartGateState();
47036
+ const after = pruneRestartGateState(before, now());
47037
+ state = after;
47038
+ if (after.pending.length !== before.pending.length || after.epoch !== before.epoch) await persist();
47039
+ return publish();
47040
+ }
47041
+ };
47042
+ }
47043
+ let sharedGate = null;
47044
+ let sweepTimer = null;
47045
+ /** The one gate instance every route and boot step shares. */
47046
+ function getRestartGate() {
47047
+ if (!sharedGate) sharedGate = createRestartGate();
47048
+ return sharedGate;
47049
+ }
47050
+ /**
47051
+ * Prune expired requests on a timer.
47052
+ *
47053
+ * Reads alone cannot clear the banner: a requester that dies simply stops
47054
+ * polling, so without this nothing would ever re-publish the shrunken
47055
+ * projection to the dashboard.
47056
+ */
47057
+ function startRestartGateSweep(gate, deps = {}) {
47058
+ const timer = (deps.setIntervalFn ?? setInterval)(() => {
47059
+ gate.sweep().catch((error) => {
47060
+ console.error("[restart-gate] Sweep failed:", error);
47061
+ });
47062
+ }, SWEEP_INTERVAL_MS);
47063
+ timer.unref?.();
47064
+ return timer;
47065
+ }
47066
+ /**
47067
+ * Resolve the persisted epoch and start the sweep.
47068
+ *
47069
+ * Boot resolution is lazy inside the gate too, so a requester polling a
47070
+ * still-booting server gets the same answer this call produces — there is no
47071
+ * window where a poll races ahead of startup.
47072
+ */
47073
+ async function initRestartGate(deps = {}) {
47074
+ const gate = getRestartGate();
47075
+ await gate.read();
47076
+ if (sweepTimer) return;
47077
+ sweepTimer = startRestartGateSweep(gate, deps);
47078
+ }
47079
+ //#endregion
47080
+ //#region ../../lib/restart-gate-client.ts
47081
+ init_config();
47082
+ /**
47083
+ * Set on any `pan restart` child spawned by a requester that has already
47084
+ * cleared the gate for that restart — the post-merge deploy script does exactly
47085
+ * that. Without it the child registers a second request and waits for a second
47086
+ * approval, so one deploy would cost the operator two clicks.
47087
+ */
47088
+ const RESTART_GATE_CLAIMED_ENV = "OVERDECK_RESTART_GATE_CLAIMED";
47089
+ //#endregion
47404
47090
  //#region ../../lib/sync-startup-gate.ts
47405
47091
  var sync_startup_gate_exports = /* @__PURE__ */ __exportAll({
47406
47092
  isStartupSyncNeededSync: () => isStartupSyncNeededSync,
@@ -47542,7 +47228,7 @@ const getVersionRoute = HttpRouter.add("GET", "/api/version", Effect.promise(asy
47542
47228
  const version = await getOverdeckVersion();
47543
47229
  let supervisorUrl = null;
47544
47230
  try {
47545
- const { getSupervisorUrlSync } = await import("./supervisor-DX8VsPnb.js");
47231
+ const { getSupervisorUrlSync } = await import("./supervisor-v0cYN2Vp.js");
47546
47232
  supervisorUrl = getSupervisorUrlSync();
47547
47233
  } catch {}
47548
47234
  return jsonResponse({
@@ -47552,11 +47238,11 @@ const getVersionRoute = HttpRouter.add("GET", "/api/version", Effect.promise(asy
47552
47238
  });
47553
47239
  }));
47554
47240
  const getPrerequisitesRoute = HttpRouter.add("GET", "/api/prerequisites", Effect.promise(async () => {
47555
- const { checkSystemPrerequisites } = await import("./system-prerequisites-BbGZ_WHF.js");
47241
+ const { checkSystemPrerequisites } = await import("./system-prerequisites-QKtIYXI2.js");
47556
47242
  return jsonResponse(await checkSystemPrerequisites());
47557
47243
  }));
47558
47244
  const getSetupDiagnosticsRoute = HttpRouter.add("GET", "/api/diagnostics/setup", Effect.promise(async () => {
47559
- const { collectSetupDiagnostics } = await import("./system-prerequisites-BbGZ_WHF.js");
47245
+ const { collectSetupDiagnostics } = await import("./system-prerequisites-QKtIYXI2.js");
47560
47246
  return jsonResponse(await collectSetupDiagnostics(await getOverdeckVersion()));
47561
47247
  }));
47562
47248
  const getSyncStatusRoute = HttpRouter.add("GET", "/api/sync-status", Effect.sync(() => {
@@ -47600,7 +47286,7 @@ const getConfirmationsRoute = HttpRouter.add("GET", "/api/confirmations", Effect
47600
47286
  const postConfirmationRespondRoute = HttpRouter.add("POST", "/api/confirmations/:id/respond", Effect.gen(function* () {
47601
47287
  const request = yield* HttpServerRequest.HttpServerRequest;
47602
47288
  const id = new URL(request.url, "http://localhost").pathname.split("/")[3] || "";
47603
- const { confirmed } = yield* readJsonBody$10;
47289
+ const { confirmed } = yield* readJsonBody$11;
47604
47290
  const confirmationRequest = pendingConfirmations.get(id);
47605
47291
  if (!confirmationRequest) return jsonResponse({ error: "Confirmation request not found" }, { status: 404 });
47606
47292
  return yield* Effect.promise(async () => {
@@ -47736,7 +47422,7 @@ const postShadowMonitorRoute = HttpRouter.add("POST", "/api/shadow/:issueId/moni
47736
47422
  const projectPath = await getProjectPath(issuePrefix);
47737
47423
  const workspacePath = join(projectPath, "workspaces", `feature-${issueLower}`);
47738
47424
  if (!existsSync$1(workspacePath)) return jsonResponse({ error: "Workspace not found" }, { status: 404 });
47739
- const { gatherArtifacts, generateBasicInference, updateInferenceDocumentSync } = await import("./shadow-engineering-C6oO_PiR.js");
47425
+ const { gatherArtifacts, generateBasicInference, updateInferenceDocumentSync } = await import("./shadow-engineering-BxiFrIKv.js");
47740
47426
  const config = {
47741
47427
  issueId,
47742
47428
  workspacePath,
@@ -47758,7 +47444,7 @@ const postShadowObserveRoute = HttpRouter.add("POST", "/api/shadow/:issueId/obse
47758
47444
  const issueId = new URL(request.url, "http://localhost").pathname.split("/")[3] || "";
47759
47445
  const issueLower = issueId.toLowerCase();
47760
47446
  const issuePrefix = extractPrefixSync(issueId) ?? issueId.split("-")[0];
47761
- const { mode } = yield* readJsonBody$10;
47447
+ const { mode } = yield* readJsonBody$11;
47762
47448
  return yield* Effect.promise(async () => {
47763
47449
  try {
47764
47450
  const projectPath = await getProjectPath(issuePrefix);
@@ -47766,7 +47452,7 @@ const postShadowObserveRoute = HttpRouter.add("POST", "/api/shadow/:issueId/obse
47766
47452
  if (!existsSync$1(workspacePath)) return jsonResponse({ error: "Workspace not found" }, { status: 404 });
47767
47453
  const ghConfig = getGitHubConfig();
47768
47454
  if (!ghConfig) return jsonResponse({ error: "GitHub not configured - Observer requires GitHub" }, { status: 400 });
47769
- const { runObserverCycle } = await import("./shadow-engineering-C6oO_PiR.js");
47455
+ const { runObserverCycle } = await import("./shadow-engineering-BxiFrIKv.js");
47770
47456
  const firstRepo = ghConfig.repos[0];
47771
47457
  const config = {
47772
47458
  issueId,
@@ -47812,12 +47498,21 @@ const postDevRebuildRoute = HttpRouter.add("POST", "/api/dev/rebuild", Effect.ge
47812
47498
  }
47813
47499
  });
47814
47500
  }));
47815
- const postRestartDashboardRoute = HttpRouter.add("POST", "/api/system/restart-dashboard", Effect.sync(() => {
47501
+ const postRestartDashboardRoute = HttpRouter.add("POST", "/api/system/restart-dashboard", Effect.promise(async () => {
47502
+ try {
47503
+ await getRestartGate().satisfyForDirectRestart(`dashboard-ui:${process.pid}`);
47504
+ } catch (error) {
47505
+ console.error("[restart-dashboard] restart-gate implicit approval failed:", error);
47506
+ }
47816
47507
  try {
47817
47508
  const invocation = panCliInvocation(["restart", "--dashboard"]);
47818
47509
  const child = spawn(invocation.command, invocation.args, {
47819
47510
  detached: true,
47820
- stdio: "ignore"
47511
+ stdio: "ignore",
47512
+ env: {
47513
+ ...process.env,
47514
+ [RESTART_GATE_CLAIMED_ENV]: "1"
47515
+ }
47821
47516
  });
47822
47517
  child.on("error", (err) => {
47823
47518
  console.error("[restart-dashboard] pan restart spawn failed:", err);
@@ -49535,6 +49230,7 @@ init_summary_fork();
49535
49230
  init_conversation_compaction();
49536
49231
  init_conversations();
49537
49232
  init_behavior();
49233
+ init_session_pane_choice();
49538
49234
  function isClaudeCodeConversation(conv) {
49539
49235
  return getHarnessBehavior(conv.harness).transcriptKind === "claude-jsonl";
49540
49236
  }
@@ -49586,6 +49282,109 @@ async function handleConversationPaneChoiceAnswer(rawId, body, deps = {}) {
49586
49282
  }
49587
49283
  }
49588
49284
  //#endregion
49285
+ //#region ../../lib/overdeck/claude-session-file-search.ts
49286
+ /**
49287
+ * By-id search for Claude Code transcripts under ~/.claude/projects/.
49288
+ *
49289
+ * Claude keys session files by the cwd AT RUNTIME, so when a repo directory is
49290
+ * renamed (e.g. Projects/panopticon-cli → Projects/overdeck) a conversation's
49291
+ * recorded cwd goes stale and the deterministic sessionFilePath(cwd, id)
49292
+ * points at a dir that no longer exists, while the JSONL itself lives under
49293
+ * the new encoded dir. A by-id search recovers it. The conversation-search
49294
+ * indexer also catalogs subagent transcripts
49295
+ * (<session-dir>/subagents/agent-<id>.jsonl), so palette hits arrive carrying
49296
+ * bare agent ids that only a one-level-deeper sweep can resolve.
49297
+ */
49298
+ const SAFE_SESSION_ID_PATTERN$1 = /^[a-zA-Z0-9_-]{1,128}$/;
49299
+ const SAFE_DIR_PATTERN = /^[a-zA-Z0-9_.-]+$/;
49300
+ const STAT_BATCH_SIZE = 50;
49301
+ const sessionFileByIdCache$1 = /* @__PURE__ */ new Map();
49302
+ const SESSION_FILE_MISS_TTL_MS$1 = 6e4;
49303
+ function cachedLookup(id) {
49304
+ const cached = sessionFileByIdCache$1.get(id);
49305
+ if (!cached) return void 0;
49306
+ if (cached.path) {
49307
+ if (existsSync$1(cached.path)) return cached.path;
49308
+ sessionFileByIdCache$1.delete(id);
49309
+ return;
49310
+ }
49311
+ if (Date.now() - cached.ts < SESSION_FILE_MISS_TTL_MS$1) return null;
49312
+ }
49313
+ async function firstExisting(candidates) {
49314
+ for (let i = 0; i < candidates.length; i += STAT_BATCH_SIZE) {
49315
+ const batch = candidates.slice(i, i + STAT_BATCH_SIZE);
49316
+ const found = (await Promise.all(batch.map(async (candidate) => {
49317
+ try {
49318
+ await stat(candidate);
49319
+ return candidate;
49320
+ } catch {
49321
+ return null;
49322
+ }
49323
+ }))).find((c) => c !== null);
49324
+ if (found) return found;
49325
+ }
49326
+ return null;
49327
+ }
49328
+ /** Find a main-session JSONL `<project-dir>/<session-id>.jsonl` by session id. */
49329
+ async function findClaudeSessionFileById$1(sessionId) {
49330
+ if (!SAFE_SESSION_ID_PATTERN$1.test(sessionId)) return null;
49331
+ const cached = cachedLookup(sessionId);
49332
+ if (cached !== void 0) return cached;
49333
+ try {
49334
+ const claudeProjects = join(homedir$1(), ".claude", "projects");
49335
+ const found = await firstExisting((await readdir(claudeProjects)).filter((dir) => SAFE_DIR_PATTERN.test(dir)).map((dir) => join(claudeProjects, dir, `${sessionId}.jsonl`)));
49336
+ if (found) {
49337
+ sessionFileByIdCache$1.set(sessionId, {
49338
+ path: found,
49339
+ ts: Date.now()
49340
+ });
49341
+ return found;
49342
+ }
49343
+ } catch {}
49344
+ sessionFileByIdCache$1.set(sessionId, {
49345
+ path: null,
49346
+ ts: Date.now()
49347
+ });
49348
+ return null;
49349
+ }
49350
+ /**
49351
+ * Find a subagent transcript `<session-dir>/subagents/agent-<id>.jsonl` by its
49352
+ * agent id, searching every session dir of every project dir. Same
49353
+ * memoization contract as findClaudeSessionFileById: the sweep readdir+stats
49354
+ * one level deeper, so a miss is cached for the TTL and a found path is
49355
+ * re-verified with one existsSync.
49356
+ */
49357
+ async function findSubagentTranscriptById(agentId) {
49358
+ if (!SAFE_SESSION_ID_PATTERN$1.test(agentId)) return null;
49359
+ const cached = cachedLookup(agentId);
49360
+ if (cached !== void 0) return cached;
49361
+ try {
49362
+ const claudeProjects = join(homedir$1(), ".claude", "projects");
49363
+ const projectDirs = (await readdir(claudeProjects)).filter((dir) => SAFE_DIR_PATTERN.test(dir));
49364
+ for (const projectDir of projectDirs) {
49365
+ let sessionDirs;
49366
+ try {
49367
+ sessionDirs = await readdir(join(claudeProjects, projectDir));
49368
+ } catch {
49369
+ continue;
49370
+ }
49371
+ const found = await firstExisting(sessionDirs.filter((entry) => SAFE_DIR_PATTERN.test(entry) && !entry.endsWith(".jsonl")).map((entry) => join(claudeProjects, projectDir, entry, "subagents", `${agentId}.jsonl`)));
49372
+ if (found) {
49373
+ sessionFileByIdCache$1.set(agentId, {
49374
+ path: found,
49375
+ ts: Date.now()
49376
+ });
49377
+ return found;
49378
+ }
49379
+ }
49380
+ } catch {}
49381
+ sessionFileByIdCache$1.set(agentId, {
49382
+ path: null,
49383
+ ts: Date.now()
49384
+ });
49385
+ return null;
49386
+ }
49387
+ //#endregion
49589
49388
  //#region ../../lib/overdeck/conversation-reads.ts
49590
49389
  init_concurrency$1();
49591
49390
  init_agent_enrichment();
@@ -49600,6 +49399,7 @@ init_conversation_service();
49600
49399
  init_pi_conversation_parser();
49601
49400
  init_ohmypi_conversation_parser();
49602
49401
  init_codex_conversation_parser();
49402
+ init_jsonl_resolver();
49603
49403
  init_kimi_conversation_parser();
49604
49404
  function result(body, status) {
49605
49405
  return status === void 0 ? { body } : {
@@ -49623,61 +49423,20 @@ const SAFE_SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]{1,128}$/;
49623
49423
  * allowed to trigger it.
49624
49424
  */
49625
49425
  const CLAUDE_SESSION_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
49626
- /** The transcript of an indexed-but-unregistered Claude session, or null. */
49627
- async function resolveUnregisteredClaudeSessionFile(name) {
49628
- if (!CLAUDE_SESSION_UUID_PATTERN.test(name)) return null;
49629
- return findClaudeSessionFileById$1(name);
49630
- }
49631
49426
  /**
49632
- * Find a Claude Code session JSONL by its (globally-unique) session id, searching
49633
- * every project dir under ~/.claude/projects/. Claude keys session files by the
49634
- * cwd AT RUNTIME, so when a repo directory is renamed (e.g. Projects/panopticon-cli
49635
- * → Projects/overdeck) a conversation's recorded cwd goes stale and the
49636
- * deterministic sessionFilePath(cwd, id) points at a dir that no longer exists,
49637
- * while the JSONL itself lives under the new encoded dir. A by-id search recovers
49638
- * it. Mirrors the cross-dir lookup the non-DB specialist/agent fallback already
49639
- * uses below.
49427
+ * A Claude Code subagent transcript id, as used to name
49428
+ * `<session-dir>/subagents/agent-<id>.jsonl`. The search indexer recurses into
49429
+ * subagents dirs, so those transcripts appear in palette results with the bare
49430
+ * agent id as their sessionId; clicking one arrives here. Like the UUID shape,
49431
+ * only this exact shape may trigger the by-id sweep — and the 10-hex floor
49432
+ * keeps Overdeck's own short `agent-<digits>` work-agent names out of it
49433
+ * (those resolve through resolveSpecialistSessionFile above, or nowhere).
49640
49434
  */
49641
- const sessionFileByIdCache$1 = /* @__PURE__ */ new Map();
49642
- const SESSION_FILE_MISS_TTL_MS$1 = 6e4;
49643
- async function findClaudeSessionFileById$1(sessionId) {
49644
- if (!SAFE_SESSION_ID_PATTERN.test(sessionId)) return null;
49645
- const cached = sessionFileByIdCache$1.get(sessionId);
49646
- if (cached) {
49647
- if (cached.path) {
49648
- if (existsSync$1(cached.path)) return cached.path;
49649
- sessionFileByIdCache$1.delete(sessionId);
49650
- } else if (Date.now() - cached.ts < SESSION_FILE_MISS_TTL_MS$1) return null;
49651
- }
49652
- try {
49653
- const claudeProjects = join(homedir$1(), ".claude", "projects");
49654
- const dirs = await readdir(claudeProjects);
49655
- const SAFE_DIR_PATTERN = /^[a-zA-Z0-9_.-]+$/;
49656
- const candidates = dirs.filter((dir) => SAFE_DIR_PATTERN.test(dir)).map((dir) => join(claudeProjects, dir, `${sessionId}.jsonl`));
49657
- const STAT_BATCH_SIZE = 50;
49658
- for (let i = 0; i < candidates.length; i += STAT_BATCH_SIZE) {
49659
- const batch = candidates.slice(i, i + STAT_BATCH_SIZE);
49660
- const found = (await Promise.all(batch.map(async (candidate) => {
49661
- try {
49662
- await stat(candidate);
49663
- return candidate;
49664
- } catch {
49665
- return null;
49666
- }
49667
- }))).find((c) => c !== null);
49668
- if (found) {
49669
- sessionFileByIdCache$1.set(sessionId, {
49670
- path: found,
49671
- ts: Date.now()
49672
- });
49673
- return found;
49674
- }
49675
- }
49676
- } catch {}
49677
- sessionFileByIdCache$1.set(sessionId, {
49678
- path: null,
49679
- ts: Date.now()
49680
- });
49435
+ const SUBAGENT_TRANSCRIPT_ID_PATTERN = /^agent-[0-9a-f]{10,20}$/i;
49436
+ /** The transcript of an indexed-but-unregistered Claude session, or null. */
49437
+ async function resolveUnregisteredClaudeSessionFile(name) {
49438
+ if (CLAUDE_SESSION_UUID_PATTERN.test(name)) return findClaudeSessionFileById$1(name);
49439
+ if (SUBAGENT_TRANSCRIPT_ID_PATTERN.test(name)) return findSubagentTranscriptById(name);
49681
49440
  return null;
49682
49441
  }
49683
49442
  async function resolveSessionFile(conv) {
@@ -51048,6 +50807,66 @@ function isInGraphQLCooldown() {
51048
50807
  return Date.now() - cooldownStartedAt < GRAPHQL_COOLDOWN_MS;
51049
50808
  }
51050
50809
  //#endregion
50810
+ //#region ../../lib/ci/project-ci-observation.ts
50811
+ init_projects();
50812
+ let projectByRepo = null;
50813
+ let projectLookupExpiresAt = 0;
50814
+ const PROJECT_LOOKUP_TTL_MS = 300 * 1e3;
50815
+ subscribeProjectsConfigInvalidation(() => {
50816
+ projectByRepo = null;
50817
+ projectLookupExpiresAt = 0;
50818
+ });
50819
+ function buildProjectLookup(projects) {
50820
+ const lookup = /* @__PURE__ */ new Map();
50821
+ for (const project of projects) {
50822
+ const repo = project.config.github_repo;
50823
+ if (!repo) continue;
50824
+ lookup.set(repo.toLowerCase(), {
50825
+ projectKey: project.key,
50826
+ repo,
50827
+ branch: project.config.workspace?.default_branch ?? "main"
50828
+ });
50829
+ }
50830
+ return lookup;
50831
+ }
50832
+ /** Resolve "owner/repo" from the invalidation-aware project registry cache. */
50833
+ function resolveProjectForRepo(fullName, projects) {
50834
+ if (!fullName) return null;
50835
+ let lookup;
50836
+ if (projects) lookup = buildProjectLookup(projects);
50837
+ else {
50838
+ const now = Date.now();
50839
+ if (!projectByRepo || now >= projectLookupExpiresAt) {
50840
+ projectByRepo = buildProjectLookup(listProjectsSync());
50841
+ projectLookupExpiresAt = now + PROJECT_LOOKUP_TTL_MS;
50842
+ }
50843
+ lookup = projectByRepo;
50844
+ }
50845
+ return lookup.get(fullName.toLowerCase()) ?? null;
50846
+ }
50847
+ /** Map a check_suite webhook payload only when its SHA was independently
50848
+ * verified as the current default-branch head. */
50849
+ function observationFromCheckSuite(payload, now, projects, authoritativeHeadSha) {
50850
+ const project = resolveProjectForRepo(payload.repository?.full_name, projects);
50851
+ const suite = payload.check_suite;
50852
+ if (!project || !suite) return null;
50853
+ if (suite.app?.slug !== "github-actions") return null;
50854
+ if (suite.head_branch !== project.branch) return null;
50855
+ if (!suite.head_sha || suite.id == null) return null;
50856
+ if (suite.head_sha !== authoritativeHeadSha) return null;
50857
+ return {
50858
+ projectKey: project.projectKey,
50859
+ repo: project.repo,
50860
+ branch: project.branch,
50861
+ headSha: suite.head_sha,
50862
+ suiteId: String(suite.id),
50863
+ status: suite.status ?? "queued",
50864
+ conclusion: suite.conclusion ?? null,
50865
+ observedAt: suite.updated_at ?? now,
50866
+ authoritativeHead: true
50867
+ };
50868
+ }
50869
+ //#endregion
51051
50870
  //#region ../../lib/webhook-handlers.ts
51052
50871
  /**
51053
50872
  * GitHub webhook event handlers (PAN-905)
@@ -51059,6 +50878,7 @@ function isInGraphQLCooldown() {
51059
50878
  init_review_status();
51060
50879
  init_tracker_config();
51061
50880
  init_errors();
50881
+ init_activity_logger();
51062
50882
  function issueIdFromBranch(ref) {
51063
50883
  const match = ref.match(/(?:feature|strike|bypass)\/([a-z]+-\d+)$/i);
51064
50884
  return match ? match[1].toUpperCase() : null;
@@ -51189,7 +51009,7 @@ async function refreshMergeStateFromGitHub(issueId, repo, prNumber) {
51189
51009
  let mergeState;
51190
51010
  let isDraft;
51191
51011
  let checksFailed;
51192
- const { isGitHubAppConfigured, getPullRequestState } = await import("./github-app-C33lDk9Z.js");
51012
+ const { isGitHubAppConfigured, getPullRequestState } = await import("./github-app-Oi5hdn1n.js");
51193
51013
  if (isGitHubAppConfigured()) {
51194
51014
  const prState = await Effect.runPromise(getPullRequestState(owner, repoName, prNumber));
51195
51015
  mergeable = prState.mergeable === null ? "UNKNOWN" : prState.mergeable ? "MERGEABLE" : "CONFLICTING";
@@ -51265,6 +51085,19 @@ async function refreshMergeStateFromGitHub(issueId, repo, prNumber) {
51265
51085
  }
51266
51086
  }
51267
51087
  async function handleCheckSuitePromise(payload) {
51088
+ const project = resolveProjectForRepo(payload.repository?.full_name);
51089
+ const projectSuite = payload.check_suite;
51090
+ if (project && projectSuite?.app?.slug === "github-actions" && projectSuite.head_branch === project.branch && projectSuite.head_sha && projectSuite.id != null) try {
51091
+ const authoritativeHead = await resolveDefaultBranchHead(project.repo, project.branch);
51092
+ const observation = observationFromCheckSuite(payload, (/* @__PURE__ */ new Date()).toISOString(), void 0, authoritativeHead);
51093
+ if (observation) await appendDomainEventAsync({
51094
+ type: "project.ci_suite_observed",
51095
+ timestamp: observation.observedAt,
51096
+ payload: observation
51097
+ });
51098
+ } catch (error) {
51099
+ console.warn("[webhook] Could not verify project CI branch head:", error);
51100
+ }
51268
51101
  if (!isTrackedRepositorySync(payload.repository?.full_name)) return;
51269
51102
  const suite = payload.check_suite;
51270
51103
  if (!suite) return;
@@ -51339,9 +51172,24 @@ async function handlePullRequestPromise(payload) {
51339
51172
  if (!issueId) return;
51340
51173
  bumpIssuePrTabCacheGeneration(issueId);
51341
51174
  const repo = payload.repository.full_name;
51175
+ if ([
51176
+ "opened",
51177
+ "closed",
51178
+ "reopened"
51179
+ ].includes(payload.action ?? "")) try {
51180
+ const { listProjectsSync, resolveProjectFromIssueSync } = await import("./projects-LftaVK99.js");
51181
+ const resolved = resolveProjectFromIssueSync(issueId);
51182
+ const project = resolved ? listProjectsSync().find((entry) => entry.key === resolved.projectKey)?.config : void 0;
51183
+ if (project) {
51184
+ const { enqueueProjectResourceRefresh } = await import("./project-resource-refresh-queue-BaZC79S3.js");
51185
+ enqueueProjectResourceRefresh(project, `pull_request:${payload.action}`);
51186
+ }
51187
+ } catch (err) {
51188
+ console.warn(`[webhook] Failed to enqueue membership refresh for ${issueId}: ${err?.message ?? err}`);
51189
+ }
51342
51190
  if (payload.action === "closed" && pr.merged === true) try {
51343
- const { postMergeLifecycle } = await import("./merge-agent-BRSz26Oh.js");
51344
- const { resolveProjectFromIssueSync } = await import("./projects-DvPEAP18.js");
51191
+ const { postMergeLifecycle } = await import("./merge-agent-BuoC_PRZ.js");
51192
+ const { resolveProjectFromIssueSync } = await import("./projects-LftaVK99.js");
51345
51193
  const project = resolveProjectFromIssueSync(issueId);
51346
51194
  if (project) {
51347
51195
  const branchName = pr.head.ref;
@@ -51647,6 +51495,7 @@ init_providers();
51647
51495
  init_paths();
51648
51496
  init_behavior();
51649
51497
  init_tmux();
51498
+ init_jsonl_resolver();
51650
51499
  const execFileAsync$4 = promisify(execFile);
51651
51500
  const SAFE_MODEL_PATTERN = MODEL_ID_PATTERN;
51652
51501
  const SESSION_FILE_MISS_TTL_MS = 2e3;
@@ -51748,11 +51597,11 @@ function parseSummaryForkFocus(value) {
51748
51597
  ok: true,
51749
51598
  focus: void 0
51750
51599
  };
51751
- if (focus.length > 500) return {
51600
+ if (focus.length > 1e4) return {
51752
51601
  ok: false,
51753
- error: "focus must be 500 characters or fewer"
51602
+ error: "focus must be 10000 characters or fewer"
51754
51603
  };
51755
- if (/[\x00-\x1f\x7f]/u.test(focus)) return {
51604
+ if (/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/u.test(focus)) return {
51756
51605
  ok: false,
51757
51606
  error: "focus must not contain control characters"
51758
51607
  };
@@ -51865,13 +51714,21 @@ async function injectForkSummary(conv, summary, caller) {
51865
51714
  if (outcome === "accepted") return "submitted";
51866
51715
  const normalizePaneVerification = (value) => value.replace(/[─-╿]/g, "").replace(/\s+/g, "");
51867
51716
  const verify = normalizePaneVerification(deliveryVerifyLine(summary).slice(0, 40));
51717
+ const composerStillHoldsPayload = async () => {
51718
+ if (verify.length < 3) return false;
51719
+ const viewport = await capturePaneViewport(conv.tmuxSession);
51720
+ if (viewport) {
51721
+ const composer = activeComposerRegion(viewport);
51722
+ if (composer !== null) return normalizePaneVerification(composer).includes(verify);
51723
+ }
51724
+ return normalizePaneVerification(await capturePaneText(conv.tmuxSession, 40)).includes(verify);
51725
+ };
51868
51726
  for (let nudge = 1; nudge <= 2; nudge++) {
51869
- const pane = await capturePaneText(conv.tmuxSession, 40);
51870
- if (!(verify.length >= 3 && normalizePaneVerification(pane).includes(verify))) return outcome === "unknown" ? "submitted" : "stranded";
51727
+ if (!await composerStillHoldsPayload()) return outcome === "unknown" ? "submitted" : "stranded";
51871
51728
  console.warn(`[${caller}] ${conv.name} still has the delivered summary in its composer — sending standalone Enter (${nudge}/2)`);
51872
51729
  await sendKeysAsync(conv.tmuxSession, "C-m", `${caller}:enter-nudge`);
51873
51730
  if (await confirmForkPromptAccepted(conv.tmuxSession, 8e3) === "accepted") return "submitted";
51874
- if (!normalizePaneVerification(await capturePaneText(conv.tmuxSession, 40)).includes(verify)) return "submitted";
51731
+ if (!await composerStillHoldsPayload()) return "submitted";
51875
51732
  }
51876
51733
  return "stranded";
51877
51734
  }
@@ -51904,7 +51761,7 @@ async function runForkPipeline(convName, parentConv, sessionId, summaryModel, fo
51904
51761
  let forkFallbackReason = null;
51905
51762
  const buildSummary = async () => {
51906
51763
  if (localSummaryOnly) try {
51907
- return await Effect.runPromise(generateFallbackSummary(parentSessionFile));
51764
+ return await Effect.runPromise(generateFallbackSummary(parentSessionFile, parentConv.harness ?? void 0));
51908
51765
  } catch (error) {
51909
51766
  console.warn(`[fork-pipeline] Heuristic fallback summary failed: ${error instanceof Error ? error.message : String(error)}`);
51910
51767
  return "";
@@ -51915,7 +51772,7 @@ async function runForkPipeline(convName, parentConv, sessionId, summaryModel, fo
51915
51772
  if (!forkFallbackReason) forkFallbackReason = `LLM summary failed: ${error instanceof Error ? error.message : String(error)}`;
51916
51773
  console.warn(`[fork-pipeline] LLM summary failed, falling back to heuristic: ${error instanceof Error ? error.message : String(error)}`);
51917
51774
  try {
51918
- return await Effect.runPromise(generateFallbackSummary(parentSessionFile));
51775
+ return await Effect.runPromise(generateFallbackSummary(parentSessionFile, parentConv.harness ?? void 0));
51919
51776
  } catch (heuristicError) {
51920
51777
  console.warn(`[fork-pipeline] Heuristic fallback also failed: ${heuristicError instanceof Error ? heuristicError.message : String(heuristicError)}`);
51921
51778
  return "";
@@ -52206,7 +52063,7 @@ startConversationModelBackfill(resolveSessionFile);
52206
52063
  function conversationReadJson(response) {
52207
52064
  return jsonResponse(response.body, response.status === void 0 ? void 0 : { status: response.status });
52208
52065
  }
52209
- const readJsonBody$9 = Effect.gen(function* () {
52066
+ const readJsonBody$10 = Effect.gen(function* () {
52210
52067
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
52211
52068
  try {
52212
52069
  return text ? JSON.parse(text) : {};
@@ -52266,7 +52123,7 @@ const postConversationRoute = HttpRouter.add("POST", "/api/conversations", Effec
52266
52123
  const request = yield* HttpServerRequest.HttpServerRequest;
52267
52124
  const originCheck = validateOrigin$1(request);
52268
52125
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52269
- const body = yield* readJsonBody$9;
52126
+ const body = yield* readJsonBody$10;
52270
52127
  const reqOrigin = getHeader(request, "origin") ?? "none";
52271
52128
  const reqReferer = getHeader(request, "referer") ?? "none";
52272
52129
  const reqUserAgent = getHeader(request, "user-agent") ?? "none";
@@ -52281,18 +52138,24 @@ const postConversationStopRoute = HttpRouter.add("POST", "/api/conversations/:na
52281
52138
  const name = (yield* HttpRouter.params)["name"] ?? "";
52282
52139
  return yield* Effect.promise(async () => handleConversationStop(name, { resolveSessionFileForCleanup: (conv) => conv.sessionFile ?? null }));
52283
52140
  }));
52141
+ const postConversationClearForkStateRoute = HttpRouter.add("POST", "/api/conversations/:name/clear-fork-state", Effect.gen(function* () {
52142
+ const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52143
+ if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52144
+ const params = yield* HttpRouter.params;
52145
+ return yield* Effect.promise(() => handleConversationClearForkState(params["name"] ?? ""));
52146
+ }));
52284
52147
  const postConversationResumeRoute = HttpRouter.add("POST", "/api/conversations/:name/resume", Effect.gen(function* () {
52285
52148
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52286
52149
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52287
52150
  const name = (yield* HttpRouter.params)["name"] ?? "";
52288
- const body = yield* readJsonBody$9;
52151
+ const body = yield* readJsonBody$10;
52289
52152
  return yield* Effect.promise(async () => handleConversationResume(name, body, { resolveSessionFile }));
52290
52153
  }));
52291
52154
  const postConversationSwitchModelRoute = HttpRouter.add("POST", "/api/conversations/:name/switch-model", Effect.gen(function* () {
52292
52155
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52293
52156
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52294
52157
  const name = (yield* HttpRouter.params)["name"] ?? "";
52295
- const body = yield* readJsonBody$9;
52158
+ const body = yield* readJsonBody$10;
52296
52159
  return yield* Effect.promise(async () => {
52297
52160
  try {
52298
52161
  return await handleConversationSwitchModel(name, body);
@@ -52307,7 +52170,7 @@ const postConversationThinkingLevelRoute = HttpRouter.add("POST", "/api/conversa
52307
52170
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52308
52171
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52309
52172
  const name = (yield* HttpRouter.params)["name"] ?? "";
52310
- const body = yield* readJsonBody$9;
52173
+ const body = yield* readJsonBody$10;
52311
52174
  return yield* Effect.promise(async () => {
52312
52175
  try {
52313
52176
  return await handleConversationThinkingLevel(name, body);
@@ -52404,7 +52267,7 @@ const postConversationDeleteImageRoute = HttpRouter.add("POST", "/api/conversati
52404
52267
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52405
52268
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52406
52269
  const name = (yield* HttpRouter.params)["name"] ?? "";
52407
- const body = yield* readJsonBody$9;
52270
+ const body = yield* readJsonBody$10;
52408
52271
  return yield* Effect.promise(async () => {
52409
52272
  try {
52410
52273
  return await handleConversationImageDelete(name, body);
@@ -52419,7 +52282,7 @@ const postConversationMessageRoute = HttpRouter.add("POST", "/api/conversations/
52419
52282
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52420
52283
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52421
52284
  const name = (yield* HttpRouter.params)["name"] ?? "";
52422
- const body = yield* readJsonBody$9;
52285
+ const body = yield* readJsonBody$10;
52423
52286
  return yield* Effect.promise(async () => {
52424
52287
  try {
52425
52288
  return await handleConversationMessage(name, body, conversationMessageDependencies);
@@ -52439,14 +52302,14 @@ const postConversationCodexApprovalRoute = HttpRouter.add("POST", "/api/conversa
52439
52302
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52440
52303
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52441
52304
  const rawId = (yield* HttpRouter.params)["id"] ?? "";
52442
- const body = yield* readJsonBody$9;
52305
+ const body = yield* readJsonBody$10;
52443
52306
  return yield* Effect.promise(() => handleConversationCodexApproval(rawId, body));
52444
52307
  }));
52445
52308
  const postConversationPaneChoiceRoute = HttpRouter.add("POST", "/api/conversations/:id/pane-choice", Effect.gen(function* () {
52446
52309
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52447
52310
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52448
52311
  const rawId = (yield* HttpRouter.params)["id"] ?? "";
52449
- const body = yield* readJsonBody$9;
52312
+ const body = yield* readJsonBody$10;
52450
52313
  return yield* Effect.promise(async () => {
52451
52314
  const result = await handleConversationPaneChoiceAnswer(rawId, body);
52452
52315
  return jsonResponse(result.body, { status: result.status });
@@ -52456,7 +52319,7 @@ const postConversationDeliveryMethodRoute = HttpRouter.add("POST", "/api/convers
52456
52319
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52457
52320
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52458
52321
  const name = (yield* HttpRouter.params)["name"] ?? "";
52459
- const body = yield* readJsonBody$9;
52322
+ const body = yield* readJsonBody$10;
52460
52323
  return yield* Effect.promise(async () => {
52461
52324
  try {
52462
52325
  return await handleConversationDeliveryMethod(name, body);
@@ -52471,7 +52334,7 @@ const postConversationControlAckRoute = HttpRouter.add("POST", "/api/conversatio
52471
52334
  const request = yield* HttpServerRequest.HttpServerRequest;
52472
52335
  const originCheck = validateConversationControlAckOrigin(request.headers, request.method);
52473
52336
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52474
- const body = yield* readJsonBody$9;
52337
+ const body = yield* readJsonBody$10;
52475
52338
  return yield* Effect.promise(async () => {
52476
52339
  try {
52477
52340
  const result = handleConversationControlAck(body);
@@ -52487,7 +52350,7 @@ const patchConversationRoute = HttpRouter.add("PATCH", "/api/conversations/:name
52487
52350
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52488
52351
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52489
52352
  const name = (yield* HttpRouter.params)["name"] ?? "";
52490
- const body = yield* readJsonBody$9;
52353
+ const body = yield* readJsonBody$10;
52491
52354
  return yield* Effect.promise(async () => {
52492
52355
  try {
52493
52356
  const result = patchConversationTitle(name, body);
@@ -52504,7 +52367,7 @@ const patchConversationMoveRoute = HttpRouter.add("PATCH", "/api/conversations/:
52504
52367
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52505
52368
  const params = yield* HttpRouter.params;
52506
52369
  const name = decodeURIComponent(params["name"] ?? "");
52507
- const body = yield* readJsonBody$9;
52370
+ const body = yield* readJsonBody$10;
52508
52371
  return yield* Effect.promise(async () => {
52509
52372
  try {
52510
52373
  const result = await handleConversationMove(name, body, { invalidateListEnrichmentCache: invalidateConversationListEnrichmentCache });
@@ -52591,14 +52454,14 @@ const postConversationSummaryForkRoute = HttpRouter.add("POST", "/api/conversati
52591
52454
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52592
52455
  const params = yield* HttpRouter.params;
52593
52456
  const name = decodeURIComponent(params["name"] ?? "");
52594
- const body = yield* readJsonBody$9;
52457
+ const body = yield* readJsonBody$10;
52595
52458
  return yield* Effect.promise(() => handleConversationSummaryFork(name, body));
52596
52459
  }));
52597
52460
  const postConversationPlanActionRoute = HttpRouter.add("POST", "/api/conversations/:name/plan-action", Effect.gen(function* () {
52598
52461
  const originCheck = validateOrigin$1(yield* HttpServerRequest.HttpServerRequest);
52599
52462
  if (!originCheck.ok) return jsonResponse({ error: originCheck.error }, { status: 403 });
52600
52463
  const name = (yield* HttpRouter.params)["name"] ?? "";
52601
- const body = yield* readJsonBody$9;
52464
+ const body = yield* readJsonBody$10;
52602
52465
  return yield* Effect.promise(() => handleConversationPlanAction(name, body));
52603
52466
  }));
52604
52467
  const conversationDiffDependencies = {
@@ -52653,7 +52516,7 @@ const getConversationAboutRoute = HttpRouter.add("GET", "/api/conversations/:nam
52653
52516
  return conversationReadJson(await getConversationAbout(name, new URL(request.url, "http://localhost").searchParams.get("refresh") === "1", conversationReadDependencies));
52654
52517
  });
52655
52518
  }));
52656
- const conversationsRouteLayer = Layer.mergeAll(getConversationsRoute, getConversationsPendingInputRoute, getArchivedConversationsRoute, getConversationRoute, getConversationHandoffDocRoute, postConversationRoute, patchConversationRoute, patchConversationMoveRoute, deleteConversationRoute, postConversationStopRoute, postConversationResumeRoute, postConversationSwitchModelRoute, postConversationThinkingLevelRoute, postConversationCompactRoute, postConversationAbortRoute, postConversationRestartAllRoute, postConversationArchiveRoute, postConversationUnarchiveRoute, getConversationMessagesRoute, getConversationMessageLocatorRoute, postConversationUploadImageRoute, postConversationDeleteImageRoute, postConversationMessageRoute, postConversationCodexApprovalRoute, postConversationPaneChoiceRoute, postConversationDeliveryMethodRoute, postConversationControlAckRoute, postConversationFavoriteRoute, deleteConversationFavoriteRoute, postConversationSummaryForkRoute, postConversationPlanActionRoute, getConversationDiffsRoute, getConversationDiffFullRoute, getConversationDiffTurnRoute, postConversationRetitleRoute, getConversationAboutRoute);
52519
+ const conversationsRouteLayer = Layer.mergeAll(getConversationsRoute, getConversationsPendingInputRoute, getArchivedConversationsRoute, getConversationRoute, getConversationHandoffDocRoute, postConversationRoute, patchConversationRoute, patchConversationMoveRoute, deleteConversationRoute, postConversationStopRoute, postConversationClearForkStateRoute, postConversationResumeRoute, postConversationSwitchModelRoute, postConversationThinkingLevelRoute, postConversationCompactRoute, postConversationAbortRoute, postConversationRestartAllRoute, postConversationArchiveRoute, postConversationUnarchiveRoute, getConversationMessagesRoute, getConversationMessageLocatorRoute, postConversationUploadImageRoute, postConversationDeleteImageRoute, postConversationMessageRoute, postConversationCodexApprovalRoute, postConversationPaneChoiceRoute, postConversationDeliveryMethodRoute, postConversationControlAckRoute, postConversationFavoriteRoute, deleteConversationFavoriteRoute, postConversationSummaryForkRoute, postConversationPlanActionRoute, getConversationDiffsRoute, getConversationDiffFullRoute, getConversationDiffTurnRoute, postConversationRetitleRoute, getConversationAboutRoute);
52657
52520
  //#endregion
52658
52521
  //#region routes/show.ts
52659
52522
  /**
@@ -52700,7 +52563,7 @@ const showRouteLayer = Layer.mergeAll(getShowRoute, getShowShadowRoute, getShowH
52700
52563
  //#endregion
52701
52564
  //#region routes/project-rename.ts
52702
52565
  init_projects();
52703
- const readJsonBody$8 = Effect.gen(function* () {
52566
+ const readJsonBody$9 = Effect.gen(function* () {
52704
52567
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
52705
52568
  try {
52706
52569
  return text ? JSON.parse(text) : {};
@@ -52712,7 +52575,7 @@ const postProjectRenameRoute = HttpRouter.add("POST", "/api/projects/:projectKey
52712
52575
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
52713
52576
  if (authError) return authError;
52714
52577
  const projectIdentifier = (yield* HttpRouter.params)["projectKey"] ?? "";
52715
- const body = yield* readJsonBody$8;
52578
+ const body = yield* readJsonBody$9;
52716
52579
  if (typeof body.name !== "string") return jsonResponse({ error: "Project name must be a string" }, { status: 400 });
52717
52580
  const result = yield* Effect.result(renameProject(projectIdentifier, body.name));
52718
52581
  if (Result$1.isFailure(result)) {
@@ -52860,7 +52723,7 @@ async function registerProjectFromPath(opts) {
52860
52723
  registerProjectSync(key, projectConfig);
52861
52724
  const seededContextLayer = ensureProjectLayer(fullPath);
52862
52725
  try {
52863
- const { preTrustDirectorySync } = await import("./workspace-manager-5BKPV6SY.js");
52726
+ const { preTrustDirectorySync } = await import("./workspace-manager-jfkKAEuO.js");
52864
52727
  preTrustDirectorySync(fullPath);
52865
52728
  } catch {}
52866
52729
  let hooksInstalled = 0;
@@ -52880,6 +52743,7 @@ init_render();
52880
52743
  init_assemble();
52881
52744
  init_agents$1();
52882
52745
  init_projects();
52746
+ init_jsonl_resolver();
52883
52747
  function awaitingInputFromProjection(agentId, agentSnapshotsById) {
52884
52748
  const agent = agentSnapshotsById?.get(agentId);
52885
52749
  if (!agent) return void 0;
@@ -52998,7 +52862,6 @@ async function buildSpecialistSessionNodes(options) {
52998
52862
  }
52999
52863
  //#endregion
53000
52864
  //#region ../../lib/overdeck/specs.ts
53001
- init_specs();
53002
52865
  const findSpecByIssueThroughOverdeck = findSpecByIssue;
53003
52866
  //#endregion
53004
52867
  //#region routes/projects.ts
@@ -53015,6 +52878,7 @@ init_concurrency$1();
53015
52878
  init_src();
53016
52879
  init_agents$1();
53017
52880
  init_agent_input_detection();
52881
+ init_jsonl_resolver();
53018
52882
  init_pan_dir();
53019
52883
  init_io();
53020
52884
  init_specs();
@@ -53022,7 +52886,7 @@ init_paths();
53022
52886
  init_resource_utils();
53023
52887
  const execAsync$3 = promisify(exec);
53024
52888
  async function getIssueDataService() {
53025
- const { getSharedIssueService } = await import("./issue-service-singleton-CL6hESX2.js");
52889
+ const { getSharedIssueService } = await import("./issue-service-singleton-CvgNAWqK.js");
53026
52890
  return getSharedIssueService();
53027
52891
  }
53028
52892
  /** Returns true if the path exists (any type). */
@@ -53424,7 +53288,7 @@ const getProjectReleaseStatusRoute = HttpRouter.add("GET", "/api/projects/:proje
53424
53288
  const projectKey = (yield* HttpRouter.params)["projectKey"] ?? "";
53425
53289
  return jsonResponse(yield* Effect.tryPromise({
53426
53290
  try: async () => {
53427
- const { fetchProjectReleaseStatus } = await import("./project-pipelines-CCkebHOu.js");
53291
+ const { fetchProjectReleaseStatus } = await import("./project-pipelines-By_5WcT4.js");
53428
53292
  return fetchProjectReleaseStatus(projectKey);
53429
53293
  },
53430
53294
  catch: (err) => new Error(err instanceof Error ? err.message : String(err))
@@ -53735,7 +53599,7 @@ init_projects();
53735
53599
  const getProjectMergeTrainRoute = HttpRouter.add("GET", "/api/projects/:projectKey/merge-train", httpHandler(Effect.gen(function* () {
53736
53600
  const config = getProjectSync((yield* HttpRouter.params)["projectKey"] ?? "");
53737
53601
  if (!config) return jsonResponse({ error: "Project not found" }, { status: 404 });
53738
- const { isMergeTrainEnabledForProject } = yield* Effect.promise(() => import("./merge-sync-CM2-myXu.js"));
53602
+ const { isMergeTrainEnabledForProject } = yield* Effect.promise(() => import("./merge-sync-0m2Q087q.js"));
53739
53603
  return jsonResponse({
53740
53604
  value: config.merge_train ?? null,
53741
53605
  effective: isMergeTrainEnabledForProject(config)
@@ -53749,7 +53613,7 @@ const postProjectMergeTrainRoute = HttpRouter.add("POST", "/api/projects/:projec
53749
53613
  if (!project) return jsonResponse({ error: "Project not found" }, { status: 404 });
53750
53614
  const v = (yield* readProjectJsonBody).value;
53751
53615
  if (v !== "enabled" && v !== "disabled" && v !== null) return jsonResponse({ error: "value must be 'enabled', 'disabled', or null" }, { status: 400 });
53752
- const { isMergeTrainEnabledForProject } = yield* Effect.promise(() => import("./merge-sync-CM2-myXu.js"));
53616
+ const { isMergeTrainEnabledForProject } = yield* Effect.promise(() => import("./merge-sync-0m2Q087q.js"));
53753
53617
  yield* Effect.promise(() => setProjectMergeTrain(key, v));
53754
53618
  const updated = { ...project };
53755
53619
  if (v === null) delete updated.merge_train;
@@ -53827,7 +53691,7 @@ async function queueEntryForProject(key, config, enabled) {
53827
53691
  * not blank the whole response, so a failed project reports an empty queue.
53828
53692
  */
53829
53693
  async function getMergeTrainQueuesPayload() {
53830
- const { isMergeTrainEnabledForProject } = await import("./merge-sync-CM2-myXu.js");
53694
+ const { isMergeTrainEnabledForProject } = await import("./merge-sync-0m2Q087q.js");
53831
53695
  const projects = listProjectsSync();
53832
53696
  return (await Promise.allSettled(projects.map(({ key, config }) => queueEntryForProject(key, config, isMergeTrainEnabledForProject(config))))).flatMap((outcome, i) => {
53833
53697
  if (outcome.status === "fulfilled") return [outcome.value];
@@ -53845,8 +53709,8 @@ async function getMergeTrainQueuesPayload() {
53845
53709
  }
53846
53710
  /** PAN-1696 AC2: per-project generation chains across every tracked project. */
53847
53711
  async function getMergeTrainGenerationsPayload() {
53848
- const { isMergeTrainEnabledForProject } = await import("./merge-sync-CM2-myXu.js");
53849
- const { getUatGenerationsPayload } = await import("./uat-train-COSy-vEX.js");
53712
+ const { isMergeTrainEnabledForProject } = await import("./merge-sync-0m2Q087q.js");
53713
+ const { getUatGenerationsPayload } = await import("./uat-train-CycEzpbE.js");
53850
53714
  return (await Promise.allSettled(listProjectsSync().map(async ({ key, config }) => ({
53851
53715
  projectKey: key,
53852
53716
  projectName: config.name,
@@ -53860,7 +53724,7 @@ async function defaultOrderedIssueIdsForProject(projectPath) {
53860
53724
  return (await Effect.runPromise(computeMergeQueueFromCandidates(candidates, projectPath).pipe(Effect.provide(layer)))).map((item) => item.issueId);
53861
53725
  }
53862
53726
  async function defaultMergeOne(issueId) {
53863
- const { triggerMerge } = await import("./merge-ops-DtHx17Vd.js");
53727
+ const { triggerMerge } = await import("./merge-ops-DabXHp2i.js");
53864
53728
  const r = await triggerMerge(issueId);
53865
53729
  return r.success ? { ok: true } : {
53866
53730
  ok: false,
@@ -53888,13 +53752,13 @@ async function postMergeTrainMergeNextPayload(payload, deps = {}) {
53888
53752
  status: 404,
53889
53753
  body: { error: `Unknown project key: ${projectKey}` }
53890
53754
  };
53891
- const { isMergeTrainEnabledForProject } = await import("./merge-sync-CM2-myXu.js");
53755
+ const { isMergeTrainEnabledForProject } = await import("./merge-sync-0m2Q087q.js");
53892
53756
  if (!isMergeTrainEnabledForProject(config)) return {
53893
53757
  status: 409,
53894
53758
  body: { error: `merge-train is disabled for project ${projectKey}` }
53895
53759
  };
53896
53760
  const issueIds = (await (deps.getOrderedIssueIds ?? defaultOrderedIssueIdsForProject)(resolve(config.path))).slice(0, n);
53897
- const { shipMergeBatch } = await import("./merge-batch-CFMEtTxv.js");
53761
+ const { shipMergeBatch } = await import("./merge-batch-B8bVjFWS.js");
53898
53762
  return {
53899
53763
  status: 200,
53900
53764
  body: {
@@ -53924,7 +53788,7 @@ async function postMergeTrainAssemblePayload(payload) {
53924
53788
  status: 404,
53925
53789
  body: { error: `Unknown project key: ${projectKey}` }
53926
53790
  };
53927
- const { runUatTrainReconcile } = await import("./uat-train-COSy-vEX.js");
53791
+ const { runUatTrainReconcile } = await import("./uat-train-CycEzpbE.js");
53928
53792
  return {
53929
53793
  status: 200,
53930
53794
  body: { projects: [{
@@ -53936,7 +53800,7 @@ async function postMergeTrainAssemblePayload(payload) {
53936
53800
  }] }
53937
53801
  };
53938
53802
  }
53939
- const { runUatTrainReconcileAllProjects } = await import("./uat-train-COSy-vEX.js");
53803
+ const { runUatTrainReconcileAllProjects } = await import("./uat-train-CycEzpbE.js");
53940
53804
  return {
53941
53805
  status: 200,
53942
53806
  body: { projects: await runUatTrainReconcileAllProjects({ force: true }) }
@@ -53952,13 +53816,13 @@ function uatGenerationNameFromParam(param) {
53952
53816
  return decoded.startsWith("uat/") ? decoded : `uat/${decoded}`;
53953
53817
  }
53954
53818
  async function postMergeTrainGenerationShipPayload(name, version) {
53955
- const { getUatGenerationSync } = await import("./merge-sync-CM2-myXu.js");
53819
+ const { getUatGenerationSync } = await import("./merge-sync-0m2Q087q.js");
53956
53820
  const generation = getUatGenerationSync(name);
53957
53821
  if (!generation) return {
53958
53822
  status: 404,
53959
53823
  body: { error: `No UAT generation named ${name}` }
53960
53824
  };
53961
- const { shipPromotedBatch, ShipPromotedBatchError } = await import("./ship-record-BgUPnpT0.js");
53825
+ const { shipPromotedBatch, ShipPromotedBatchError } = await import("./ship-record-DHWH1hLz.js");
53962
53826
  try {
53963
53827
  return {
53964
53828
  status: 200,
@@ -53986,7 +53850,7 @@ const postMergeTrainGenerationStackRoute = HttpRouter.add("POST", "/api/merge-tr
53986
53850
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
53987
53851
  if (authError) return authError;
53988
53852
  const name = uatGenerationNameFromParam((yield* HttpRouter.params)["name"] ?? "");
53989
- const { postUatGenerationStackPayload } = yield* Effect.promise(() => import("./uat-train-COSy-vEX.js"));
53853
+ const { postUatGenerationStackPayload } = yield* Effect.promise(() => import("./uat-train-CycEzpbE.js"));
53990
53854
  const result = yield* Effect.promise(() => postUatGenerationStackPayload(name));
53991
53855
  if (!result.ok) return jsonResponse({ error: result.error }, { status: result.status });
53992
53856
  return jsonResponse({
@@ -54003,8 +53867,8 @@ const postMergeTrainGenerationPromoteRoute = HttpRouter.add("POST", "/api/merge-
54003
53867
  const rawShipVersion = parsed.body["shipVersion"];
54004
53868
  if (rawShipVersion !== void 0 && (typeof rawShipVersion !== "string" || !/^\d+\.\d+\.\d+$/.test(rawShipVersion))) return jsonResponse({ error: "shipVersion must look like 48.8.0" }, { status: 400 });
54005
53869
  const name = uatGenerationNameFromParam((yield* HttpRouter.params)["name"] ?? "");
54006
- const { postUatGenerationPromotePayload } = yield* Effect.promise(() => import("./uat-train-COSy-vEX.js"));
54007
- const { firePostMergeLifecycle } = yield* Effect.promise(() => import("./specialists-xXcJHAyg.js"));
53870
+ const { postUatGenerationPromotePayload } = yield* Effect.promise(() => import("./uat-train-CycEzpbE.js"));
53871
+ const { firePostMergeLifecycle } = yield* Effect.promise(() => import("./specialists-B-4zyE4Y.js"));
54008
53872
  const result = yield* Effect.promise(() => postUatGenerationPromotePayload(name, firePostMergeLifecycle, rawShipVersion));
54009
53873
  if (!result.success) return jsonResponse(result, { status: result.reason === "not-found" ? 404 : result.reason === "merge-failed" ? 500 : 409 });
54010
53874
  return jsonResponse(result);
@@ -54276,8 +54140,9 @@ function parseRule(raw) {
54276
54140
  }
54277
54141
  async function renderBundledRulesAsync(harness) {
54278
54142
  const includeDev = isDevMode();
54143
+ const disabled = configDisabledRuleNames();
54279
54144
  const entries = await readdir(SYNC_SOURCES.rules, { withFileTypes: true }).catch(() => []);
54280
- const rendered = (await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".md")).sort((a, b) => a.name.localeCompare(b.name)).map(async (entry) => {
54145
+ const rendered = (await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".md")).filter((entry) => !disabled.has(entry.name.replace(/\.md$/, ""))).sort((a, b) => a.name.localeCompare(b.name)).map(async (entry) => {
54281
54146
  const file = join(SYNC_SOURCES.rules, entry.name);
54282
54147
  assertPathInside(SYNC_SOURCES.rules, file);
54283
54148
  const rule = parseRule(await readFile(file, "utf-8"));
@@ -54443,7 +54308,7 @@ function issueIdFromWorkspacePath(workspacePath) {
54443
54308
  const match = /(?:^|[^a-z0-9])([a-z]+-\d+)(?:[^a-z0-9]|$)/i.exec(workspacePath);
54444
54309
  return match ? match[1].toUpperCase() : null;
54445
54310
  }
54446
- function readJsonBody$7() {
54311
+ function readJsonBody$8() {
54447
54312
  return Effect.gen(function* () {
54448
54313
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
54449
54314
  return text ? JSON.parse(text) : {};
@@ -54457,7 +54322,7 @@ const getContextLayersRoute = HttpRouter.add("GET", "/api/context/layers", httpH
54457
54322
  return jsonResponse(yield* Effect.promise(() => loadContextLayers(projects)));
54458
54323
  })));
54459
54324
  const postContextPreviewRoute = HttpRouter.add("POST", "/api/context/preview", httpHandler(Effect.gen(function* () {
54460
- const body = yield* readJsonBody$7();
54325
+ const body = yield* readJsonBody$8();
54461
54326
  const parsed = yield* Effect.try({
54462
54327
  try: () => decodePreviewRequest(body),
54463
54328
  catch: (error) => new Error(error instanceof Error ? error.message : String(error))
@@ -54466,7 +54331,7 @@ const postContextPreviewRoute = HttpRouter.add("POST", "/api/context/preview", h
54466
54331
  return jsonResponse(yield* Effect.promise(() => previewContextLayers(projects, parsed)));
54467
54332
  })));
54468
54333
  const putContextLayerRoute = HttpRouter.add("PUT", "/api/context/layers", httpHandler(Effect.gen(function* () {
54469
- const body = yield* readJsonBody$7();
54334
+ const body = yield* readJsonBody$8();
54470
54335
  const parsed = yield* Effect.try({
54471
54336
  try: () => decodeSaveRequest(body),
54472
54337
  catch: (error) => new Error(error instanceof Error ? error.message : String(error))
@@ -54833,7 +54698,7 @@ async function installOx() {
54833
54698
  * GET /api/prereqs/:feature — check which tools are missing for a feature
54834
54699
  * POST /api/prereqs/install — install a specific tool by name
54835
54700
  */
54836
- const readJsonBody$6 = Effect.gen(function* () {
54701
+ const readJsonBody$7 = Effect.gen(function* () {
54837
54702
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
54838
54703
  try {
54839
54704
  return text ? JSON.parse(text) : {};
@@ -54870,7 +54735,7 @@ const checkFeatureRoute = HttpRouter.add("GET", "/api/prereqs/:feature", httpHan
54870
54735
  });
54871
54736
  })));
54872
54737
  const installToolRoute = HttpRouter.add("POST", "/api/prereqs/install", httpHandler(Effect.gen(function* () {
54873
- const tool = (yield* readJsonBody$6).tool;
54738
+ const tool = (yield* readJsonBody$7).tool;
54874
54739
  if (!tool) return jsonResponse({ error: "Missing 'tool' in request body" }, { status: 400 });
54875
54740
  if (!INSTALLABLE_TOOLS.some((t) => t === tool)) return jsonResponse({ error: `Tool '${tool}' is not auto-installable` }, { status: 400 });
54876
54741
  const result = yield* Effect.promise(() => installTool(tool));
@@ -55678,7 +55543,7 @@ function getCheckpointWorker() {
55678
55543
  return worker;
55679
55544
  }
55680
55545
  async function runInline(operation, payload) {
55681
- const { claimTranscriptRange, commitTranscriptRange, releaseTranscriptRange, getTranscriptCheckpoint, listTranscriptCheckpoints } = await import("./checkpoints-DRALkfDS.js");
55546
+ const { claimTranscriptRange, commitTranscriptRange, releaseTranscriptRange, getTranscriptCheckpoint, listTranscriptCheckpoints } = await import("./checkpoints-Cb6CWT4S.js");
55682
55547
  switch (operation) {
55683
55548
  case "claimTranscriptRange": return claimTranscriptRange(payload);
55684
55549
  case "commitTranscriptRange": return commitTranscriptRange(payload);
@@ -56840,7 +56705,7 @@ function buildPendingTurn(input, fromOffset, toOffset, compressed) {
56840
56705
  };
56841
56706
  }
56842
56707
  async function emitMemoryObservationCreated(observation, timestamp) {
56843
- const { initEventStore } = await import("./event-store-BgEjNsvk.js");
56708
+ const { initEventStore } = await import("./event-store-Db4w4YIY.js");
56844
56709
  await (await initEventStore()).appendAsync({
56845
56710
  type: "memory.observation_created",
56846
56711
  timestamp,
@@ -58585,8 +58450,9 @@ const diffsRouteLayer = Layer.mergeAll(getDiffsRoute, getTurnDiffRoute, getFullD
58585
58450
  //#endregion
58586
58451
  //#region routes/linear-mcp-auth.ts
58587
58452
  init_issue_service_singleton();
58453
+ init_conversations();
58588
58454
  const LINEAR_MCP_AUTH_CALLBACK_COPY_PREFIX = "The operator completed the Linear OAuth authorization in their browser. Finish the flow now: call mcp__linear__complete_authentication with callback_url set to exactly this URL:";
58589
- const readJsonBody$5 = Effect.gen(function* () {
58455
+ const readJsonBody$6 = Effect.gen(function* () {
58590
58456
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
58591
58457
  return text ? JSON.parse(text) : {};
58592
58458
  });
@@ -58631,13 +58497,42 @@ function withIssueUrls(intervention) {
58631
58497
  }))
58632
58498
  };
58633
58499
  }
58500
+ /**
58501
+ * Attach each blocked conversation's canonical dashboard URL — /conv/<rowid>,
58502
+ * the DB row id, which is how conversations are displayed everywhere else in
58503
+ * the dashboard. Resolved through the conversations read door by name.
58504
+ * Best-effort: an unresolvable conversation falls back to null and the banner
58505
+ * renders the id as plain text.
58506
+ */
58507
+ function withConversationUrls(intervention) {
58508
+ return {
58509
+ ...intervention,
58510
+ blockedAgents: intervention.blockedAgents.map((agent) => {
58511
+ if (!agent.agentId.startsWith("conv-")) return {
58512
+ ...agent,
58513
+ conversationUrl: null
58514
+ };
58515
+ let conversationUrl = null;
58516
+ try {
58517
+ const conversation = getConversationByName(agent.agentId);
58518
+ conversationUrl = conversation === null ? null : `/conv/${conversation.id}`;
58519
+ } catch {
58520
+ conversationUrl = null;
58521
+ }
58522
+ return {
58523
+ ...agent,
58524
+ conversationUrl
58525
+ };
58526
+ })
58527
+ };
58528
+ }
58634
58529
  const getLinearMcpAuthRoute = HttpRouter.add("GET", "/api/linear-mcp-auth", httpHandler(Effect.gen(function* () {
58635
- return jsonResponse(withIssueUrls(yield* Effect.promise(() => resolveLinearMcpAuthIntervention())));
58530
+ return jsonResponse(withConversationUrls(withIssueUrls(yield* Effect.promise(() => resolveLinearMcpAuthIntervention()))));
58636
58531
  })));
58637
58532
  const postLinearMcpAuthCallbackRoute = HttpRouter.add("POST", "/api/linear-mcp-auth/callback", httpHandler(Effect.gen(function* () {
58638
58533
  const originError = rejectInvalidOrigin(yield* HttpServerRequest.HttpServerRequest);
58639
58534
  if (originError) return originError;
58640
- const body = yield* readJsonBody$5;
58535
+ const body = yield* readJsonBody$6;
58641
58536
  const callbackUrl = typeof body["callbackUrl"] === "string" ? body["callbackUrl"] : "";
58642
58537
  if (!isValidLinearMcpCallbackUrl(callbackUrl)) return jsonResponse({
58643
58538
  success: false,
@@ -58685,7 +58580,7 @@ const linearMcpAuthRouteLayer = Layer.mergeAll(getLinearMcpAuthRoute, postLinear
58685
58580
  * folded into that RPC surface.
58686
58581
  */
58687
58582
  init_tmux();
58688
- const readJsonBody$4 = Effect.gen(function* () {
58583
+ const readJsonBody$5 = Effect.gen(function* () {
58689
58584
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
58690
58585
  return text ? JSON.parse(text) : {};
58691
58586
  });
@@ -58709,7 +58604,7 @@ function generateTerminalSessionName() {
58709
58604
  const postTerminalRoute = HttpRouter.add("POST", "/api/terminals", httpHandler(Effect.gen(function* () {
58710
58605
  const authError = rejectUnauthorized(yield* HttpServerRequest.HttpServerRequest);
58711
58606
  if (authError) return authError;
58712
- const cwd = resolveCwd((yield* readJsonBody$4).cwd);
58607
+ const cwd = resolveCwd((yield* readJsonBody$5).cwd);
58713
58608
  const sessionName = generateTerminalSessionName();
58714
58609
  yield* createSession(sessionName, cwd, void 0, { env: { PATH: process.env.PATH || "" } });
58715
58610
  return jsonResponse({
@@ -59608,12 +59503,12 @@ async function pauseFlywheelRunForDashboard() {
59608
59503
  if (before.activeRunId) try {
59609
59504
  const { readFile } = await import("node:fs/promises");
59610
59505
  const { join } = await import("node:path");
59611
- const { getAgentDir } = await import("./agents-megfmQHM.js");
59506
+ const { getAgentDir } = await import("./agents-DpCuoF65.js");
59612
59507
  const sessionId = (await readFile(join(getAgentDir(FLYWHEEL_ORCHESTRATOR_AGENT_ID), "session.id"), "utf-8")).trim();
59613
59508
  if (sessionId) await saveResumeSessionId(before.activeRunId, sessionId);
59614
59509
  } catch {}
59615
59510
  await setPaused(true);
59616
- await import("./agents-megfmQHM.js").then(({ stopAgent }) => Effect.runPromise(stopAgent(FLYWHEEL_ORCHESTRATOR_AGENT_ID, "operator")));
59511
+ await import("./agents-DpCuoF65.js").then(({ stopAgent }) => Effect.runPromise(stopAgent(FLYWHEEL_ORCHESTRATOR_AGENT_ID, "operator")));
59617
59512
  return {
59618
59513
  before,
59619
59514
  after: await readGateSnapshot(),
@@ -59623,7 +59518,7 @@ async function pauseFlywheelRunForDashboard() {
59623
59518
  async function abortFlywheelRunForDashboard() {
59624
59519
  const candidate = await getActiveRunId();
59625
59520
  if (!candidate) return { aborted: await resolveLiveFlywheelRunId() ?? null };
59626
- const { stopAgent } = await import("./agents-megfmQHM.js");
59521
+ const { stopAgent } = await import("./agents-DpCuoF65.js");
59627
59522
  await Effect.runPromise(stopAgent(FLYWHEEL_ORCHESTRATOR_AGENT_ID, "operator"));
59628
59523
  await abortFlywheelRun(candidate);
59629
59524
  return { aborted: candidate };
@@ -60076,7 +59971,7 @@ async function assertWritePathInsideRoot(projectRoot, candidate) {
60076
59971
  }
60077
59972
  return { ok: true };
60078
59973
  }
60079
- const readJsonBody$3 = Effect.gen(function* () {
59974
+ const readJsonBody$4 = Effect.gen(function* () {
60080
59975
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
60081
59976
  try {
60082
59977
  return {
@@ -60302,7 +60197,7 @@ async function getFlywheelConversationPayload() {
60302
60197
  };
60303
60198
  }
60304
60199
  async function postFlywheelReportPayload() {
60305
- const { flywheelReportCommand } = await import("./flywheel-BwYPDlhK.js");
60200
+ const { flywheelReportCommand } = await import("./flywheel-v1cCOBx-.js");
60306
60201
  await flywheelReportCommand({ cwd: process.cwd() });
60307
60202
  return {
60308
60203
  status: 200,
@@ -60577,7 +60472,7 @@ const getFlywheelBriefRoute = HttpRouter.add("GET", "/api/flywheel/brief", httpH
60577
60472
  const postFlywheelBriefRoute = HttpRouter.add("POST", "/api/flywheel/brief", httpHandler(Effect.gen(function* () {
60578
60473
  const authError = rejectUnauthorizedDashboardRequest(yield* HttpServerRequest.HttpServerRequest);
60579
60474
  if (authError) return authError;
60580
- const parsed = yield* readJsonBody$3;
60475
+ const parsed = yield* readJsonBody$4;
60581
60476
  if (!parsed.ok) return jsonResponse({ error: parsed.error }, { status: 400 });
60582
60477
  const body = parsed.body;
60583
60478
  if (typeof body.content !== "string") return jsonResponse({ error: "content must be a string" }, { status: 400 });
@@ -60597,7 +60492,7 @@ const postFlywheelBriefRoute = HttpRouter.add("POST", "/api/flywheel/brief", htt
60597
60492
  });
60598
60493
  })));
60599
60494
  const getUatCandidateRoute = HttpRouter.add("GET", "/api/flywheel/uat-candidate", httpHandler(Effect.gen(function* () {
60600
- const { getUatCandidatePayload } = yield* Effect.promise(() => import("./uat-train-COSy-vEX.js"));
60495
+ const { getUatCandidatePayload } = yield* Effect.promise(() => import("./uat-train-CycEzpbE.js"));
60601
60496
  return jsonResponse(yield* Effect.promise(() => getUatCandidatePayload()));
60602
60497
  })));
60603
60498
  const getFlywheelStateRoute = HttpRouter.add("GET", "/api/flywheel/state", httpHandler(Effect.gen(function* () {
@@ -60808,7 +60703,7 @@ function previewBrief(book) {
60808
60703
  return `${lines.join("\n")}\n`;
60809
60704
  }
60810
60705
  async function defaultStartOrderBook(book, project) {
60811
- const { startFlywheelRun } = await import("./flywheel-BwYPDlhK.js");
60706
+ const { startFlywheelRun } = await import("./flywheel-v1cCOBx-.js");
60812
60707
  return startFlywheelRun({
60813
60708
  cwd: resolveProjectPath(project),
60814
60709
  orders: book.id
@@ -60895,8 +60790,9 @@ async function deleteOrderItemPayload(bookId, issueId, deps = {}, projectKey) {
60895
60790
  async function patchOrderItemPayload(bookId, issueId, body, deps = {}, projectKey) {
60896
60791
  return routeResult(async () => {
60897
60792
  const { stateRoot } = resolveOrdersStateRoot(deps, projectKey);
60898
- const existing = requireBook(stateRoot, bookId).items.find((item) => item.issue.toUpperCase() === issueId.toUpperCase());
60899
- if (!existing) throw new Error(`Issue ${issueId.toUpperCase()} is not in order book ${bookId}`);
60793
+ const canonicalIssue = normalizeOrderIssueId(stateRoot, issueId).toUpperCase();
60794
+ const existing = requireBook(stateRoot, bookId).items.find((item) => item.issue.toUpperCase() === canonicalIssue);
60795
+ if (!existing) throw new Error(`Issue ${canonicalIssue} is not in order book ${bookId}`);
60900
60796
  let changed = false;
60901
60797
  if (body["lane"] !== void 0 || body["order"] !== void 0) {
60902
60798
  await moveItem(stateRoot, bookId, issueId, lane(body["lane"], existing.lane), positiveInteger(body["order"], "order", existing.order));
@@ -60962,7 +60858,7 @@ async function getPreviewBriefPayload(bookId, deps = {}, projectKey) {
60962
60858
  };
60963
60859
  });
60964
60860
  }
60965
- const readJsonBody$2 = Effect.gen(function* () {
60861
+ const readJsonBody$3 = Effect.gen(function* () {
60966
60862
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
60967
60863
  if (!text) return {
60968
60864
  ok: true,
@@ -61009,7 +60905,7 @@ function makeOrdersRouteLayer(deps = {}) {
61009
60905
  const request = yield* HttpServerRequest.HttpServerRequest;
61010
60906
  const authError = mutationAuth(request);
61011
60907
  if (authError) return authError;
61012
- const parsed = yield* readJsonBody$2;
60908
+ const parsed = yield* readJsonBody$3;
61013
60909
  if (!parsed.ok) return jsonResponse({ error: "Request body must be a JSON object" }, { status: 400 });
61014
60910
  return resultResponse(yield* Effect.promise(() => postOrderPayload(parsed.body, deps, projectParam(request))));
61015
60911
  })));
@@ -61022,7 +60918,7 @@ function makeOrdersRouteLayer(deps = {}) {
61022
60918
  const request = yield* HttpServerRequest.HttpServerRequest;
61023
60919
  const authError = mutationAuth(request);
61024
60920
  if (authError) return authError;
61025
- const parsed = yield* readJsonBody$2;
60921
+ const parsed = yield* readJsonBody$3;
61026
60922
  if (!parsed.ok) return jsonResponse({ error: "Request body must be a JSON object" }, { status: 400 });
61027
60923
  const id = (yield* HttpRouter.params)["id"] ?? "";
61028
60924
  return resultResponse(yield* Effect.promise(() => patchOrderPayload(id, parsed.body, deps, projectParam(request))));
@@ -61031,7 +60927,7 @@ function makeOrdersRouteLayer(deps = {}) {
61031
60927
  const request = yield* HttpServerRequest.HttpServerRequest;
61032
60928
  const authError = mutationAuth(request);
61033
60929
  if (authError) return authError;
61034
- const parsed = yield* readJsonBody$2;
60930
+ const parsed = yield* readJsonBody$3;
61035
60931
  if (!parsed.ok) return jsonResponse({ error: "Request body must be a JSON object" }, { status: 400 });
61036
60932
  const id = (yield* HttpRouter.params)["id"] ?? "";
61037
60933
  return resultResponse(yield* Effect.promise(() => postOrderItemsPayload(id, parsed.body, deps, projectParam(request))));
@@ -61047,7 +60943,7 @@ function makeOrdersRouteLayer(deps = {}) {
61047
60943
  const request = yield* HttpServerRequest.HttpServerRequest;
61048
60944
  const authError = mutationAuth(request);
61049
60945
  if (authError) return authError;
61050
- const parsed = yield* readJsonBody$2;
60946
+ const parsed = yield* readJsonBody$3;
61051
60947
  if (!parsed.ok) return jsonResponse({ error: "Request body must be a JSON object" }, { status: 400 });
61052
60948
  const params = yield* HttpRouter.params;
61053
60949
  return resultResponse(yield* Effect.promise(() => patchOrderItemPayload(params["id"] ?? "", params["issue"] ?? "", parsed.body, deps, projectParam(request))));
@@ -63348,7 +63244,8 @@ function getBacklogSequence(projectKey) {
63348
63244
  //#region routes/backlog.ts
63349
63245
  init_review_status();
63350
63246
  init_control_settings();
63351
- const readJsonBody$1 = Effect.gen(function* () {
63247
+ init_jsonl_resolver();
63248
+ const readJsonBody$2 = Effect.gen(function* () {
63352
63249
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
63353
63250
  try {
63354
63251
  return text ? JSON.parse(text) : {};
@@ -63424,7 +63321,7 @@ const getBacklogSequenceRoute = HttpRouter.add("GET", "/api/backlog/sequence", h
63424
63321
  const postBacklogRegenerateRoute = HttpRouter.add("POST", "/api/backlog/sequence/regenerate", httpHandler(Effect.gen(function* () {
63425
63322
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
63426
63323
  if (authError) return authError;
63427
- const body = yield* readJsonBody$1;
63324
+ const body = yield* readJsonBody$2;
63428
63325
  const projectRoot = process.cwd();
63429
63326
  const passRaw = body["pass"];
63430
63327
  const pass = typeof passRaw === "string" && new Set([
@@ -63459,7 +63356,7 @@ const postBacklogRegenerateRoute = HttpRouter.add("POST", "/api/backlog/sequence
63459
63356
  const postBacklogGateRoute = HttpRouter.add("POST", "/api/backlog/sequence/gate", httpHandler(Effect.gen(function* () {
63460
63357
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
63461
63358
  if (authError) return authError;
63462
- const body = yield* readJsonBody$1;
63359
+ const body = yield* readJsonBody$2;
63463
63360
  const issueId = String(body["issueId"] ?? "");
63464
63361
  const rawGate = String(body["gate"] ?? "");
63465
63362
  if (!issueId) return yield* Effect.fail(/* @__PURE__ */ new Error("issueId is required"));
@@ -63494,7 +63391,7 @@ const postBacklogGateRoute = HttpRouter.add("POST", "/api/backlog/sequence/gate"
63494
63391
  const postBacklogPlanningRoute = HttpRouter.add("POST", "/api/backlog/sequence/planning", httpHandler(Effect.gen(function* () {
63495
63392
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
63496
63393
  if (authError) return authError;
63497
- const body = yield* readJsonBody$1;
63394
+ const body = yield* readJsonBody$2;
63498
63395
  const issueId = String(body["issueId"] ?? "");
63499
63396
  const planning = String(body["planning"] ?? "");
63500
63397
  if (!issueId) return yield* Effect.fail(/* @__PURE__ */ new Error("issueId is required"));
@@ -63610,7 +63507,7 @@ const getBacklogForecastRoute = HttpRouter.add("GET", "/api/backlog/forecast", h
63610
63507
  const postBacklogLabelsRoute = HttpRouter.add("POST", "/api/backlog/sequence/labels", httpHandler(Effect.gen(function* () {
63611
63508
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
63612
63509
  if (authError) return authError;
63613
- const body = yield* readJsonBody$1;
63510
+ const body = yield* readJsonBody$2;
63614
63511
  const issueId = String(body["issueId"] ?? "");
63615
63512
  if (!issueId) return yield* Effect.fail(/* @__PURE__ */ new Error("issueId is required"));
63616
63513
  return yield* Effect.promise(async () => {
@@ -63899,7 +63796,7 @@ async function handleTieredCallout(rawBody, deps = {}) {
63899
63796
  }
63900
63797
  };
63901
63798
  }
63902
- const readJsonBody = Effect.gen(function* () {
63799
+ const readJsonBody$1 = Effect.gen(function* () {
63903
63800
  const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
63904
63801
  try {
63905
63802
  return text ? JSON.parse(text) : {};
@@ -63908,12 +63805,72 @@ const readJsonBody = Effect.gen(function* () {
63908
63805
  }
63909
63806
  });
63910
63807
  const postTieredCalloutsRoute = HttpRouter.add("POST", "/api/tiered/callouts", httpHandler(Effect.gen(function* () {
63911
- const body = yield* readJsonBody;
63808
+ const body = yield* readJsonBody$1;
63912
63809
  const result = yield* Effect.promise(() => handleTieredCallout(body));
63913
63810
  return jsonResponse(result.body, { status: result.status });
63914
63811
  })));
63915
63812
  const tieredCalloutsRouteLayer = Layer.mergeAll(postTieredCalloutsRoute);
63916
63813
  //#endregion
63814
+ //#region routes/restart-gate.ts
63815
+ /**
63816
+ * Restart-gate routes (PAN-3729) — the pinned wire contract for voluntary
63817
+ * dashboard restarts.
63818
+ *
63819
+ * POST /api/restart-gate/requests upsert + poll + TTL refresh (every 5s)
63820
+ * POST /api/restart-gate/claim take the exclusive right to restart
63821
+ * POST /api/restart-gate/approve operator approval (banner, `pan restart approve`)
63822
+ * GET /api/restart-gate read door for the current gate
63823
+ *
63824
+ * These handlers are deliberately thin: every state transition happens inside
63825
+ * `services/restart-gate.ts`, the one writer for gate state. Nothing here
63826
+ * touches the gate file.
63827
+ *
63828
+ * A requester that gets 404 from these paths is talking to a server built
63829
+ * before this feature and proceeds ungated — that compat rule is what lets the
63830
+ * gate itself be deployed through an ungated restart.
63831
+ */
63832
+ const VALID_KINDS = [
63833
+ "deploy",
63834
+ "reload",
63835
+ "restart"
63836
+ ];
63837
+ const readJsonBody = Effect.gen(function* () {
63838
+ const text = yield* (yield* HttpServerRequest.HttpServerRequest).text;
63839
+ try {
63840
+ return text ? JSON.parse(text) : {};
63841
+ } catch {
63842
+ return {};
63843
+ }
63844
+ });
63845
+ const postRequestRoute = HttpRouter.add("POST", "/api/restart-gate/requests", httpHandler(Effect.gen(function* () {
63846
+ const body = yield* readJsonBody;
63847
+ const requesterId = typeof body["requesterId"] === "string" ? body["requesterId"].trim() : "";
63848
+ const kind = body["kind"];
63849
+ const reason = typeof body["reason"] === "string" ? body["reason"] : "";
63850
+ const builtSha = typeof body["builtSha"] === "string" ? body["builtSha"] : void 0;
63851
+ if (!requesterId) return jsonResponse({ error: "requesterId is required" }, { status: 400 });
63852
+ if (typeof kind !== "string" || !VALID_KINDS.includes(kind)) return jsonResponse({ error: `kind must be one of: ${VALID_KINDS.join(", ")}` }, { status: 400 });
63853
+ return jsonResponse(yield* Effect.promise(() => getRestartGate().request({
63854
+ requesterId,
63855
+ kind,
63856
+ reason,
63857
+ ...builtSha === void 0 ? {} : { builtSha }
63858
+ })));
63859
+ })));
63860
+ const postClaimRoute = HttpRouter.add("POST", "/api/restart-gate/claim", httpHandler(Effect.gen(function* () {
63861
+ const body = yield* readJsonBody;
63862
+ const requesterId = typeof body["requesterId"] === "string" ? body["requesterId"].trim() : "";
63863
+ if (!requesterId) return jsonResponse({ error: "requesterId is required" }, { status: 400 });
63864
+ return jsonResponse(yield* Effect.promise(() => getRestartGate().claim(requesterId)));
63865
+ })));
63866
+ const postApproveRoute = HttpRouter.add("POST", "/api/restart-gate/approve", httpHandler(Effect.gen(function* () {
63867
+ return jsonResponse(yield* Effect.promise(() => getRestartGate().approve()));
63868
+ })));
63869
+ const getRestartGateRoute = HttpRouter.add("GET", "/api/restart-gate", httpHandler(Effect.gen(function* () {
63870
+ return jsonResponse(yield* Effect.promise(() => getRestartGate().read()));
63871
+ })));
63872
+ const restartGateRouteLayer = Layer.mergeAll(postRequestRoute, postClaimRoute, postApproveRoute, getRestartGateRoute);
63873
+ //#endregion
63917
63874
  //#region server-bind.ts
63918
63875
  function isAddressInUseError(error) {
63919
63876
  if (!error || typeof error !== "object") return false;
@@ -64049,7 +64006,7 @@ const staticRouteLayer = HttpRouter.add("GET", "*", Effect.gen(function* () {
64049
64006
  if (filePath.endsWith("index.html")) return HttpServerResponse.setHeader(res, "Cache-Control", "no-cache, no-store, must-revalidate");
64050
64007
  return res;
64051
64008
  }));
64052
- const makeRoutesLayer = Layer.mergeAll(healthRouteLayer, dashboardSessionPreflightRouteLayer, dashboardSessionRouteLayer, websocketRpcRouteLayer, issuesRouteLayer, pipelineMembershipRouteLayer, parkedRouteLayer, velocityRouteLayer, agentsRouteLayer, workspacesRouteLayer, workspaceRegistryRouteLayer, specialistsRouteLayer, costsRouteLayer, cloisterRouteLayer, resourcesRouteLayer, commandDeckRouteLayer, remoteRouteLayer, settingsRouteLayer, voiceRouteLayer, autopresoRouteLayer, metricsRouteLayer, miscRouteLayer, paletteRouteLayer, conversationsRouteLayer, eventsRouteLayer, showRouteLayer, projectsRouteLayer, projectsMergeTrainRouteLayer, mergeTrainRouteLayer, contextRouteLayer, commandsRouteLayer, adminRouteLayer, prereqsRouteLayer, cliproxyRouteLayer, ttsRouteLayer, webhooksRouteLayer, hooksRouteLayer, diffsRouteLayer, codexAuthRouteLayer, linearMcpAuthRouteLayer, terminalsRouteLayer, discoveredSessionsRouteLayer, flywheelRouteLayer, ordersRouteLayer, artifactsRouteLayer, featureRegistryRouteLayer, fsRouteLayer, tieredCalloutsRouteLayer, backlogRouteLayer, internalEventsRouteLayer, knowledgeViewerRouteLayer, staticRouteLayer);
64009
+ const makeRoutesLayer = Layer.mergeAll(healthRouteLayer, dashboardSessionPreflightRouteLayer, dashboardSessionRouteLayer, websocketRpcRouteLayer, issuesRouteLayer, pipelineMembershipRouteLayer, parkedRouteLayer, velocityRouteLayer, agentsRouteLayer, workspacesRouteLayer, workspaceRegistryRouteLayer, specialistsRouteLayer, costsRouteLayer, cloisterRouteLayer, resourcesRouteLayer, commandDeckRouteLayer, remoteRouteLayer, settingsRouteLayer, voiceRouteLayer, autopresoRouteLayer, metricsRouteLayer, miscRouteLayer, paletteRouteLayer, conversationsRouteLayer, eventsRouteLayer, showRouteLayer, projectsRouteLayer, projectsMergeTrainRouteLayer, mergeTrainRouteLayer, contextRouteLayer, commandsRouteLayer, adminRouteLayer, prereqsRouteLayer, cliproxyRouteLayer, ttsRouteLayer, webhooksRouteLayer, hooksRouteLayer, diffsRouteLayer, codexAuthRouteLayer, linearMcpAuthRouteLayer, terminalsRouteLayer, discoveredSessionsRouteLayer, flywheelRouteLayer, ordersRouteLayer, artifactsRouteLayer, featureRegistryRouteLayer, fsRouteLayer, tieredCalloutsRouteLayer, backlogRouteLayer, internalEventsRouteLayer, restartGateRouteLayer, knowledgeViewerRouteLayer, staticRouteLayer);
64053
64010
  const OverdeckAgentsResolverLive = AgentsResolverLive.pipe(Layer.provide(Layer.mergeAll(DbLive, TmuxLive)));
64054
64011
  const OverdeckCostResolverLive = CostResolverLive.pipe(Layer.provide(DbLive));
64055
64012
  const ReadModelWithOverdeckLive = ReadModelServiceLive.pipe(Layer.provide(OverdeckAgentsResolverLive));
@@ -64491,123 +64448,6 @@ function startReviewStatusReconcileService() {
64491
64448
  return true;
64492
64449
  }
64493
64450
  //#endregion
64494
- //#region services/project-resource-refresh-queue.ts
64495
- init_projects();
64496
- const PROJECT_RESOURCE_CONVERGENCE_INTERVAL_MS = 5 * 6e4;
64497
- function createProjectResourceRefreshQueue(deps) {
64498
- const debounceMs = deps.debounceMs ?? 1e3;
64499
- const now = deps.now ?? Date.now;
64500
- const pending = /* @__PURE__ */ new Map();
64501
- const reasons = /* @__PURE__ */ new Map();
64502
- const idleWaiters = /* @__PURE__ */ new Set();
64503
- let activeProjectPaths = [];
64504
- let timer = null;
64505
- let running = false;
64506
- let stopped = false;
64507
- let lastStartedAt = null;
64508
- let lastCompletedAt = null;
64509
- let lastError = null;
64510
- const isIdle = () => !running && timer === null && pending.size === 0;
64511
- const resolveIdleWaiters = () => {
64512
- if (!isIdle()) return;
64513
- for (const resolve of idleWaiters) resolve();
64514
- idleWaiters.clear();
64515
- };
64516
- const drain = async () => {
64517
- timer = null;
64518
- if (running || stopped) return;
64519
- running = true;
64520
- try {
64521
- while (!stopped && pending.size > 0) {
64522
- const projects = [...pending.values()];
64523
- const reasonsByProjectPath = /* @__PURE__ */ new Map();
64524
- for (const project of projects) {
64525
- reasonsByProjectPath.set(project.path, new Set(reasons.get(project.path) ?? []));
64526
- reasons.delete(project.path);
64527
- }
64528
- pending.clear();
64529
- activeProjectPaths = projects.map((project) => project.path);
64530
- lastStartedAt = now();
64531
- try {
64532
- await deps.refreshProjects(projects, { reasonsByProjectPath });
64533
- lastError = null;
64534
- } catch (error) {
64535
- lastError = error instanceof Error ? error.message : String(error);
64536
- console.warn("[project-resource-refresh] batch failed:", lastError);
64537
- } finally {
64538
- activeProjectPaths = [];
64539
- lastCompletedAt = now();
64540
- }
64541
- }
64542
- } finally {
64543
- running = false;
64544
- resolveIdleWaiters();
64545
- }
64546
- };
64547
- const schedule = () => {
64548
- if (stopped || running || timer) return;
64549
- timer = setTimeout(() => void drain(), debounceMs);
64550
- timer.unref?.();
64551
- };
64552
- const enqueueProject = (project, reason) => {
64553
- if (stopped) return;
64554
- pending.set(project.path, project);
64555
- const projectReasons = reasons.get(project.path) ?? /* @__PURE__ */ new Set();
64556
- projectReasons.add(reason);
64557
- reasons.set(project.path, projectReasons);
64558
- schedule();
64559
- };
64560
- return {
64561
- enqueueProject,
64562
- enqueueProjects(projects, reason) {
64563
- for (const project of projects) enqueueProject(project, reason);
64564
- },
64565
- whenIdle() {
64566
- if (isIdle()) return Promise.resolve();
64567
- return new Promise((resolve) => idleWaiters.add(resolve));
64568
- },
64569
- getState() {
64570
- return {
64571
- running,
64572
- activeProjectPaths: [...activeProjectPaths],
64573
- pendingProjectPaths: [...pending.keys()],
64574
- lastStartedAt,
64575
- lastCompletedAt,
64576
- lastError
64577
- };
64578
- },
64579
- stop() {
64580
- stopped = true;
64581
- if (timer) clearTimeout(timer);
64582
- timer = null;
64583
- pending.clear();
64584
- reasons.clear();
64585
- resolveIdleWaiters();
64586
- }
64587
- };
64588
- }
64589
- const MEMBERSHIP_REFRESH_REASONS = new Set(["boot-warm", "periodic-convergence"]);
64590
- const projectResourceRefreshQueue = createProjectResourceRefreshQueue({ refreshProjects: (projects, context) => refreshResourceAllocatedProjects(projects, { refreshMembership: [...context.reasonsByProjectPath.values()].some((projectReasons) => [...projectReasons].some((reason) => MEMBERSHIP_REFRESH_REASONS.has(reason))) }) });
64591
- function enqueueProjectsResourceRefresh(projects, reason) {
64592
- projectResourceRefreshQueue.enqueueProjects(projects, reason);
64593
- }
64594
- function whenProjectResourceRefreshIdle() {
64595
- return projectResourceRefreshQueue.whenIdle();
64596
- }
64597
- function getProjectResourceRefreshQueueState() {
64598
- return projectResourceRefreshQueue.getState();
64599
- }
64600
- function stopProjectResourceRefreshQueue() {
64601
- projectResourceRefreshQueue.stop();
64602
- }
64603
- function startProjectResourceConvergence() {
64604
- const timer = setInterval(() => {
64605
- enqueueProjectsResourceRefresh(listProjectsSync().map((entry) => entry.config), "periodic-convergence");
64606
- }, PROJECT_RESOURCE_CONVERGENCE_INTERVAL_MS);
64607
- timer.unref?.();
64608
- return () => clearInterval(timer);
64609
- }
64610
- //#endregion
64611
64451
  //#region services/resource-refresh-triggers.ts
64612
64452
  init_agents$1();
64613
64453
  init_projects();
@@ -64617,7 +64457,8 @@ const TRIGGER_EVENT_TYPES = new Set([
64617
64457
  "agent.started",
64618
64458
  "agent.stopped",
64619
64459
  "agent.completed",
64620
- "agent.heartbeat_dead"
64460
+ "agent.heartbeat_dead",
64461
+ "issue.statusChanged"
64621
64462
  ]);
64622
64463
  function createResourceRefreshTriggers(deps) {
64623
64464
  const warn = deps.warn ?? ((message) => console.warn(message));
@@ -64635,7 +64476,8 @@ function createResourceRefreshTriggers(deps) {
64635
64476
  warn(`[resource-refresh] skipped ${event.type}: affected project could not be resolved`);
64636
64477
  return;
64637
64478
  }
64638
- deps.enqueueProjects([project], event.type);
64479
+ const reason = event.type === "issue.statusChanged" && Array.isArray(payload?.labels) && payload.labels.some((label) => String(label).toLowerCase() === "closed-out") ? "issue.statusChanged:closed-out" : event.type;
64480
+ deps.enqueueProjects([project], reason);
64639
64481
  });
64640
64482
  }
64641
64483
  function startResourceRefreshTriggers() {
@@ -66179,7 +66021,7 @@ const RESTART_MARKER = join$1(homedir(), ".overdeck", "dashboard-restarting.json
66179
66021
  * loads new content-hashed chunk filenames (no ERR_MODULE_NOT_FOUND after rebuild).
66180
66022
  */
66181
66023
  async function defaultLifecycleRunner(pending) {
66182
- const { postMergeLifecycle, notifyTldrDaemon } = await import("./merge-agent-BRSz26Oh.js");
66024
+ const { postMergeLifecycle, notifyTldrDaemon } = await import("./merge-agent-BuoC_PRZ.js");
66183
66025
  await postMergeLifecycle(pending.issueId, pending.projectPath, pending.sourceBranch, { skipDeploy: true });
66184
66026
  if (pending.sourceBranch) await notifyTldrDaemon(pending.projectPath, pending.sourceBranch);
66185
66027
  }
@@ -66376,7 +66218,7 @@ function failureReason(result) {
66376
66218
  return result.error ?? result.message ?? `merge returned status ${result.statusCode ?? "unknown"}`;
66377
66219
  }
66378
66220
  async function defaultMergeIssue(issueId) {
66379
- const { triggerMerge } = await import("./merge-ops-DtHx17Vd.js");
66221
+ const { triggerMerge } = await import("./merge-ops-DabXHp2i.js");
66380
66222
  return triggerMerge(issueId);
66381
66223
  }
66382
66224
  function defaultAnnounceFailure(issueId, reason) {
@@ -66879,7 +66721,7 @@ const defaultDependencies = {
66879
66721
  inspect: inspectStateMigration,
66880
66722
  ensureWorktree: ensureStateWorktree,
66881
66723
  migrate: async (projectKey, project, signal) => {
66882
- const { migrateProjectState } = await import("./state-migrate-CJKEwpB0.js");
66724
+ const { migrateProjectState } = await import("./state-migrate-C6H3jfHE.js");
66883
66725
  await migrateProjectState(projectKey, { signal }, project);
66884
66726
  },
66885
66727
  clearCache: clearStateMigrationCache,
@@ -67091,7 +66933,7 @@ if (shouldStartStaleCheckRetriggerService()) {
67091
66933
  }
67092
66934
  if (process.env.OVERDECK_MODE === "desktop") (async () => {
67093
66935
  try {
67094
- const { provisionClaudeHooks } = await import("./claude-hooks-provision-B_tv3wzE.js");
66936
+ const { provisionClaudeHooks } = await import("./claude-hooks-provision-C5JHpxTS.js");
67095
66937
  const result = await provisionClaudeHooks();
67096
66938
  if (!result.ok) console.warn(`[overdeck] Claude hook provisioning skipped: ${result.reason}`);
67097
66939
  else if (result.changed) console.log(`[overdeck] Claude hooks provisioned: ${result.binariesSynced} scripts, registered ${result.registered.length} hook(s)${result.pruned.length ? `, pruned ${result.pruned.length} stale` : ""}`);
@@ -67436,7 +67278,7 @@ const handleShutdownSignal = async (signal) => {
67436
67278
  await stopAllKnowledgeViewers().catch((err) => console.warn("[knowledge-viewer] shutdown failed:", err?.message ?? err));
67437
67279
  await stopDeaconChild().catch((err) => console.warn("[deacon-supervisor] child shutdown failed:", err?.message ?? err));
67438
67280
  try {
67439
- const { killAllGateProcessGroups } = await import("./validation-BdCjzWLN.js");
67281
+ const { killAllGateProcessGroups } = await import("./validation-CHovCoTT.js");
67440
67282
  const reaped = killAllGateProcessGroups();
67441
67283
  if (reaped > 0) console.log(`[overdeck] reaped ${reaped} in-flight gate process group(s)`);
67442
67284
  } catch (err) {
@@ -67490,8 +67332,9 @@ reconcileStaleGitHubBlockers().then((n) => {
67490
67332
  });
67491
67333
  }
67492
67334
  }).catch((err) => console.warn(`[overdeck] Startup blocker reconciliation failed: ${err.message}`));
67335
+ await startProjectCiRefillAfterProjectionReady(900 * 1e3);
67493
67336
  try {
67494
- const { resetProcessingToQueued, requeueOrphanedMergingAutoMerges } = await import("./merge-sync-CM2-myXu.js");
67337
+ const { resetProcessingToQueued, requeueOrphanedMergingAutoMerges } = await import("./merge-sync-0m2Q087q.js");
67495
67338
  const resetCount = resetProcessingToQueued();
67496
67339
  if (resetCount > 0) {
67497
67340
  console.log(`[overdeck] Reset ${resetCount} stuck merge queue entries to queued`);
@@ -67516,13 +67359,16 @@ try {
67516
67359
  }
67517
67360
  await processPendingLifecycle();
67518
67361
  await processPendingFeedbackDeliveries();
67362
+ await initRestartGate().catch((err) => {
67363
+ console.warn(`[overdeck] Restart gate init failed: ${err instanceof Error ? err.message : String(err)}`);
67364
+ });
67519
67365
  if (process.env.OVERDECK_DISABLE_AUTO_MERGE === "1") console.log("[overdeck] Auto-merge executor SKIPPED (OVERDECK_DISABLE_AUTO_MERGE=1)");
67520
67366
  else {
67521
67367
  startAutoMergeExecutor();
67522
67368
  console.log("[overdeck] Auto-merge executor started");
67523
67369
  }
67524
67370
  try {
67525
- const { reconcileInterruptedVerifications } = await import("./verification-runner-C6wdZda2.js");
67371
+ const { reconcileInterruptedVerifications } = await import("./verification-runner-BuqGwm2t.js");
67526
67372
  const interrupted = reconcileInterruptedVerifications();
67527
67373
  if (interrupted > 0) console.log(`[overdeck] recovered ${interrupted} orphaned verification worker(s)`);
67528
67374
  } catch (err) {