@overdeck/desktop 0.45.12 → 0.45.13

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 (323) hide show
  1. package/drizzle/overdeck/0000_overdeck_init.sql +33 -0
  2. package/package.json +7 -2
  3. package/server/{acceptance-criteria-1LHgD9vg.js → acceptance-criteria-CfujPRrz.js} +2 -2
  4. package/server/{advancing-selfheal-BqsLWqEM.js → advancing-selfheal-Bn5QiLtn.js} +4 -4
  5. package/server/{agent-gc-CUb52n7s.js → agent-gc-Cl9Nm0Zu.js} +3 -3
  6. package/server/{agent-state-D-moNwhA.js → agent-state-C6Rm6FPR.js} +1 -1
  7. package/server/{agent-state-service-BzESvLOf.js → agent-state-service-JhFzYCP_.js} +5 -5
  8. package/server/{agent-state-service-BaZH7sXJ.js → agent-state-service-U8feBf8t.js} +1 -1
  9. package/server/{agents-C4kZ8a2r.js → agents-CxbuBjID.js} +1 -1
  10. package/server/{agents-B5LfpLPv.js → agents-DqQa4Dq_.js} +88 -64
  11. package/server/{archive-planning-oX1pj6nY.js → archive-planning-CPitEZo4.js} +3 -3
  12. package/server/{archive-planning-BbZe-8IK.js → archive-planning-DmpT1_14.js} +1 -1
  13. package/server/{artifact-index-jobs-DGr6bxev.js → artifact-index-jobs-sMnNtPhy.js} +2 -2
  14. package/server/{auto-commit-CGQlb4rV.js → auto-commit-wZ9X7Isd.js} +1 -1
  15. package/server/{backlog-auto-trigger-BlJHikOm.js → backlog-auto-trigger-Cf9C8fwD.js} +2 -2
  16. package/server/{bd-process-lock-i3CYMS-B.js → bd-process-lock-D1aJxeYv.js} +2 -2
  17. package/server/{beads-BNU-fb48.js → beads-CivpXztb.js} +1 -1
  18. package/server/{beads-DD7fYCl5.js → beads-DRoj6-e1.js} +4 -4
  19. package/server/{beads-query-e6oku4P5.js → beads-query-tOsAYP5h.js} +2 -2
  20. package/server/{behavior-CPf0pbOt.js → behavior-D3d2mVyD.js} +3 -3
  21. package/server/{briefing-freshness-B2FdLwIv.js → briefing-freshness-BL3Q6p7R.js} +4 -4
  22. package/server/{checkpoint-manager-JryW6MpM.js → checkpoint-manager-DCxjQvP_.js} +2 -2
  23. package/server/{checkpoint-manager-eFgaMMu4.js → checkpoint-manager-j5URlFY7.js} +1 -1
  24. package/server/checkpoint-worker.js +1 -1
  25. package/server/{checkpoints-qvOqvMuC.js → checkpoints-BoX1H2Hf.js} +2 -2
  26. package/server/{checkpoints-BK17oicz.js → checkpoints-Bu_M_Q9W.js} +1 -1
  27. package/server/claude-hooks-provision-D-jGXmu1.js +360 -0
  28. package/server/{claude-permissions-B6bWGh9d.js → claude-permissions-DxIjkOVl.js} +2 -2
  29. package/server/{claude-settings-overlay-BPdhTPjo.js → claude-settings-overlay-5b9X2S0C.js} +1 -1
  30. package/server/{claude-settings-overlay-CRyyKKXQ.js → claude-settings-overlay-BPDS6GfE.js} +2 -2
  31. package/server/cli-CqgiSAU8.js +3 -0
  32. package/server/{cli-B75AieAM.js → cli-s7bPWy-E.js} +9 -9
  33. package/server/{cliproxy-CCzwuSNe.js → cliproxy-BituqWtR.js} +2 -2
  34. package/server/{cliproxy-DOQf66G9.js → cliproxy-D3sHB0sI.js} +1 -1
  35. package/server/{close-issue-_X3MXJyG.js → close-issue-CrBE7voz.js} +4 -4
  36. package/server/{closed-issue-reaper-CLR7ClsO.js → closed-issue-reaper-BRQBc7Xa.js} +1 -1
  37. package/server/{closed-issue-reaper-BsUfBSjM.js → closed-issue-reaper-DX9mYUji.js} +9 -9
  38. package/server/{codex-CY-QRuU9.js → codex-Bi1ITSOo.js} +1 -1
  39. package/server/{codex-B4KEpX5V.js → codex-CO0HrK3j.js} +5 -5
  40. package/server/{compact-beads-cZds2MTr.js → compact-beads-CrA8-k10.js} +1 -1
  41. package/server/{compact-beads-uEDccC76.js → compact-beads-DUkCUFxA.js} +3 -3
  42. package/server/{config-DARrpYWA.js → config-B4_d7z7z.js} +1 -1
  43. package/server/{config-8sjaU6jZ.js → config-DsCxzjXK.js} +2 -2
  44. package/server/{config-yaml-ClpGgrf6.js → config-yaml-C_djSurJ.js} +2 -2
  45. package/server/{conflict-gate-Ds9_2yjd.js → conflict-gate-CpOn9KC-.js} +1 -1
  46. package/server/{conflict-gate-BtB_o-Vi.js → conflict-gate-D47Kl78u.js} +3 -3
  47. package/server/{context-layers-r2ywnQYA.js → context-layers-BNhUBTkf.js} +3 -3
  48. package/server/{context-layers-CRCk1QG7.js → context-layers-CHl3Nroz.js} +2 -2
  49. package/server/{control-settings-D1B3u6HP.js → control-settings-KyYNXZLv.js} +4 -4
  50. package/server/{conversation-compaction-D86Zo2Ci.js → conversation-compaction-D3aS5PnS.js} +8 -8
  51. package/server/{conversation-compaction-CZRVk4hg.js → conversation-compaction-D4Wed1BJ.js} +1 -1
  52. package/server/{conversation-service-CuTVU8dV.js → conversation-service-CFZIjs-M.js} +5 -5
  53. package/server/{conversation-service-CkL-6MuG.js → conversation-service-DcDB5usR.js} +1 -1
  54. package/server/{conversations-DfJKBDwB.js → conversations-BSOU5qnu.js} +4 -4
  55. package/server/{conversations-BmWEluPL.js → conversations-BbDPrz89.js} +1 -1
  56. package/server/{cost-DAPYN6iA.js → cost-BE_ulOrw.js} +3 -3
  57. package/server/{cost-CCnqa5xK.js → cost-CaiG63FG.js} +2 -2
  58. package/server/{cost-sync-BDL10Nwu.js → cost-sync-D6AX8jv-.js} +3 -3
  59. package/server/{dag-Dv2r5bVD.js → dag-BQFtXOuJ.js} +3 -3
  60. package/server/{dangerous-git-ops-Dcw7PbYo.js → dangerous-git-ops-04Ba-Qu3.js} +1 -1
  61. package/server/dashboard-db-worker.js +6 -6
  62. package/server/{deacon-CM0MxbS8.js → deacon-2EvA9Ci3.js} +97 -97
  63. package/server/{deacon-DYnZH7kC.js → deacon-Bz-6Wjmn.js} +3 -3
  64. package/server/deacon-swarm-B8pgK2a7.js +2 -0
  65. package/server/{deacon-swarm-BstYoz8Q.js → deacon-swarm-DYYOzHRH.js} +10 -10
  66. package/server/deacon.js +7 -7
  67. package/server/{devcontainer-renderer-CaYOG9JN.js → devcontainer-renderer-Dx0C7VWJ.js} +2 -2
  68. package/server/dist-BYSj075e.js +3 -0
  69. package/server/{dist-BIC8spJ0.js → dist-ya66D9ze.js} +1 -1
  70. package/server/{docker-DDI1shu3.js → docker-D2TbXDO6.js} +2 -2
  71. package/server/{ensure-devcontainer-CbSXvN9W.js → ensure-devcontainer-BIShzs3M.js} +1 -1
  72. package/server/{ensure-devcontainer-DCAg3ksz.js → ensure-devcontainer-BTiMfFp5.js} +3 -3
  73. package/server/{event-store-DU3HkZlN.js → event-store-C02Gprug.js} +1 -1
  74. package/server/{event-store-DCMqyI07.js → event-store-C71x6h0i.js} +3 -3
  75. package/server/{events-BfiosVAn.js → events-BFDuPV6n.js} +3 -3
  76. package/server/{events-DLRxpSuV.js → events-D2gP2-Yv.js} +1 -1
  77. package/server/{factory-BMtWV9iv.js → factory-ByfbrCab.js} +4 -4
  78. package/server/{feature-registry-population-DA7bO6Zn.js → feature-registry-population-CSH66UO8.js} +4 -4
  79. package/server/{feature-registry-storage-nAY1fbBt.js → feature-registry-storage-DW7dUefc.js} +2 -2
  80. package/server/{features-DMu7eGmU.js → features-x_aLR7U9.js} +2 -2
  81. package/server/{feedback-target-DHqcw3cN.js → feedback-target-BFo9fScH.js} +6 -6
  82. package/server/{feedback-target-B2SEai8-.js → feedback-target-C4VMPTZu.js} +1 -1
  83. package/server/{feedback-writer-qvm7UON7.js → feedback-writer-B9ZqnnX3.js} +4 -4
  84. package/server/{feedback-writer-DMBdS_jL.js → feedback-writer-DCyd75yJ.js} +1 -1
  85. package/server/{flywheel-Dfpx4bIV.js → flywheel-D9NKvWqb.js} +11 -11
  86. package/server/{flywheel-k4FPtCQ_.js → flywheel-DB48X7Nn.js} +1 -1
  87. package/server/{flywheel-D2LdPSic.js → flywheel-DwQCoZQG.js} +13 -13
  88. package/server/{flywheel-merge-order-CB4lbXeJ.js → flywheel-merge-order-DrjmFXg4.js} +6 -6
  89. package/server/{flywheel-merge-order-CttTazRY.js → flywheel-merge-order-f1bi5XIf.js} +1 -1
  90. package/server/{forge-CoPFXFyl.js → forge-C-SoKy8U.js} +2 -2
  91. package/server/forge-CUCYK7h_.js +2 -0
  92. package/server/{from-B0YoJl9-.js → from-fu7ZumnY.js} +1 -1
  93. package/server/{fts-db-DAHW1yA_.js → fts-db-CL-YzSRG.js} +2 -2
  94. package/server/{fts-operations-DDXDBi0d.js → fts-operations-Bylu5NjM.js} +2 -2
  95. package/server/{git-utils-B90Zjzfl.js → git-utils-C8koBs8j.js} +2 -2
  96. package/server/{git-utils-DbfC0zls.js → git-utils-Ym380hJZ.js} +1 -1
  97. package/server/{github-app-C7lftMNj.js → github-app-DIr70YLg.js} +1 -1
  98. package/server/{github-app-BecAnXRX.js → github-app-DhycHVLF.js} +2 -2
  99. package/server/{github-client-D21rCIXk.js → github-client-7gkcXcBS.js} +2 -2
  100. package/server/{github-client-BwtKZtM0.js → github-client-Ji9lUTNF.js} +1 -1
  101. package/server/{github-pr-lookup-CzVWuysl.js → github-pr-lookup-rt7T9FwA.js} +2 -2
  102. package/server/{harness-resolve-SkRJm4a7.js → harness-resolve-CvGXUnAF.js} +3 -3
  103. package/server/{health-events-BT0aAfeA.js → health-events-D4E1DLN-.js} +2 -2
  104. package/server/{health-events-DA_JLpgZ.js → health-events-DDfkoO5a.js} +1 -1
  105. package/server/{hooks-DxEn2BoY.js → hooks-D_6pAbuJ.js} +2 -2
  106. package/server/{hooks-BQxRXtRb.js → hooks-DvdnCVv6.js} +1 -1
  107. package/server/{idle-stack-reaper-C7fJL8jH.js → idle-stack-reaper-DNbV9-fj.js} +1 -1
  108. package/server/{idle-stack-reaper-DGy7tvC9.js → idle-stack-reaper-cDRXDpgE.js} +2 -2
  109. package/server/{infra-DE3C4PMr.js → infra-Clew3DpF.js} +50 -3
  110. package/server/{injection-Dt22tGvS.js → injection-QCIHOpk6.js} +1 -1
  111. package/server/{injection-Cc4Qt8LZ.js → injection-ql0Nddcn.js} +7 -7
  112. package/server/inspect-agent-D8UBDgfR.js +2 -0
  113. package/server/{inspect-agent-DOaCDkCF.js → inspect-agent-DY18KEx4.js} +9 -9
  114. package/server/{internal-token-B_1YLWLI.js → internal-token-BeXjPLKy.js} +2 -2
  115. package/server/{internal-token-nobT6FhA.js → internal-token-C90jBp-y.js} +1 -1
  116. package/server/{io-A7ZuOBkz.js → io-CbAFXQge.js} +2 -2
  117. package/server/{issue-closed-Da3DeomA.js → issue-closed-BYC2TCk-.js} +4 -4
  118. package/server/{issue-lifecycle-543pQX9D.js → issue-lifecycle-BoJa6qIt.js} +21 -21
  119. package/server/{issue-lifecycle-Bd9XBJAQ.js → issue-lifecycle-CLHbj8RS.js} +1 -1
  120. package/server/{issue-service-singleton-BC2JLZi7.js → issue-service-singleton-3g_CCY-1.js} +1 -1
  121. package/server/{issue-service-singleton-Brc3t0SV.js → issue-service-singleton-BS9NENuR.js} +8 -8
  122. package/server/{issues-D3kt9UWE.js → issues-BPcqPqfV.js} +2 -2
  123. package/server/{label-cleanup-w9X_T3AQ.js → label-cleanup-CwiCSZrb.js} +2 -2
  124. package/server/{layers-Cwe1J-9o.js → layers-OHHLphl0.js} +2 -2
  125. package/server/{lifecycle-f1GbDK33.js → lifecycle-B8IdvUbt.js} +6 -6
  126. package/server/{lifecycle-io-D56q8zlO.js → lifecycle-io-BMCH1Bxg.js} +1 -1
  127. package/server/{lifecycle-io-Bqvj0m3i.js → lifecycle-io-C73m5e6R.js} +4 -4
  128. package/server/{linear-client-Bh4T4S-c.js → linear-client-BMxgycoy.js} +1 -1
  129. package/server/{linear-client-CfJMTAYd.js → linear-client-CgQlM4aT.js} +2 -2
  130. package/server/memory-fts-worker.js +1 -1
  131. package/server/{merge-ZrXFM3jv.js → merge-B7Oi-g6k.js} +3 -3
  132. package/server/{merge-DRMPa8CQ.js → merge-BRkVaIx-.js} +1 -1
  133. package/server/merge-agent-Bwm34MZ5.js +3 -0
  134. package/server/{merge-agent-CHHs5S_0.js → merge-agent-DNFFsiEm.js} +61 -26
  135. package/server/{merge-batch-BwhGdlh4.js → merge-batch-BpYXUaqJ.js} +1 -1
  136. package/server/{merge-blockers-BMhDpMl_.js → merge-blockers-DIOZmqdK.js} +2 -2
  137. package/server/merge-ops-B7m-hBEZ.js +2 -0
  138. package/server/{merge-rebase-R7MfqpiE.js → merge-rebase-C8WH39MB.js} +2 -2
  139. package/server/{merge-set-B3Breacq.js → merge-set-CsEE2CyQ.js} +9 -5
  140. package/server/{merge-set-D-iXNP0I.js → merge-set-DOsBTBQc.js} +1 -1
  141. package/server/{merge-sync-DHWbGtjR.js → merge-sync-C2B322Ot.js} +2 -2
  142. package/server/{merge-sync-bOOtfeXR.js → merge-sync-CcLM2vwW.js} +1 -1
  143. package/server/{merge-train-98ptZrPT.js → merge-train-BIm7-7cy.js} +3 -3
  144. package/server/{merge-train-deps-B5FWJTE2.js → merge-train-deps-DG1oQ2DT.js} +4 -4
  145. package/server/{merge-verification-BGiuiXAK.js → merge-verification-BAbjxEd5.js} +4 -4
  146. package/server/{multipart-parser-D7mzNNDm.js → multipart-parser-jKtKAXtl.js} +2 -2
  147. package/server/node_modules/.package-lock.json +1 -1
  148. package/server/{orphan-proposed-reconciler-CSuxivr9.js → orphan-proposed-reconciler-BqVGaOIj.js} +1 -1
  149. package/server/{orphan-proposed-reconciler-BSGCNJ6X.js → orphan-proposed-reconciler-zHrwJ3xr.js} +9 -9
  150. package/server/package-lock.json +2 -2
  151. package/server/package.json +1 -1
  152. package/server/{pan-dir-DoPtdHrp.js → pan-dir-BlNrLzW7.js} +3 -3
  153. package/server/{paths-CVDLPxXp.js → paths-CiVeo4N_.js} +2 -2
  154. package/server/{pipeline-notifier-WD2dnOsR.js → pipeline-notifier-DBF6dHxH.js} +2 -2
  155. package/server/{pipeline-notifier-BtYHbBPl.js → pipeline-notifier-nkWCe042.js} +1 -1
  156. package/server/{projects-Bqfwuqet.js → projects-BqRMlDOv.js} +1 -1
  157. package/server/{prompts-Cg7e9FPb.js → prompts-CXbQvevY.js} +2 -2
  158. package/server/{providers-fLduChnX.js → providers-CUdAb5Qu.js} +7 -7
  159. package/server/{providers-JjK6izqX.js → providers-gZ0cUgQM.js} +1 -1
  160. package/server/public/assets/{chunk-BO2N2NFS-aNlsGDCu.js → chunk-BO2N2NFS-C-6y8VFI.js} +4 -4
  161. package/server/public/assets/{diagram-OG6HWLK6-CnjkrvT8.js → diagram-OG6HWLK6-NACO1xW5.js} +1 -1
  162. package/server/public/assets/{dist-CGKBCieA.js → dist-D1FjqGgm.js} +1 -1
  163. package/server/public/assets/{dist-Bg3Sbsx4.js → dist-DQD-ZjQY.js} +3 -3
  164. package/server/public/assets/{ganttDiagram-6RSMTGT7-C8LLKj23.js → ganttDiagram-6RSMTGT7-CEMAKgmE.js} +1 -1
  165. package/server/public/assets/{highlighted-body-OFNGDK62-BSDEUvhW.js → highlighted-body-OFNGDK62-D5lC7FW8.js} +1 -1
  166. package/server/public/assets/{index-LQIfhmgI.js → index-BDqWyuZQ.js} +140 -140
  167. package/server/public/assets/{linear-DEbYZoxg.js → linear-DDHAMRPB.js} +1 -1
  168. package/server/public/assets/mermaid-GHXKKRXX-DRM2ANcR.js +1 -0
  169. package/server/public/assets/{pieDiagram-4H26LBE5-BtZL5pXE.js → pieDiagram-4H26LBE5-DwBdeKBb.js} +1 -1
  170. package/server/public/assets/{prod-DYVvIyuh.js → prod-DAZt0c4G.js} +4 -4
  171. package/server/public/assets/{quadrantDiagram-W4KKPZXB-a7vS8Jc8.js → quadrantDiagram-W4KKPZXB-CNDLp-_m.js} +1 -1
  172. package/server/public/assets/{sankeyDiagram-5OEKKPKP-Ckbq2SWH.js → sankeyDiagram-5OEKKPKP-oIUL_uO1.js} +1 -1
  173. package/server/public/assets/{xychartDiagram-2RQKCTM6-DJyeNa99.js → xychartDiagram-2RQKCTM6-B-IM6Cck.js} +1 -1
  174. package/server/public/index.html +1 -1
  175. package/server/{pull-requests-D2SjJIwY.js → pull-requests-DZ-V7_LB.js} +1 -1
  176. package/server/{pull-requests-1WXmTBlo.js → pull-requests-kTRl7cWC.js} +3 -3
  177. package/server/rally-CRteqXe0.js +3 -0
  178. package/server/{rally-api-H5I2CBO0.js → rally-api-DpZo3WwF.js} +2 -2
  179. package/server/{rally-api-BtvwdX6d.js → rally-api-jOk4vit_.js} +1 -1
  180. package/server/{rally-client-Bt-qHiOh.js → rally-client-BQjm3aaq.js} +1 -1
  181. package/server/{rally-client-33CYZYYu.js → rally-client-CoWZeVEj.js} +4 -4
  182. package/server/{rally-8aQlLLVj.js → rally-xCTZ-UcI.js} +3 -3
  183. package/server/{rebuild-stack-KHkkrGjx.js → rebuild-stack-BZ7j27xY.js} +5 -5
  184. package/server/{rebuild-stack-CXSgAGPR.js → rebuild-stack-r-cxcr26.js} +1 -1
  185. package/server/{reconstruct-cache-D_Ml65_6.js → reconstruct-cache-13EkMg_i.js} +6 -6
  186. package/server/{record-De2syxNB.js → record-CJsjvRO4.js} +1 -1
  187. package/server/release-engine-YLTnEO_K.js +306 -0
  188. package/server/release-set-DwvT_Opu.js +125 -0
  189. package/server/{remote-CGuognN3.js → remote-9u9WL0NJ.js} +3 -3
  190. package/server/{remote-D0Old0Cv.js → remote-B062S1Kc.js} +3 -3
  191. package/server/{remote-agents-UHoi4oGr.js → remote-agents-B4eWgwNd.js} +1 -1
  192. package/server/{remote-agents-DfhMq6kQ.js → remote-agents-BBTg-vLT.js} +5 -5
  193. package/server/{remote-completion-RZYePR_0.js → remote-completion-B0rmBnbL.js} +12 -12
  194. package/server/resume-R7xkSmLW.js +3 -0
  195. package/server/{review-agent-uwVftH98.js → review-agent-Bf9XjLnl.js} +1 -1
  196. package/server/{review-agent-sZBCpEVv.js → review-agent-tfR5RDzG.js} +22 -22
  197. package/server/{review-artifacts-C7a45b1_.js → review-artifacts-D0_IE6DQ.js} +6 -6
  198. package/server/{review-context-CErbQpKL.js → review-context-CXO5ml5D.js} +7 -7
  199. package/server/{review-monitor-DHD9m_kh.js → review-monitor-DfFUSx0J.js} +2 -2
  200. package/server/{review-status-JhQ3qlDS.js → review-status-B0Axo-Ma.js} +1 -1
  201. package/server/{review-status-gPndPUBc.js → review-status-BcfwcAcO.js} +23 -16
  202. package/server/{review-status-enrichment-qWvWckYN.js → review-status-enrichment-Cp5kFTGl.js} +3 -3
  203. package/server/{review-status-sync-B_GrEke8.js → review-status-sync-Bc0c_u12.js} +1 -1
  204. package/server/{review-status-sync-D3A9KX95.js → review-status-sync-CEFty1pW.js} +9 -5
  205. package/server/{review-verdict-feedback-4WZ5ZdbC.js → review-verdict-feedback-BOKRLLDf.js} +6 -6
  206. package/server/{review-verdict-feedback-Zo0r_z4m.js → review-verdict-feedback-BnGtT0vN.js} +1 -1
  207. package/server/{rollup-Bmhn80tB.js → rollup-BVqFuiS9.js} +1 -1
  208. package/server/{rollup-BrUIKMv_.js → rollup-C22QDVxh.js} +8 -8
  209. package/server/{scanner-BIGumel_.js → scanner-BLCnuXqY.js} +7 -7
  210. package/server/{sequence-io-DA0akEQN.js → sequence-io-BozlUb6f.js} +4 -4
  211. package/server/{sequencer-agent-DeflKafB.js → sequencer-agent-BEDEHfd2.js} +5 -5
  212. package/server/server.js +251 -160
  213. package/server/{service-V0sUK-OR.js → service-C8jKYZ0w.js} +42 -42
  214. package/server/{session-fork-Yx3UcAQf.js → session-fork-BDGksK4e.js} +2 -2
  215. package/server/{settings-CFEeQRj2.js → settings-CSLhh6qR.js} +2 -2
  216. package/server/settings-CSaXtkoA.js +2 -0
  217. package/server/{settings-CxVate0h.js → settings-DrRQCren.js} +3 -3
  218. package/server/{shadow-engineering-BRxnVSDk.js → shadow-engineering-BMcBN-Of.js} +2 -2
  219. package/server/{shadow-state-BiMwdyl1.js → shadow-state-B4ayC7nx.js} +2 -2
  220. package/server/{shadow-state-1aS8FijU.js → shadow-state-CHqWHD3T.js} +1 -1
  221. package/server/{ship-log-CMWH3H5-.js → ship-log-CDVmOlZP.js} +1 -1
  222. package/server/{smart-compaction-Bw1K_Sbl.js → smart-compaction-C-F5sP9P.js} +7 -7
  223. package/server/{smart-compaction-xblMyVpT.js → smart-compaction-V9DBrGcr.js} +1 -1
  224. package/server/{spawn-planning-session-CzDFSKAQ.js → spawn-planning-session-Bz4_JES2.js} +1 -1
  225. package/server/{spawn-planning-session-DxLxcM7m.js → spawn-planning-session-dSpOU0lP.js} +15 -15
  226. package/server/{specialist-completion-BiEXUHfD.js → specialist-completion-Coz3eTSr.js} +1 -1
  227. package/server/{specialist-context-BfkTA81h.js → specialist-context-fmb03vXQ.js} +5 -5
  228. package/server/{specialist-handoff-logger-BiKuLtNm.js → specialist-handoff-logger-B9HK_lRu.js} +2 -2
  229. package/server/{specialist-logs-CFJjGsLC.js → specialist-logs-B24R2B9Y.js} +3 -3
  230. package/server/{specialists-BLIreoE7.js → specialists-B6f5-5nG.js} +1 -1
  231. package/server/{specialists-DjHbwQ_p.js → specialists-BGNZ0_ZW.js} +18 -18
  232. package/server/{specialists-B4byf18k.js → specialists-CL7E8yUg.js} +75 -75
  233. package/server/{specialists-DdvpFNt1.js → specialists-Chvvwf5z.js} +1 -1
  234. package/server/specs-oaaYaA5c.js +3 -0
  235. package/server/{src-CALBEUMX.js → src-BVxZuHMg.js} +3 -3
  236. package/server/{src-mK_M_ZIj.js → src-D-VXCC9C.js} +5 -5
  237. package/server/{src-fgbU-jJ-.js → src-DGAEtABV.js} +13 -2
  238. package/server/{stack-health-BFM8YlHw.js → stack-health-BKbTTOT2.js} +1 -1
  239. package/server/{stack-health-Qd7rPiVe.js → stack-health-C-le5erA.js} +2 -2
  240. package/server/{state-home-C2Bicw9N.js → state-home-CoyWsECg.js} +6 -6
  241. package/server/{summary-fork-EWWBvzgE.js → summary-fork-BF_0vxrq.js} +2 -2
  242. package/server/{summary-fork-DezPkJSm.js → summary-fork-BlE30Q-I.js} +8 -8
  243. package/server/supervisor-03Tj_Wra.js +2 -0
  244. package/server/{supervisor-D5GC5jUM.js → supervisor-BSeML_p0.js} +2 -2
  245. package/server/{swarm-readiness-Cf9mommA.js → swarm-readiness-CQ4sjrXc.js} +3 -3
  246. package/server/{system-prerequisites-BsI9hxh9.js → system-prerequisites-DnmLYOnU.js} +13 -1
  247. package/server/{teardown-workspace-CWz1pbEK.js → teardown-workspace-CpcjDrZ4.js} +12 -12
  248. package/server/{test-agent-queue-TiVXe3ZT.js → test-agent-queue-Bq298zZl.js} +5 -5
  249. package/server/{tldr-daemon-C_1frSDj.js → tldr-daemon-CaSUXd9r.js} +2 -2
  250. package/server/{tldr-daemon-Big5IZ_M.js → tldr-daemon-Rn1Zue0P.js} +1 -1
  251. package/server/{tmux-D57f-XNv.js → tmux-BVc-NeKM.js} +2 -2
  252. package/server/{tmux-DClqWwb8.js → tmux-CbcrkUx5.js} +1 -1
  253. package/server/{token-_qujO3JZ.js → token-D2OC_9ms.js} +1 -1
  254. package/server/{tracker-config-BmdJU_w6.js → tracker-config-C1Y_2CIo.js} +2 -2
  255. package/server/{tracker-config-B_Ubts1Z.js → tracker-config-EsBoOWEy.js} +1 -1
  256. package/server/{tracker-utils-Bg-Sevcv.js → tracker-utils-DSb9cfrF.js} +1 -1
  257. package/server/{tracker-utils-CWFt6jjV.js → tracker-utils-lph9C3Pw.js} +2 -2
  258. package/server/{tunnel-UBf2vyAL.js → tunnel-BFBCeo97.js} +2 -2
  259. package/server/{tunnel-hOBNQbmF.js → tunnel-DDe-ATFF.js} +1 -1
  260. package/server/{uat-train-DGkIkLxu.js → uat-train-8T24rPzc.js} +1 -1
  261. package/server/{uat-train-qNanv5hN.js → uat-train-DtKHHy1U.js} +23 -23
  262. package/server/{validation-B0QaLIHP.js → validation-COOXwNXU.js} +1 -1
  263. package/server/{validation-C4wegCvH.js → validation-lyudzPvD.js} +3 -3
  264. package/server/{verification-runner-CntudBes.js → verification-runner-DO0nYTJx.js} +11 -11
  265. package/server/{verification-runner-DdleMNLq.js → verification-runner-Dd1FX8Qk.js} +1 -1
  266. package/server/{vtt-parser-CKc-smWM.js → vtt-parser-C57tEF7-.js} +1 -1
  267. package/server/{work-agent-prompt-CG5jFV9A.js → work-agent-prompt-B2F3ZwKm.js} +11 -11
  268. package/server/workflows-B4fIN8VP.js +2 -0
  269. package/server/{workflows-BK2xs_a8.js → workflows-Clz_AFwR.js} +13 -13
  270. package/server/{workspace-CLrSIRCx.js → workspace-CY_2-Ddv.js} +3 -3
  271. package/server/{workspace-C9lC5o3E.js → workspace-D0rCFemz.js} +1 -1
  272. package/server/{workspace-manager-Cb2a7bg9.js → workspace-manager-BIfpzqdU.js} +1 -1
  273. package/server/{workspace-manager-BJhW2sky.js → workspace-manager-D6NgGkiF.js} +10 -10
  274. package/server/{workspace-metadata-QQmo_Z0l.js → workspace-metadata-C8yn8kAH.js} +2 -2
  275. package/server/{workspace-metadata-CTRnr323.js → workspace-metadata-DfgR40YU.js} +1 -1
  276. package/server/{workspaces-Ca4zZs12.js → workspaces-DOeHyKmA.js} +104 -92
  277. package/sync-sources/hooks/ask-user-question-hook +87 -0
  278. package/sync-sources/hooks/auto-approve-hook +96 -0
  279. package/sync-sources/hooks/codex-notify-hook +62 -0
  280. package/sync-sources/hooks/gh-issue-trailer-hook +4 -0
  281. package/sync-sources/hooks/gh-issue-trailer-hook.d.ts +7 -0
  282. package/sync-sources/hooks/gh-issue-trailer-hook.d.ts.map +1 -0
  283. package/sync-sources/hooks/gh-issue-trailer-hook.js +239 -0
  284. package/sync-sources/hooks/gh-issue-trailer-hook.js.map +1 -0
  285. package/sync-sources/hooks/gh-issue-trailer-hook.ts +296 -0
  286. package/sync-sources/hooks/git-hooks/post-checkout +109 -0
  287. package/sync-sources/hooks/heartbeat-hook +113 -0
  288. package/sync-sources/hooks/notification-hook +70 -0
  289. package/sync-sources/hooks/notify-complete +79 -0
  290. package/sync-sources/hooks/pan-hook-lib.sh +153 -0
  291. package/sync-sources/hooks/permission-event-hook +24 -0
  292. package/sync-sources/hooks/post-compact-hook +25 -0
  293. package/sync-sources/hooks/pre-compact-hook +26 -0
  294. package/sync-sources/hooks/pre-tool-hook +35 -0
  295. package/sync-sources/hooks/record-cost-event.d.ts +1 -0
  296. package/sync-sources/hooks/record-cost-event.js +31858 -0
  297. package/sync-sources/hooks/record-cost-event.js.map +1 -0
  298. package/sync-sources/hooks/record-cost-event.ts +267 -0
  299. package/sync-sources/hooks/rtk-bash-filter +152 -0
  300. package/sync-sources/hooks/session-start-hook +80 -0
  301. package/sync-sources/hooks/specialist-stop-hook +106 -0
  302. package/sync-sources/hooks/statusline.sh +169 -0
  303. package/sync-sources/hooks/stop-hook +217 -0
  304. package/sync-sources/hooks/tldr-post-edit +72 -0
  305. package/sync-sources/hooks/tldr-read-enforcer +340 -0
  306. package/sync-sources/hooks/tmux-send-keys-guard +87 -0
  307. package/sync-sources/hooks/tsdown.config.ts +14 -0
  308. package/sync-sources/hooks/user-prompt-submit-hook +57 -0
  309. package/sync-sources/hooks/work-agent-stop-hook +424 -0
  310. package/server/cli-Ch_BWJB2.js +0 -3
  311. package/server/deacon-swarm-CSWGRfzr.js +0 -2
  312. package/server/dist-BUplB3Od.js +0 -3
  313. package/server/forge-IgLR0Ist.js +0 -2
  314. package/server/inspect-agent-CYoWAeeB.js +0 -2
  315. package/server/merge-agent-CfohxFWM.js +0 -3
  316. package/server/merge-ops-Czke6UAp.js +0 -2
  317. package/server/public/assets/mermaid-GHXKKRXX-CZOsRYoT.js +0 -1
  318. package/server/rally-Ba9QoNYc.js +0 -3
  319. package/server/resume-CmxF3Kjz.js +0 -3
  320. package/server/settings-DEhYpW0k.js +0 -2
  321. package/server/specs-CVH1kvz3.js +0 -3
  322. package/server/supervisor-DQMK2e3I.js +0 -2
  323. package/server/workflows-pKw9yRSV.js +0 -2
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { homedir, tmpdir } from 'node:os';
4
+ import { basename, join } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ interface PreToolUseEvent {
8
+ tool_name?: string;
9
+ tool_input?: {
10
+ command?: string;
11
+ [key: string]: unknown;
12
+ };
13
+ }
14
+
15
+ interface Token {
16
+ text: string;
17
+ start: number;
18
+ end: number;
19
+ }
20
+
21
+ type HookEnv = Record<string, string | undefined>;
22
+
23
+ const FLYWHEEL_RUN_ID_PATTERN = /^RUN-\d+$/;
24
+
25
+ function shellQuote(value: string): string {
26
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
27
+ }
28
+
29
+ function tokenize(command: string): Token[] {
30
+ const tokens: Token[] = [];
31
+ let text = '';
32
+ let start = -1;
33
+ let quote: 'single' | 'double' | null = null;
34
+ let escape = false;
35
+
36
+ const flush = (end: number): void => {
37
+ if (start !== -1) tokens.push({ text, start, end });
38
+ text = '';
39
+ start = -1;
40
+ };
41
+
42
+ for (let index = 0; index < command.length; index += 1) {
43
+ const char = command[index];
44
+ if (start === -1 && !/\s/.test(char)) start = index;
45
+
46
+ if (escape) {
47
+ text += char;
48
+ escape = false;
49
+ continue;
50
+ }
51
+
52
+ if (quote === 'single') {
53
+ if (char === "'") quote = null;
54
+ else text += char;
55
+ continue;
56
+ }
57
+
58
+ if (quote === 'double') {
59
+ if (char === '"') quote = null;
60
+ else if (char === '\\') escape = true;
61
+ else text += char;
62
+ continue;
63
+ }
64
+
65
+ if (/\s/.test(char)) {
66
+ flush(index);
67
+ continue;
68
+ }
69
+
70
+ if (char === "'") {
71
+ quote = 'single';
72
+ continue;
73
+ }
74
+
75
+ if (char === '"') {
76
+ quote = 'double';
77
+ continue;
78
+ }
79
+
80
+ if (char === '\\') {
81
+ escape = true;
82
+ continue;
83
+ }
84
+
85
+ text += char;
86
+ }
87
+
88
+ flush(command.length);
89
+ return tokens;
90
+ }
91
+
92
+ function findGhIssueCreate(tokens: Token[]): number {
93
+ for (let index = 0; index <= tokens.length - 3; index += 1) {
94
+ if (tokens[index].text === 'gh' && tokens[index + 1].text === 'issue' && tokens[index + 2].text === 'create') {
95
+ return index;
96
+ }
97
+ }
98
+ return -1;
99
+ }
100
+
101
+ function containsFlywheelRunId(body: string): boolean {
102
+ return /^Flywheel-Run-Id:/m.test(body);
103
+ }
104
+
105
+ function resolveDiscoveredIn(env: HookEnv): string | null {
106
+ const agentId = env.OVERDECK_AGENT_ID;
107
+ if (!agentId || basename(agentId) !== agentId) return null;
108
+
109
+ const overdeckHome = env.OVERDECK_HOME ?? join(env.HOME ?? homedir(), '.overdeck');
110
+ const statePath = join(overdeckHome, 'agents', agentId, 'state.json');
111
+ if (!existsSync(statePath)) return null;
112
+
113
+ try {
114
+ const parsed = JSON.parse(readFileSync(statePath, 'utf-8')) as { issueId?: unknown };
115
+ return typeof parsed.issueId === 'string' && parsed.issueId.trim() ? parsed.issueId.trim() : null;
116
+ } catch {
117
+ return null;
118
+ }
119
+ }
120
+
121
+ function buildTrailer(env: HookEnv): string | null {
122
+ const runId = env.OVERDECK_FLYWHEEL_RUN_ID?.trim();
123
+ if (!runId || !FLYWHEEL_RUN_ID_PATTERN.test(runId)) return null;
124
+
125
+ const filedBy = env.OVERDECK_FLYWHEEL_AGENT_ROLE === 'flywheel' ? 'agent' : 'operator';
126
+ const discoveredIn = resolveDiscoveredIn(env);
127
+ const lines = [
128
+ '---',
129
+ `Flywheel-Run-Id: ${runId}`,
130
+ `Flywheel-Filed-By: ${filedBy}`,
131
+ discoveredIn ? `Flywheel-Discovered-In: ${discoveredIn}` : undefined,
132
+ ].filter((line): line is string => line !== undefined);
133
+ return `\n\n${lines.join('\n')}\n`;
134
+ }
135
+
136
+ function replaceSpan(command: string, start: number, end: number, replacement: string): string {
137
+ return `${command.slice(0, start)}${replacement}${command.slice(end)}`;
138
+ }
139
+
140
+ function findFlag(tokens: Token[], ghIndex: number, flagName: '--body' | '--body-file'): { flag: Token; value?: Token; inline: boolean } | null {
141
+ for (let index = ghIndex + 3; index < tokens.length; index += 1) {
142
+ const token = tokens[index];
143
+ if (token.text === flagName) return { flag: token, value: tokens[index + 1], inline: false };
144
+ if (token.text.startsWith(`${flagName}=`)) return { flag: token, inline: true };
145
+ }
146
+ return null;
147
+ }
148
+
149
+ function inlineFlagValue(flag: Token): { value: string; valueStart: number; valueEnd: number } | null {
150
+ const equalsOffset = flag.text.indexOf('=');
151
+ if (equalsOffset === -1) return null;
152
+ const valueStart = flag.start + equalsOffset + 1;
153
+ return { value: flag.text.slice(equalsOffset + 1), valueStart, valueEnd: flag.end };
154
+ }
155
+
156
+ function appendBodyFlag(command: string, tokens: Token[], ghIndex: number, trailer: string): string | null {
157
+ const bodyFlag = findFlag(tokens, ghIndex, '--body');
158
+ if (!bodyFlag) return null;
159
+
160
+ const body = bodyFlag.inline ? inlineFlagValue(bodyFlag.flag) : bodyFlag.value;
161
+ if (!body) return null;
162
+ const bodyText = 'text' in body ? body.text : body.value;
163
+ if (containsFlywheelRunId(bodyText)) return command;
164
+
165
+ const appended = `${bodyText}${trailer}`;
166
+ if ('text' in body) return replaceSpan(command, body.start, body.end, shellQuote(appended));
167
+ return replaceSpan(command, body.valueStart, body.valueEnd, shellQuote(appended));
168
+ }
169
+
170
+ function writeTempBodyFile(body: string): string {
171
+ const dir = mkdtempSync(join(tmpdir(), 'pan-gh-issue-body-'));
172
+ const path = join(dir, 'body.md');
173
+ writeFileSync(path, body, 'utf-8');
174
+ return path;
175
+ }
176
+
177
+ function appendBodyFileFlag(command: string, tokens: Token[], ghIndex: number, trailer: string): string | null {
178
+ const bodyFileFlag = findFlag(tokens, ghIndex, '--body-file');
179
+ if (!bodyFileFlag) return null;
180
+
181
+ const pathValue = bodyFileFlag.inline ? inlineFlagValue(bodyFileFlag.flag) : bodyFileFlag.value;
182
+ if (!pathValue) return null;
183
+ const pathText = 'text' in pathValue ? pathValue.text : pathValue.value;
184
+
185
+ if (pathText === '-') return appendStdinBody(command, tokens[ghIndex].start, trailer);
186
+ if (!existsSync(pathText)) return null;
187
+
188
+ const body = readFileSync(pathText, 'utf-8');
189
+ if (containsFlywheelRunId(body)) return command;
190
+
191
+ const tempPath = writeTempBodyFile(`${body}${trailer}`);
192
+ if ('text' in pathValue) return replaceSpan(command, pathValue.start, pathValue.end, shellQuote(tempPath));
193
+ return replaceSpan(command, pathValue.valueStart, pathValue.valueEnd, shellQuote(tempPath));
194
+ }
195
+
196
+ function findPipeBefore(command: string, beforeIndex: number): number {
197
+ let quote: 'single' | 'double' | null = null;
198
+ let escape = false;
199
+ let pipeIndex = -1;
200
+
201
+ for (let index = 0; index < beforeIndex; index += 1) {
202
+ const char = command[index];
203
+ if (escape) {
204
+ escape = false;
205
+ continue;
206
+ }
207
+ if (quote === 'single') {
208
+ if (char === "'") quote = null;
209
+ continue;
210
+ }
211
+ if (quote === 'double') {
212
+ if (char === '"') quote = null;
213
+ else if (char === '\\') escape = true;
214
+ continue;
215
+ }
216
+ if (char === "'") quote = 'single';
217
+ else if (char === '"') quote = 'double';
218
+ else if (char === '\\') escape = true;
219
+ else if (char === '|' && command[index + 1] !== '|' && command[index - 1] !== '|') pipeIndex = index;
220
+ }
221
+
222
+ return pipeIndex;
223
+ }
224
+
225
+ function appendHereDoc(command: string, trailer: string): string | null {
226
+ const match = command.match(/(<<-?\s*['"]?([A-Za-z_][A-Za-z0-9_-]*)['"]?[^\n]*\n)([\s\S]*?)(\n\2\s*)$/);
227
+ if (!match || match.index === undefined) return null;
228
+ const body = match[3];
229
+ if (containsFlywheelRunId(body)) return command;
230
+ const bodyStart = match.index + match[1].length;
231
+ const bodyEnd = bodyStart + body.length;
232
+ return replaceSpan(command, bodyStart, bodyEnd, `${body}${trailer}`);
233
+ }
234
+
235
+ function appendStdinBody(command: string, ghStart: number, trailer: string): string | null {
236
+ if (command.includes('Flywheel-Run-Id:')) return command;
237
+
238
+ const hereDoc = appendHereDoc(command, trailer);
239
+ if (hereDoc) return hereDoc;
240
+
241
+ const pipeIndex = findPipeBefore(command, ghStart);
242
+ if (pipeIndex === -1) return null;
243
+
244
+ const producer = command.slice(0, pipeIndex).trim();
245
+ const consumer = command.slice(pipeIndex + 1).trimStart();
246
+ if (!producer || !consumer) return null;
247
+ return `{ ${producer}; printf %s ${shellQuote(trailer)}; } | ${consumer}`;
248
+ }
249
+
250
+ function buildUpdatedInput(command: string): Record<string, unknown> {
251
+ return {
252
+ hookSpecificOutput: {
253
+ hookEventName: 'PreToolUse',
254
+ permissionDecisionReason: 'Flywheel issue provenance trailers added',
255
+ updatedInput: { command },
256
+ },
257
+ };
258
+ }
259
+
260
+ export function rewriteGhIssueCreateCommand(command: string, env: HookEnv = process.env): string | null {
261
+ const trailer = buildTrailer(env);
262
+ if (!trailer) return null;
263
+
264
+ const tokens = tokenize(command);
265
+ const ghIndex = findGhIssueCreate(tokens);
266
+ if (ghIndex === -1) return null;
267
+
268
+ const bodyCommand = appendBodyFlag(command, tokens, ghIndex, trailer);
269
+ if (bodyCommand !== null) return bodyCommand === command ? null : bodyCommand;
270
+
271
+ const bodyFileCommand = appendBodyFileFlag(command, tokens, ghIndex, trailer);
272
+ if (bodyFileCommand !== null) return bodyFileCommand === command ? null : bodyFileCommand;
273
+
274
+ return null;
275
+ }
276
+
277
+ export function runGhIssueTrailerHook(input: string, env: HookEnv = process.env): string {
278
+ let event: PreToolUseEvent;
279
+ try {
280
+ event = JSON.parse(input) as PreToolUseEvent;
281
+ } catch {
282
+ return '{}';
283
+ }
284
+
285
+ const command = event.tool_name === 'Bash' ? event.tool_input?.command : undefined;
286
+ if (typeof command !== 'string') return '{}';
287
+
288
+ const updatedCommand = rewriteGhIssueCreateCommand(command, env);
289
+ if (!updatedCommand) return '{}';
290
+ return JSON.stringify(buildUpdatedInput(updatedCommand));
291
+ }
292
+
293
+ if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
294
+ const input = readFileSync(0, 'utf-8');
295
+ process.stdout.write(runGhIssueTrailerHook(input));
296
+ }
@@ -0,0 +1,109 @@
1
+ #!/bin/bash
2
+ #
3
+ # Git post-checkout hook to guard main project directories
4
+ # Prevents accidental checkouts away from main in the primary project directory
5
+ #
6
+ # Install: ln -sf /path/to/overdeck/scripts/git-hooks/post-checkout .git/hooks/post-checkout
7
+ # Or: pan projects add /path/to/project (auto-installs hooks)
8
+ #
9
+ # This hook only activates in the MAIN project directory (not worktrees).
10
+ # Worktrees can freely checkout any branch - that's their purpose.
11
+ #
12
+ # Auto-revert behavior:
13
+ # - Agents (OVERDECK_AGENT=1): Always auto-revert (agents should never checkout in main)
14
+ # - Manual (OVERDECK_AUTO_REVERT_CHECKOUT=1): Opt-in auto-revert for humans
15
+ # - Default: Warn only, don't revert
16
+
17
+ # Get the previous and new HEAD refs
18
+ PREV_HEAD=$1
19
+ NEW_HEAD=$2
20
+ IS_BRANCH_CHECKOUT=$3 # 1 if branch checkout, 0 if file checkout
21
+
22
+ # Only care about branch checkouts
23
+ if [ "$IS_BRANCH_CHECKOUT" != "1" ]; then
24
+ exit 0
25
+ fi
26
+
27
+ # Check if we're in a worktree (worktrees have .git as a file, not directory)
28
+ if [ -f ".git" ]; then
29
+ # This is a worktree - allow any checkout
30
+ exit 0
31
+ fi
32
+
33
+ # Check if .git is a directory (main repo)
34
+ if [ ! -d ".git" ]; then
35
+ # Not a git repo at all
36
+ exit 0
37
+ fi
38
+
39
+ # Get current branch name
40
+ CURRENT_BRANCH=$(git branch --show-current 2>/dev/null)
41
+
42
+ # If we're on main or master, all good
43
+ if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
44
+ exit 0
45
+ fi
46
+
47
+ # We're in the main project directory and NOT on main - this is bad!
48
+ echo ""
49
+ echo "╔══════════════════════════════════════════════════════════════════════════════╗"
50
+ echo "║ ⚠️ WARNING: Main project directory is not on 'main' branch! ║"
51
+ echo "╠══════════════════════════════════════════════════════════════════════════════╣"
52
+ echo "║ ║"
53
+ echo "║ Current branch: $CURRENT_BRANCH"
54
+ echo "║ Location: $(pwd)"
55
+ echo "║ ║"
56
+ echo "║ The main project directory should ALWAYS stay on 'main'. ║"
57
+ echo "║ All feature work should happen in workspaces (git worktrees). ║"
58
+ echo "║ ║"
59
+ echo "║ To fix this: ║"
60
+ echo "║ git checkout main ║"
61
+ echo "║ ║"
62
+ echo "║ To work on a feature: ║"
63
+ echo "║ pan workspace create ISSUE-ID ║"
64
+ echo "║ ║"
65
+ echo "╚══════════════════════════════════════════════════════════════════════════════╝"
66
+ echo ""
67
+
68
+ # Auto-revert for agents and planning sessions
69
+ # They should NEVER be checking out in main project
70
+ IS_OVERDECK_SESSION=0
71
+
72
+ # Check explicit environment variables
73
+ if [ "$OVERDECK_AGENT" = "1" ] || [ -n "$OVERDECK_AGENT_ID" ]; then
74
+ IS_OVERDECK_SESSION=1
75
+ fi
76
+
77
+ # Check for planning session
78
+ if [ "$OVERDECK_PLANNING" = "1" ] || [ -n "$OVERDECK_PLANNING_ISSUE" ]; then
79
+ IS_OVERDECK_SESSION=1
80
+ fi
81
+
82
+ # Check tmux session name pattern (agent-* or planning-* or specialist-*)
83
+ if [ -n "$TMUX" ]; then
84
+ TMUX_SESSION=$(tmux display-message -p '#{session_name}' 2>/dev/null || true)
85
+ case "$TMUX_SESSION" in
86
+ agent-*|planning-*|specialist-*)
87
+ IS_OVERDECK_SESSION=1
88
+ ;;
89
+ esac
90
+ fi
91
+
92
+ if [ "$IS_OVERDECK_SESSION" = "1" ]; then
93
+ echo "🤖 Overdeck session detected - auto-reverting to main branch..."
94
+ git checkout main --quiet
95
+ echo "✓ Reverted to main branch. Agents/planning must use workspaces for feature branches."
96
+ exit 0
97
+ fi
98
+
99
+ # Check for manual auto-revert environment variable
100
+ if [ "$OVERDECK_AUTO_REVERT_CHECKOUT" = "1" ]; then
101
+ echo "Auto-reverting to main branch (OVERDECK_AUTO_REVERT_CHECKOUT=1)..."
102
+ git checkout main --quiet
103
+ echo "Reverted to main branch."
104
+ exit 0
105
+ fi
106
+
107
+ # Return success but with warning - don't block the checkout
108
+ # The warning is enough for humans to notice
109
+ exit 0
@@ -0,0 +1,113 @@
1
+ #!/bin/bash
2
+ # ~/.overdeck/bin/heartbeat-hook (PAN-800)
3
+ #
4
+ # Fires on Claude Code PostToolUse. POSTs agent.activity_changed(working, tool)
5
+ # to the dashboard, then records the cost event.
6
+ #
7
+ # Rewritten from the ~200-line jq read-modify-write version to a pure POST
8
+ # emitter. runtime.json and heartbeats/<id>.json are no longer written —
9
+ # AgentStateService's SubscriptionRef + projection_cache is canonical.
10
+ # activity.jsonl is retained as a forensic grep-able artifact (cheap to keep).
11
+ # The sessions.json append-only list is retained because it's a bookkeeping
12
+ # record of Claude session UUIDs, not runtime state.
13
+ # Cost-event recording stays on its own flock-serialized path.
14
+
15
+ set +e
16
+
17
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
18
+ # shellcheck source=pan-hook-lib.sh
19
+ . "$SCRIPT_DIR/pan-hook-lib.sh" 2>/dev/null || exit 0
20
+
21
+ pan_resolve_agent_id || exit 0
22
+
23
+ TOOL_INFO=$(cat 2>/dev/null || echo '{}')
24
+
25
+ HAVE_JQ=0
26
+ if command -v jq >/dev/null 2>&1; then HAVE_JQ=1; fi
27
+
28
+ TOOL_NAME="unknown"
29
+ TOOL_INPUT=""
30
+ CLAUDE_SESSION_ID=""
31
+ if [ "$HAVE_JQ" = "1" ]; then
32
+ TOOL_NAME=$(echo "$TOOL_INFO" | jq -r '.tool_name // "unknown"' 2>/dev/null || echo "unknown")
33
+ TOOL_INPUT=$(echo "$TOOL_INFO" | jq -r '.tool_input | tostring | .[0:100] // ""' 2>/dev/null || echo "")
34
+ CLAUDE_SESSION_ID=$(echo "$TOOL_INFO" | jq -r '.session_id // ""' 2>/dev/null || echo "")
35
+ fi
36
+
37
+ TS=$(date -Iseconds)
38
+
39
+ # ── Emit agent.activity_changed(working, tool) ─────────────────────────────
40
+ if [ "$HAVE_JQ" = "1" ]; then
41
+ BODY=$(jq -n --arg tool "$TOOL_NAME" --arg ts "$TS" \
42
+ '{kind: "activity", activity: "working", tool: $tool, timestamp: $ts}')
43
+ else
44
+ BODY="{\"kind\":\"activity\",\"activity\":\"working\",\"tool\":\"$TOOL_NAME\",\"timestamp\":\"$TS\"}"
45
+ fi
46
+ pan_emit_event "$AGENT_ID" "$BODY"
47
+
48
+ # ── Activity log (retained for forensics) ─────────────────────────────────
49
+ AGENT_DIR="$HOME/.overdeck/agents/$AGENT_ID"
50
+ mkdir -p "$AGENT_DIR" 2>/dev/null
51
+ if [ "$HAVE_JQ" = "1" ]; then
52
+ ENTRY=$(jq -n --arg ts "$TS" --arg tool "$TOOL_NAME" --arg action "$TOOL_INPUT" \
53
+ '{ts: $ts, tool: $tool, action: $action}' 2>/dev/null || echo "")
54
+ if [ -n "$ENTRY" ]; then
55
+ echo "$ENTRY" >> "$AGENT_DIR/activity.jsonl" 2>/dev/null || true
56
+ # Prune to last 100 entries.
57
+ if [ -f "$AGENT_DIR/activity.jsonl" ]; then
58
+ TMP="$AGENT_DIR/activity.jsonl.tmp"
59
+ tail -n 100 "$AGENT_DIR/activity.jsonl" > "$TMP" 2>/dev/null \
60
+ && mv "$TMP" "$AGENT_DIR/activity.jsonl" 2>/dev/null || true
61
+ fi
62
+ fi
63
+ fi
64
+
65
+ # ── Claude session history (append-only bookkeeping) ──────────────────────
66
+ if [ "$HAVE_JQ" = "1" ] && [ -n "$CLAUDE_SESSION_ID" ]; then
67
+ SESSIONS_FILE="$AGENT_DIR/sessions.json"
68
+ if [ -f "$SESSIONS_FILE" ]; then
69
+ if ! jq -e --arg sid "$CLAUDE_SESSION_ID" 'any(.[]; . == $sid)' "$SESSIONS_FILE" >/dev/null 2>&1; then
70
+ TMP="$SESSIONS_FILE.tmp"
71
+ jq --arg sid "$CLAUDE_SESSION_ID" '. + [$sid]' "$SESSIONS_FILE" > "$TMP" 2>/dev/null \
72
+ && mv "$TMP" "$SESSIONS_FILE" 2>/dev/null || true
73
+ fi
74
+ else
75
+ echo "[\"$CLAUDE_SESSION_ID\"]" > "$SESSIONS_FILE" 2>/dev/null || true
76
+ fi
77
+ fi
78
+
79
+ # ── Cost-event recording (unchanged, its own flock-serialized path) ──────
80
+ COST_SCRIPT=""
81
+ if [ -f "$HOME/.overdeck/bin/record-cost-event.js" ]; then
82
+ COST_SCRIPT="$HOME/.overdeck/bin/record-cost-event.js"
83
+ elif [ -f "$SCRIPT_DIR/record-cost-event.js" ]; then
84
+ COST_SCRIPT="$SCRIPT_DIR/record-cost-event.js"
85
+ fi
86
+
87
+ if [ -n "$COST_SCRIPT" ] && [ -n "$CLAUDE_SESSION_ID" ]; then
88
+ GIT_BRANCH=$(git branch --show-current 2>/dev/null || echo "")
89
+ WORKSPACE=$(pwd)
90
+
91
+ if [ -z "$OVERDECK_ISSUE_ID" ]; then
92
+ if [[ "$GIT_BRANCH" =~ (pan|min|aud|krux|cli|PAN|MIN|AUD|KRUX|CLI)[-]([0-9]+) ]]; then
93
+ OVERDECK_ISSUE_ID="${BASH_REMATCH[1]^^}-${BASH_REMATCH[2]}"
94
+ fi
95
+ fi
96
+ if [ -z "$OVERDECK_ISSUE_ID" ]; then
97
+ if [[ "$WORKSPACE" =~ (pan|min|aud|krux|cli|PAN|MIN|AUD|KRUX|CLI)[-]([0-9]+) ]]; then
98
+ OVERDECK_ISSUE_ID="${BASH_REMATCH[1]^^}-${BASH_REMATCH[2]}"
99
+ fi
100
+ fi
101
+ export OVERDECK_ISSUE_ID="${OVERDECK_ISSUE_ID:-UNKNOWN}"
102
+ export OVERDECK_SESSION_TYPE="${OVERDECK_SESSION_TYPE:-implementation}"
103
+
104
+ STATE_DIR="$HOME/.overdeck/costs/state"
105
+ mkdir -p "$STATE_DIR" 2>/dev/null
106
+ LOCK_FILE="$STATE_DIR/${CLAUDE_SESSION_ID}.lock"
107
+ {
108
+ flock -x -w 30 200
109
+ echo "$TOOL_INFO" | node "$COST_SCRIPT" 2>/dev/null || true
110
+ } 200>"$LOCK_FILE"
111
+ fi
112
+
113
+ exit 0
@@ -0,0 +1,70 @@
1
+ #!/bin/bash
2
+ # ~/.overdeck/bin/notification-hook (PAN-800)
3
+ #
4
+ # Fires on Claude Code Notification events. If the notification looks like a
5
+ # permission prompt or a request for human input, emits
6
+ # agent.waiting_started(reason=...). Logs the raw payload for future analysis.
7
+ #
8
+ # PAN-709 note: the Notification event fires for system/desktop notifications
9
+ # from Claude Code, NOT for in-terminal tool approval dialogs. In-terminal
10
+ # prompts are detected separately by the deacon tmux-tail scanner (still
11
+ # active during the PAN-800 migration; scheduled for replacement in Phase 5).
12
+
13
+ set +e
14
+
15
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
16
+ # shellcheck source=pan-hook-lib.sh
17
+ . "$SCRIPT_DIR/pan-hook-lib.sh" 2>/dev/null || exit 0
18
+
19
+ pan_resolve_agent_id || exit 0
20
+
21
+ NOTIF_INFO=$(cat 2>/dev/null || echo '{}')
22
+
23
+ HAVE_JQ=0
24
+ if command -v jq >/dev/null 2>&1; then HAVE_JQ=1; fi
25
+
26
+ NOTIF_MSG=""
27
+ if [ "$HAVE_JQ" = "1" ]; then
28
+ NOTIF_MSG=$(echo "$NOTIF_INFO" | jq -r '.message // ""' 2>/dev/null || echo "")
29
+ fi
30
+
31
+ TS=$(date -Iseconds)
32
+
33
+ # Log the raw notification for forensics. Kept at 500 entries.
34
+ LOG_DIR="$HOME/.overdeck/logs"
35
+ mkdir -p "$LOG_DIR" 2>/dev/null
36
+ LOG_FILE="$LOG_DIR/notifications.jsonl"
37
+ if [ "$HAVE_JQ" = "1" ]; then
38
+ jq -n --arg ts "$TS" --arg agent "$AGENT_ID" --argjson payload "$NOTIF_INFO" \
39
+ '{ts: $ts, agent: $agent, payload: $payload}' >> "$LOG_FILE" 2>/dev/null || true
40
+ if [ -f "$LOG_FILE" ]; then
41
+ TMP="$LOG_FILE.tmp"
42
+ tail -n 500 "$LOG_FILE" > "$TMP" 2>/dev/null && mv "$TMP" "$LOG_FILE" 2>/dev/null || true
43
+ fi
44
+ fi
45
+
46
+ # Classify the notification. The message strings come from Claude Code's own
47
+ # notification payloads; we're pattern-matching the keywords that indicate the
48
+ # agent is stalled waiting for the human.
49
+ REASON=""
50
+ if echo "$NOTIF_MSG" | grep -qiE '(permission|approval|allow.*tool|confirm.*tool)'; then
51
+ REASON="tool_permission"
52
+ elif echo "$NOTIF_MSG" | grep -qiE '(question|needs.*input|waiting.*for|needs your)'; then
53
+ REASON="user_question"
54
+ elif echo "$NOTIF_MSG" | grep -qiE '(disambiguat|choose|select|which)'; then
55
+ REASON="disambiguation"
56
+ fi
57
+
58
+ if [ -n "$REASON" ]; then
59
+ if [ "$HAVE_JQ" = "1" ]; then
60
+ BODY=$(jq -n --arg reason "$REASON" --arg msg "$NOTIF_MSG" --arg ts "$TS" \
61
+ '{kind: "waiting_start", reason: $reason, message: $msg, timestamp: $ts}')
62
+ else
63
+ # Fallback: minimal body, no message field. Escaping arbitrary NOTIF_MSG
64
+ # into JSON by hand is error-prone.
65
+ BODY="{\"kind\":\"waiting_start\",\"reason\":\"$REASON\",\"timestamp\":\"$TS\"}"
66
+ fi
67
+ pan_emit_event "$AGENT_ID" "$BODY"
68
+ fi
69
+
70
+ exit 0
@@ -0,0 +1,79 @@
1
+ #!/bin/bash
2
+ # notify-complete: Send desktop notification when agent completes work
3
+ # Part of Overdeck - works on WSL2/Windows, Linux, and macOS
4
+ #
5
+ # Usage: notify-complete <issue-id> <title> [mr-url]
6
+ #
7
+ # Examples:
8
+ # notify-complete MIN-665 "Fixed login button"
9
+ # notify-complete PAN-96 "Implemented templates" "https://gitlab.com/mr/123"
10
+
11
+ ISSUE_ID="${1:-UNKNOWN}"
12
+ TITLE="${2:-Agent completed work}"
13
+ MR_URL="${3:-}"
14
+
15
+ # Log to completion file
16
+ COMPLETION_LOG="$HOME/.overdeck/agent-completed.log"
17
+ mkdir -p "$(dirname "$COMPLETION_LOG")"
18
+ echo "$(date '+%Y-%m-%d %H:%M:%S') | ${ISSUE_ID} | ${TITLE} | ${MR_URL}" >> "$COMPLETION_LOG"
19
+
20
+ # Detect platform and send notification
21
+ send_notification() {
22
+ local title="$1"
23
+ local message="$2"
24
+
25
+ # WSL2/Windows - use PowerShell toast notifications
26
+ if command -v powershell.exe &>/dev/null; then
27
+ powershell.exe -Command "
28
+ \$xml = @\"
29
+ <toast>
30
+ <visual>
31
+ <binding template=\"ToastText02\">
32
+ <text id=\"1\">${title}</text>
33
+ <text id=\"2\">${message}</text>
34
+ </binding>
35
+ </visual>
36
+ <audio src=\"ms-winsoundevent:Notification.Default\"/>
37
+ </toast>
38
+ \"@
39
+
40
+ [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
41
+ [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
42
+
43
+ \$template = New-Object Windows.Data.Xml.Dom.XmlDocument
44
+ \$template.LoadXml(\$xml)
45
+ \$toast = New-Object Windows.UI.Notifications.ToastNotification \$template
46
+ [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('Overdeck').Show(\$toast)
47
+ " 2>/dev/null && return 0
48
+
49
+ # Fallback: MessageBox
50
+ powershell.exe -Command "[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('${message}', '${title}', 'OK', 'Information')" 2>/dev/null &
51
+ return 0
52
+ fi
53
+
54
+ # macOS - use osascript
55
+ if command -v osascript &>/dev/null; then
56
+ osascript -e "display notification \"${message}\" with title \"${title}\"" 2>/dev/null
57
+ return 0
58
+ fi
59
+
60
+ # Linux - use notify-send
61
+ if command -v notify-send &>/dev/null; then
62
+ notify-send "${title}" "${message}" 2>/dev/null
63
+ return 0
64
+ fi
65
+
66
+ # Fallback - just print to console
67
+ echo "[NOTIFICATION] ${title}: ${message}"
68
+ }
69
+
70
+ # Build notification message
71
+ if [ -n "$MR_URL" ]; then
72
+ MESSAGE="${TITLE} - Ready for review"
73
+ else
74
+ MESSAGE="${TITLE} - Work complete"
75
+ fi
76
+
77
+ send_notification "Overdeck: ${ISSUE_ID}" "$MESSAGE"
78
+
79
+ echo "Notification sent for ${ISSUE_ID}"