@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.
- package/drizzle/overdeck/0000_overdeck_init.sql +33 -0
- package/package.json +7 -2
- package/server/{acceptance-criteria-1LHgD9vg.js → acceptance-criteria-CfujPRrz.js} +2 -2
- package/server/{advancing-selfheal-BqsLWqEM.js → advancing-selfheal-Bn5QiLtn.js} +4 -4
- package/server/{agent-gc-CUb52n7s.js → agent-gc-Cl9Nm0Zu.js} +3 -3
- package/server/{agent-state-D-moNwhA.js → agent-state-C6Rm6FPR.js} +1 -1
- package/server/{agent-state-service-BzESvLOf.js → agent-state-service-JhFzYCP_.js} +5 -5
- package/server/{agent-state-service-BaZH7sXJ.js → agent-state-service-U8feBf8t.js} +1 -1
- package/server/{agents-C4kZ8a2r.js → agents-CxbuBjID.js} +1 -1
- package/server/{agents-B5LfpLPv.js → agents-DqQa4Dq_.js} +88 -64
- package/server/{archive-planning-oX1pj6nY.js → archive-planning-CPitEZo4.js} +3 -3
- package/server/{archive-planning-BbZe-8IK.js → archive-planning-DmpT1_14.js} +1 -1
- package/server/{artifact-index-jobs-DGr6bxev.js → artifact-index-jobs-sMnNtPhy.js} +2 -2
- package/server/{auto-commit-CGQlb4rV.js → auto-commit-wZ9X7Isd.js} +1 -1
- package/server/{backlog-auto-trigger-BlJHikOm.js → backlog-auto-trigger-Cf9C8fwD.js} +2 -2
- package/server/{bd-process-lock-i3CYMS-B.js → bd-process-lock-D1aJxeYv.js} +2 -2
- package/server/{beads-BNU-fb48.js → beads-CivpXztb.js} +1 -1
- package/server/{beads-DD7fYCl5.js → beads-DRoj6-e1.js} +4 -4
- package/server/{beads-query-e6oku4P5.js → beads-query-tOsAYP5h.js} +2 -2
- package/server/{behavior-CPf0pbOt.js → behavior-D3d2mVyD.js} +3 -3
- package/server/{briefing-freshness-B2FdLwIv.js → briefing-freshness-BL3Q6p7R.js} +4 -4
- package/server/{checkpoint-manager-JryW6MpM.js → checkpoint-manager-DCxjQvP_.js} +2 -2
- package/server/{checkpoint-manager-eFgaMMu4.js → checkpoint-manager-j5URlFY7.js} +1 -1
- package/server/checkpoint-worker.js +1 -1
- package/server/{checkpoints-qvOqvMuC.js → checkpoints-BoX1H2Hf.js} +2 -2
- package/server/{checkpoints-BK17oicz.js → checkpoints-Bu_M_Q9W.js} +1 -1
- package/server/claude-hooks-provision-D-jGXmu1.js +360 -0
- package/server/{claude-permissions-B6bWGh9d.js → claude-permissions-DxIjkOVl.js} +2 -2
- package/server/{claude-settings-overlay-BPdhTPjo.js → claude-settings-overlay-5b9X2S0C.js} +1 -1
- package/server/{claude-settings-overlay-CRyyKKXQ.js → claude-settings-overlay-BPDS6GfE.js} +2 -2
- package/server/cli-CqgiSAU8.js +3 -0
- package/server/{cli-B75AieAM.js → cli-s7bPWy-E.js} +9 -9
- package/server/{cliproxy-CCzwuSNe.js → cliproxy-BituqWtR.js} +2 -2
- package/server/{cliproxy-DOQf66G9.js → cliproxy-D3sHB0sI.js} +1 -1
- package/server/{close-issue-_X3MXJyG.js → close-issue-CrBE7voz.js} +4 -4
- package/server/{closed-issue-reaper-CLR7ClsO.js → closed-issue-reaper-BRQBc7Xa.js} +1 -1
- package/server/{closed-issue-reaper-BsUfBSjM.js → closed-issue-reaper-DX9mYUji.js} +9 -9
- package/server/{codex-CY-QRuU9.js → codex-Bi1ITSOo.js} +1 -1
- package/server/{codex-B4KEpX5V.js → codex-CO0HrK3j.js} +5 -5
- package/server/{compact-beads-cZds2MTr.js → compact-beads-CrA8-k10.js} +1 -1
- package/server/{compact-beads-uEDccC76.js → compact-beads-DUkCUFxA.js} +3 -3
- package/server/{config-DARrpYWA.js → config-B4_d7z7z.js} +1 -1
- package/server/{config-8sjaU6jZ.js → config-DsCxzjXK.js} +2 -2
- package/server/{config-yaml-ClpGgrf6.js → config-yaml-C_djSurJ.js} +2 -2
- package/server/{conflict-gate-Ds9_2yjd.js → conflict-gate-CpOn9KC-.js} +1 -1
- package/server/{conflict-gate-BtB_o-Vi.js → conflict-gate-D47Kl78u.js} +3 -3
- package/server/{context-layers-r2ywnQYA.js → context-layers-BNhUBTkf.js} +3 -3
- package/server/{context-layers-CRCk1QG7.js → context-layers-CHl3Nroz.js} +2 -2
- package/server/{control-settings-D1B3u6HP.js → control-settings-KyYNXZLv.js} +4 -4
- package/server/{conversation-compaction-D86Zo2Ci.js → conversation-compaction-D3aS5PnS.js} +8 -8
- package/server/{conversation-compaction-CZRVk4hg.js → conversation-compaction-D4Wed1BJ.js} +1 -1
- package/server/{conversation-service-CuTVU8dV.js → conversation-service-CFZIjs-M.js} +5 -5
- package/server/{conversation-service-CkL-6MuG.js → conversation-service-DcDB5usR.js} +1 -1
- package/server/{conversations-DfJKBDwB.js → conversations-BSOU5qnu.js} +4 -4
- package/server/{conversations-BmWEluPL.js → conversations-BbDPrz89.js} +1 -1
- package/server/{cost-DAPYN6iA.js → cost-BE_ulOrw.js} +3 -3
- package/server/{cost-CCnqa5xK.js → cost-CaiG63FG.js} +2 -2
- package/server/{cost-sync-BDL10Nwu.js → cost-sync-D6AX8jv-.js} +3 -3
- package/server/{dag-Dv2r5bVD.js → dag-BQFtXOuJ.js} +3 -3
- package/server/{dangerous-git-ops-Dcw7PbYo.js → dangerous-git-ops-04Ba-Qu3.js} +1 -1
- package/server/dashboard-db-worker.js +6 -6
- package/server/{deacon-CM0MxbS8.js → deacon-2EvA9Ci3.js} +97 -97
- package/server/{deacon-DYnZH7kC.js → deacon-Bz-6Wjmn.js} +3 -3
- package/server/deacon-swarm-B8pgK2a7.js +2 -0
- package/server/{deacon-swarm-BstYoz8Q.js → deacon-swarm-DYYOzHRH.js} +10 -10
- package/server/deacon.js +7 -7
- package/server/{devcontainer-renderer-CaYOG9JN.js → devcontainer-renderer-Dx0C7VWJ.js} +2 -2
- package/server/dist-BYSj075e.js +3 -0
- package/server/{dist-BIC8spJ0.js → dist-ya66D9ze.js} +1 -1
- package/server/{docker-DDI1shu3.js → docker-D2TbXDO6.js} +2 -2
- package/server/{ensure-devcontainer-CbSXvN9W.js → ensure-devcontainer-BIShzs3M.js} +1 -1
- package/server/{ensure-devcontainer-DCAg3ksz.js → ensure-devcontainer-BTiMfFp5.js} +3 -3
- package/server/{event-store-DU3HkZlN.js → event-store-C02Gprug.js} +1 -1
- package/server/{event-store-DCMqyI07.js → event-store-C71x6h0i.js} +3 -3
- package/server/{events-BfiosVAn.js → events-BFDuPV6n.js} +3 -3
- package/server/{events-DLRxpSuV.js → events-D2gP2-Yv.js} +1 -1
- package/server/{factory-BMtWV9iv.js → factory-ByfbrCab.js} +4 -4
- package/server/{feature-registry-population-DA7bO6Zn.js → feature-registry-population-CSH66UO8.js} +4 -4
- package/server/{feature-registry-storage-nAY1fbBt.js → feature-registry-storage-DW7dUefc.js} +2 -2
- package/server/{features-DMu7eGmU.js → features-x_aLR7U9.js} +2 -2
- package/server/{feedback-target-DHqcw3cN.js → feedback-target-BFo9fScH.js} +6 -6
- package/server/{feedback-target-B2SEai8-.js → feedback-target-C4VMPTZu.js} +1 -1
- package/server/{feedback-writer-qvm7UON7.js → feedback-writer-B9ZqnnX3.js} +4 -4
- package/server/{feedback-writer-DMBdS_jL.js → feedback-writer-DCyd75yJ.js} +1 -1
- package/server/{flywheel-Dfpx4bIV.js → flywheel-D9NKvWqb.js} +11 -11
- package/server/{flywheel-k4FPtCQ_.js → flywheel-DB48X7Nn.js} +1 -1
- package/server/{flywheel-D2LdPSic.js → flywheel-DwQCoZQG.js} +13 -13
- package/server/{flywheel-merge-order-CB4lbXeJ.js → flywheel-merge-order-DrjmFXg4.js} +6 -6
- package/server/{flywheel-merge-order-CttTazRY.js → flywheel-merge-order-f1bi5XIf.js} +1 -1
- package/server/{forge-CoPFXFyl.js → forge-C-SoKy8U.js} +2 -2
- package/server/forge-CUCYK7h_.js +2 -0
- package/server/{from-B0YoJl9-.js → from-fu7ZumnY.js} +1 -1
- package/server/{fts-db-DAHW1yA_.js → fts-db-CL-YzSRG.js} +2 -2
- package/server/{fts-operations-DDXDBi0d.js → fts-operations-Bylu5NjM.js} +2 -2
- package/server/{git-utils-B90Zjzfl.js → git-utils-C8koBs8j.js} +2 -2
- package/server/{git-utils-DbfC0zls.js → git-utils-Ym380hJZ.js} +1 -1
- package/server/{github-app-C7lftMNj.js → github-app-DIr70YLg.js} +1 -1
- package/server/{github-app-BecAnXRX.js → github-app-DhycHVLF.js} +2 -2
- package/server/{github-client-D21rCIXk.js → github-client-7gkcXcBS.js} +2 -2
- package/server/{github-client-BwtKZtM0.js → github-client-Ji9lUTNF.js} +1 -1
- package/server/{github-pr-lookup-CzVWuysl.js → github-pr-lookup-rt7T9FwA.js} +2 -2
- package/server/{harness-resolve-SkRJm4a7.js → harness-resolve-CvGXUnAF.js} +3 -3
- package/server/{health-events-BT0aAfeA.js → health-events-D4E1DLN-.js} +2 -2
- package/server/{health-events-DA_JLpgZ.js → health-events-DDfkoO5a.js} +1 -1
- package/server/{hooks-DxEn2BoY.js → hooks-D_6pAbuJ.js} +2 -2
- package/server/{hooks-BQxRXtRb.js → hooks-DvdnCVv6.js} +1 -1
- package/server/{idle-stack-reaper-C7fJL8jH.js → idle-stack-reaper-DNbV9-fj.js} +1 -1
- package/server/{idle-stack-reaper-DGy7tvC9.js → idle-stack-reaper-cDRXDpgE.js} +2 -2
- package/server/{infra-DE3C4PMr.js → infra-Clew3DpF.js} +50 -3
- package/server/{injection-Dt22tGvS.js → injection-QCIHOpk6.js} +1 -1
- package/server/{injection-Cc4Qt8LZ.js → injection-ql0Nddcn.js} +7 -7
- package/server/inspect-agent-D8UBDgfR.js +2 -0
- package/server/{inspect-agent-DOaCDkCF.js → inspect-agent-DY18KEx4.js} +9 -9
- package/server/{internal-token-B_1YLWLI.js → internal-token-BeXjPLKy.js} +2 -2
- package/server/{internal-token-nobT6FhA.js → internal-token-C90jBp-y.js} +1 -1
- package/server/{io-A7ZuOBkz.js → io-CbAFXQge.js} +2 -2
- package/server/{issue-closed-Da3DeomA.js → issue-closed-BYC2TCk-.js} +4 -4
- package/server/{issue-lifecycle-543pQX9D.js → issue-lifecycle-BoJa6qIt.js} +21 -21
- package/server/{issue-lifecycle-Bd9XBJAQ.js → issue-lifecycle-CLHbj8RS.js} +1 -1
- package/server/{issue-service-singleton-BC2JLZi7.js → issue-service-singleton-3g_CCY-1.js} +1 -1
- package/server/{issue-service-singleton-Brc3t0SV.js → issue-service-singleton-BS9NENuR.js} +8 -8
- package/server/{issues-D3kt9UWE.js → issues-BPcqPqfV.js} +2 -2
- package/server/{label-cleanup-w9X_T3AQ.js → label-cleanup-CwiCSZrb.js} +2 -2
- package/server/{layers-Cwe1J-9o.js → layers-OHHLphl0.js} +2 -2
- package/server/{lifecycle-f1GbDK33.js → lifecycle-B8IdvUbt.js} +6 -6
- package/server/{lifecycle-io-D56q8zlO.js → lifecycle-io-BMCH1Bxg.js} +1 -1
- package/server/{lifecycle-io-Bqvj0m3i.js → lifecycle-io-C73m5e6R.js} +4 -4
- package/server/{linear-client-Bh4T4S-c.js → linear-client-BMxgycoy.js} +1 -1
- package/server/{linear-client-CfJMTAYd.js → linear-client-CgQlM4aT.js} +2 -2
- package/server/memory-fts-worker.js +1 -1
- package/server/{merge-ZrXFM3jv.js → merge-B7Oi-g6k.js} +3 -3
- package/server/{merge-DRMPa8CQ.js → merge-BRkVaIx-.js} +1 -1
- package/server/merge-agent-Bwm34MZ5.js +3 -0
- package/server/{merge-agent-CHHs5S_0.js → merge-agent-DNFFsiEm.js} +61 -26
- package/server/{merge-batch-BwhGdlh4.js → merge-batch-BpYXUaqJ.js} +1 -1
- package/server/{merge-blockers-BMhDpMl_.js → merge-blockers-DIOZmqdK.js} +2 -2
- package/server/merge-ops-B7m-hBEZ.js +2 -0
- package/server/{merge-rebase-R7MfqpiE.js → merge-rebase-C8WH39MB.js} +2 -2
- package/server/{merge-set-B3Breacq.js → merge-set-CsEE2CyQ.js} +9 -5
- package/server/{merge-set-D-iXNP0I.js → merge-set-DOsBTBQc.js} +1 -1
- package/server/{merge-sync-DHWbGtjR.js → merge-sync-C2B322Ot.js} +2 -2
- package/server/{merge-sync-bOOtfeXR.js → merge-sync-CcLM2vwW.js} +1 -1
- package/server/{merge-train-98ptZrPT.js → merge-train-BIm7-7cy.js} +3 -3
- package/server/{merge-train-deps-B5FWJTE2.js → merge-train-deps-DG1oQ2DT.js} +4 -4
- package/server/{merge-verification-BGiuiXAK.js → merge-verification-BAbjxEd5.js} +4 -4
- package/server/{multipart-parser-D7mzNNDm.js → multipart-parser-jKtKAXtl.js} +2 -2
- package/server/node_modules/.package-lock.json +1 -1
- package/server/{orphan-proposed-reconciler-CSuxivr9.js → orphan-proposed-reconciler-BqVGaOIj.js} +1 -1
- package/server/{orphan-proposed-reconciler-BSGCNJ6X.js → orphan-proposed-reconciler-zHrwJ3xr.js} +9 -9
- package/server/package-lock.json +2 -2
- package/server/package.json +1 -1
- package/server/{pan-dir-DoPtdHrp.js → pan-dir-BlNrLzW7.js} +3 -3
- package/server/{paths-CVDLPxXp.js → paths-CiVeo4N_.js} +2 -2
- package/server/{pipeline-notifier-WD2dnOsR.js → pipeline-notifier-DBF6dHxH.js} +2 -2
- package/server/{pipeline-notifier-BtYHbBPl.js → pipeline-notifier-nkWCe042.js} +1 -1
- package/server/{projects-Bqfwuqet.js → projects-BqRMlDOv.js} +1 -1
- package/server/{prompts-Cg7e9FPb.js → prompts-CXbQvevY.js} +2 -2
- package/server/{providers-fLduChnX.js → providers-CUdAb5Qu.js} +7 -7
- package/server/{providers-JjK6izqX.js → providers-gZ0cUgQM.js} +1 -1
- package/server/public/assets/{chunk-BO2N2NFS-aNlsGDCu.js → chunk-BO2N2NFS-C-6y8VFI.js} +4 -4
- package/server/public/assets/{diagram-OG6HWLK6-CnjkrvT8.js → diagram-OG6HWLK6-NACO1xW5.js} +1 -1
- package/server/public/assets/{dist-CGKBCieA.js → dist-D1FjqGgm.js} +1 -1
- package/server/public/assets/{dist-Bg3Sbsx4.js → dist-DQD-ZjQY.js} +3 -3
- package/server/public/assets/{ganttDiagram-6RSMTGT7-C8LLKj23.js → ganttDiagram-6RSMTGT7-CEMAKgmE.js} +1 -1
- package/server/public/assets/{highlighted-body-OFNGDK62-BSDEUvhW.js → highlighted-body-OFNGDK62-D5lC7FW8.js} +1 -1
- package/server/public/assets/{index-LQIfhmgI.js → index-BDqWyuZQ.js} +140 -140
- package/server/public/assets/{linear-DEbYZoxg.js → linear-DDHAMRPB.js} +1 -1
- package/server/public/assets/mermaid-GHXKKRXX-DRM2ANcR.js +1 -0
- package/server/public/assets/{pieDiagram-4H26LBE5-BtZL5pXE.js → pieDiagram-4H26LBE5-DwBdeKBb.js} +1 -1
- package/server/public/assets/{prod-DYVvIyuh.js → prod-DAZt0c4G.js} +4 -4
- package/server/public/assets/{quadrantDiagram-W4KKPZXB-a7vS8Jc8.js → quadrantDiagram-W4KKPZXB-CNDLp-_m.js} +1 -1
- package/server/public/assets/{sankeyDiagram-5OEKKPKP-Ckbq2SWH.js → sankeyDiagram-5OEKKPKP-oIUL_uO1.js} +1 -1
- package/server/public/assets/{xychartDiagram-2RQKCTM6-DJyeNa99.js → xychartDiagram-2RQKCTM6-B-IM6Cck.js} +1 -1
- package/server/public/index.html +1 -1
- package/server/{pull-requests-D2SjJIwY.js → pull-requests-DZ-V7_LB.js} +1 -1
- package/server/{pull-requests-1WXmTBlo.js → pull-requests-kTRl7cWC.js} +3 -3
- package/server/rally-CRteqXe0.js +3 -0
- package/server/{rally-api-H5I2CBO0.js → rally-api-DpZo3WwF.js} +2 -2
- package/server/{rally-api-BtvwdX6d.js → rally-api-jOk4vit_.js} +1 -1
- package/server/{rally-client-Bt-qHiOh.js → rally-client-BQjm3aaq.js} +1 -1
- package/server/{rally-client-33CYZYYu.js → rally-client-CoWZeVEj.js} +4 -4
- package/server/{rally-8aQlLLVj.js → rally-xCTZ-UcI.js} +3 -3
- package/server/{rebuild-stack-KHkkrGjx.js → rebuild-stack-BZ7j27xY.js} +5 -5
- package/server/{rebuild-stack-CXSgAGPR.js → rebuild-stack-r-cxcr26.js} +1 -1
- package/server/{reconstruct-cache-D_Ml65_6.js → reconstruct-cache-13EkMg_i.js} +6 -6
- package/server/{record-De2syxNB.js → record-CJsjvRO4.js} +1 -1
- package/server/release-engine-YLTnEO_K.js +306 -0
- package/server/release-set-DwvT_Opu.js +125 -0
- package/server/{remote-CGuognN3.js → remote-9u9WL0NJ.js} +3 -3
- package/server/{remote-D0Old0Cv.js → remote-B062S1Kc.js} +3 -3
- package/server/{remote-agents-UHoi4oGr.js → remote-agents-B4eWgwNd.js} +1 -1
- package/server/{remote-agents-DfhMq6kQ.js → remote-agents-BBTg-vLT.js} +5 -5
- package/server/{remote-completion-RZYePR_0.js → remote-completion-B0rmBnbL.js} +12 -12
- package/server/resume-R7xkSmLW.js +3 -0
- package/server/{review-agent-uwVftH98.js → review-agent-Bf9XjLnl.js} +1 -1
- package/server/{review-agent-sZBCpEVv.js → review-agent-tfR5RDzG.js} +22 -22
- package/server/{review-artifacts-C7a45b1_.js → review-artifacts-D0_IE6DQ.js} +6 -6
- package/server/{review-context-CErbQpKL.js → review-context-CXO5ml5D.js} +7 -7
- package/server/{review-monitor-DHD9m_kh.js → review-monitor-DfFUSx0J.js} +2 -2
- package/server/{review-status-JhQ3qlDS.js → review-status-B0Axo-Ma.js} +1 -1
- package/server/{review-status-gPndPUBc.js → review-status-BcfwcAcO.js} +23 -16
- package/server/{review-status-enrichment-qWvWckYN.js → review-status-enrichment-Cp5kFTGl.js} +3 -3
- package/server/{review-status-sync-B_GrEke8.js → review-status-sync-Bc0c_u12.js} +1 -1
- package/server/{review-status-sync-D3A9KX95.js → review-status-sync-CEFty1pW.js} +9 -5
- package/server/{review-verdict-feedback-4WZ5ZdbC.js → review-verdict-feedback-BOKRLLDf.js} +6 -6
- package/server/{review-verdict-feedback-Zo0r_z4m.js → review-verdict-feedback-BnGtT0vN.js} +1 -1
- package/server/{rollup-Bmhn80tB.js → rollup-BVqFuiS9.js} +1 -1
- package/server/{rollup-BrUIKMv_.js → rollup-C22QDVxh.js} +8 -8
- package/server/{scanner-BIGumel_.js → scanner-BLCnuXqY.js} +7 -7
- package/server/{sequence-io-DA0akEQN.js → sequence-io-BozlUb6f.js} +4 -4
- package/server/{sequencer-agent-DeflKafB.js → sequencer-agent-BEDEHfd2.js} +5 -5
- package/server/server.js +251 -160
- package/server/{service-V0sUK-OR.js → service-C8jKYZ0w.js} +42 -42
- package/server/{session-fork-Yx3UcAQf.js → session-fork-BDGksK4e.js} +2 -2
- package/server/{settings-CFEeQRj2.js → settings-CSLhh6qR.js} +2 -2
- package/server/settings-CSaXtkoA.js +2 -0
- package/server/{settings-CxVate0h.js → settings-DrRQCren.js} +3 -3
- package/server/{shadow-engineering-BRxnVSDk.js → shadow-engineering-BMcBN-Of.js} +2 -2
- package/server/{shadow-state-BiMwdyl1.js → shadow-state-B4ayC7nx.js} +2 -2
- package/server/{shadow-state-1aS8FijU.js → shadow-state-CHqWHD3T.js} +1 -1
- package/server/{ship-log-CMWH3H5-.js → ship-log-CDVmOlZP.js} +1 -1
- package/server/{smart-compaction-Bw1K_Sbl.js → smart-compaction-C-F5sP9P.js} +7 -7
- package/server/{smart-compaction-xblMyVpT.js → smart-compaction-V9DBrGcr.js} +1 -1
- package/server/{spawn-planning-session-CzDFSKAQ.js → spawn-planning-session-Bz4_JES2.js} +1 -1
- package/server/{spawn-planning-session-DxLxcM7m.js → spawn-planning-session-dSpOU0lP.js} +15 -15
- package/server/{specialist-completion-BiEXUHfD.js → specialist-completion-Coz3eTSr.js} +1 -1
- package/server/{specialist-context-BfkTA81h.js → specialist-context-fmb03vXQ.js} +5 -5
- package/server/{specialist-handoff-logger-BiKuLtNm.js → specialist-handoff-logger-B9HK_lRu.js} +2 -2
- package/server/{specialist-logs-CFJjGsLC.js → specialist-logs-B24R2B9Y.js} +3 -3
- package/server/{specialists-BLIreoE7.js → specialists-B6f5-5nG.js} +1 -1
- package/server/{specialists-DjHbwQ_p.js → specialists-BGNZ0_ZW.js} +18 -18
- package/server/{specialists-B4byf18k.js → specialists-CL7E8yUg.js} +75 -75
- package/server/{specialists-DdvpFNt1.js → specialists-Chvvwf5z.js} +1 -1
- package/server/specs-oaaYaA5c.js +3 -0
- package/server/{src-CALBEUMX.js → src-BVxZuHMg.js} +3 -3
- package/server/{src-mK_M_ZIj.js → src-D-VXCC9C.js} +5 -5
- package/server/{src-fgbU-jJ-.js → src-DGAEtABV.js} +13 -2
- package/server/{stack-health-BFM8YlHw.js → stack-health-BKbTTOT2.js} +1 -1
- package/server/{stack-health-Qd7rPiVe.js → stack-health-C-le5erA.js} +2 -2
- package/server/{state-home-C2Bicw9N.js → state-home-CoyWsECg.js} +6 -6
- package/server/{summary-fork-EWWBvzgE.js → summary-fork-BF_0vxrq.js} +2 -2
- package/server/{summary-fork-DezPkJSm.js → summary-fork-BlE30Q-I.js} +8 -8
- package/server/supervisor-03Tj_Wra.js +2 -0
- package/server/{supervisor-D5GC5jUM.js → supervisor-BSeML_p0.js} +2 -2
- package/server/{swarm-readiness-Cf9mommA.js → swarm-readiness-CQ4sjrXc.js} +3 -3
- package/server/{system-prerequisites-BsI9hxh9.js → system-prerequisites-DnmLYOnU.js} +13 -1
- package/server/{teardown-workspace-CWz1pbEK.js → teardown-workspace-CpcjDrZ4.js} +12 -12
- package/server/{test-agent-queue-TiVXe3ZT.js → test-agent-queue-Bq298zZl.js} +5 -5
- package/server/{tldr-daemon-C_1frSDj.js → tldr-daemon-CaSUXd9r.js} +2 -2
- package/server/{tldr-daemon-Big5IZ_M.js → tldr-daemon-Rn1Zue0P.js} +1 -1
- package/server/{tmux-D57f-XNv.js → tmux-BVc-NeKM.js} +2 -2
- package/server/{tmux-DClqWwb8.js → tmux-CbcrkUx5.js} +1 -1
- package/server/{token-_qujO3JZ.js → token-D2OC_9ms.js} +1 -1
- package/server/{tracker-config-BmdJU_w6.js → tracker-config-C1Y_2CIo.js} +2 -2
- package/server/{tracker-config-B_Ubts1Z.js → tracker-config-EsBoOWEy.js} +1 -1
- package/server/{tracker-utils-Bg-Sevcv.js → tracker-utils-DSb9cfrF.js} +1 -1
- package/server/{tracker-utils-CWFt6jjV.js → tracker-utils-lph9C3Pw.js} +2 -2
- package/server/{tunnel-UBf2vyAL.js → tunnel-BFBCeo97.js} +2 -2
- package/server/{tunnel-hOBNQbmF.js → tunnel-DDe-ATFF.js} +1 -1
- package/server/{uat-train-DGkIkLxu.js → uat-train-8T24rPzc.js} +1 -1
- package/server/{uat-train-qNanv5hN.js → uat-train-DtKHHy1U.js} +23 -23
- package/server/{validation-B0QaLIHP.js → validation-COOXwNXU.js} +1 -1
- package/server/{validation-C4wegCvH.js → validation-lyudzPvD.js} +3 -3
- package/server/{verification-runner-CntudBes.js → verification-runner-DO0nYTJx.js} +11 -11
- package/server/{verification-runner-DdleMNLq.js → verification-runner-Dd1FX8Qk.js} +1 -1
- package/server/{vtt-parser-CKc-smWM.js → vtt-parser-C57tEF7-.js} +1 -1
- package/server/{work-agent-prompt-CG5jFV9A.js → work-agent-prompt-B2F3ZwKm.js} +11 -11
- package/server/workflows-B4fIN8VP.js +2 -0
- package/server/{workflows-BK2xs_a8.js → workflows-Clz_AFwR.js} +13 -13
- package/server/{workspace-CLrSIRCx.js → workspace-CY_2-Ddv.js} +3 -3
- package/server/{workspace-C9lC5o3E.js → workspace-D0rCFemz.js} +1 -1
- package/server/{workspace-manager-Cb2a7bg9.js → workspace-manager-BIfpzqdU.js} +1 -1
- package/server/{workspace-manager-BJhW2sky.js → workspace-manager-D6NgGkiF.js} +10 -10
- package/server/{workspace-metadata-QQmo_Z0l.js → workspace-metadata-C8yn8kAH.js} +2 -2
- package/server/{workspace-metadata-CTRnr323.js → workspace-metadata-DfgR40YU.js} +1 -1
- package/server/{workspaces-Ca4zZs12.js → workspaces-DOeHyKmA.js} +104 -92
- package/sync-sources/hooks/ask-user-question-hook +87 -0
- package/sync-sources/hooks/auto-approve-hook +96 -0
- package/sync-sources/hooks/codex-notify-hook +62 -0
- package/sync-sources/hooks/gh-issue-trailer-hook +4 -0
- package/sync-sources/hooks/gh-issue-trailer-hook.d.ts +7 -0
- package/sync-sources/hooks/gh-issue-trailer-hook.d.ts.map +1 -0
- package/sync-sources/hooks/gh-issue-trailer-hook.js +239 -0
- package/sync-sources/hooks/gh-issue-trailer-hook.js.map +1 -0
- package/sync-sources/hooks/gh-issue-trailer-hook.ts +296 -0
- package/sync-sources/hooks/git-hooks/post-checkout +109 -0
- package/sync-sources/hooks/heartbeat-hook +113 -0
- package/sync-sources/hooks/notification-hook +70 -0
- package/sync-sources/hooks/notify-complete +79 -0
- package/sync-sources/hooks/pan-hook-lib.sh +153 -0
- package/sync-sources/hooks/permission-event-hook +24 -0
- package/sync-sources/hooks/post-compact-hook +25 -0
- package/sync-sources/hooks/pre-compact-hook +26 -0
- package/sync-sources/hooks/pre-tool-hook +35 -0
- package/sync-sources/hooks/record-cost-event.d.ts +1 -0
- package/sync-sources/hooks/record-cost-event.js +31858 -0
- package/sync-sources/hooks/record-cost-event.js.map +1 -0
- package/sync-sources/hooks/record-cost-event.ts +267 -0
- package/sync-sources/hooks/rtk-bash-filter +152 -0
- package/sync-sources/hooks/session-start-hook +80 -0
- package/sync-sources/hooks/specialist-stop-hook +106 -0
- package/sync-sources/hooks/statusline.sh +169 -0
- package/sync-sources/hooks/stop-hook +217 -0
- package/sync-sources/hooks/tldr-post-edit +72 -0
- package/sync-sources/hooks/tldr-read-enforcer +340 -0
- package/sync-sources/hooks/tmux-send-keys-guard +87 -0
- package/sync-sources/hooks/tsdown.config.ts +14 -0
- package/sync-sources/hooks/user-prompt-submit-hook +57 -0
- package/sync-sources/hooks/work-agent-stop-hook +424 -0
- package/server/cli-Ch_BWJB2.js +0 -3
- package/server/deacon-swarm-CSWGRfzr.js +0 -2
- package/server/dist-BUplB3Od.js +0 -3
- package/server/forge-IgLR0Ist.js +0 -2
- package/server/inspect-agent-CYoWAeeB.js +0 -2
- package/server/merge-agent-CfohxFWM.js +0 -3
- package/server/merge-ops-Czke6UAp.js +0 -2
- package/server/public/assets/mermaid-GHXKKRXX-CZOsRYoT.js +0 -1
- package/server/rally-Ba9QoNYc.js +0 -3
- package/server/resume-CmxF3Kjz.js +0 -3
- package/server/settings-DEhYpW0k.js +0 -2
- package/server/specs-CVH1kvz3.js +0 -3
- package/server/supervisor-DQMK2e3I.js +0 -2
- package/server/workflows-pKw9yRSV.js +0 -2
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Record cost events from Claude Code transcript data
|
|
4
|
+
* Called by heartbeat-hook with PostToolUse JSON on stdin
|
|
5
|
+
*
|
|
6
|
+
* Claude Code's PostToolUse events do NOT include token usage.
|
|
7
|
+
* Instead, we read usage from the transcript JSONL file
|
|
8
|
+
* (available via the transcript_path field in the event).
|
|
9
|
+
*
|
|
10
|
+
* Uses byte-offset tracking to efficiently process only new
|
|
11
|
+
* transcript entries on each invocation.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readFileSync, existsSync, writeFileSync, mkdirSync, openSync, readSync, fstatSync, closeSync } from 'fs';
|
|
15
|
+
import { execFileSync } from 'child_process';
|
|
16
|
+
import { join } from 'path';
|
|
17
|
+
import { homedir } from 'os';
|
|
18
|
+
import { calculateCostSync, getPricingSync, AIProvider } from '../../src/lib/cost.js';
|
|
19
|
+
import { appendCostEventSync } from '../../src/lib/costs/events.js';
|
|
20
|
+
import { captureTldrMetricsSync, type TldrSessionMetrics } from '../../src/lib/tldr-daemon.js';
|
|
21
|
+
|
|
22
|
+
// ============== Types ==============
|
|
23
|
+
|
|
24
|
+
interface PostToolUseEvent {
|
|
25
|
+
session_id?: string;
|
|
26
|
+
transcript_path?: string;
|
|
27
|
+
tool_name?: string;
|
|
28
|
+
tool_use_id?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface TranscriptUsage {
|
|
32
|
+
input_tokens?: number;
|
|
33
|
+
output_tokens?: number;
|
|
34
|
+
cache_read_input_tokens?: number;
|
|
35
|
+
cache_creation_input_tokens?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface TranscriptEntry {
|
|
39
|
+
type?: string;
|
|
40
|
+
message?: {
|
|
41
|
+
model?: string;
|
|
42
|
+
usage?: TranscriptUsage;
|
|
43
|
+
};
|
|
44
|
+
requestId?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ============== Main ==============
|
|
48
|
+
|
|
49
|
+
// Read PostToolUse event from stdin
|
|
50
|
+
let event: PostToolUseEvent;
|
|
51
|
+
try {
|
|
52
|
+
const input = readFileSync(0, 'utf-8');
|
|
53
|
+
event = JSON.parse(input) as PostToolUseEvent;
|
|
54
|
+
} catch {
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Need transcript path to read usage data
|
|
59
|
+
const transcriptPath = event?.transcript_path;
|
|
60
|
+
if (!transcriptPath || !existsSync(transcriptPath)) {
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const sessionId = event?.session_id || 'unknown';
|
|
65
|
+
|
|
66
|
+
// State tracking: byte offset per session to avoid re-processing
|
|
67
|
+
const stateDir = join(process.env.HOME || homedir(), '.overdeck', 'costs', 'state');
|
|
68
|
+
mkdirSync(stateDir, { recursive: true });
|
|
69
|
+
const stateFile = join(stateDir, `${sessionId}.offset`);
|
|
70
|
+
|
|
71
|
+
let lastOffset = 0;
|
|
72
|
+
if (existsSync(stateFile)) {
|
|
73
|
+
try {
|
|
74
|
+
lastOffset = parseInt(readFileSync(stateFile, 'utf-8').trim(), 10) || 0;
|
|
75
|
+
} catch { /* start from 0 */ }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Load persisted seen requestIds to guard against crash-before-write duplicates (PAN-238)
|
|
79
|
+
// Claude Code's transcript can have multiple entries per requestId — we emit exactly one event per requestId.
|
|
80
|
+
const seenFile = join(stateDir, `${sessionId}.seen`);
|
|
81
|
+
const seenRequestIds = new Set<string>();
|
|
82
|
+
if (existsSync(seenFile)) {
|
|
83
|
+
try {
|
|
84
|
+
const seenContent = readFileSync(seenFile, 'utf-8').trim();
|
|
85
|
+
if (seenContent) {
|
|
86
|
+
for (const id of seenContent.split('\n')) {
|
|
87
|
+
if (id.trim()) seenRequestIds.add(id.trim());
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} catch { /* start fresh */ }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Read only NEW content from the transcript (efficient for large files)
|
|
94
|
+
let fd: number;
|
|
95
|
+
try {
|
|
96
|
+
fd = openSync(transcriptPath, 'r');
|
|
97
|
+
} catch {
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const stat = fstatSync(fd);
|
|
102
|
+
if (stat.size <= lastOffset) {
|
|
103
|
+
closeSync(fd);
|
|
104
|
+
// Save current size even if no new content (handles file truncation)
|
|
105
|
+
writeFileSync(stateFile, String(stat.size), 'utf-8');
|
|
106
|
+
process.exit(0);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const bytesToRead = stat.size - lastOffset;
|
|
110
|
+
const buffer = Buffer.alloc(bytesToRead);
|
|
111
|
+
readSync(fd, buffer, 0, bytesToRead, lastOffset);
|
|
112
|
+
closeSync(fd);
|
|
113
|
+
|
|
114
|
+
const newContent = buffer.toString('utf-8');
|
|
115
|
+
const lines = newContent.split('\n');
|
|
116
|
+
|
|
117
|
+
// Get agent/issue context from environment, with git branch fallback
|
|
118
|
+
const agentId: string = process.env.OVERDECK_AGENT_ID || 'unattributed';
|
|
119
|
+
let issueId: string = process.env.OVERDECK_ISSUE_ID || '';
|
|
120
|
+
const sessionType: string = process.env.OVERDECK_SESSION_TYPE || 'implementation';
|
|
121
|
+
// Caveman A/B test variant — set by agent launcher when agents.caveman.ab_test is active (PAN-611)
|
|
122
|
+
const cavemanVariant = process.env.OVERDECK_CAVEMAN_VARIANT as 'enabled' | 'disabled' | 'off' | undefined;
|
|
123
|
+
|
|
124
|
+
// Infer issue ID from git branch if not set (covers ad-hoc Claude sessions)
|
|
125
|
+
if (!issueId || issueId === 'UNKNOWN') {
|
|
126
|
+
try {
|
|
127
|
+
const branch = execFileSync('git', ['branch', '--show-current'], {
|
|
128
|
+
encoding: 'utf-8',
|
|
129
|
+
timeout: 2000,
|
|
130
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
131
|
+
}).trim();
|
|
132
|
+
const branchMatch = branch.match(/(pan|min|aud|krux|cli)[-](\d+)/i);
|
|
133
|
+
if (branchMatch) {
|
|
134
|
+
issueId = `${branchMatch[1].toUpperCase()}-${branchMatch[2]}`;
|
|
135
|
+
}
|
|
136
|
+
} catch {
|
|
137
|
+
// Git not available or not in a repo — that's fine
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Final fallback
|
|
142
|
+
if (!issueId) {
|
|
143
|
+
issueId = 'UNKNOWN';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Capture TLDR metrics for this batch (PAN-236)
|
|
147
|
+
// Find workspace root via git (same process already used for branch detection above)
|
|
148
|
+
let tldrMetrics: TldrSessionMetrics | null = null;
|
|
149
|
+
try {
|
|
150
|
+
const workspaceRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
|
151
|
+
encoding: 'utf-8',
|
|
152
|
+
timeout: 2000,
|
|
153
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
154
|
+
}).trim();
|
|
155
|
+
if (workspaceRoot) {
|
|
156
|
+
tldrMetrics = captureTldrMetricsSync(workspaceRoot);
|
|
157
|
+
}
|
|
158
|
+
} catch { /* git not available or no workspace — skip TLDR metrics */ }
|
|
159
|
+
|
|
160
|
+
// Process new transcript lines looking for assistant messages with usage
|
|
161
|
+
let tldrAttachedToFirstEvent = false;
|
|
162
|
+
for (const line of lines) {
|
|
163
|
+
if (!line.trim()) continue;
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const entry = JSON.parse(line) as TranscriptEntry;
|
|
167
|
+
|
|
168
|
+
// Only process assistant messages that have usage data
|
|
169
|
+
if (entry.type !== 'assistant' || !entry.message?.usage) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Skip already-seen requestIds — transcript has multiple entries per API request (PAN-238)
|
|
174
|
+
const requestId = entry.requestId;
|
|
175
|
+
if (requestId) {
|
|
176
|
+
if (seenRequestIds.has(requestId)) {
|
|
177
|
+
continue; // Duplicate entry for this request — already emitted a cost event
|
|
178
|
+
}
|
|
179
|
+
seenRequestIds.add(requestId);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const usage = entry.message.usage;
|
|
183
|
+
const model: string = entry.message.model || 'claude-sonnet-4';
|
|
184
|
+
|
|
185
|
+
const inputTokens = usage.input_tokens || 0;
|
|
186
|
+
const outputTokens = usage.output_tokens || 0;
|
|
187
|
+
const cacheReadTokens = usage.cache_read_input_tokens || 0;
|
|
188
|
+
const cacheWriteTokens = usage.cache_creation_input_tokens || 0;
|
|
189
|
+
|
|
190
|
+
// Skip entries with zero tokens
|
|
191
|
+
if (inputTokens === 0 && outputTokens === 0 && cacheReadTokens === 0 && cacheWriteTokens === 0) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Determine provider from model name
|
|
196
|
+
let provider: AIProvider = 'anthropic';
|
|
197
|
+
if (model.includes('gpt')) {
|
|
198
|
+
provider = 'openai';
|
|
199
|
+
} else if (model.includes('gemini')) {
|
|
200
|
+
provider = 'google';
|
|
201
|
+
} else if (model.includes('kimi') || model.toLowerCase().startsWith('minimax')) {
|
|
202
|
+
provider = 'custom';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Get pricing and calculate cost (Sync variants — the Effect-returning
|
|
206
|
+
// getPricing/calculateCost are lazy and silently broke recording, PAN-1570)
|
|
207
|
+
const pricing = getPricingSync(provider, model);
|
|
208
|
+
if (!pricing) continue;
|
|
209
|
+
|
|
210
|
+
const cost = calculateCostSync({
|
|
211
|
+
inputTokens,
|
|
212
|
+
outputTokens,
|
|
213
|
+
cacheReadTokens,
|
|
214
|
+
cacheWriteTokens,
|
|
215
|
+
cacheTTL: '5m',
|
|
216
|
+
}, pricing);
|
|
217
|
+
|
|
218
|
+
// Attach TLDR metrics to the first event in each batch (delta since last batch)
|
|
219
|
+
const tldrFields = tldrMetrics && !tldrAttachedToFirstEvent && tldrMetrics.interceptions + tldrMetrics.bypasses > 0
|
|
220
|
+
? {
|
|
221
|
+
tldrInterceptions: tldrMetrics.interceptions,
|
|
222
|
+
tldrBypasses: tldrMetrics.bypasses,
|
|
223
|
+
tldrTokensSaved: tldrMetrics.estimatedTokensSaved,
|
|
224
|
+
tldrBypassReasons: Object.keys(tldrMetrics.bypassReasons).length > 0
|
|
225
|
+
? tldrMetrics.bypassReasons
|
|
226
|
+
: undefined,
|
|
227
|
+
}
|
|
228
|
+
: {};
|
|
229
|
+
|
|
230
|
+
if (tldrMetrics && !tldrAttachedToFirstEvent) {
|
|
231
|
+
tldrAttachedToFirstEvent = true;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Record the cost event.
|
|
235
|
+
// NOTE: appendCostEventSync (not the Effect-returning appendCostEvent) — the
|
|
236
|
+
// latter is a lazy Effect that does nothing unless run, which silently dropped
|
|
237
|
+
// every cost event after the PAN-1249 Effect migration (PAN-1570).
|
|
238
|
+
appendCostEventSync({
|
|
239
|
+
ts: new Date().toISOString(),
|
|
240
|
+
type: 'cost',
|
|
241
|
+
agentId,
|
|
242
|
+
issueId,
|
|
243
|
+
sessionType,
|
|
244
|
+
provider,
|
|
245
|
+
model,
|
|
246
|
+
input: inputTokens,
|
|
247
|
+
output: outputTokens,
|
|
248
|
+
cacheRead: cacheReadTokens,
|
|
249
|
+
cacheWrite: cacheWriteTokens,
|
|
250
|
+
cost,
|
|
251
|
+
...(requestId ? { requestId } : {}),
|
|
252
|
+
sessionId,
|
|
253
|
+
...tldrFields,
|
|
254
|
+
...(cavemanVariant ? { cavemanVariant } : {}),
|
|
255
|
+
});
|
|
256
|
+
} catch {
|
|
257
|
+
// Skip malformed lines silently
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Save new byte offset and seen requestIds for next invocation
|
|
262
|
+
writeFileSync(stateFile, String(stat.size), 'utf-8');
|
|
263
|
+
if (seenRequestIds.size > 0) {
|
|
264
|
+
writeFileSync(seenFile, Array.from(seenRequestIds).join('\n') + '\n', 'utf-8');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
process.exit(0);
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ~/.overdeck/bin/rtk-bash-filter
|
|
3
|
+
# PreToolUse hook on Bash — delegates command rewriting to rtk-ai/rtk so
|
|
4
|
+
# expensive command output can be filtered before Claude Code runs the command.
|
|
5
|
+
#
|
|
6
|
+
# Bypasses (allows normal Bash execution):
|
|
7
|
+
# - Non-Bash tool_name
|
|
8
|
+
# - jq unavailable or malformed PreToolUse JSON
|
|
9
|
+
# - OVERDECK_RTK_ENABLED is unset/false and agents.rtk.enabled is absent/false
|
|
10
|
+
# - ~/.overdeck/bin/rtk is missing or not executable
|
|
11
|
+
# - rtk exits non-zero, emits no output, or emits an invalid PreToolUse response
|
|
12
|
+
# - rtk chooses not to rewrite a command, including commands whose output it
|
|
13
|
+
# expects to be too small to benefit from filtering
|
|
14
|
+
#
|
|
15
|
+
# Don't use set -e — hooks must never break Claude Code execution.
|
|
16
|
+
set +e
|
|
17
|
+
|
|
18
|
+
rtk_truthy() {
|
|
19
|
+
case "$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')" in
|
|
20
|
+
1|true|yes|on|enabled) return 0 ;;
|
|
21
|
+
*) return 1 ;;
|
|
22
|
+
esac
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
rtk_project_root() {
|
|
26
|
+
local current
|
|
27
|
+
current="$PWD"
|
|
28
|
+
while [ "$current" != "/" ]; do
|
|
29
|
+
if [ -e "$current/.git" ]; then
|
|
30
|
+
printf '%s\n' "$current"
|
|
31
|
+
return 0
|
|
32
|
+
fi
|
|
33
|
+
current=$(dirname "$current")
|
|
34
|
+
done
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
rtk_read_config_enabled() {
|
|
38
|
+
local config_path
|
|
39
|
+
config_path="$1"
|
|
40
|
+
[ -z "$config_path" ] && return 0
|
|
41
|
+
[ ! -f "$config_path" ] && return 0
|
|
42
|
+
|
|
43
|
+
awk '
|
|
44
|
+
function trim(s) { sub(/^[ \t\r\n]+/, "", s); sub(/[ \t\r\n]+$/, "", s); return s }
|
|
45
|
+
BEGIN { in_agents = 0; in_rtk = 0; agents_indent = -1; rtk_indent = -1 }
|
|
46
|
+
{
|
|
47
|
+
line = $0
|
|
48
|
+
sub(/#.*/, "", line)
|
|
49
|
+
if (line ~ /^[[:space:]]*$/) next
|
|
50
|
+
match(line, /^[ ]*/)
|
|
51
|
+
indent = RLENGTH
|
|
52
|
+
key = line
|
|
53
|
+
sub(/^[[:space:]]*/, "", key)
|
|
54
|
+
|
|
55
|
+
if (key ~ /^agents:[[:space:]]*$/) {
|
|
56
|
+
in_agents = 1
|
|
57
|
+
in_rtk = 0
|
|
58
|
+
agents_indent = indent
|
|
59
|
+
next
|
|
60
|
+
}
|
|
61
|
+
if (in_agents && indent <= agents_indent) {
|
|
62
|
+
in_agents = 0
|
|
63
|
+
in_rtk = 0
|
|
64
|
+
}
|
|
65
|
+
if (in_agents && key ~ /^rtk:[[:space:]]*$/) {
|
|
66
|
+
in_rtk = 1
|
|
67
|
+
rtk_indent = indent
|
|
68
|
+
next
|
|
69
|
+
}
|
|
70
|
+
if (in_rtk && indent <= rtk_indent) {
|
|
71
|
+
in_rtk = 0
|
|
72
|
+
}
|
|
73
|
+
if (in_rtk && key ~ /^enabled:[[:space:]]*/) {
|
|
74
|
+
sub(/^enabled:[[:space:]]*/, "", key)
|
|
75
|
+
gsub(/"/, "", key)
|
|
76
|
+
gsub(/\047/, "", key)
|
|
77
|
+
print trim(key)
|
|
78
|
+
exit
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
' "$config_path" 2>/dev/null
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
rtk_config_enabled_value() {
|
|
85
|
+
local config_path project_root value result
|
|
86
|
+
|
|
87
|
+
if [ -n "${OVERDECK_CONFIG:-}" ]; then
|
|
88
|
+
value=$(rtk_read_config_enabled "$OVERDECK_CONFIG")
|
|
89
|
+
else
|
|
90
|
+
value=$(rtk_read_config_enabled "$HOME/.overdeck/config.yaml")
|
|
91
|
+
fi
|
|
92
|
+
[ -n "$value" ] && result="$value"
|
|
93
|
+
|
|
94
|
+
project_root=$(rtk_project_root)
|
|
95
|
+
if [ -n "$project_root" ]; then
|
|
96
|
+
if [ -f "$project_root/.pan.yaml" ]; then
|
|
97
|
+
config_path="$project_root/.pan.yaml"
|
|
98
|
+
elif [ -f "$project_root/.overdeck.yaml" ]; then
|
|
99
|
+
config_path="$project_root/.overdeck.yaml"
|
|
100
|
+
else
|
|
101
|
+
config_path=""
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
value=$(rtk_read_config_enabled "$config_path")
|
|
105
|
+
[ -n "$value" ] && result="$value"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
printf '%s\n' "$result"
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
RTK_BIN="$HOME/.overdeck/bin/rtk"
|
|
112
|
+
|
|
113
|
+
if [ -n "${OVERDECK_RTK_ENABLED+x}" ]; then
|
|
114
|
+
if ! rtk_truthy "$OVERDECK_RTK_ENABLED"; then
|
|
115
|
+
exit 0
|
|
116
|
+
fi
|
|
117
|
+
else
|
|
118
|
+
CONFIG_VALUE=$(rtk_config_enabled_value)
|
|
119
|
+
if ! rtk_truthy "$CONFIG_VALUE"; then
|
|
120
|
+
exit 0
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
if [ ! -x "$RTK_BIN" ]; then
|
|
125
|
+
exit 0
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
129
|
+
exit 0
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
INPUT=$(cat 2>/dev/null || echo '{}')
|
|
133
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null)
|
|
134
|
+
if [ "$TOOL_NAME" != "Bash" ]; then
|
|
135
|
+
exit 0
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
RTK_OUTPUT=$(printf '%s' "$INPUT" | "$RTK_BIN" hook claude 2>/dev/null)
|
|
139
|
+
RTK_STATUS=$?
|
|
140
|
+
if [ $RTK_STATUS -ne 0 ] || [ -z "$RTK_OUTPUT" ]; then
|
|
141
|
+
exit 0
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
if ! printf '%s' "$RTK_OUTPUT" | jq -e '
|
|
145
|
+
.hookSpecificOutput.hookEventName == "PreToolUse"
|
|
146
|
+
and (.hookSpecificOutput.updatedInput.command | type == "string")
|
|
147
|
+
' >/dev/null 2>&1; then
|
|
148
|
+
exit 0
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
printf '%s\n' "$RTK_OUTPUT"
|
|
152
|
+
exit 0
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ~/.overdeck/bin/session-start-hook (PAN-800)
|
|
3
|
+
#
|
|
4
|
+
# Fires on Claude Code SessionStart. Emits agent.activity_changed(idle) so the
|
|
5
|
+
# runtime snapshot is current before the first tool fires, and emits
|
|
6
|
+
# agent.model_set when the model is inferable from the payload or env.
|
|
7
|
+
#
|
|
8
|
+
# This hook replaces the waitForReadySignal tmux fallback referenced in
|
|
9
|
+
# PAN-759 — the hook that was supposed to exist from the start but was never
|
|
10
|
+
# registered in ~/.claude/settings.json by the installer.
|
|
11
|
+
|
|
12
|
+
set +e
|
|
13
|
+
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
15
|
+
# shellcheck source=pan-hook-lib.sh
|
|
16
|
+
. "$SCRIPT_DIR/pan-hook-lib.sh" 2>/dev/null || exit 0
|
|
17
|
+
|
|
18
|
+
pan_resolve_agent_id || exit 0
|
|
19
|
+
|
|
20
|
+
INPUT=$(cat 2>/dev/null || echo '{}')
|
|
21
|
+
|
|
22
|
+
CLAUDE_SESSION_ID=""
|
|
23
|
+
MODEL=""
|
|
24
|
+
if command -v jq >/dev/null 2>&1; then
|
|
25
|
+
CLAUDE_SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // ""' 2>/dev/null)
|
|
26
|
+
MODEL=$(echo "$INPUT" | jq -r '.model // .model_name // ""' 2>/dev/null)
|
|
27
|
+
fi
|
|
28
|
+
[ -z "$MODEL" ] && MODEL="${ANTHROPIC_MODEL:-}"
|
|
29
|
+
|
|
30
|
+
TS=$(date -Iseconds)
|
|
31
|
+
|
|
32
|
+
pan_emit_event "$AGENT_ID" "{\"kind\":\"activity\",\"activity\":\"idle\",\"timestamp\":\"$TS\"}"
|
|
33
|
+
|
|
34
|
+
# PAN-1594: write the ready.json readiness signal that waitForReadySignal()
|
|
35
|
+
# consumes. Claude-side counterpart to the Pi extension's handleSessionStart
|
|
36
|
+
# writer (packages/pi-extension/src/index.ts). Closes the PAN-759 gap where the
|
|
37
|
+
# hook emitted the idle event but never wrote the file, which forced
|
|
38
|
+
# waitForReadySignal onto a tmux pane-scrape fallback coupled to permission-mode
|
|
39
|
+
# footer text. clearReadySignal() removes this file before every (re)launch, so
|
|
40
|
+
# its presence means "this session reached the prompt".
|
|
41
|
+
READY_DIR="${OVERDECK_HOME:-$HOME/.overdeck}/agents/$AGENT_ID"
|
|
42
|
+
mkdir -p "$READY_DIR" 2>/dev/null
|
|
43
|
+
if command -v jq >/dev/null 2>&1; then
|
|
44
|
+
jq -n --arg agentId "$AGENT_ID" --arg sid "$CLAUDE_SESSION_ID" --arg ts "$TS" \
|
|
45
|
+
'{ready: true, agentId: $agentId, sessionId: (if $sid == "" then null else $sid end), reason: "session-start", timestamp: $ts}' \
|
|
46
|
+
> "$READY_DIR/ready.json" 2>/dev/null || true
|
|
47
|
+
else
|
|
48
|
+
printf '{"ready":true,"agentId":"%s","sessionId":"%s","reason":"session-start","timestamp":"%s"}\n' \
|
|
49
|
+
"$AGENT_ID" "$CLAUDE_SESSION_ID" "$TS" > "$READY_DIR/ready.json" 2>/dev/null || true
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
if [ -n "$MODEL" ]; then
|
|
53
|
+
if command -v jq >/dev/null 2>&1; then
|
|
54
|
+
BODY=$(jq -n --arg model "$MODEL" --arg sid "$CLAUDE_SESSION_ID" --arg ts "$TS" \
|
|
55
|
+
'if $sid == "" then {kind: "model_set", model: $model, timestamp: $ts}
|
|
56
|
+
else {kind: "model_set", model: $model, claudeSessionId: $sid, timestamp: $ts} end')
|
|
57
|
+
elif [ -n "$CLAUDE_SESSION_ID" ]; then
|
|
58
|
+
BODY="{\"kind\":\"model_set\",\"model\":\"$MODEL\",\"claudeSessionId\":\"$CLAUDE_SESSION_ID\",\"timestamp\":\"$TS\"}"
|
|
59
|
+
else
|
|
60
|
+
BODY="{\"kind\":\"model_set\",\"model\":\"$MODEL\",\"timestamp\":\"$TS\"}"
|
|
61
|
+
fi
|
|
62
|
+
pan_emit_event "$AGENT_ID" "$BODY"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
INTERNAL_TOKEN="${OVERDECK_INTERNAL_TOKEN:-}"
|
|
66
|
+
if [ -z "$INTERNAL_TOKEN" ]; then
|
|
67
|
+
TOKEN_PATH="${OVERDECK_HOME:-$HOME/.overdeck}/internal-token"
|
|
68
|
+
if [ -f "$TOKEN_PATH" ]; then
|
|
69
|
+
INTERNAL_TOKEN=$(cat "$TOKEN_PATH" 2>/dev/null || true)
|
|
70
|
+
fi
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
if command -v jq >/dev/null 2>&1; then
|
|
74
|
+
SESSION_BODY=$(printf '%s' "$INPUT" | jq -c --arg agentId "$AGENT_ID" '. + {agentId: $agentId}' 2>/dev/null)
|
|
75
|
+
if [ -n "$SESSION_BODY" ]; then
|
|
76
|
+
curl -s -m 0.5 -o /dev/null -X POST -H 'Content-Type: application/json' -H "x-overdeck-internal-token: $INTERNAL_TOKEN" --data "$SESSION_BODY" "$PAN_DASHBOARD_URL/api/memory/session/start" 2>/dev/null || true
|
|
77
|
+
fi
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
exit 0
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ~/.overdeck/bin/specialist-stop-hook
|
|
3
|
+
# Called when a specialist agent goes idle - detects completion patterns
|
|
4
|
+
#
|
|
5
|
+
# This hook is chained from stop-hook and only runs for specialist agents.
|
|
6
|
+
# It captures the last 50 lines of terminal output and looks for completion
|
|
7
|
+
# patterns to auto-trigger status updates.
|
|
8
|
+
|
|
9
|
+
# Don't use set -e - we want the hook to be resilient to failures
|
|
10
|
+
# and never break Claude Code execution
|
|
11
|
+
|
|
12
|
+
# Get agent ID from env or tmux session name
|
|
13
|
+
if [ -n "$OVERDECK_AGENT_ID" ]; then
|
|
14
|
+
AGENT_ID="$OVERDECK_AGENT_ID"
|
|
15
|
+
elif [ -n "$TMUX" ]; then
|
|
16
|
+
AGENT_ID=$(tmux display-message -p '#S' 2>/dev/null)
|
|
17
|
+
else
|
|
18
|
+
exit 0 # Not in a tracked session
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Check if this is a specialist agent
|
|
22
|
+
case "$AGENT_ID" in
|
|
23
|
+
specialist-review-agent|specialist-test-agent|specialist-merge-agent)
|
|
24
|
+
;;
|
|
25
|
+
*)
|
|
26
|
+
exit 0 # Not a specialist, skip
|
|
27
|
+
;;
|
|
28
|
+
esac
|
|
29
|
+
|
|
30
|
+
# Get the specialist type from agent ID
|
|
31
|
+
SPECIALIST_TYPE="${AGENT_ID#specialist-}"
|
|
32
|
+
|
|
33
|
+
# Capture the last 50 lines of terminal output
|
|
34
|
+
OUTPUT=$(tmux capture-pane -t "$AGENT_ID" -p -S -50 2>/dev/null || echo "")
|
|
35
|
+
|
|
36
|
+
if [ -z "$OUTPUT" ]; then
|
|
37
|
+
exit 0 # No output to analyze
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Define completion patterns for each specialist (case-insensitive grep -E patterns)
|
|
41
|
+
case "$SPECIALIST_TYPE" in
|
|
42
|
+
review-agent)
|
|
43
|
+
# Patterns that indicate review passed
|
|
44
|
+
PASS_PATTERN="[Rr]eview (passed|complete|PASSED|COMPLETE)|LGTM|[Nn]o issues found|[Cc]ode review complete|✓.*[Pp]assed"
|
|
45
|
+
# Patterns that indicate review failed/blocked
|
|
46
|
+
FAIL_PATTERN="[Rr]eview (failed|blocked|FAILED|BLOCKED)|[Ii]ssues found|[Nn]eeds changes|[Bb]locked"
|
|
47
|
+
STATUS_FIELD="reviewStatus"
|
|
48
|
+
;;
|
|
49
|
+
test-agent)
|
|
50
|
+
# Patterns that indicate tests passed
|
|
51
|
+
PASS_PATTERN="(all )?[Tt]ests? passed|test suite passed|0 failed|✓.*[Pp]assed|Tests PASSED"
|
|
52
|
+
# Patterns that indicate tests failed
|
|
53
|
+
FAIL_PATTERN="[Tt]ests? failed|test failures|[0-9]+ failed|✗.*[Ff]ailed|Tests FAILED"
|
|
54
|
+
STATUS_FIELD="testStatus"
|
|
55
|
+
;;
|
|
56
|
+
merge-agent)
|
|
57
|
+
# Patterns that indicate merge complete
|
|
58
|
+
PASS_PATTERN="[Mm]erge (complete|successful)|[Pp]ushed to|[Mm]erged to main|[Mm]erged successfully"
|
|
59
|
+
# Patterns that indicate merge failed
|
|
60
|
+
FAIL_PATTERN="[Mm]erge conflict|[Cc]annot merge|[Mm]erge failed"
|
|
61
|
+
STATUS_FIELD="mergeStatus"
|
|
62
|
+
;;
|
|
63
|
+
*)
|
|
64
|
+
exit 0
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
|
|
68
|
+
# Check for completion patterns (look at output)
|
|
69
|
+
STATUS=""
|
|
70
|
+
if echo "$OUTPUT" | grep -qE "$PASS_PATTERN"; then
|
|
71
|
+
STATUS="passed"
|
|
72
|
+
elif echo "$OUTPUT" | grep -qE "$FAIL_PATTERN"; then
|
|
73
|
+
STATUS="failed"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
if [ -z "$STATUS" ]; then
|
|
77
|
+
exit 0 # No recognized completion pattern - specialist is just idle
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# Get current issue from specialist state file
|
|
81
|
+
STATE_FILE="$HOME/.overdeck/agents/$AGENT_ID/state.json"
|
|
82
|
+
ISSUE_ID=""
|
|
83
|
+
|
|
84
|
+
if [ -f "$STATE_FILE" ] && command -v jq &> /dev/null; then
|
|
85
|
+
ISSUE_ID=$(jq -r '.currentIssue // ""' "$STATE_FILE" 2>/dev/null || echo "")
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
if [ -z "$ISSUE_ID" ] || [ "$ISSUE_ID" = "null" ]; then
|
|
89
|
+
# No issue ID - cannot report completion
|
|
90
|
+
exit 0
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Report completion to dashboard API (non-blocking background process)
|
|
94
|
+
# Only if dashboard is running
|
|
95
|
+
if curl -s -f --max-time 0.5 "http://localhost:3011/health" > /dev/null 2>&1; then
|
|
96
|
+
curl -s -X POST "http://localhost:3011/api/specialists/$SPECIALIST_TYPE/auto-complete" \
|
|
97
|
+
-H "Content-Type: application/json" \
|
|
98
|
+
-d "{\"issueId\":\"$ISSUE_ID\",\"status\":\"$STATUS\"}" \
|
|
99
|
+
> /dev/null 2>&1 &
|
|
100
|
+
|
|
101
|
+
# Log the completion detection
|
|
102
|
+
echo "[specialist-stop-hook] Detected completion: $SPECIALIST_TYPE -> $ISSUE_ID -> $STATUS" \
|
|
103
|
+
>> "$HOME/.overdeck/logs/hooks.log" 2>/dev/null || true
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
exit 0
|