@overdeck/desktop 0.45.16 → 0.45.18

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 (365) hide show
  1. package/dist-electron/main.js +149 -158
  2. package/dist-electron/main.js.map +1 -1
  3. package/dist-electron/preload.js +17 -2
  4. package/dist-electron/preload.js.map +1 -1
  5. package/package.json +5 -4
  6. package/server/acceptance-criteria-aQFKQf-J.js +62 -0
  7. package/server/{advancing-selfheal-DJYAvGv-.js → advancing-selfheal-DgwQgm4D.js} +6 -6
  8. package/server/{agent-gc-D0wDIeV1.js → agent-gc-kpzxqT7P.js} +3 -3
  9. package/server/agent-state-C_6TG-Ad.js +3 -0
  10. package/server/{agent-state-service-CZrayD_G.js → agent-state-service-BUfovFfB.js} +1 -1
  11. package/server/{agent-state-service-DFslS5go.js → agent-state-service-nUD3qfob.js} +5 -5
  12. package/server/agents-BA15AQqo.js +3 -0
  13. package/server/{briefing-freshness-DESTCWo-.js → agents-BHBxr8c9.js} +5 -131
  14. package/server/{archive-planning-CbghE9-o.js → archive-planning-CzCW9Ifl.js} +5 -10
  15. package/server/{archive-planning-CoyIbgGK.js → archive-planning-D-QsBufn.js} +1 -1
  16. package/server/{artifact-index-jobs-CcSrUoSE.js → artifact-index-jobs-qqa51B2Z.js} +2 -2
  17. package/server/{backlog-auto-trigger-BfgDsII0.js → backlog-auto-trigger-B7Bi0bvY.js} +2 -2
  18. package/server/{behavior-BTpYbAv4.js → behavior-CWqNMqE5.js} +2 -2
  19. package/server/briefing-freshness-DuxIE1yr.js +131 -0
  20. package/server/{checkpoint-manager-BwFdegJF.js → checkpoint-manager-DF6hb9Jw.js} +3 -3
  21. package/server/{checkpoint-manager-DWSXooZV.js → checkpoint-manager-DixkLus7.js} +1 -1
  22. package/server/checkpoint-worker.js +1 -1
  23. package/server/{checkpoints-fjadfOKF.js → checkpoints-B1Z42tJE.js} +1 -1
  24. package/server/{checkpoints-BtUonbs3.js → checkpoints-BiviJqei.js} +2 -2
  25. package/server/{claude-hooks-provision-DiK62u0k.js → claude-hooks-provision-BeMGi4ty.js} +1 -1
  26. package/server/{claude-hooks-provision-DAtxutOs.js → claude-hooks-provision-Du_PkMsp.js} +2 -2
  27. package/server/{claude-permissions-CThLgf8d.js → claude-permissions-BB6agcOZ.js} +2 -2
  28. package/server/{claude-settings-overlay-BF9MPIwx.js → claude-settings-overlay-CAq2oFSK.js} +2 -2
  29. package/server/{claude-settings-overlay-Dx_Uqcmv.js → claude-settings-overlay-DUWWLd6M.js} +1 -1
  30. package/server/cli-BFgrSWKV.js +3 -0
  31. package/server/{cli-ByKIIMfT.js → cli-C33xPZNm.js} +9 -9
  32. package/server/{cliproxy-C_GuT5DU.js → cliproxy-BQX1TL6N.js} +1 -1
  33. package/server/{cliproxy-B4c1BUvs.js → cliproxy-CGBA1GzA.js} +2 -2
  34. package/server/{close-issue-BOuLKr6e.js → close-issue-DNv8npc1.js} +5 -5
  35. package/server/{closed-issue-reaper-CksfuiFD.js → closed-issue-reaper-DrqgBJlr.js} +1 -1
  36. package/server/{closed-issue-reaper-DCAYzNXW.js → closed-issue-reaper-LoMnnjtJ.js} +9 -9
  37. package/server/codex-DxLivxri.js +3 -0
  38. package/server/{codex-parser-mFYZh8vR.js → codex-parser-DboQnEXN.js} +2 -2
  39. package/server/{codex-BbqIRZjd.js → codex-sgWVCGUd.js} +43 -18
  40. package/server/{config-Dj6N8EP9.js → config-6MCHOZ2N.js} +1 -1
  41. package/server/{config-DVLdmnMJ.js → config-DfaUXr6r.js} +2 -2
  42. package/server/{config-yaml-cNOZcEww.js → config-yaml-CqaAyn8y.js} +74 -74
  43. package/server/{conflict-gate-BMKm_5DV.js → conflict-gate-BF_zhcmb.js} +3 -3
  44. package/server/{conflict-gate-CuXUv-bP.js → conflict-gate-BubJprtD.js} +1 -1
  45. package/server/{context-layers-c0JqYHcS.js → context-layers-BFrxfl0l.js} +17 -3
  46. package/server/{context-layers-CeAwSYNt.js → context-layers-DWL_8HhY.js} +2 -2
  47. package/server/{control-settings-D4EFsRBd.js → control-settings-BguNQ1F_.js} +4 -4
  48. package/server/{conversation-compaction-kHVfVRg3.js → conversation-compaction-CRKAf2qP.js} +1 -1
  49. package/server/{conversation-compaction-BCggyih4.js → conversation-compaction-DxSXl0pT.js} +8 -8
  50. package/server/{conversation-service-BTzObqGi.js → conversation-service-DzuY9qoH.js} +1 -1
  51. package/server/{conversation-service-B8LFQQm1.js → conversation-service-mFVFdDQK.js} +6 -6
  52. package/server/{conversations-B-lcHv-5.js → conversations-BX5aD-6F.js} +4 -4
  53. package/server/{conversations-BM7zlXjr.js → conversations-BajHQ60c.js} +1 -1
  54. package/server/{cost-D9kPIY_5.js → cost-BoqD1Pxz.js} +2 -2
  55. package/server/{cost-BcpRQ-7o.js → cost-DuZ5vlv-.js} +3 -3
  56. package/server/{cost-sync-DF6odxK9.js → cost-sync-BYnmnMkY.js} +3 -3
  57. package/server/{dag-DKI3sOmX.js → dag-C6kYyF17.js} +7 -243
  58. package/server/{dangerous-git-ops-Bn18PEcN.js → dangerous-git-ops-q5OPtXMd.js} +1 -1
  59. package/server/dashboard-db-worker.js +6 -6
  60. package/server/{deacon-DONuopff.js → deacon-CwCiNuEZ.js} +3 -3
  61. package/server/{deacon-DdARMjZq.js → deacon-Dru5onpk.js} +233 -162
  62. package/server/{deacon-nudge-log-B-naf89q.js → deacon-nudge-log-ilDfxrhK.js} +1 -1
  63. package/server/{deacon-swarm-BNGkmYR_.js → deacon-swarm-BPmBmSoU.js} +298 -72
  64. package/server/deacon-swarm-CKyGJng1.js +2 -0
  65. package/server/deacon.js +14 -7
  66. package/server/{devcontainer-renderer-C-34Sxyz.js → devcontainer-renderer-BqGNCzvN.js} +3 -3
  67. package/server/{dist-BMXvKiZP.js → dist-BwlEiLCU.js} +1 -1
  68. package/server/dist-Bx4KkgYL.js +3 -0
  69. package/server/{dist-src-BgGUblXg.js → dist-src-BE0Denfs.js} +1 -1
  70. package/server/{docker-apZ9pBYw.js → docker-CNjXS72x.js} +2 -2
  71. package/server/{ensure-devcontainer-Bqi1EF1P.js → ensure-devcontainer-5e9xOve4.js} +4 -4
  72. package/server/{ensure-devcontainer-Dq3KoOIl.js → ensure-devcontainer-C6gyUQdE.js} +1 -1
  73. package/server/{esm-shims-BEjvINX3.js → esm-shims-Cso7IGBC.js} +1 -1
  74. package/server/{event-store-CqDgfbAs.js → event-store-D9UhQyMS.js} +1 -1
  75. package/server/{event-store-D89fMfXS.js → event-store-KZnWUKWh.js} +3 -3
  76. package/server/{events-S_C0pvl6.js → events-2eFUPdqz.js} +3 -3
  77. package/server/{events-rIGncmP1.js → events-BYbvqZky.js} +1 -1
  78. package/server/{factory-DV18m0rc.js → factory-BtaRsHFC.js} +20 -17
  79. package/server/{feature-registry-population-CqZSnqQi.js → feature-registry-population-Ca2UaV0U.js} +4 -4
  80. package/server/{feature-registry-storage-BeXmNBwK.js → feature-registry-storage-DaP-bQxO.js} +2 -2
  81. package/server/{features-u5XeMaOK.js → features-DqvaoQoa.js} +2 -2
  82. package/server/{feedback-target-CwyWf0Dg.js → feedback-target-BXWdOiYI.js} +9 -7
  83. package/server/{feedback-target-DDG1PWl3.js → feedback-target-BblmMe9P.js} +1 -1
  84. package/server/{feedback-writer-BsJiw5aT.js → feedback-writer-CULeOOY4.js} +1 -1
  85. package/server/{feedback-writer-D20HSXre.js → feedback-writer-Dn8o9ZyE.js} +4 -4
  86. package/server/{flywheel-RCnHAgc4.js → flywheel-BUWdcfhq.js} +1 -1
  87. package/server/{flywheel-Dczmgchd.js → flywheel-CqkO3cDj.js} +15 -28
  88. package/server/{flywheel-9Y1X7IM-.js → flywheel-D9r1mw2U.js} +13 -13
  89. package/server/{flywheel-merge-order-DEtEd3aK.js → flywheel-merge-order-LDzQDwSg.js} +1 -1
  90. package/server/{flywheel-merge-order-CtCYsFJP.js → flywheel-merge-order-VtjUweEb.js} +6 -6
  91. package/server/forge-DJy3Zx4s.js +2 -0
  92. package/server/{forge-DFDThFil.js → forge-wEollMCi.js} +22 -12
  93. package/server/{from-NSJypkI8.js → from-B2tOYhYV.js} +1 -1
  94. package/server/{fts-db-C5A_TTOM.js → fts-db-Bgzn2RO7.js} +2 -2
  95. package/server/{fts-operations-DvCSimfU.js → fts-operations-Bj8yutnR.js} +2 -2
  96. package/server/{git-utils-Dr0L7mFk.js → git-utils-GxlL0tmt.js} +2 -2
  97. package/server/{git-utils-C0neHvQx.js → git-utils-q8jNoBts.js} +1 -1
  98. package/server/{github-app-Bwt9lK4A.js → github-app-BrYwK_Gb.js} +1 -1
  99. package/server/{github-app-u9-SX7Gc.js → github-app-tUbb8Ldr.js} +8 -3
  100. package/server/{github-client-Btyy3uan.js → github-client-BwBU41jK.js} +3 -3
  101. package/server/{github-client-Do3k-N1W.js → github-client-D6CNsftm.js} +1 -1
  102. package/server/{github-pr-lookup-DOF1U2WW.js → github-pr-lookup-BS5PqkJb.js} +2 -2
  103. package/server/{harness-resolve-C6g2R0Cd.js → harness-resolve-Dx8hUsvC.js} +3 -3
  104. package/server/{health-events-B4u-2a9m.js → health-events-2DLp-5Xp.js} +2 -2
  105. package/server/{health-events-Bos3sk5g.js → health-events-B0mj6Iae.js} +1 -1
  106. package/server/{hooks-uEr8WTx_.js → hooks-BDcQJDUe.js} +1 -1
  107. package/server/{hooks-BCoOjL_R.js → hooks-BS_JrvYP.js} +3 -3
  108. package/server/hume-B4seN95Y.js +3 -0
  109. package/server/{hume-BqxYKbUf.js → hume-BRhNKyXQ.js} +2 -2
  110. package/server/{idle-stack-reaper-DbZ8ukMd.js → idle-stack-reaper-BCITXNW5.js} +2 -2
  111. package/server/{idle-stack-reaper-H0W6XtHh.js → idle-stack-reaper-C1ymihno.js} +1 -1
  112. package/server/{infra-Ba9mS6e6.js → infra-_Kx1m9pm.js} +9 -4
  113. package/server/{injection-C1DKXeIZ.js → injection-Bvhyg_MV.js} +1 -1
  114. package/server/{injection-yrMBxzVq.js → injection-CCaYkofq.js} +7 -7
  115. package/server/{inspect-agent-B-mnb4uh.js → inspect-agent-BqyZ4pCo.js} +35 -67
  116. package/server/inspect-agent-DCJQm9Wu.js +2 -0
  117. package/server/{internal-token-BtqSbKTx.js → internal-token-Cl-1IxaE.js} +2 -2
  118. package/server/{internal-token-BPYEaXFh.js → internal-token-D-t28de5.js} +1 -1
  119. package/server/{io-VEGSAqsd.js → io-DkC4sFSy.js} +36 -43
  120. package/server/{issue-closed-BxcePXL-.js → issue-closed-Cpl4VDUM.js} +41 -6
  121. package/server/{issue-lifecycle--8MRxrG1.js → issue-lifecycle-CFR8TJ22.js} +22 -37
  122. package/server/{issue-lifecycle-CdMUauyb.js → issue-lifecycle-YNTy3OT3.js} +1 -1
  123. package/server/{issue-service-singleton-MZsDhAob.js → issue-service-singleton-D81mCts_.js} +1 -1
  124. package/server/{issue-service-singleton-CkTUI-eu.js → issue-service-singleton-ldvUUXi3.js} +29 -29
  125. package/server/{issues-CBAsuoAO.js → issues-DIEHt9sq.js} +2 -2
  126. package/server/{jsonl-parser-BUW5_sSK.js → jsonl-parser-Cd5jIqh7.js} +3 -3
  127. package/server/{label-cleanup-htK6fBRU.js → label-cleanup-Btny6Gyo.js} +3 -3
  128. package/server/{state-home-CEvD_v5F.js → launcher-generator-BXLM9f4b.js} +7 -127
  129. package/server/{layers-jjL16At6.js → layers-gCJlK62m.js} +2 -2
  130. package/server/lifecycle-D7aQUnTO.js +12 -0
  131. package/server/{lifecycle-io-DXv8Utct.js → lifecycle-io-DQBF-GHO.js} +1 -1
  132. package/server/{lifecycle-io-IehcRt2v.js → lifecycle-io-FfPUtz-y.js} +4 -4
  133. package/server/{linear-client-D9cSQfvD.js → linear-client-CDH2D6Qy.js} +3 -3
  134. package/server/{linear-client-By7hjwuN.js → linear-client-WrYrUIAH.js} +1 -1
  135. package/server/memory-fts-worker.js +1 -1
  136. package/server/{merge-BN8FGJ2q.js → merge-BsDgUxFz.js} +3 -3
  137. package/server/{merge-BLcEZNXz.js → merge-Dervs4BF.js} +1 -1
  138. package/server/{merge-agent-B3u2szOL.js → merge-agent-D6DNhe9j.js} +64 -51
  139. package/server/{merge-agent-ejC7Wos8.js → merge-agent-DMQTJMP0.js} +1 -1
  140. package/server/{merge-batch-DyqlgYGp.js → merge-batch-Bv6Z5K2H.js} +1 -1
  141. package/server/{merge-blockers-cq-aS2KG.js → merge-blockers-WWWi6Ur2.js} +2 -2
  142. package/server/merge-ops-h9OCnIVz.js +2 -0
  143. package/server/{merge-rebase-Dl7yIxtV.js → merge-rebase-Czth9ggm.js} +2 -2
  144. package/server/{merge-set-CZ9Nbay0.js → merge-set-DNc4zBqd.js} +3 -3
  145. package/server/{merge-set-Dy0D0r3i.js → merge-set-vuE3MEVt.js} +1 -1
  146. package/server/{merge-sync-D7jWLgCC.js → merge-sync-B2KSk54U.js} +2 -2
  147. package/server/{merge-sync-CG9kDCdT.js → merge-sync-B9nHdUGx.js} +1 -1
  148. package/server/{merge-train-CH33XJOH.js → merge-train-DJgr81tF.js} +3 -3
  149. package/server/{merge-train-deps-JoVdGnOg.js → merge-train-deps-B2OWS0k9.js} +4 -4
  150. package/server/{merge-verification-D4wTChdX.js → merge-verification-BBIXUEqa.js} +4 -4
  151. package/server/{multipart-parser-Csn8U-K9.js → multipart-parser-9DhuAkPd.js} +2 -2
  152. package/server/node_modules/.package-lock.json +11 -11
  153. package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/package.json +3 -3
  154. package/server/node_modules/toml/README.md +54 -0
  155. package/server/node_modules/toml/index.d.ts +42 -1
  156. package/server/node_modules/toml/index.js +3 -3
  157. package/server/node_modules/toml/lib/compiler.js +35 -3
  158. package/server/node_modules/toml/lib/parser.js +224 -143
  159. package/server/node_modules/toml/package.json +3 -1
  160. package/server/node_modules/ws/lib/receiver.js +15 -32
  161. package/server/node_modules/ws/lib/websocket-server.js +4 -4
  162. package/server/node_modules/ws/lib/websocket.js +4 -4
  163. package/server/node_modules/ws/package.json +5 -1
  164. package/server/{orphan-proposed-reconciler-DI_IS1p_.js → orphan-proposed-reconciler-B8H41C4a.js} +14 -24
  165. package/server/{orphan-proposed-reconciler-BIcNu4tl.js → orphan-proposed-reconciler-DbTmT7qy.js} +1 -1
  166. package/server/package-lock.json +12 -12
  167. package/server/package.json +1 -1
  168. package/server/{pan-dir-CQIfKG8c.js → pan-dir-BTw4MdSe.js} +4 -4
  169. package/server/{paths-Blj6A9AJ.js → paths-Btkc8mzp.js} +2 -2
  170. package/server/{pipeline-notifier-BH4PAi-w.js → pipeline-notifier-3frIvSi3.js} +1 -1
  171. package/server/{pipeline-notifier-D_WYtEwl.js → pipeline-notifier-DTd19f18.js} +2 -2
  172. package/server/{project-pipelines-jMTitpeO.js → project-pipelines-B95fcAek.js} +2 -2
  173. package/server/projects-Dc9aoVoG.js +3 -0
  174. package/server/{prompts-B3njaImU.js → prompts-CIVmjHxn.js} +2 -2
  175. package/server/{providers-DnPxkHoG.js → providers-BLLk5IIb.js} +1 -1
  176. package/server/{providers-BbEyFhPX.js → providers-C-yWibCk.js} +7 -7
  177. package/server/public/assets/{chunk-BO2N2NFS-3qh9TUJi.js → chunk-BO2N2NFS-DzKZyoKY.js} +4 -4
  178. package/server/public/assets/{diagram-OG6HWLK6-D8UVTPj7.js → diagram-OG6HWLK6-Cx8mWUb8.js} +1 -1
  179. package/server/public/assets/{dist-BvLLn1YC.js → dist-BqccLhaw.js} +3 -3
  180. package/server/public/assets/{dist-CyubL7Wj.js → dist-rC3nAs_O.js} +1 -1
  181. package/server/public/assets/{ganttDiagram-6RSMTGT7-BI4E1LbQ.js → ganttDiagram-6RSMTGT7-DLYPLf5T.js} +1 -1
  182. package/server/public/assets/{highlighted-body-OFNGDK62-D_bapWkF.js → highlighted-body-OFNGDK62-D4DqixbV.js} +1 -1
  183. package/server/public/assets/index-CPcysUHk.js +796 -0
  184. package/server/public/assets/index-H5M0yhM4.css +1 -0
  185. package/server/public/assets/{linear-CEdobObr.js → linear-yqcXkDfj.js} +1 -1
  186. package/server/public/assets/mermaid-GHXKKRXX-CWdZ_heB.js +1 -0
  187. package/server/public/assets/{pieDiagram-4H26LBE5-DT79L01f.js → pieDiagram-4H26LBE5-DhraIOaV.js} +1 -1
  188. package/server/public/assets/{prod-CR_K2DFV.js → prod-DKUunUdN.js} +4 -4
  189. package/server/public/assets/{quadrantDiagram-W4KKPZXB-BEkKXXrL.js → quadrantDiagram-W4KKPZXB-DPiRcToa.js} +1 -1
  190. package/server/public/assets/{sankeyDiagram-5OEKKPKP-BxSCqn-j.js → sankeyDiagram-5OEKKPKP-3An5HNkZ.js} +1 -1
  191. package/server/public/assets/{xychartDiagram-2RQKCTM6-DicwJGG_.js → xychartDiagram-2RQKCTM6-lbEOjfqQ.js} +1 -1
  192. package/server/public/index.html +2 -2
  193. package/server/{pull-requests-43LPDfM8.js → pull-requests-D7AL5woD.js} +1 -1
  194. package/server/{pull-requests-DyUkQl4W.js → pull-requests-NDDNtqNq.js} +3 -3
  195. package/server/{agents-B9GwfCyp.js → queries-C0LCGG21.js} +710 -325
  196. package/server/{rally-BtWjybOa.js → rally-4oKvnxLG.js} +3 -3
  197. package/server/rally-DF5a3ioP.js +3 -0
  198. package/server/{rally-api-B-osULNL.js → rally-api-41tT6ikZ.js} +2 -2
  199. package/server/{rally-api-B-YA_oXx.js → rally-api-BsaQ8Vnz.js} +1 -1
  200. package/server/{rally-client-sErNQBO0.js → rally-client-Bo4hNcCZ.js} +5 -5
  201. package/server/{rally-client-CzFymP7P.js → rally-client-b5PT1x5L.js} +1 -1
  202. package/server/{reap-terminal-sessions-DnDQ7pf9.js → reap-terminal-sessions-BR39qflC.js} +1 -1
  203. package/server/{reap-terminal-sessions-2s-fvilz.js → reap-terminal-sessions-CFkuquQj.js} +1 -1
  204. package/server/{rebuild-stack-nGD_nPZo.js → rebuild-stack-C7JPUom6.js} +1 -1
  205. package/server/{rebuild-stack-CoU-HqZj.js → rebuild-stack-Ddv6W017.js} +5 -5
  206. package/server/{reconstruct-cache-Wj8GrYB0.js → reconstruct-cache-Gqhm---K.js} +6 -6
  207. package/server/record-DLOqfbkI.js +3 -0
  208. package/server/record-update-BltEmPge.js +168 -0
  209. package/server/record-update-CDp7aTaT.js +3 -0
  210. package/server/recovery-trip-Cn7KJVkS.js +44 -0
  211. package/server/{release-engine-CBLQXDlH.js → release-engine-BYzmIBf9.js} +5 -5
  212. package/server/{release-set-BNiqi7hy.js → release-set-7pnxFOWR.js} +3 -3
  213. package/server/{remote-DW_TWQnr.js → remote-Cvu4CSDk.js} +3 -3
  214. package/server/{remote-agents-C4cyxHQS.js → remote-agents-C2C6z9tj.js} +6 -33
  215. package/server/{remote-agents-Cv-U-_V8.js → remote-agents-DYY5fFpd.js} +1 -1
  216. package/server/{remote-completion-PhXGGFQy.js → remote-completion-2Kb4IDg_.js} +13 -13
  217. package/server/{remote-DcO9An_f.js → remote-rN0ecjHE.js} +3 -3
  218. package/server/resume-BFLl-yLn.js +3 -0
  219. package/server/{review-agent-Dn-yn7Zj.js → review-agent-BZvk0N5G.js} +31 -23
  220. package/server/{review-agent-u5q3ip7H.js → review-agent-CpSHLzed.js} +1 -1
  221. package/server/{review-artifacts-D4T04aYI.js → review-artifacts-PCo53YMn.js} +5 -19
  222. package/server/{review-context-Rc0VDLG_.js → review-context-M7QtJlJq.js} +8 -8
  223. package/server/{review-monitor-BC--miCO.js → review-monitor-BLC5mTTg.js} +2 -2
  224. package/server/{review-status-CG0iDuWa.js → review-status-77N3PoZr.js} +1 -1
  225. package/server/{review-status-Dc1l4dVz.js → review-status-DANr0t-v.js} +32 -58
  226. package/server/{review-status-enrichment-C1a1OG_1.js → review-status-enrichment-DwOg4UfL.js} +3 -3
  227. package/server/{review-status-sync-CfSixhhX.js → review-status-sync-Bd08OOFA.js} +1 -1
  228. package/server/{review-status-sync-CAr-hfnJ.js → review-status-sync-BjTUJ5fx.js} +2 -2
  229. package/server/{review-verdict-feedback-D2Q960wX.js → review-verdict-feedback-BsFLjN_6.js} +1 -1
  230. package/server/{review-verdict-feedback-CVDbIDBe.js → review-verdict-feedback-CBf-J_wS.js} +8 -8
  231. package/server/{rollup-DctoIu-A.js → rollup-Bu0f2EyN.js} +8 -8
  232. package/server/{rollup-CakjztPl.js → rollup-DTCCdEy4.js} +1 -1
  233. package/server/{scanner-BTM1jc_u.js → scanner-BlZ2vB7j.js} +7 -7
  234. package/server/{sequence-io-pnoIDGv4.js → sequence-io-ylyDtz2J.js} +4 -4
  235. package/server/{sequencer-agent-9Soi-WL-.js → sequencer-agent-DsWQ-87H.js} +6 -17
  236. package/server/server.js +4695 -4093
  237. package/server/{service-DfTVoqJg.js → service-CLVBC_1Y.js} +116 -90
  238. package/server/{session-fork-C4jAFHj8.js → session-fork-DlEIAhRy.js} +2 -2
  239. package/server/{session-history-DanhhiCw.js → session-history-bnOFKMwf.js} +4 -4
  240. package/server/settings-CP3GGon2.js +2 -0
  241. package/server/{settings-Cuc12oP_.js → settings-Cqa-8nyj.js} +2 -2
  242. package/server/{settings-DfT3f86D.js → settings-gJrdLZy2.js} +3 -3
  243. package/server/{shadow-engineering-bKuKTCn-.js → shadow-engineering-fq1YEKV3.js} +3 -3
  244. package/server/{shadow-state-CVHpRWlb.js → shadow-state-BqeFAygK.js} +1 -1
  245. package/server/{shadow-state-DJz6_pb_.js → shadow-state-RptE9Cau.js} +2 -2
  246. package/server/shadow-utils-BMWr5tRT.js +39 -0
  247. package/server/{ship-log-CwqPFfqx.js → ship-log-BRQQi2lU.js} +1 -1
  248. package/server/{smart-compaction-CiWfGfRZ.js → smart-compaction-CmoXpjeU.js} +7 -7
  249. package/server/{smart-compaction-B4KlpZGN.js → smart-compaction-DldUel4B.js} +1 -1
  250. package/server/{spawn-planning-session-CU-DwyDl.js → spawn-planning-session-CoS6LTc6.js} +16 -16
  251. package/server/{spawn-planning-session-D5N3RuLG.js → spawn-planning-session-DT2tSMxo.js} +1 -1
  252. package/server/{specialist-completion-CJcv-NXH.js → specialist-completion-pJtESo7m.js} +1 -1
  253. package/server/{specialist-context-B2HlbNxS.js → specialist-context-CspI4Eog.js} +5 -5
  254. package/server/{specialist-handoff-logger-CQyF1ygu.js → specialist-handoff-logger-Duz9RGvk.js} +2 -2
  255. package/server/{specialist-logs-CdcUpfjj.js → specialist-logs-DtSkPJZK.js} +3 -3
  256. package/server/{specialists-D7AcFi1u.js → specialists-CywEMwxk.js} +1 -1
  257. package/server/{specialists-k22_Btaq.js → specialists-D9-dMUtI.js} +1 -1
  258. package/server/{specialists-CFgw_0Q6.js → specialists-Dax7tqXC.js} +161 -448
  259. package/server/{specialists-CwzFdapR.js → specialists-GF42OOqd.js} +18 -18
  260. package/server/specs-VwcFtEDi.js +3 -0
  261. package/server/{src-B4TTzNSr.js → src-By3D85Ry.js} +6 -1
  262. package/server/{src-BvpMg4EB.js → src-CqyFg52C.js} +5 -5
  263. package/server/{src-D4YUZrwR.js → src-DhxM-eCb.js} +6 -6
  264. package/server/{stack-health-DVN7zRnL.js → stack-health-BsEVrJZ6.js} +1 -1
  265. package/server/{stack-health-CSgcYcr8.js → stack-health-C-SnpRHh.js} +2 -2
  266. package/server/stale-task-claims-vTxmRzLi.js +69 -0
  267. package/server/state-home-Bur1y4oH.js +213 -0
  268. package/server/{state-mapping-C13UaCL7.js → state-mapping-Ci0pkac4.js} +1 -1
  269. package/server/state-migrate-D3VveYfO.js +362 -0
  270. package/server/{stuck-remediation-CxsyxwFO.js → stuck-remediation-B699-p8v.js} +36 -41
  271. package/server/{stuck-remediation-nTIvhGOR.js → stuck-remediation-CaFYYTQW.js} +1 -1
  272. package/server/{summary-fork-CnRMPCYd.js → summary-fork-BxnF8Xh0.js} +2 -2
  273. package/server/{summary-fork-gKSoFAnK.js → summary-fork-COqYpVa3.js} +8 -8
  274. package/server/supervisor/{paths-3R6b989k.js → paths-Bk6hJRH9.js} +4 -3
  275. package/server/supervisor/pty-supervisor.js +2 -2
  276. package/server/supervisor/{pty-token-CScQ32Rj.js → pty-token-BZS5GYdG.js} +2 -2
  277. package/server/supervisor-eWAAmXKu.js +2 -0
  278. package/server/{supervisor-CZMs8s0M.js → supervisor-liMgIPDF.js} +2 -2
  279. package/server/{swarm-readiness-h6-pwY8w.js → swarm-readiness-sXB1vhzo.js} +3 -3
  280. package/server/{system-prerequisites-DZZTi2G6.js → system-prerequisites-Bz6KdkFJ.js} +1 -13
  281. package/server/{teardown-workspace-B4D-oCVg.js → teardown-workspace-DvzqnmUF.js} +14 -71
  282. package/server/{test-agent-queue-CnuYku4B.js → test-agent-queue-hAU1Ah08.js} +5 -5
  283. package/server/{tldr-daemon-CuA8hz21.js → tldr-daemon-Bam7Xhoo.js} +2 -2
  284. package/server/{tldr-daemon-CgZQ3jmZ.js → tldr-daemon-DhGwd88s.js} +1 -1
  285. package/server/tmux-C-rgxRDA.js +3 -0
  286. package/server/{tmux-C3g9VFcg.js → tmux-U55cNGFG.js} +92 -4
  287. package/server/{token-g_sJ19g3.js → token-Dsa-i36o.js} +2 -2
  288. package/server/{token-util-DiwnnbJo.js → token-util-BWNpH96m.js} +1 -1
  289. package/server/token-util-DRt0j2nQ.js +3 -0
  290. package/server/{tracker-config-dQxC15vH.js → tracker-config-OkdbaUCm.js} +2 -2
  291. package/server/{tracker-utils--z8FLSWn.js → tracker-utils-CghXMF3q.js} +2 -2
  292. package/server/{tracker-utils-DkKyRT0H.js → tracker-utils-DdzUiPNU.js} +1 -1
  293. package/server/{tunnel-BpWZs0Jy.js → tunnel-D1YxesBL.js} +3 -3
  294. package/server/{tunnel-CN2px87h.js → tunnel-DjlzgTl3.js} +1 -1
  295. package/server/typed-errors-CH4roFIj.js +3 -0
  296. package/server/{typed-errors-sLpGfegz.js → typed-errors-n_Tnb4Fh.js} +3 -4
  297. package/server/{types-BLS_Zbmd.js → types-DOjWNv3Z.js} +1 -1
  298. package/server/{types-tlXf80x3.js → types-DXBMm4mX.js} +1 -1
  299. package/server/{uat-train-utGVmqdm.js → uat-train-CaaWs9Rp.js} +1 -1
  300. package/server/{uat-train-BRo6DM7p.js → uat-train-CqN34zFx.js} +24 -25
  301. package/server/{validation-CsPVsoA0.js → validation-4-z2Cw4z.js} +70 -23
  302. package/server/validation-DpTNakM6.js +3 -0
  303. package/server/verification-artifact-DK1xb1zG.js +56 -0
  304. package/server/verification-artifact-JD_edpZ9.js +2 -0
  305. package/server/{verification-runner-CMT5WRMS.js → verification-runner-BjHN80pJ.js} +338 -58
  306. package/server/verification-runner-ShYu5Ph3.js +2 -0
  307. package/server/{vtt-parser-C_XPlifj.js → vtt-parser-QnRfcjiU.js} +1 -1
  308. package/server/{work-agent-prompt-ZTAb2Hyf.js → work-agent-prompt-BiJ43Der.js} +12 -88
  309. package/server/workflows-B4C3lY9E.js +2 -0
  310. package/server/{workflows-CXRwhw_o.js → workflows-DkTotz_m.js} +17 -24
  311. package/server/{workspace-CNfuj1-5.js → workspace-CuN0ev4Z.js} +3 -3
  312. package/server/{workspace-9UEsKuiP.js → workspace-DQ4vVivd.js} +1 -1
  313. package/server/{workspace-config-ChWOECy0.js → workspace-config-C77NKnsV.js} +1 -1
  314. package/server/{workspace-manager-BO-6k3sP.js → workspace-manager-B1mYn0lN.js} +1 -1
  315. package/server/{workspace-manager-D8AByFIT.js → workspace-manager-Beeo2aKF.js} +23 -48
  316. package/server/{workspace-metadata-CvC268MN.js → workspace-metadata-BZC5BmoP.js} +2 -2
  317. package/server/{workspace-metadata-DZiJtnuF.js → workspace-metadata-Cy7_ZACL.js} +1 -1
  318. package/server/{workspaces-D-uIoqbg.js → workspaces-CGuzW1Ia.js} +182 -152
  319. package/sync-sources/hooks/codex-notify-hook +64 -8
  320. package/sync-sources/hooks/record-cost-event.js +1109 -36
  321. package/sync-sources/hooks/record-cost-event.js.map +1 -1
  322. package/sync-sources/hooks/statusline.sh +2 -2
  323. package/sync-sources/hooks/work-agent-stop-hook +1 -2
  324. package/server/acceptance-criteria-BZ_nQS1f.js +0 -33
  325. package/server/agent-state-lGvgPP4m.js +0 -3
  326. package/server/agents-CEcaxSkR.js +0 -3
  327. package/server/auto-commit-IW-eik_b.js +0 -3
  328. package/server/bd-process-lock-XAXAet9O.js +0 -390
  329. package/server/beads-B1u04n3o.js +0 -2
  330. package/server/beads-BeSMEjGT.js +0 -649
  331. package/server/beads-query-Dl4FhT8J.js +0 -95
  332. package/server/beads-restore-BUItPOjI.js +0 -23
  333. package/server/cli-D9cUTbBr.js +0 -3
  334. package/server/codex-BYPz6ZdF.js +0 -3
  335. package/server/compact-beads-CyJtoXJi.js +0 -94
  336. package/server/compact-beads-N00E4EVa.js +0 -3
  337. package/server/deacon-swarm-CvdFekIO.js +0 -2
  338. package/server/dist-BNwrgsUO.js +0 -3
  339. package/server/export-BJHSVwKP.js +0 -87
  340. package/server/forge-8y6aEPTB.js +0 -2
  341. package/server/hume-CerGi2RH.js +0 -3
  342. package/server/inspect-agent-CWkeAB7J.js +0 -2
  343. package/server/lifecycle-Ck2UR27D.js +0 -14
  344. package/server/merge-ops-CFkQtXEj.js +0 -2
  345. package/server/projects-CrBE6IhN.js +0 -3
  346. package/server/public/assets/index-BAZxZ-8I.js +0 -796
  347. package/server/public/assets/index-FBG3JBfq.css +0 -1
  348. package/server/public/assets/mermaid-GHXKKRXX-BYP8MI37.js +0 -1
  349. package/server/rally-oggyp4cs.js +0 -3
  350. package/server/record-lEYK__LD.js +0 -3
  351. package/server/recovery-trip-BT7nb9OV.js +0 -98
  352. package/server/resolver-C7dLn8OK.js +0 -158
  353. package/server/resume-BYZBIab-.js +0 -3
  354. package/server/settings-Cy7SCFO9.js +0 -2
  355. package/server/specs-RzcDgozr.js +0 -3
  356. package/server/supervisor-CfX192ma.js +0 -2
  357. package/server/tmux-By8E_Yv_.js +0 -3
  358. package/server/token-util-C9u4An3K.js +0 -3
  359. package/server/tracker-config-BzfVj41Z.js +0 -3
  360. package/server/typed-errors-CrN1AByg.js +0 -3
  361. package/server/validation-Dq_wwcw3.js +0 -3
  362. package/server/verification-runner-D0Uh-9jc.js +0 -2
  363. package/server/workflows-BLwxUMP7.js +0 -2
  364. package/server/writer-BUweuRPx.js +0 -3
  365. package/server/writer-CrP2xuBn.js +0 -251
@@ -6,16 +6,17 @@ import { dirname, join, resolve, sep } from "path";
6
6
  import { homedir, totalmem } from "os";
7
7
  import { fileURLToPath } from "url";
8
8
  import * as NFS from "node:fs";
9
- import { appendFileSync as appendFileSync$1, existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, renameSync, writeFileSync as writeFileSync$1 } from "node:fs";
9
+ import { appendFileSync as appendFileSync$1, closeSync as closeSync$1, existsSync as existsSync$1, fsyncSync, mkdirSync as mkdirSync$1, openSync as openSync$1, readFileSync as readFileSync$1, renameSync, rmSync, writeFileSync as writeFileSync$1 } from "node:fs";
10
10
  import * as Path from "node:path";
11
11
  import { basename, dirname as dirname$1, isAbsolute, join as join$1, resolve as resolve$1 } from "node:path";
12
- import { readFile } from "node:fs/promises";
12
+ import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
13
13
  import * as OS from "node:os";
14
+ import { hostname } from "node:os";
14
15
  import * as NodeChildProcess from "node:child_process";
15
16
  import { execFile as execFile$1 } from "node:child_process";
16
17
  import * as Crypto from "node:crypto";
17
18
  import * as NodeUrl from "node:url";
18
- import { mkdir, writeFile } from "fs/promises";
19
+ import { mkdir as mkdir$1, writeFile as writeFile$1 } from "fs/promises";
19
20
  import { promisify } from "node:util";
20
21
  import { promisify as promisify$1 } from "util";
21
22
  //#region \0rolldown/runtime.js
@@ -2907,7 +2908,7 @@ const isNone = isNone$1;
2907
2908
  * @category Pattern matching
2908
2909
  * @since 2.0.0
2909
2910
  */
2910
- const match$1 = /* @__PURE__ */ dual(2, (self, { onNone, onSome }) => isNone(self) ? onNone() : onSome(self.value));
2911
+ const match$3 = /* @__PURE__ */ dual(2, (self, { onNone, onSome }) => isNone(self) ? onNone() : onSome(self.value));
2911
2912
  /**
2912
2913
  * Extracts the value from a `Some`, or evaluates a fallback thunk on `None`.
2913
2914
  *
@@ -4552,7 +4553,7 @@ const weeks = (weeks) => make$7(weeks * 6048e5);
4552
4553
  * @category getters
4553
4554
  * @since 2.0.0
4554
4555
  */
4555
- const toMillis = (self) => match(fromInputUnsafe(self), {
4556
+ const toMillis = (self) => match$2(fromInputUnsafe(self), {
4556
4557
  onMillis: identity,
4557
4558
  onNanos: (nanos) => Number(nanos) / 1e6,
4558
4559
  onInfinity: () => Infinity,
@@ -4615,7 +4616,7 @@ const toNanosUnsafe = (input) => {
4615
4616
  * @category pattern matching
4616
4617
  * @since 2.0.0
4617
4618
  */
4618
- const match = /* @__PURE__ */ dual(2, (self, options) => {
4619
+ const match$2 = /* @__PURE__ */ dual(2, (self, options) => {
4619
4620
  switch (self.value._tag) {
4620
4621
  case "Millis": return options.onMillis(self.value.millis);
4621
4622
  case "Nanos": return options.onNanos(self.value.nanos);
@@ -5726,6 +5727,11 @@ const matchEffect$2 = /* @__PURE__ */ dual(2, (self, options) => matchCauseEffec
5726
5727
  onSuccess: options.onSuccess
5727
5728
  }));
5728
5729
  /** @internal */
5730
+ const match$1 = /* @__PURE__ */ dual(2, (self, options) => matchEffect$2(self, {
5731
+ onFailure: (error) => sync$1(() => options.onFailure(error)),
5732
+ onSuccess: (value) => sync$1(() => options.onSuccess(value))
5733
+ }));
5734
+ /** @internal */
5729
5735
  const exit = (self) => effectIsExit(self) ? exitSucceed(self) : exitPrimitive(self);
5730
5736
  const exitPrimitive = /* @__PURE__ */ makePrimitive({
5731
5737
  op: "Exit",
@@ -5743,6 +5749,11 @@ const exitPrimitive = /* @__PURE__ */ makePrimitive({
5743
5749
  /** @internal */
5744
5750
  const timeoutOrElse$1 = /* @__PURE__ */ dual(2, (self, options) => raceFirst$1(self, flatMap$1(sleep(options.duration), options.orElse)));
5745
5751
  /** @internal */
5752
+ const timeout$1 = /* @__PURE__ */ dual(2, (self, duration) => timeoutOrElse$1(self, {
5753
+ duration,
5754
+ orElse: () => fail$3(new TimeoutError())
5755
+ }));
5756
+ /** @internal */
5746
5757
  const ScopeTypeId = "~effect/Scope";
5747
5758
  /** @internal */
5748
5759
  const ScopeCloseableTypeId = "~effect/Scope/Closeable";
@@ -6097,6 +6108,26 @@ const runForkWith = (context) => (effect, options) => {
6097
6108
  /** @internal */
6098
6109
  const runFork$1 = /* @__PURE__ */ runForkWith(/* @__PURE__ */ empty$2());
6099
6110
  /** @internal */
6111
+ const runPromiseExitWith = (context) => {
6112
+ const runFork = runForkWith(context);
6113
+ return (effect, options) => {
6114
+ const fiber = runFork(effect, options);
6115
+ return new Promise((resolve) => {
6116
+ fiber.addObserver((exit) => resolve(exit));
6117
+ });
6118
+ };
6119
+ };
6120
+ /** @internal */
6121
+ const runPromiseWith = (context) => {
6122
+ const runPromiseExit = runPromiseExitWith(context);
6123
+ return (effect, options) => runPromiseExit(effect, options).then((exit) => {
6124
+ if (exit._tag === "Failure") throw causeSquash(exit.cause);
6125
+ return exit.value;
6126
+ });
6127
+ };
6128
+ /** @internal */
6129
+ const runPromise$1 = /* @__PURE__ */ runPromiseWith(/* @__PURE__ */ empty$2());
6130
+ /** @internal */
6100
6131
  const runSyncExitWith = (context) => {
6101
6132
  const runFork = runForkWith(context);
6102
6133
  return (effect) => {
@@ -6207,7 +6238,15 @@ const processOrPerformanceNow = /* @__PURE__ */ function() {
6207
6238
  const clockWith = (f) => withFiber((fiber) => f(fiber.getRef(ClockRef)));
6208
6239
  /** @internal */
6209
6240
  const sleep = (duration) => clockWith((clock) => clock.sleep(fromInputUnsafe(duration)));
6210
- TaggedError$1("TimeoutError");
6241
+ /** @internal */
6242
+ const TimeoutErrorTypeId = "~effect/Cause/TimeoutError";
6243
+ /** @internal */
6244
+ var TimeoutError = class extends TaggedError$1("TimeoutError") {
6245
+ [TimeoutErrorTypeId] = TimeoutErrorTypeId;
6246
+ constructor(message) {
6247
+ super({ message });
6248
+ }
6249
+ };
6211
6250
  TaggedError$1("IllegalArgumentError");
6212
6251
  TaggedError$1("ExceededCapacityError");
6213
6252
  /** @internal */
@@ -6464,6 +6503,46 @@ const tracerLogger = /* @__PURE__ */ loggerMake(({ cause, fiber, logLevel, messa
6464
6503
  */
6465
6504
  const fail$2 = causeFail;
6466
6505
  /**
6506
+ * Collapses a `Cause` into a single `unknown` value, picking the "most
6507
+ * important" failure in this order:
6508
+ *
6509
+ * **When to use**
6510
+ *
6511
+ * Use to collapse a structured cause to the single value that synchronous and
6512
+ * promise runners would throw.
6513
+ *
6514
+ * **Details**
6515
+ *
6516
+ * 1. First `Fail` error (the `E` value)
6517
+ * 2. First `Die` defect
6518
+ * 3. A generic `Error("All fibers interrupted without error")` for interrupt-only causes
6519
+ * 4. A generic `Error("Empty cause")` for `empty`
6520
+ *
6521
+ * This is the function used by `Effect.runPromise` and `Effect.runSync` to
6522
+ * decide what to throw.
6523
+ *
6524
+ * **Gotchas**
6525
+ *
6526
+ * This function is lossy. Use {@link prettyErrors} or iterate `cause.reasons`
6527
+ * when you need all failures.
6528
+ *
6529
+ * **Example** (squashing a cause)
6530
+ *
6531
+ * ```ts
6532
+ * import { Cause } from "effect"
6533
+ *
6534
+ * console.log(Cause.squash(Cause.fail("error"))) // "error"
6535
+ * console.log(Cause.squash(Cause.die("defect"))) // "defect"
6536
+ * ```
6537
+ *
6538
+ * @see {@link prettyErrors} — non-lossy conversion to `Array<Error>`
6539
+ * @see {@link pretty} — human-readable string rendering
6540
+ *
6541
+ * @category destructors
6542
+ * @since 2.0.0
6543
+ */
6544
+ const squash = causeSquash;
6545
+ /**
6467
6546
  * Returns a `Result` whose success value is the first typed error value `E`
6468
6547
  * from a `Fail` reason in the cause. If the cause has no `Fail` reason,
6469
6548
  * the failure value is the original cause narrowed to `Cause<never>`, because
@@ -6926,7 +7005,7 @@ const makeUnsafe$1 = scopeMakeUnsafe;
6926
7005
  * @category combinators
6927
7006
  * @since 4.0.0
6928
7007
  */
6929
- const provide$1 = provideScope;
7008
+ const provide$3 = provideScope;
6930
7009
  /**
6931
7010
  * Registers a finalizer effect on a scope.
6932
7011
  *
@@ -7193,9 +7272,124 @@ var MemoMapImpl = class {
7193
7272
  * @since 4.0.0
7194
7273
  */
7195
7274
  const makeMemoMapUnsafe = () => new MemoMapImpl();
7196
- (class extends Service()("effect/Layer/CurrentMemoMap") {
7275
+ /**
7276
+ * Context service for the current `MemoMap` used in layer construction.
7277
+ *
7278
+ * **When to use**
7279
+ *
7280
+ * Use when building custom layer operations that need to access the current
7281
+ * memoization map from the fiber context.
7282
+ *
7283
+ * **Details**
7284
+ *
7285
+ * This service wraps a `MemoMap` as a `Context.Service`, making it available
7286
+ * for dependency injection during layer construction.
7287
+ *
7288
+ * @see {@link MemoMap} the memoization map type wrapped by this service
7289
+ *
7290
+ * @category models
7291
+ * @since 3.13.0
7292
+ */
7293
+ var CurrentMemoMap = class extends Service()("effect/Layer/CurrentMemoMap") {
7197
7294
  static getOrCreate = /* @__PURE__ */ getOrElse(this, makeMemoMapUnsafe);
7198
- });
7295
+ };
7296
+ /**
7297
+ * Builds a layer into an `Effect` value, using the specified `MemoMap` to memoize
7298
+ * the layer construction.
7299
+ *
7300
+ * **Example** (Building layers with an explicit memo map)
7301
+ *
7302
+ * ```ts
7303
+ * import { Context, Effect, Layer } from "effect"
7304
+ *
7305
+ * class Database extends Context.Service<Database, {
7306
+ * readonly query: (sql: string) => Effect.Effect<string>
7307
+ * }>()("Database") {}
7308
+ *
7309
+ * class Logger extends Context.Service<Logger, {
7310
+ * readonly log: (msg: string) => Effect.Effect<void>
7311
+ * }>()("Logger") {}
7312
+ *
7313
+ * // Build layers with explicit memoization control
7314
+ * const program = Effect.gen(function*() {
7315
+ * const memoMap = yield* Layer.makeMemoMap
7316
+ * const scope = yield* Effect.scope
7317
+ *
7318
+ * // Build database layer with memoization
7319
+ * const dbLayer = Layer.succeed(Database, {
7320
+ * query: Effect.fn("Database.query")((sql: string) => Effect.succeed("result"))
7321
+ * })
7322
+ * const dbContext = yield* Layer.buildWithMemoMap(dbLayer, memoMap, scope)
7323
+ *
7324
+ * // Build logger layer with same memoization (reuses memo if same layer)
7325
+ * const loggerLayer = Layer.succeed(Logger, {
7326
+ * log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(msg)))
7327
+ * })
7328
+ * const loggerContext = yield* Layer.buildWithMemoMap(
7329
+ * loggerLayer,
7330
+ * memoMap,
7331
+ * scope
7332
+ * )
7333
+ *
7334
+ * return {
7335
+ * database: Context.get(dbContext, Database),
7336
+ * logger: Context.get(loggerContext, Logger)
7337
+ * }
7338
+ * })
7339
+ * ```
7340
+ *
7341
+ * @category memo map
7342
+ * @since 2.0.0
7343
+ */
7344
+ const buildWithMemoMap = /* @__PURE__ */ dual(3, (self, memoMap, scope) => provideService(map$4(self.build(memoMap, scope), add(CurrentMemoMap, memoMap)), CurrentMemoMap, memoMap));
7345
+ /**
7346
+ * Builds a layer using an explicit scope.
7347
+ *
7348
+ * **When to use**
7349
+ *
7350
+ * Use to control the lifetime of layer resources with a scope supplied by the
7351
+ * caller.
7352
+ *
7353
+ * **Details**
7354
+ *
7355
+ * Resources created by the layer are released when the supplied scope is
7356
+ * closed, unless a resource extends its own scope.
7357
+ *
7358
+ * **Example** (Building a layer with an explicit scope)
7359
+ *
7360
+ * ```ts
7361
+ * import { Context, Effect, Layer, Scope } from "effect"
7362
+ *
7363
+ * class Database extends Context.Service<Database, {
7364
+ * readonly query: (sql: string) => Effect.Effect<string>
7365
+ * }>()("Database") {}
7366
+ *
7367
+ * // Build a layer with explicit scope control
7368
+ * const program = Effect.gen(function*() {
7369
+ * const scope = yield* Effect.scope
7370
+ *
7371
+ * const dbLayer = Layer.effect(Database, Effect.gen(function*() {
7372
+ * console.log("Initializing database...")
7373
+ * yield* Scope.addFinalizer(
7374
+ * scope,
7375
+ * Effect.sync(() => console.log("Database closed"))
7376
+ * )
7377
+ * return { query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result: ${sql}`)) }
7378
+ * }))
7379
+ *
7380
+ * // Build with specific scope - resources tied to this scope
7381
+ * const context = yield* Layer.buildWithScope(dbLayer, scope)
7382
+ * const database = Context.get(context, Database)
7383
+ *
7384
+ * return yield* database.query("SELECT * FROM users")
7385
+ * // Database will be closed when scope is closed
7386
+ * })
7387
+ * ```
7388
+ *
7389
+ * @category destructors
7390
+ * @since 2.0.0
7391
+ */
7392
+ const buildWithScope = /* @__PURE__ */ dual(2, (self, scope) => withFiber((fiber) => buildWithMemoMap(self, CurrentMemoMap.getOrCreate(fiber.context), scope)));
7199
7393
  /**
7200
7394
  * Constructs a layer that provides a single service from an already available
7201
7395
  * value.
@@ -7353,7 +7547,7 @@ const effectImpl = (service, effect) => effectContext(map$4(effect, (value) => m
7353
7547
  * @category constructors
7354
7548
  * @since 2.0.0
7355
7549
  */
7356
- const effectContext = (effect) => fromBuildMemo((_, scope) => provide$1(effect, scope));
7550
+ const effectContext = (effect) => fromBuildMemo((_, scope) => provide$3(effect, scope));
7357
7551
  const mergeAllEffect = (layers, memoMap, scope) => {
7358
7552
  const parentScope = forkUnsafe(scope, "parallel");
7359
7553
  return forEach$2(layers, (layer) => layer.build(memoMap, forkUnsafe(parentScope, "sequential")), { concurrency: layers.length }).pipe(map$4((context) => mergeAll$1(...context)));
@@ -7483,7 +7677,7 @@ const provideWith = (self, that, f) => fromBuild((memoMap, scope) => flatMap$1(A
7483
7677
  * @category utils
7484
7678
  * @since 2.0.0
7485
7679
  */
7486
- const provide = /* @__PURE__ */ dual(2, (self, that) => provideWith(self, that, identity));
7680
+ const provide$2 = /* @__PURE__ */ dual(2, (self, that) => provideWith(self, that, identity));
7487
7681
  /**
7488
7682
  * Provides a base class for yieldable errors.
7489
7683
  *
@@ -7740,6 +7934,11 @@ const matchEffect$1 = /* @__PURE__ */ dual(2, (self, options) => matchCauseEffec
7740
7934
  }
7741
7935
  }));
7742
7936
  //#endregion
7937
+ //#region ../../node_modules/.bun/effect@4.0.0-beta.73/node_modules/effect/dist/internal/layer.js
7938
+ const provideLayer = (self, layer, options) => scopedWith$1((scope) => flatMap$1(options?.local ? buildWithMemoMap(layer, makeMemoMapUnsafe(), scope) : buildWithScope(layer, scope), (context) => provideContext(self, context)));
7939
+ /** @internal */
7940
+ const provide$1 = /* @__PURE__ */ dual((args) => isEffect(args[0]), (self, source, options) => isContext(source) ? provideContext(self, source) : provideLayer(self, Array.isArray(source) ? mergeAll(...source) : source, options));
7941
+ //#endregion
7743
7942
  //#region ../../node_modules/.bun/effect@4.0.0-beta.73/node_modules/effect/dist/Effect.js
7744
7943
  /**
7745
7944
  * Executes an effectful operation for each element in an `Iterable`.
@@ -8755,6 +8954,65 @@ const orDie = orDie$1;
8755
8954
  */
8756
8955
  const ignore = ignore$1;
8757
8956
  /**
8957
+ * Adds a time limit to an effect, triggering a timeout if the effect exceeds
8958
+ * the duration.
8959
+ *
8960
+ * **When to use**
8961
+ *
8962
+ * Use when exceeding the time limit should be represented as a typed
8963
+ * failure. Use `timeoutOption` when a timeout should become `Option.none`, and
8964
+ * `timeoutOrElse` when you want to run a fallback effect.
8965
+ *
8966
+ * **Details**
8967
+ *
8968
+ * The `timeout` function allows you to specify a time limit for an
8969
+ * effect's execution. If the effect does not complete within the given time, a
8970
+ * `TimeoutException` is raised. This can be useful for controlling how long
8971
+ * your program waits for a task to finish, ensuring that it doesn't hang
8972
+ * indefinitely if the task takes too long.
8973
+ *
8974
+ * **Gotchas**
8975
+ *
8976
+ * If the timeout wins, the source effect is interrupted.
8977
+ *
8978
+ * **Example** (Failing when work takes too long)
8979
+ *
8980
+ * ```ts
8981
+ * import { Effect } from "effect"
8982
+ *
8983
+ * const task = Effect.gen(function*() {
8984
+ * console.log("Start processing...")
8985
+ * yield* Effect.sleep("2 seconds") // Simulates a delay in processing
8986
+ * console.log("Processing complete.")
8987
+ * return "Result"
8988
+ * })
8989
+ *
8990
+ * // Output will show a TimeoutException as the task takes longer
8991
+ * // than the specified timeout duration
8992
+ * const timedEffect = task.pipe(Effect.timeout("1 second"))
8993
+ *
8994
+ * Effect.runPromiseExit(timedEffect).then(console.log)
8995
+ * // Output:
8996
+ * // Start processing...
8997
+ * // {
8998
+ * // _id: 'Exit',
8999
+ * // _tag: 'Failure',
9000
+ * // cause: {
9001
+ * // _id: 'Cause',
9002
+ * // _tag: 'Fail',
9003
+ * // failure: { _tag: 'TimeoutException' }
9004
+ * // }
9005
+ * // }
9006
+ * ```
9007
+ *
9008
+ * @see {@link timeoutOption} for returning `Option.none` on timeout.
9009
+ * @see {@link timeoutOrElse} for a version that allows specifying both success and timeout handlers.
9010
+ *
9011
+ * @category delays & timeouts
9012
+ * @since 2.0.0
9013
+ */
9014
+ const timeout = timeout$1;
9015
+ /**
8758
9016
  * Applies a timeout to an effect, with a fallback effect executed if the timeout is reached.
8759
9017
  *
8760
9018
  * **When to use**
@@ -8841,6 +9099,59 @@ const timeoutOrElse = timeoutOrElse$1;
8841
9099
  */
8842
9100
  const raceFirst = raceFirst$1;
8843
9101
  /**
9102
+ * Handles both success and failure cases of an effect without performing side
9103
+ * effects.
9104
+ *
9105
+ * **When to use**
9106
+ *
9107
+ * Use when this is useful for structuring your code to respond differently to success or
9108
+ * failure without triggering side effects.
9109
+ *
9110
+ * **Details**
9111
+ *
9112
+ * `match` lets you define custom handlers for both success and failure
9113
+ * scenarios. You provide separate functions to handle each case, allowing you
9114
+ * to process the result if the effect succeeds, or handle the error if the
9115
+ * effect fails.
9116
+ *
9117
+ * **Example** (Matching success and failure values)
9118
+ *
9119
+ * ```ts
9120
+ * import { Data, Effect } from "effect"
9121
+ *
9122
+ * class ExampleError extends Data.TaggedError("ExampleError")<{ readonly message: string }> {}
9123
+ *
9124
+ * const success: Effect.Effect<number, ExampleError> = Effect.succeed(42)
9125
+ *
9126
+ * const program1 = Effect.match(success, {
9127
+ * onFailure: (error) => `failure: ${error.message}`,
9128
+ * onSuccess: (value) => `success: ${value}`
9129
+ * })
9130
+ *
9131
+ * // Run and log the result of the successful effect
9132
+ * Effect.runPromise(program1).then(console.log)
9133
+ * // Output: "success: 42"
9134
+ *
9135
+ * const failure: Effect.Effect<number, ExampleError> = Effect.fail(
9136
+ * new ExampleError({ message: "Uh oh!" })
9137
+ * )
9138
+ *
9139
+ * const program2 = Effect.match(failure, {
9140
+ * onFailure: (error) => `failure: ${error.message}`,
9141
+ * onSuccess: (value) => `success: ${value}`
9142
+ * })
9143
+ *
9144
+ * // Run and log the result of the failed effect
9145
+ * Effect.runPromise(program2).then(console.log)
9146
+ * // Output: "failure: Uh oh!"
9147
+ * ```
9148
+ *
9149
+ * @see {@link matchEffect} if you need to perform side effects in the handlers.
9150
+ * @category pattern matching
9151
+ * @since 2.0.0
9152
+ */
9153
+ const match = match$1;
9154
+ /**
8844
9155
  * Handles both success and failure by running effectful handlers.
8845
9156
  *
8846
9157
  * **When to use**
@@ -8901,6 +9212,41 @@ const raceFirst = raceFirst$1;
8901
9212
  */
8902
9213
  const matchEffect = matchEffect$2;
8903
9214
  /**
9215
+ * Provides dependencies to an effect using layers or a context. Use `options.local`
9216
+ * to build the layer every time; by default, layers are shared between provide
9217
+ * calls.
9218
+ *
9219
+ * **Example** (Providing dependencies with a layer)
9220
+ *
9221
+ * ```ts
9222
+ * import { Context, Effect, Layer } from "effect"
9223
+ *
9224
+ * interface Database {
9225
+ * readonly query: (sql: string) => Effect.Effect<string>
9226
+ * }
9227
+ *
9228
+ * const Database = Context.Service<Database>("Database")
9229
+ *
9230
+ * const DatabaseLive = Layer.succeed(Database)({
9231
+ * query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result for: ${sql}`))
9232
+ * })
9233
+ *
9234
+ * const program = Effect.gen(function*() {
9235
+ * const db = yield* Database
9236
+ * return yield* db.query("SELECT * FROM users")
9237
+ * })
9238
+ *
9239
+ * const provided = Effect.provide(program, DatabaseLive)
9240
+ *
9241
+ * Effect.runPromise(provided).then(console.log)
9242
+ * // Output: "Result for: SELECT * FROM users"
9243
+ * ```
9244
+ *
9245
+ * @category environment
9246
+ * @since 2.0.0
9247
+ */
9248
+ const provide = provide$1;
9249
+ /**
8904
9250
  * Optionally accesses a service from the environment.
8905
9251
  *
8906
9252
  * **When to use**
@@ -9269,6 +9615,43 @@ const forkScoped = forkScoped$1;
9269
9615
  */
9270
9616
  const runFork = runFork$1;
9271
9617
  /**
9618
+ * Executes an effect and returns the result as a `Promise`.
9619
+ *
9620
+ * **When to use**
9621
+ *
9622
+ * Use when you need to execute an effect and work with the
9623
+ * result using `Promise` syntax, typically for compatibility with other
9624
+ * promise-based code.
9625
+ *
9626
+ * If the effect succeeds, the promise will resolve with the result. If the
9627
+ * effect fails, the promise will reject with an error.
9628
+ *
9629
+ * **Example** (Running a successful effect as a Promise)
9630
+ *
9631
+ * ```ts
9632
+ * import { Effect } from "effect"
9633
+ *
9634
+ * Effect.runPromise(Effect.succeed(1)).then(console.log)
9635
+ * // Output: 1
9636
+ * ```
9637
+ *
9638
+ * **Example** (Running effects as promises)
9639
+ *
9640
+ * ```ts
9641
+ * //Example: Handling a Failing Effect as a Rejected Promise
9642
+ * import { Effect } from "effect"
9643
+ *
9644
+ * Effect.runPromise(Effect.fail("my error")).catch(console.error)
9645
+ * // Output:
9646
+ * // (FiberFailure) Error: my error
9647
+ * ```
9648
+ *
9649
+ * @see {@link runPromiseExit} for a version that returns an `Exit` type instead of rejecting.
9650
+ * @category running effects
9651
+ * @since 2.0.0
9652
+ */
9653
+ const runPromise = runPromise$1;
9654
+ /**
9272
9655
  * Executes an effect synchronously and returns its success value.
9273
9656
  *
9274
9657
  * **When to use**
@@ -10734,7 +11117,7 @@ const toTransform = (channel) => channel.transform;
10734
11117
  const asyncQueue = (scope, f, options) => make$4({
10735
11118
  capacity: options?.bufferSize,
10736
11119
  strategy: options?.strategy
10737
- }).pipe(tap((queue) => addFinalizer(scope, shutdown(queue))), tap((queue) => forkIn(provide$1(f(queue), scope), scope)));
11120
+ }).pipe(tap((queue) => addFinalizer(scope, shutdown(queue))), tap((queue) => forkIn(provide$3(f(queue), scope), scope)));
10738
11121
  /**
10739
11122
  * Creates a `Channel` that interacts with a callback function using a queue, emitting arrays.
10740
11123
  *
@@ -11101,7 +11484,7 @@ const unwrap$2 = (channel) => fromTransform$1((upstream, scope) => {
11101
11484
  let pull;
11102
11485
  return succeed(suspend$2(() => {
11103
11486
  if (pull) return pull;
11104
- return channel.pipe(provide$1(scope), flatMap((channel) => toTransform(channel)(upstream, scope)), flatMap((pull_) => pull = pull_));
11487
+ return channel.pipe(provide$3(scope), flatMap((channel) => toTransform(channel)(upstream, scope)), flatMap((pull_) => pull = pull_));
11105
11488
  }));
11106
11489
  });
11107
11490
  const runWith = (self, f, onHalt) => suspend$2(() => {
@@ -11132,7 +11515,7 @@ const runWith = (self, f, onHalt) => suspend$2(() => {
11132
11515
  * @category execution
11133
11516
  * @since 4.0.0
11134
11517
  */
11135
- const runFold = /* @__PURE__ */ dual(3, (self, initial, f) => suspend$2(() => {
11518
+ const runFold$1 = /* @__PURE__ */ dual(3, (self, initial, f) => suspend$2(() => {
11136
11519
  let state = initial();
11137
11520
  return runWith(self, (pull) => whileLoop({
11138
11521
  while: constTrue,
@@ -12103,11 +12486,39 @@ const run = /* @__PURE__ */ dual(2, (self, sink) => scopedWith((scope) => toPull
12103
12486
  * @category destructors
12104
12487
  * @since 2.0.0
12105
12488
  */
12106
- const runCollect = (self) => runFold(self.channel, () => [], (acc, chunk) => {
12489
+ const runCollect = (self) => runFold$1(self.channel, () => [], (acc, chunk) => {
12107
12490
  for (let i = 0; i < chunk.length; i++) acc.push(chunk[i]);
12108
12491
  return acc;
12109
12492
  });
12110
12493
  /**
12494
+ * Runs the stream and folds elements using a pure reducer.
12495
+ *
12496
+ * **Example** (Folding stream values)
12497
+ *
12498
+ * ```ts
12499
+ * import { Console, Effect, Stream } from "effect"
12500
+ *
12501
+ * const program = Effect.gen(function*() {
12502
+ * const total = yield* Stream.runFold(
12503
+ * Stream.make(1, 2, 3),
12504
+ * () => 0,
12505
+ * (acc, n) => acc + n
12506
+ * )
12507
+ * yield* Console.log(total)
12508
+ * })
12509
+ *
12510
+ * Effect.runPromise(program)
12511
+ * // 6
12512
+ * ```
12513
+ *
12514
+ * @category destructors
12515
+ * @since 2.0.0
12516
+ */
12517
+ const runFold = /* @__PURE__ */ dual(3, (self, initial, f) => runFold$1(self.channel, initial, (acc, arr) => {
12518
+ for (let i = 0; i < arr.length; i++) acc = f(acc, arr[i]);
12519
+ return acc;
12520
+ }));
12521
+ /**
12111
12522
  * Concatenates all emitted strings into a single string.
12112
12523
  *
12113
12524
  * **Example** (Joining strings from a stream)
@@ -12128,7 +12539,7 @@ const runCollect = (self) => runFold(self.channel, () => [], (acc, chunk) => {
12128
12539
  * @category destructors
12129
12540
  * @since 2.0.0
12130
12541
  */
12131
- const mkString = (self) => runFold(self.channel, () => "", (acc, chunk) => acc + chunk.join(""));
12542
+ const mkString = (self) => runFold$1(self.channel, () => "", (acc, chunk) => acc + chunk.join(""));
12132
12543
  //#endregion
12133
12544
  //#region ../../node_modules/.bun/effect@4.0.0-beta.73/node_modules/effect/dist/FileSystem.js
12134
12545
  /**
@@ -12317,7 +12728,7 @@ const make$3 = (impl) => FileSystem.of({
12317
12728
  return fromPull(succeed(flatMap(suspend$2(() => {
12318
12729
  if (bytesToRead !== void 0 && bytesToRead <= totalBytesRead) return done$1();
12319
12730
  return bytesToRead !== void 0 && bytesToRead - totalBytesRead < chunkSize ? file.readAlloc(bytesToRead - totalBytesRead) : readChunk;
12320
- }), match$1({
12731
+ }), match$3({
12321
12732
  onNone: () => done$1(),
12322
12733
  onSome: (buf) => {
12323
12734
  totalBytesRead += BigInt(buf.length);
@@ -12563,6 +12974,7 @@ join(OVERDECK_HOME, "certs");
12563
12974
  join(CONFIG_DIR, "config.toml");
12564
12975
  join(CONFIG_DIR, "settings.json");
12565
12976
  const CLAUDE_DIR = join(homedir(), ".claude");
12977
+ join(homedir(), ".agents", "skills");
12566
12978
  join(homedir(), ".codex"), join(homedir(), ".cursor"), join(homedir(), ".gemini"), join(homedir(), ".opencode");
12567
12979
  join(CLAUDE_DIR, "skills"), join(CLAUDE_DIR, "commands"), join(CLAUDE_DIR, "agents");
12568
12980
  join(join(OVERDECK_HOME, "templates"), "claude-md", "sections");
@@ -12607,7 +13019,8 @@ TaggedError("VcsError");
12607
13019
  TaggedError("VcsTimeoutError");
12608
13020
  TaggedError("FsError");
12609
13021
  TaggedError("FsNotFoundError");
12610
- TaggedError("GitError");
13022
+ /** A git command exited with a non-zero code. */
13023
+ var GitError = class extends TaggedError("GitError") {};
12611
13024
  TaggedError("MergeConflictError");
12612
13025
  /** A tmux command failed. */
12613
13026
  var TmuxError = class extends TaggedError("TmuxError") {};
@@ -18417,7 +18830,7 @@ const makeTempFileFactory = (method) => {
18417
18830
  const directory = yield* makeDirectory(options);
18418
18831
  const random = Crypto.randomBytes(6).toString("hex");
18419
18832
  const name = Path.join(directory, options?.suffix ? `${random}${options.suffix}` : random);
18420
- yield* writeFile$1(name, new Uint8Array(0));
18833
+ yield* writeFile$2(name, new Uint8Array(0));
18421
18834
  return name;
18422
18835
  });
18423
18836
  };
@@ -18524,7 +18937,7 @@ const watchNode = (path) => callback((queue) => acquireRelease(sync(() => {
18524
18937
  return watcher;
18525
18938
  }), (watcher) => sync(() => watcher.close())));
18526
18939
  const watch = (backend, path) => stat$1(path).pipe(map$3((stat) => backend.pipe(flatMap$2((_) => _.register(path, stat)), getOrElse$1(() => watchNode(path)))), unwrap);
18527
- const writeFile$1 = (path, data, options) => callback$1((resume, signal) => {
18940
+ const writeFile$2 = (path, data, options) => callback$1((resume, signal) => {
18528
18941
  try {
18529
18942
  NFS.writeFile(path, data, {
18530
18943
  signal,
@@ -18564,7 +18977,7 @@ const makeFileSystem = /* @__PURE__ */ map$3(/* @__PURE__ */ serviceOption(Watch
18564
18977
  watch(path) {
18565
18978
  return watch(backend, path);
18566
18979
  },
18567
- writeFile: writeFile$1
18980
+ writeFile: writeFile$2
18568
18981
  }));
18569
18982
  //#endregion
18570
18983
  //#region ../../node_modules/.bun/@effect+platform-node@4.0.0-beta.73/node_modules/@effect/platform-node/dist/NodeFileSystem.js
@@ -25395,6 +25808,20 @@ function listProjectsSync() {
25395
25808
  }));
25396
25809
  }
25397
25810
  /**
25811
+ * Find project by workspace path.
25812
+ * Matches any project whose root path is an ancestor of the given path.
25813
+ * Used to resolve the tracker (GitHub/GitLab) from a workspace directory.
25814
+ */
25815
+ function findProjectByPathSync(workspacePath) {
25816
+ const config = loadProjectsConfigSync();
25817
+ const normalizedTarget = resolve(workspacePath);
25818
+ for (const [, projectConfig] of Object.entries(config.projects)) {
25819
+ const normalizedProject = resolve(projectConfig.path);
25820
+ if (normalizedTarget === normalizedProject || normalizedTarget.startsWith(normalizedProject + "/")) return projectConfig;
25821
+ }
25822
+ return null;
25823
+ }
25824
+ /**
25398
25825
  * Resolve the correct project path for an issue based on labels
25399
25826
  *
25400
25827
  * @param project - The project config
@@ -25499,10 +25926,11 @@ function resolveProjectFromIssueSync(issueId, labels = []) {
25499
25926
  function projectKey(project, explicit) {
25500
25927
  if (explicit) return explicit;
25501
25928
  const projectPath = resolve$1(project.path);
25502
- return listProjectsSync().find(({ config }) => resolve$1(config.path) === projectPath)?.key ?? basename(projectPath);
25929
+ return (listProjectsSync() ?? []).find(({ config }) => resolve$1(config.path) === projectPath)?.key ?? basename(projectPath);
25503
25930
  }
25504
25931
  //#endregion
25505
25932
  //#region ../../src/lib/state-read-home.ts
25933
+ const STATE_BRANCH = "overdeck-state";
25506
25934
  function validMarker(value) {
25507
25935
  if (!value || typeof value !== "object") return false;
25508
25936
  const marker = value;
@@ -25528,17 +25956,455 @@ function resolveStateReadHomeSync(project, projectKey$1) {
25528
25956
  };
25529
25957
  }
25530
25958
  }
25531
- promisify(execFile$1);
25532
- layer$4.pipe(provide(mergeAll(layer$2, layer)));
25533
- const DEFAULT_STATE_FLUSH_WINDOW_MS = 0;
25534
- parseStateFlushWindowMs(process.env.OVERDECK_STATE_FLUSH_WINDOW_MS);
25535
- function parseStateFlushWindowMs(value) {
25536
- if (!value) return DEFAULT_STATE_FLUSH_WINDOW_MS;
25959
+ //#endregion
25960
+ //#region ../../src/lib/state-migration-lock.ts
25961
+ function stateMigrationLockPath(projectKey) {
25962
+ return join$1(getOverdeckHome(), "locks", "state-migration", `${projectKey}.lock`);
25963
+ }
25964
+ function isStateMigrationLocked(projectKey) {
25965
+ try {
25966
+ closeSync$1(openSync$1(stateMigrationLockPath(projectKey), "wx"));
25967
+ rmSync(stateMigrationLockPath(projectKey));
25968
+ return false;
25969
+ } catch {
25970
+ return true;
25971
+ }
25972
+ }
25973
+ //#endregion
25974
+ //#region ../../src/lib/state-plane.ts
25975
+ const execFileAsync$1 = promisify(execFile$1);
25976
+ const STATE_PLANE_PATHS = [
25977
+ ".pan/records/",
25978
+ ".pan/continues/",
25979
+ ".pan/continue.json",
25980
+ ".pan/specs/",
25981
+ ".pan/test/",
25982
+ ".pan/review/",
25983
+ ".pan/feedback/"
25984
+ ];
25985
+ function isStatePlanePath(relativePath) {
25986
+ const normalized = relativePath.trim().replace(/\\/g, "/");
25987
+ return STATE_PLANE_PATHS.some((statePath) => {
25988
+ if (statePath.endsWith("/")) return normalized === statePath.slice(0, -1) || normalized.startsWith(statePath);
25989
+ return normalized === statePath;
25990
+ });
25991
+ }
25992
+ async function isStatePlaneOnlyDiff(baseSha, tipSha, repoRoot) {
25993
+ const { stdout } = await execFileAsync$1("git", [
25994
+ "diff",
25995
+ "--name-only",
25996
+ baseSha,
25997
+ tipSha
25998
+ ], {
25999
+ cwd: repoRoot,
26000
+ encoding: "utf-8"
26001
+ });
26002
+ return stdout.split("\n").map((line) => line.trim()).filter(Boolean).every(isStatePlanePath);
26003
+ }
26004
+ //#endregion
26005
+ //#region ../../src/lib/pan-dir/auto-commit.ts
26006
+ /**
26007
+ * Auto-commit helper for operational state files (.pan/, .beads/).
26008
+ *
26009
+ * Background: planning and work agents continuously write to .pan/continues/,
26010
+ * .pan/specs/, .pan/drafts/, and .beads/issues.jsonl on the project root.
26011
+ * Without this helper those writes accumulate uncommitted on `main`, requiring
26012
+ * periodic manual "chore: sync workspace state" passes from the operator and
26013
+ * making the project repo stay perpetually dirty.
26014
+ *
26015
+ * This module exposes a serialized write-through commit primitive that pan-dir
26016
+ * writers call after they update a file. Commits are:
26017
+ * - scheduled on the next event-loop turn so every state update reaches git + origin
26018
+ * - serialized within a process so the git index is never contested
26019
+ * - best-effort for synchronous callers: failures are logged and reported by flushes
26020
+ * - main-only: feature branches have their own commit cadence owned by agents
26021
+ *
26022
+ * Cross-machine concern: when an agent's state is canonical on `main`, moving
26023
+ * the agent between machines becomes "stop on A, pull on B, resume on B." The
26024
+ * sync-state-via-commit shape this helper produces is the substrate for that.
26025
+ */
26026
+ const spawnerLayer = layer$4.pipe(provide$2(mergeAll(layer$2, layer)));
26027
+ const DEFAULT_STATE_PUSH_TIMEOUT_MS = 3e4;
26028
+ function parsePositiveInteger(value, fallback) {
26029
+ if (!value) return fallback;
25537
26030
  const parsed = Number(value);
25538
- if (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_STATE_FLUSH_WINDOW_MS;
26031
+ if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
25539
26032
  return parsed;
25540
26033
  }
25541
- Promise.resolve();
26034
+ /**
26035
+ * Paths that must never enter a pipeline auto-commit, regardless of gitignore
26036
+ * state. Mirrors the exclusion list in src/lib/cloister/merge-agent.ts.
26037
+ */
26038
+ const AUTO_COMMIT_EXCLUDED_PATHS = [
26039
+ ".pan/kickoff.md",
26040
+ ".pan/continue.json",
26041
+ ".pan/handoff-*.md",
26042
+ ".pan/spec.vbrief.json",
26043
+ ".claude/rules/",
26044
+ ".claude/skills/"
26045
+ ];
26046
+ function isAutoCommitExcludedPath(relativePath) {
26047
+ const normalized = relativePath.replace(/\\/g, "/");
26048
+ for (const pattern of AUTO_COMMIT_EXCLUDED_PATHS) if (pattern.endsWith("/")) {
26049
+ if (normalized.startsWith(pattern) || normalized === pattern.slice(0, -1)) return true;
26050
+ } else if (pattern.includes("*")) {
26051
+ if (new RegExp("^" + pattern.replace(/\./g, "\\.").replace(/\*/g, "[^/]*") + "$").test(normalized)) return true;
26052
+ } else if (normalized === pattern) return true;
26053
+ return false;
26054
+ }
26055
+ const pending = /* @__PURE__ */ new Map();
26056
+ let serializer = Promise.resolve();
26057
+ /** Run a git subcommand. Fails with GitError on non-zero exit. */
26058
+ function runGit(args, cwd) {
26059
+ return gen(function* () {
26060
+ const handle = yield* make$1("git", [...args], {
26061
+ cwd,
26062
+ env: { HUSKY: "0" },
26063
+ extendEnv: true
26064
+ });
26065
+ const stdoutBuf = yield* runFold(handle.stdout, () => Buffer.alloc(0), (acc, chunk) => Buffer.concat([acc, Buffer.from(chunk)]));
26066
+ const stderrBuf = yield* runFold(handle.stderr, () => Buffer.alloc(0), (acc, chunk) => Buffer.concat([acc, Buffer.from(chunk)]));
26067
+ const exitCode = yield* handle.exitCode;
26068
+ if (exitCode !== 0) return yield* fail(new GitError({
26069
+ command: ["git", ...args],
26070
+ stderr: stderrBuf.toString("utf-8"),
26071
+ exitCode
26072
+ }));
26073
+ return {
26074
+ stdout: stdoutBuf.toString("utf-8"),
26075
+ stderr: stderrBuf.toString("utf-8"),
26076
+ exitCode
26077
+ };
26078
+ }).pipe(scoped, provide(spawnerLayer), catchCause((cause) => fail(causeToGitError(cause, args))));
26079
+ }
26080
+ function runGitWithTimeout(args, cwd, timeoutMs) {
26081
+ return runGit(args, cwd).pipe(timeout(millis(timeoutMs)), catchCause((cause) => fail(causeToGitError(cause, args))));
26082
+ }
26083
+ function causeToGitError(cause, args) {
26084
+ const squashed = squash(cause);
26085
+ if (isGitError(squashed)) return squashed;
26086
+ return new GitError({
26087
+ command: ["git", ...args],
26088
+ stderr: String(squashed),
26089
+ exitCode: -1,
26090
+ cause
26091
+ });
26092
+ }
26093
+ function isGitError(value) {
26094
+ return typeof value === "object" && value !== null && "_tag" in value && value._tag === "GitError";
26095
+ }
26096
+ /**
26097
+ * Queue an auto-commit for one or more files. Returns immediately; the
26098
+ * serialized commit-and-push starts on the next timer turn. Callers whose
26099
+ * success depends on remote durability must also await flushAutoCommits().
26100
+ *
26101
+ * PAN-1908: `repoRoot` allows committing files to a different git checkout
26102
+ * than the project root (e.g., a declared infra repo for per-issue permanent
26103
+ * records). When omitted, commits go to `projectRoot` as before.
26104
+ */
26105
+ function queueAutoCommit(opts) {
26106
+ const { projectRoot, paths, subject } = opts;
26107
+ let { repoRoot } = opts;
26108
+ if (paths.length === 0) return;
26109
+ let expectedBranch = "main";
26110
+ if (repoRoot && existsSync(join(repoRoot, "migration-complete.json"))) expectedBranch = STATE_BRANCH;
26111
+ const project = findProjectByPathSync(projectRoot);
26112
+ if (project) {
26113
+ const key = listProjectsSync().find(({ config }) => config.path === project.path)?.key;
26114
+ if (key && isStateMigrationLocked(key)) {
26115
+ console.warn(`[pan-dir/auto-commit] refusing state write while migration lock is held for ${key}`);
26116
+ return;
26117
+ }
26118
+ const stateHome = resolveStateReadHomeSync(project);
26119
+ if (stateHome.migrated) {
26120
+ repoRoot = stateHome.root;
26121
+ expectedBranch = STATE_BRANCH;
26122
+ }
26123
+ }
26124
+ const existing = pending.get(projectRoot);
26125
+ if (existing) {
26126
+ paths.forEach((p) => existing.paths.add(p));
26127
+ existing.subjects.push(subject);
26128
+ existing.repoRoot ??= repoRoot;
26129
+ if (expectedBranch === "overdeck-state") existing.expectedBranch = STATE_BRANCH;
26130
+ return;
26131
+ }
26132
+ pending.set(projectRoot, {
26133
+ paths: new Set(paths),
26134
+ subjects: [subject],
26135
+ timer: setTimeout(() => void flushInner(projectRoot), 0),
26136
+ repoRoot,
26137
+ expectedBranch
26138
+ });
26139
+ }
26140
+ /**
26141
+ * Force a flush of any pending commits for `projectRoot`. Returns an Effect that
26142
+ * resolves after the commit attempt (success or no-op).
26143
+ */
26144
+ function flushAutoCommits(projectRoot) {
26145
+ return promise(() => flushPromise(projectRoot));
26146
+ }
26147
+ function flushPromise(projectRoot) {
26148
+ const batch = pending.get(projectRoot);
26149
+ if (!batch) return Promise.resolve({
26150
+ committed: false,
26151
+ reason: "no pending"
26152
+ });
26153
+ clearTimeout(batch.timer);
26154
+ return flushInner(projectRoot);
26155
+ }
26156
+ function flushInner(projectRoot) {
26157
+ const batch = pending.get(projectRoot);
26158
+ if (!batch) return Promise.resolve({
26159
+ committed: false,
26160
+ reason: "no pending"
26161
+ });
26162
+ pending.delete(projectRoot);
26163
+ const task = serializer.then(() => runPromise(doCommit(projectRoot, batch)));
26164
+ serializer = task.catch(() => void 0);
26165
+ return task;
26166
+ }
26167
+ function doCommit(projectRoot, batch) {
26168
+ const gitRoot = batch.repoRoot ?? projectRoot;
26169
+ return gen(function* () {
26170
+ if (!existsSync(join(gitRoot, ".git"))) {
26171
+ if (batch.expectedBranch === "overdeck-state") {
26172
+ console.warn(`[pan-dir/auto-commit] refusing state write: state worktree is missing at ${gitRoot}`);
26173
+ return {
26174
+ committed: false,
26175
+ reason: `state worktree missing: ${gitRoot}`
26176
+ };
26177
+ }
26178
+ return {
26179
+ committed: false,
26180
+ reason: "not a git repo"
26181
+ };
26182
+ }
26183
+ const branchResult = yield* runGit([
26184
+ "rev-parse",
26185
+ "--abbrev-ref",
26186
+ "HEAD"
26187
+ ], gitRoot).pipe(matchEffect({
26188
+ onSuccess: (r) => succeed(r.stdout.trim()),
26189
+ onFailure: (err) => succeed({
26190
+ committed: false,
26191
+ errored: true,
26192
+ reason: `branch check failed: ${err.stderr || err._tag}`
26193
+ })
26194
+ }));
26195
+ if (typeof branchResult !== "string") return branchResult;
26196
+ const expectedBranch = batch.expectedBranch;
26197
+ if (branchResult !== expectedBranch) return {
26198
+ committed: false,
26199
+ reason: expectedBranch === "main" ? `not on main (${branchResult})` : `expected ${expectedBranch}, found ${branchResult}`
26200
+ };
26201
+ const branch = branchResult;
26202
+ yield* runGit([
26203
+ "fetch",
26204
+ "origin",
26205
+ expectedBranch
26206
+ ], gitRoot).pipe(matchEffect({
26207
+ onSuccess: () => void_,
26208
+ onFailure: () => void_
26209
+ }));
26210
+ const relativePaths = Array.from(batch.paths).map((p) => relativizeToRoot(p, gitRoot)).filter((p) => !isAutoCommitExcludedPath(p));
26211
+ if (relativePaths.length === 0) return {
26212
+ committed: false,
26213
+ reason: "all paths excluded from auto-commit"
26214
+ };
26215
+ const addOk = yield* runGit([
26216
+ "add",
26217
+ "--",
26218
+ ...relativePaths
26219
+ ], gitRoot).pipe(matchEffect({
26220
+ onSuccess: () => succeed(true),
26221
+ onFailure: (err) => {
26222
+ console.warn(`[pan-dir/auto-commit] failed for ${branch}: ${err.stderr || err._tag}`);
26223
+ return succeed({
26224
+ committed: false,
26225
+ errored: true,
26226
+ reason: err.stderr || err._tag
26227
+ });
26228
+ }
26229
+ }));
26230
+ if (typeof addOk !== "boolean") return addOk;
26231
+ if (yield* runGit([
26232
+ "diff",
26233
+ "--cached",
26234
+ "--quiet",
26235
+ "--",
26236
+ ...relativePaths
26237
+ ], gitRoot).pipe(matchEffect({
26238
+ onSuccess: () => succeed(true),
26239
+ onFailure: () => succeed(false)
26240
+ }))) return {
26241
+ committed: false,
26242
+ reason: "no diff"
26243
+ };
26244
+ const commitOk = yield* runGit([
26245
+ "commit",
26246
+ "-m",
26247
+ batch.subjects.length === 1 ? batch.subjects[0] : `chore(state): batch update ${relativePaths.length} pan/beads file(s)`,
26248
+ "--",
26249
+ ...relativePaths
26250
+ ], gitRoot).pipe(matchEffect({
26251
+ onSuccess: () => succeed(true),
26252
+ onFailure: (err) => {
26253
+ console.warn(`[pan-dir/auto-commit] failed for ${branch}: ${err.stderr || err._tag}`);
26254
+ return succeed({
26255
+ committed: false,
26256
+ errored: true,
26257
+ reason: err.stderr || err._tag
26258
+ });
26259
+ }
26260
+ }));
26261
+ if (typeof commitOk !== "boolean") return commitOk;
26262
+ const push = yield* maybePushStateCommit(gitRoot, branch);
26263
+ if (push && !push.pushed) return {
26264
+ committed: true,
26265
+ pushed: false,
26266
+ reason: push.reason
26267
+ };
26268
+ return {
26269
+ committed: true,
26270
+ pushed: push?.pushed
26271
+ };
26272
+ });
26273
+ }
26274
+ function maybePushStateCommit(gitRoot, branch) {
26275
+ return runGit([
26276
+ "remote",
26277
+ "get-url",
26278
+ "origin"
26279
+ ], gitRoot).pipe(matchEffect({
26280
+ onFailure: () => succeed(null),
26281
+ onSuccess: () => pushStateBranch(gitRoot, branch)
26282
+ }));
26283
+ }
26284
+ function pushStateBranch(gitRoot, branch) {
26285
+ if (branch === "main") return pushOriginMain(gitRoot, branch, false);
26286
+ const timeoutMs = parsePositiveInteger(process.env.OVERDECK_STATE_PUSH_TIMEOUT_MS, DEFAULT_STATE_PUSH_TIMEOUT_MS);
26287
+ return runGitWithTimeout([
26288
+ "push",
26289
+ "origin",
26290
+ branch
26291
+ ], gitRoot, timeoutMs).pipe(matchEffect({
26292
+ onSuccess: () => succeed({ pushed: true }),
26293
+ onFailure: (err) => {
26294
+ const message = err.stderr || err._tag;
26295
+ warnAutoPush(branch, `push failed: ${message}`);
26296
+ return succeed({
26297
+ pushed: false,
26298
+ reason: `push failed: ${message}`
26299
+ });
26300
+ }
26301
+ }));
26302
+ }
26303
+ function pushOriginMain(gitRoot, branch, retry) {
26304
+ return runGitWithTimeout([
26305
+ "push",
26306
+ "origin",
26307
+ "main"
26308
+ ], gitRoot, parsePositiveInteger(process.env.OVERDECK_STATE_PUSH_TIMEOUT_MS, DEFAULT_STATE_PUSH_TIMEOUT_MS)).pipe(matchEffect({
26309
+ onSuccess: () => succeed({ pushed: true }),
26310
+ onFailure: (err) => {
26311
+ const message = err.stderr || err._tag;
26312
+ if (!retry && isNonFastForwardPushError(message)) return rebaseLegacyMainAndRetry(gitRoot, branch);
26313
+ warnAutoPush(branch, `push failed: ${message}`);
26314
+ return succeed({
26315
+ pushed: false,
26316
+ reason: `push failed: ${message}`
26317
+ });
26318
+ }
26319
+ }));
26320
+ }
26321
+ function rebaseLegacyMainAndRetry(gitRoot, branch) {
26322
+ const timeoutMs = parsePositiveInteger(process.env.OVERDECK_STATE_PUSH_TIMEOUT_MS, DEFAULT_STATE_PUSH_TIMEOUT_MS);
26323
+ return gen(function* () {
26324
+ if (!(yield* runGitWithTimeout([
26325
+ "fetch",
26326
+ "origin",
26327
+ "main"
26328
+ ], gitRoot, timeoutMs).pipe(match({
26329
+ onSuccess: () => true,
26330
+ onFailure: () => false
26331
+ }))) || !(yield* isWorkingTreeClean(gitRoot, branch))) return {
26332
+ pushed: false,
26333
+ reason: "push rejected and reconciliation preconditions failed"
26334
+ };
26335
+ if (!(yield* areLocalAheadCommitsStatePlaneOnly(gitRoot, branch))) {
26336
+ warnAutoPush(branch, "non-fast-forward push rejected and at least one local-ahead commit is not state-plane-only; leaving local main ahead of origin/main");
26337
+ return {
26338
+ pushed: false,
26339
+ reason: "push rejected with non-state local commits"
26340
+ };
26341
+ }
26342
+ if (yield* runGitWithTimeout(["rebase", "origin/main"], gitRoot, timeoutMs).pipe(match({
26343
+ onSuccess: () => true,
26344
+ onFailure: () => false
26345
+ }))) return yield* pushOriginMain(gitRoot, branch, true);
26346
+ return {
26347
+ pushed: false,
26348
+ reason: "push rejected and state rebase failed"
26349
+ };
26350
+ });
26351
+ }
26352
+ function areLocalAheadCommitsStatePlaneOnly(gitRoot, branch) {
26353
+ const timeoutMs = parsePositiveInteger(process.env.OVERDECK_STATE_PUSH_TIMEOUT_MS, DEFAULT_STATE_PUSH_TIMEOUT_MS);
26354
+ return gen(function* () {
26355
+ const commits = yield* runGitWithTimeout([
26356
+ "rev-list",
26357
+ "--reverse",
26358
+ "origin/main..main"
26359
+ ], gitRoot, timeoutMs).pipe(match({
26360
+ onSuccess: (result) => result.stdout.split("\n").map((line) => line.trim()).filter(Boolean),
26361
+ onFailure: (err) => {
26362
+ warnAutoPush(branch, `local-ahead commit list failed: ${err.stderr || err._tag}`);
26363
+ return null;
26364
+ }
26365
+ }));
26366
+ if (commits === null) return false;
26367
+ for (const commit of commits) {
26368
+ const parent = yield* runGitWithTimeout([
26369
+ "rev-list",
26370
+ "--parents",
26371
+ "-n",
26372
+ "1",
26373
+ commit
26374
+ ], gitRoot, timeoutMs).pipe(match({
26375
+ onSuccess: (result) => result.stdout.trim().split(/\s+/)[1] ?? null,
26376
+ onFailure: () => null
26377
+ }));
26378
+ if (!parent) return false;
26379
+ if (!(yield* promise(() => isStatePlaneOnlyDiff(parent, commit, gitRoot)).pipe(catchCause(() => succeed(false))))) return false;
26380
+ }
26381
+ return true;
26382
+ });
26383
+ }
26384
+ function isWorkingTreeClean(gitRoot, branch) {
26385
+ return runGit(["status", "--porcelain"], gitRoot).pipe(match({
26386
+ onSuccess: (result) => {
26387
+ const clean = result.stdout.trim().length === 0;
26388
+ if (!clean) warnAutoPush(branch, "non-fast-forward push rejected and working tree is dirty; leaving local main ahead of origin/main");
26389
+ return clean;
26390
+ },
26391
+ onFailure: (err) => {
26392
+ warnAutoPush(branch, `working-tree cleanliness check failed: ${err.stderr || err._tag}`);
26393
+ return false;
26394
+ }
26395
+ }));
26396
+ }
26397
+ function isNonFastForwardPushError(message) {
26398
+ return /non-fast-forward|fetch first|failed to push some refs|rejected/i.test(message);
26399
+ }
26400
+ function warnAutoPush(branch, message) {
26401
+ console.warn(`[pan-dir/auto-commit] auto-push warning for ${branch}: ${message}`);
26402
+ }
26403
+ function relativizeToRoot(absOrRel, projectRoot) {
26404
+ const rootPrefix = projectRoot.endsWith(sep) ? projectRoot : projectRoot + sep;
26405
+ if (absOrRel.startsWith(rootPrefix)) return absOrRel.slice(rootPrefix.length);
26406
+ return absOrRel;
26407
+ }
25542
26408
  const RECORD_DIRNAME = "records";
25543
26409
  /** Workspace path for an issue, or null if no project is configured. */
25544
26410
  function getIssueWorkspacePath(issueId) {
@@ -25629,7 +26495,19 @@ function writeRecordFileAtomicSync(path, record) {
25629
26495
  preserveCorruptRecordSync(path);
25630
26496
  const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
25631
26497
  writeFileSync$1(tmp, JSON.stringify(record, null, 2), "utf-8");
26498
+ const tmpFd = openSync$1(tmp, "r");
26499
+ try {
26500
+ fsyncSync(tmpFd);
26501
+ } finally {
26502
+ closeSync$1(tmpFd);
26503
+ }
25632
26504
  renameSync(tmp, path);
26505
+ const dirFd = openSync$1(dirname$1(path), "r");
26506
+ try {
26507
+ fsyncSync(dirFd);
26508
+ } finally {
26509
+ closeSync$1(dirFd);
26510
+ }
25633
26511
  JSON.parse(readFileSync$1(path, "utf-8"));
25634
26512
  }
25635
26513
  function writeIssueRecordSync(project, issueId, record) {
@@ -25655,6 +26533,190 @@ function readIssueRecordSync(project, issueId) {
25655
26533
  return null;
25656
26534
  }
25657
26535
  }
26536
+ function queueIssueRecordCommit(project, issueId, recordPath) {
26537
+ const basePath = getIssueRecordBasePath(project, issueId);
26538
+ queueAutoCommit({
26539
+ projectRoot: basePath,
26540
+ repoRoot: basePath,
26541
+ paths: [recordPath],
26542
+ subject: `chore(records): update ${issueId.toUpperCase()} per-issue record`
26543
+ });
26544
+ return basePath;
26545
+ }
26546
+ /** Synchronous variant of ensureIssueRecord. */
26547
+ function ensureIssueRecordSync(project, issueId) {
26548
+ const path = getIssueRecordPath(project, issueId);
26549
+ try {
26550
+ const raw = readFileSync$1(path, "utf-8");
26551
+ return JSON.parse(raw);
26552
+ } catch {
26553
+ const now = (/* @__PURE__ */ new Date()).toISOString();
26554
+ return {
26555
+ issueId: issueId.toUpperCase(),
26556
+ schemaVersion: 2,
26557
+ created: now,
26558
+ updated: now,
26559
+ pipeline: {
26560
+ issueId: issueId.toUpperCase(),
26561
+ reviewStatus: "pending",
26562
+ testStatus: "pending",
26563
+ readyForMerge: false,
26564
+ updatedAt: now
26565
+ },
26566
+ closeOut: {
26567
+ usage: {
26568
+ byStage: {},
26569
+ totals: {}
26570
+ },
26571
+ merges: [],
26572
+ ranOn: hostname()
26573
+ }
26574
+ };
26575
+ }
26576
+ }
26577
+ //#endregion
26578
+ //#region ../../src/lib/pan-dir/fs-lock.ts
26579
+ /** Cross-process per-issue record locking (PAN-2648 CD-2). */
26580
+ const RECORD_LOCK_RETRY_DELAYS_MS = [
26581
+ 5,
26582
+ 10,
26583
+ 20,
26584
+ 40,
26585
+ 80,
26586
+ 160,
26587
+ 320,
26588
+ 360
26589
+ ];
26590
+ var RecordLockError = class extends Error {
26591
+ constructor(lockPath, owner) {
26592
+ super(`The per-issue record lock at ${lockPath} is held by ${owner}. Retry the command after that writer finishes.`);
26593
+ this.lockPath = lockPath;
26594
+ this.owner = owner;
26595
+ this.name = "RecordLockError";
26596
+ }
26597
+ };
26598
+ function safeSegment(value) {
26599
+ return value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-");
26600
+ }
26601
+ function recordLockPath(project, issueId) {
26602
+ const configuredKey = listProjectsSync().find(({ config }) => config.path === project.path)?.key;
26603
+ const projectKey = safeSegment(configuredKey ?? project.name ?? project.path) || "unknown-project";
26604
+ return join$1(getOverdeckHome(), "locks", "records", projectKey, `${issueId.toUpperCase()}.lock`);
26605
+ }
26606
+ function isPidDead(pid) {
26607
+ if (!pid || pid <= 0 || pid === process.pid) return false;
26608
+ try {
26609
+ process.kill(pid, 0);
26610
+ return false;
26611
+ } catch (error) {
26612
+ return error.code === "ESRCH";
26613
+ }
26614
+ }
26615
+ async function sweepRecordTmpFiles(recordPath) {
26616
+ try {
26617
+ const dir = dirname$1(recordPath);
26618
+ const base = recordPath.slice(dir.length + 1);
26619
+ const entries = await readdir(dir);
26620
+ await Promise.all(entries.filter((entry) => entry.startsWith(`${base}.`) && entry.endsWith(".tmp")).map((entry) => rm(join$1(dir, entry), { force: true })));
26621
+ } catch {}
26622
+ }
26623
+ async function readOwner(lockPath) {
26624
+ try {
26625
+ const owner = JSON.parse(await readFile(join$1(lockPath, "owner.json"), "utf8"));
26626
+ return {
26627
+ description: `${owner.writerId ?? "unknown writer"} pid=${owner.pid ?? "unknown"} acquiredAt=${owner.acquiredAt ?? "unknown"}`,
26628
+ pid: owner.pid
26629
+ };
26630
+ } catch {
26631
+ return { description: "unknown writer" };
26632
+ }
26633
+ }
26634
+ async function acquireRecordLock(lockPath, options) {
26635
+ await mkdir(dirname$1(lockPath), {
26636
+ recursive: true,
26637
+ mode: 448
26638
+ });
26639
+ const delays = options.retryDelaysMs ?? RECORD_LOCK_RETRY_DELAYS_MS;
26640
+ let lastOwner = "unknown writer";
26641
+ for (let attempt = 0; attempt <= delays.length; attempt += 1) {
26642
+ try {
26643
+ await mkdir(lockPath, { mode: 448 });
26644
+ const owner = {
26645
+ writerId: options.writerId,
26646
+ pid: process.pid,
26647
+ acquiredAt: (/* @__PURE__ */ new Date()).toISOString()
26648
+ };
26649
+ try {
26650
+ await writeFile(join$1(lockPath, "owner.json"), JSON.stringify(owner, null, 2), "utf8");
26651
+ } catch (error) {
26652
+ try {
26653
+ await rm(lockPath, {
26654
+ recursive: true,
26655
+ force: true
26656
+ });
26657
+ } catch {}
26658
+ throw error;
26659
+ }
26660
+ await sweepRecordTmpFiles(options.recordPath);
26661
+ return owner;
26662
+ } catch (error) {
26663
+ if (error.code !== "EEXIST") throw error;
26664
+ const owner = await readOwner(lockPath);
26665
+ lastOwner = owner.description;
26666
+ if (isPidDead(owner.pid)) {
26667
+ await rm(lockPath, {
26668
+ recursive: true,
26669
+ force: true
26670
+ });
26671
+ continue;
26672
+ }
26673
+ }
26674
+ const delay = delays[attempt];
26675
+ if (delay === void 0) break;
26676
+ await new Promise((resolve) => setTimeout(resolve, delay));
26677
+ }
26678
+ throw new RecordLockError(lockPath, lastOwner);
26679
+ }
26680
+ async function releaseRecordLock(lockPath) {
26681
+ await rm(lockPath, {
26682
+ recursive: true,
26683
+ force: true
26684
+ });
26685
+ }
26686
+ async function withRecordFsLock(project, issueId, options, operation) {
26687
+ const lockPath = recordLockPath(project, issueId);
26688
+ await acquireRecordLock(lockPath, options);
26689
+ try {
26690
+ return await operation();
26691
+ } finally {
26692
+ await releaseRecordLock(lockPath);
26693
+ }
26694
+ }
26695
+ //#endregion
26696
+ //#region ../../src/lib/pan-dir/record-update.ts
26697
+ /** The single locked read-modify-write door for per-issue records. */
26698
+ async function updateIssueRecord(project, issueId, mutator, options = {}) {
26699
+ const normalizedIssueId = issueId.toUpperCase();
26700
+ const recordPath = getIssueRecordPath(project, normalizedIssueId);
26701
+ const writerId = options.writerId ?? process.env.OVERDECK_AGENT_ID ?? `process-${process.pid}@${hostname()}`;
26702
+ const commit = { flush: void 0 };
26703
+ const record = await withRecordFsLock(project, normalizedIssueId, {
26704
+ writerId,
26705
+ recordPath
26706
+ }, async () => {
26707
+ const current = readIssueRecordSync(project, normalizedIssueId) ?? ensureIssueRecordSync(project, normalizedIssueId);
26708
+ const next = await mutator(current) ?? current;
26709
+ const path = writeIssueRecordSync(project, normalizedIssueId, next);
26710
+ if (options.autoCommit !== false) commit.flush = runPromise(flushAutoCommits(queueIssueRecordCommit(project, normalizedIssueId, path)));
26711
+ return readIssueRecordSync(project, normalizedIssueId) ?? next;
26712
+ });
26713
+ if (commit.flush) {
26714
+ const flushed = await commit.flush;
26715
+ if (flushed.pushed === false) throw new Error(`Failed to push ${normalizedIssueId} state: ${flushed.reason ?? "unknown push failure"}`);
26716
+ if (!flushed.committed && !["no diff", "no pending"].includes(flushed.reason ?? "")) throw new Error(`Failed to commit ${normalizedIssueId} state: ${flushed.reason ?? "unknown commit failure"}`);
26717
+ }
26718
+ return record;
26719
+ }
25658
26720
  //#endregion
25659
26721
  //#region ../../src/lib/config-yaml/schema.ts
25660
26722
  const COMPLIANCE_MODES = [
@@ -27780,12 +28842,15 @@ const DEFAULT_DOCS_TRIGGER_REGEXES = [
27780
28842
  "workspace",
27781
28843
  "specialist",
27782
28844
  "harness",
27783
- "bd",
27784
- "beads",
27785
28845
  "vbrief",
27786
28846
  "workhorse"
27787
28847
  ];
27788
28848
  const DEFAULT_CONFIG = {
28849
+ swarm: {
28850
+ mode: "off",
28851
+ maxSlots: 3,
28852
+ autoAdvance: true
28853
+ },
27789
28854
  tmux: { configMode: "managed" },
27790
28855
  enabledProviders: new Set(["anthropic"]),
27791
28856
  defaultConversationModel: "claude-sonnet-5",
@@ -28159,6 +29224,7 @@ function degradeInvalidTieredExecution(result, err) {
28159
29224
  function mergeConfigs(...configs) {
28160
29225
  const result = {
28161
29226
  ...DEFAULT_CONFIG,
29227
+ swarm: { ...DEFAULT_CONFIG.swarm },
28162
29228
  tmux: { ...DEFAULT_CONFIG.tmux },
28163
29229
  enabledProviders: new Set(DEFAULT_CONFIG.enabledProviders),
28164
29230
  providerHarnesses: { ...DEFAULT_CONFIG.providerHarnesses },
@@ -28243,6 +29309,10 @@ function mergeConfigs(...configs) {
28243
29309
  const explicitlyDisabled = /* @__PURE__ */ new Set();
28244
29310
  const validConfigs = configs.filter((c) => c !== null);
28245
29311
  for (const config of validConfigs.reverse()) {
29312
+ if (config.swarm) result.swarm = {
29313
+ ...result.swarm,
29314
+ ...config.swarm
29315
+ };
28246
29316
  if (config.models?.providers) {
28247
29317
  const providers = config.models.providers;
28248
29318
  const legacyKeys = config.api_keys || {};
@@ -30829,7 +31899,7 @@ function getManagedTmuxSocketName() {
30829
31899
  return process.env.OVERDECK_TMUX_SOCKET_NAME ?? "overdeck";
30830
31900
  }
30831
31901
  async function ensureManagedTmuxDirAsync() {
30832
- await mkdir(getTmuxDir(), { recursive: true });
31902
+ await mkdir$1(getTmuxDir(), { recursive: true });
30833
31903
  }
30834
31904
  /**
30835
31905
  * True when a tmux server is already answering on the managed socket.
@@ -31088,7 +32158,7 @@ async function reloadManagedTmuxConfigAsync() {
31088
32158
  async function ensureManagedTmuxConfigAsync() {
31089
32159
  if (tmuxContextPrepared) return;
31090
32160
  await ensureManagedTmuxDirAsync();
31091
- await writeFile(getManagedTmuxConfigPath(), MANAGED_TMUX_CONFIG_CONTENT, "utf-8");
32161
+ await writeFile$1(getManagedTmuxConfigPath(), MANAGED_TMUX_CONFIG_CONTENT, "utf-8");
31092
32162
  await reloadManagedTmuxConfigAsync();
31093
32163
  tmuxContextPrepared = true;
31094
32164
  }
@@ -31397,7 +32467,10 @@ effect(EventBus, gen(function* () {
31397
32467
  }));
31398
32468
  var Records = class extends Service()("overdeck/Records") {};
31399
32469
  succeed$1(Records, Records.of({
31400
- writeIssue: (project, issueId, record) => sync(() => writeIssueRecordSync(project, issueId, record)),
32470
+ writeIssue: (project, issueId, record) => promise(async () => {
32471
+ await updateIssueRecord(project, issueId, () => record);
32472
+ return getIssueRecordPath(project, issueId);
32473
+ }),
31401
32474
  readIssue: (project, issueId) => sync(() => readIssueRecordSync(project, issueId)),
31402
32475
  readSpec: (planRef) => sync(() => {
31403
32476
  const path = isAbsolute(planRef) ? planRef : join$1(packageRoot, planRef);