@overdeck/desktop 0.45.21 → 0.45.23
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/package.json +1 -1
- package/server/{acceptance-criteria-CJIFA8Vg.js → acceptance-criteria-DOA0KgXx.js} +5 -5
- package/server/{advancing-selfheal-CPOBO5ZS.js → advancing-selfheal-BBu6DSNm.js} +6 -6
- package/server/{agent-gc-D6PUckBB.js → agent-gc-BV1q_2EV.js} +4 -4
- package/server/agent-state-Bg0lhqwj.js +3 -0
- package/server/{agent-state-service-DHwemt96.js → agent-state-service-CnzFKSAQ.js} +1 -1
- package/server/{agent-state-service-6MFQqnFy.js → agent-state-service-HoK8U4jW.js} +5 -5
- package/server/{agents-DbrHWunF.js → agents-B4Bjbkfv.js} +4 -4
- package/server/agents-FlIgQ3ql.js +3 -0
- package/server/{archive-planning-BOnwJq8M.js → archive-planning-DYrYojxl.js} +31 -7
- package/server/{archive-planning-MPpvQJL4.js → archive-planning-zkJb3BeM.js} +1 -1
- package/server/{artifact-index-jobs-BOoySTKD.js → artifact-index-jobs-C-xy7Z5v.js} +2 -2
- package/server/{backlog-auto-trigger-BUaFI44J.js → backlog-auto-trigger-GtG71X8H.js} +3 -3
- package/server/{behavior-Dg-D8eBG.js → behavior-B_-4EKF3.js} +2 -2
- package/server/{briefing-freshness-OouGbJ7d.js → briefing-freshness-DWdW7vUm.js} +2 -2
- package/server/{build-info-27NlbKhV.js → build-info-BT096lEl.js} +3 -3
- package/server/{build-info-Cv6CI7Gu.js → build-info-DgTqZkL5.js} +1 -1
- package/server/{checkpoint-manager-C7mFCY_E.js → checkpoint-manager-B7Bt29J0.js} +1 -1
- package/server/{checkpoint-manager-D64fCC4p.js → checkpoint-manager-DDqcGyu8.js} +2 -2
- package/server/checkpoint-worker.js +1 -1
- package/server/{checkpoints-Vh-J15ge.js → checkpoints-C-AXLfYT.js} +2 -2
- package/server/{checkpoints-DwZqT2qQ.js → checkpoints-CpgCjAlN.js} +1 -1
- package/server/{claude-hooks-provision-CS5W_dhI.js → claude-hooks-provision-C8wdRnN1.js} +1 -1
- package/server/{claude-hooks-provision-BVLGfHrv.js → claude-hooks-provision-but-_qGY.js} +2 -2
- package/server/{claude-permissions-C2OrLYKL.js → claude-permissions-H_5wHQZQ.js} +2 -2
- package/server/{claude-settings-overlay-DWXjafJh.js → claude-settings-overlay-BTENVmYf.js} +1 -1
- package/server/{claude-settings-overlay-DX-fMFpC.js → claude-settings-overlay-CbSz0Dvb.js} +2 -2
- package/server/cli-BsVIHwzC.js +3 -0
- package/server/{cli-mvpEOb3w.js → cli-vBeXbPrq.js} +9 -9
- package/server/{cliproxy-Dvsr4ZkW.js → cliproxy-Bgb2XCqi.js} +2 -2
- package/server/{cliproxy-7g1nObvB.js → cliproxy-DW0V86F8.js} +1 -1
- package/server/{close-issue-8F6uawYj.js → close-issue-Dn_4c4G8.js} +5 -5
- package/server/{closed-issue-reaper-BhV-r-tC.js → closed-issue-reaper-CWpY2uBw.js} +1 -1
- package/server/{closed-issue-reaper-BaYQYF6w.js → closed-issue-reaper-hANY_ehE.js} +9 -9
- package/server/codex-Dg7Is5yb.js +3 -0
- package/server/{codex-D_UBEOwL.js → codex-TmSi-yTv.js} +30 -8
- package/server/{codex-parser-BTzlOZiV.js → codex-parser-C4gSH-IR.js} +2 -2
- package/server/{config-CrduXs4a.js → config-CCvjQf27.js} +2 -2
- package/server/{config-nAB_F-Gp.js → config-DUIhMN_T.js} +1 -1
- package/server/{config-G1TOMJZA.js → config-DjLOdbgT.js} +2 -2
- package/server/{config-yaml-Ciyp2mYe.js → config-yaml-DvyMuOle.js} +177 -211
- package/server/{conflict-gate-BKalpcjL.js → conflict-gate-BSJkNTdp.js} +1 -1
- package/server/{conflict-gate-BLUNMs1i.js → conflict-gate-CmrYpa47.js} +3 -3
- package/server/{context-layers-YNpf6Q_I.js → context-layers-B3Nt58jl.js} +2 -2
- package/server/{context-layers-Cg9ZgVfx.js → context-layers-ZYFcWiyc.js} +3 -3
- package/server/{control-settings-D_79A6gp.js → control-settings-aP1ANIlI.js} +4 -4
- package/server/{conversation-compaction-DiuZbIUB.js → conversation-compaction-CNbTLB86.js} +8 -8
- package/server/{conversation-compaction-CMIeWW4_.js → conversation-compaction-DiG5zWQq.js} +1 -1
- package/server/{conversation-service-DQybSPUK.js → conversation-service-Du-MTNpJ.js} +6 -6
- package/server/{conversation-service-CWk8mEym.js → conversation-service-Up7FEzIC.js} +1 -1
- package/server/{conversations-BJ-t3BRm.js → conversations-6mPANqvL.js} +1 -1
- package/server/{conversations-BUgGvqVL.js → conversations-DbOs1e9Q.js} +4 -4
- package/server/{cost-jJ2cgDcG.js → cost-CW4WSe72.js} +3 -3
- package/server/{cost-Drm7qeD5.js → cost-Ca0YTWDw.js} +18 -2
- package/server/{cost-sync-DzHP6zaR.js → cost-sync-C0VdGme1.js} +3 -3
- package/server/{dag-DIji6O2b.js → dag-CdOjJVDT.js} +9 -9
- package/server/{dangerous-git-ops-BebB-61h.js → dangerous-git-ops-CT-IypG3.js} +1 -1
- package/server/dashboard-db-worker.js +7 -7
- package/server/{deacon-pleYrvIm.js → deacon-DYSEJb48.js} +3 -3
- package/server/{deacon-nudge-log-C5VCKtyi.js → deacon-nudge-log-Bjg8U4Y9.js} +3 -3
- package/server/{deacon-1s7bM5zn.js → deacon-pRnyD5w9.js} +1133 -474
- package/server/deacon-swarm-9jRLS5Ke.js +2 -0
- package/server/{deacon-swarm-DmA3rJ7k.js → deacon-swarm-DftYRDo8.js} +17 -17
- package/server/deacon.js +8 -8
- package/server/{deploy-patrol-DmM6F-yw.js → deploy-patrol-Bjsho_ha.js} +136 -19
- package/server/{deploy-window-ClLq1RYf.js → deploy-window-CM6W1-c6.js} +1 -1
- package/server/{deploy-window-jw4S_Y-c.js → deploy-window-DeP_OIRk.js} +77 -10
- package/server/{dev-supervisor-Do2Stz49.js → dev-supervisor-BpMoHlkR.js} +2 -2
- package/server/{devcontainer-renderer-D8ylupco.js → devcontainer-renderer-CtUgrVKW.js} +3 -3
- package/server/dist-Bd3vn0Hw.js +3 -0
- package/server/{dist-yfR7G1BL.js → dist-DyRx4cI7.js} +1 -1
- package/server/{docker-ClwPQaba.js → docker-BK7HIcBj.js} +2 -2
- package/server/{dod-BLphkhjs.js → dod-BrSfUHm0.js} +1 -1
- package/server/{ensure-devcontainer-BA3bICoY.js → ensure-devcontainer-DRqaAkBR.js} +1 -1
- package/server/{ensure-devcontainer-CFpQatOc.js → ensure-devcontainer-DseivYEy.js} +4 -4
- package/server/{esm-shims-BZw-fTQ6.js → esm-shims-CbI3BVkl.js} +1 -1
- package/server/{event-store-DABarGNz.js → event-store-Cr5PQwFC.js} +1 -1
- package/server/{event-store-BVnON3vf.js → event-store-tdiY5eDZ.js} +3 -3
- package/server/{events-CmERlnwn.js → events-CC1dgUpx.js} +3 -3
- package/server/{events-LGeUehYW.js → events-CvvGK6LT.js} +1 -1
- package/server/{factory-CQNprtHe.js → factory-CynerjXO.js} +50 -13
- package/server/{feature-registry-population-D9Z3tYSa.js → feature-registry-population-B0pmAz0a.js} +4 -4
- package/server/{feature-registry-storage-BWymOgXE.js → feature-registry-storage-_wUBRD3J.js} +2 -2
- package/server/{features--fOza5g5.js → features-Dhxz-wLc.js} +2 -2
- package/server/{feedback-target-Dqik2WTe.js → feedback-target-CPS15Vte.js} +7 -7
- package/server/{feedback-target-Dn9vfPpz.js → feedback-target-iygZwmMc.js} +1 -1
- package/server/{feedback-writer-Wlq5-qgS.js → feedback-writer-C9b6ccN1.js} +6 -5
- package/server/{feedback-writer-DDQNV8uc.js → feedback-writer-qmiMbqTZ.js} +1 -1
- package/server/{flywheel-Q-38YhZG.js → flywheel-DMCUzDWg.js} +1 -1
- package/server/{flywheel-1Wd8WDlh.js → flywheel-DSSpWmqF.js} +13 -13
- package/server/{flywheel-DPUc8r3V.js → flywheel-DcBkQvgE.js} +14 -14
- package/server/{flywheel-merge-order-CeBuX0EJ.js → flywheel-merge-order-C-6zRLvM.js} +1 -1
- package/server/{flywheel-merge-order-4SqOXFAr.js → flywheel-merge-order-DxbQKE1d.js} +8 -8
- package/server/forge-B-ZWyTRm.js +2 -0
- package/server/{forge-DBbDpiYc.js → forge-Ch9gCFod.js} +2 -2
- package/server/{from-hh6vTBGl.js → from-CJ_aH5jD.js} +1 -1
- package/server/{fts-db-6ponMie2.js → fts-db-CKgg0VKg.js} +2 -2
- package/server/{fts-operations-KIRK165y.js → fts-operations-BrL_VTRr.js} +2 -2
- package/server/git-utils-BVa07a4a.js +198 -0
- package/server/{git-utils-DmF5xkj8.js → git-utils-Dry_Ka_D.js} +1 -1
- package/server/{github-app-B3yfECo8.js → github-app-CMBdIFBQ.js} +11 -3
- package/server/{github-app-CeSVFL6C.js → github-app-CPfoFAdV.js} +1 -1
- package/server/{github-client-Dslipypz.js → github-client--XVlDpwM.js} +2 -2
- package/server/{github-client-4A6FgA8O.js → github-client-B4QsdE-X.js} +1 -1
- package/server/{github-pr-lookup-DBP0YHMr.js → github-pr-lookup-BRbDW-qk.js} +2 -2
- package/server/harness-binary-CVio2m-u.js +106 -0
- package/server/{harness-resolve-BGpO-OVM.js → harness-resolve-qHJBhy3Z.js} +9 -15
- package/server/{health-events-CZGZ5I-A.js → health-events-C9B8y1Hm.js} +2 -2
- package/server/{health-events-CnwV_SSz.js → health-events-CpfvuVmm.js} +1 -1
- package/server/{hooks-CoNscX84.js → hooks-DUXw8A0-.js} +2 -2
- package/server/{hooks-DvX33gY_.js → hooks-ltecuFqZ.js} +1 -1
- package/server/{hume-DSJt5eA_.js → hume-BEq0bUDg.js} +2 -2
- package/server/hume-B_DbflNM.js +3 -0
- package/server/{idle-stack-reaper-5DVRoY6P.js → idle-stack-reaper-D7w9t3fE.js} +1 -1
- package/server/{idle-stack-reaper-BfL8HqYy.js → idle-stack-reaper-w1ISSlhs.js} +2 -2
- package/server/{in-flight-guard-tVGiI5ee.js → in-flight-guard-aQ1IxeI3.js} +2 -2
- package/server/{infra-DN2wSxle.js → infra-CzaSOgul.js} +4 -4
- package/server/{injection-DtlT8Akv.js → injection-DZ0PfYa4.js} +7 -7
- package/server/{injection-DK9zh_HL.js → injection-oNZeoDhL.js} +1 -1
- package/server/{inspect-agent-DKByUS_F.js → inspect-agent-DJKLWcVT.js} +15 -11
- package/server/inspect-agent-ch-F-5Ci.js +2 -0
- package/server/{internal-token-DhfFiwW7.js → internal-token-Bb4XeV2x.js} +2 -2
- package/server/{internal-token-7bYL5v6K.js → internal-token-DXdfprGr.js} +1 -1
- package/server/{io-BiM-7Zsx.js → io-B3_AHDfr.js} +160 -184
- package/server/{issue-closed-Dfw3QDyZ.js → issue-closed-zhdvQicO.js} +7 -7
- package/server/{issue-lifecycle-B7HZWnTA.js → issue-lifecycle-CreaCkjW.js} +22 -22
- package/server/{issue-lifecycle-ytsEdDlK.js → issue-lifecycle-Dy4vd0Oa.js} +1 -1
- package/server/{issue-service-singleton-CPESc4Or.js → issue-service-singleton-B5ushCvE.js} +8 -8
- package/server/{issue-service-singleton-D5EB5eYr.js → issue-service-singleton-DabvBWUp.js} +1 -1
- package/server/{issues-XYtFMxrH.js → issues-B6ToV6x1.js} +2 -2
- package/server/{jsonl-parser-DJV2eZUP.js → jsonl-parser-Dhflo1SH.js} +3 -3
- package/server/{label-cleanup-CJ4m8iRU.js → label-cleanup-BKPJm4Hv.js} +3 -3
- package/server/{label-reconciler-CNf3Ylm3.js → label-reconciler-DdWbHEBu.js} +4 -4
- package/server/{launcher-generator-5DJRiovn.js → launcher-generator-CHVm7bGT.js} +10 -9
- package/server/{layers-cZx7ibtV.js → layers-DzxSTGNA.js} +2 -2
- package/server/lifecycle-DfeyBDwA.js +121 -0
- package/server/lifecycle-io-Bsnr2K4F.js +3 -0
- package/server/{lifecycle-io-DMurK4oM.js → lifecycle-io-D8iNBcux.js} +37 -37
- package/server/{lifecycle-CE7619Xw.js → lifecycle-sycO16hj.js} +6 -6
- package/server/{linear-client-BLyN-NiP.js → linear-client-D4zqMnX7.js} +2 -2
- package/server/{linear-client-Bj1l4FOA.js → linear-client-DqhDQO9k.js} +1 -1
- package/server/memory-fts-worker.js +1 -1
- package/server/{merge-hSC2BENe.js → merge-C_ZEhbqI.js} +3 -3
- package/server/{merge-CwX2_AWm.js → merge-DK23JEdS.js} +1 -1
- package/server/{merge-agent-CnORPiri.js → merge-agent-BQM3a8z5.js} +1 -1
- package/server/{merge-agent-DnBsms_V.js → merge-agent-XrB80vfT.js} +369 -213
- package/server/{merge-batch-C2w2U2eK.js → merge-batch-Bwoyr8Je.js} +1 -1
- package/server/{merge-blockers-DhRgh76x.js → merge-blockers-BsFjGrQ8.js} +2 -2
- package/server/merge-ops-DlB1IM0Y.js +2 -0
- package/server/{merge-rebase-CE-ZyOMY.js → merge-rebase-C1KIVr0s.js} +2 -2
- package/server/{merge-set-D7YNU1ZB.js → merge-set-DLz0MkGT.js} +3 -3
- package/server/{merge-set-DHkzPCJU.js → merge-set-DnSYdBEp.js} +1 -1
- package/server/{merge-sync-De1FYva5.js → merge-sync-DZ9dojJn.js} +2 -2
- package/server/{merge-sync-CpGA9Kg7.js → merge-sync-SSv3E-pl.js} +1 -1
- package/server/{merge-train-SvkRJZ-k.js → merge-train-DxDfBTjr.js} +3 -3
- package/server/{merge-train-deps-CECJTElu.js → merge-train-deps-CyYQUksx.js} +4 -4
- package/server/{merge-verification-B3meGcXF.js → merge-verification-CSizH3HY.js} +4 -4
- package/server/{multipart-parser-ByTMgYV5.js → multipart-parser-Dt8YPN5S.js} +2 -2
- package/server/{no-resume-mode-BnInAFKs.js → no-resume-mode-Cx3K0hHi.js} +11 -8
- package/server/node_modules/.package-lock.json +5 -5
- package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/README.md +3 -3
- package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.d.ts.map +1 -1
- package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js +2 -2
- package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js.map +1 -1
- package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/package.json +5 -5
- package/server/node_modules/@effect/platform-node/node_modules/@effect/platform-node-shared/src/NodeChildProcessSpawner.ts +6 -8
- package/server/{orphan-proposed-reconciler-CAfuWTA1.js → orphan-proposed-reconciler-BTkDrl4R.js} +1 -1
- package/server/{orphan-proposed-reconciler-AxAGUouN.js → orphan-proposed-reconciler-neK8dHQk.js} +23 -14
- package/server/package-lock.json +6 -6
- package/server/package.json +1 -1
- package/server/{pan-dir-Rw17YjT1.js → pan-dir-DeVUgwA7.js} +78 -58
- package/server/{paths-FP8v3lTz.js → paths-_zEts6wc.js} +2 -2
- package/server/{pickup-xi3KTLaJ.js → pickup-Dd0Znxxy.js} +2 -2
- package/server/{pipeline-membership-BtKMNY7v.js → pipeline-membership-0HaEGDlH.js} +190 -68
- package/server/{pipeline-notifier-dQ-U4NSb.js → pipeline-notifier-6iCJplFZ.js} +1 -1
- package/server/{pipeline-notifier-BM2HLF7B.js → pipeline-notifier-D0ykk59O.js} +2 -2
- package/server/{project-pipelines-B59NfN44.js → project-pipelines-2sK1apsO.js} +2 -2
- package/server/projects-9SkRpES9.js +3 -0
- package/server/{prompts-CbqaVjbe.js → prompts-Dp4Tpk39.js} +2 -2
- package/server/providers-DKkBXhxU.js +3 -0
- package/server/{providers-d3pwXGVE.js → providers-DV7ec8l7.js} +7 -7
- package/server/public/assets/{chunk-BO2N2NFS-BxYSL7J-.js → chunk-BO2N2NFS-CltymLRg.js} +4 -4
- package/server/public/assets/{diagram-OG6HWLK6-C_F9Q2as.js → diagram-OG6HWLK6-D2f6pjgA.js} +1 -1
- package/server/public/assets/{dist-DQNg4CiF.js → dist-BWR4qFiV.js} +1 -1
- package/server/public/assets/{dist-CLSlc6cV.js → dist-DEmlBBNQ.js} +3 -3
- package/server/public/assets/{ganttDiagram-6RSMTGT7-Cq0my-0C.js → ganttDiagram-6RSMTGT7-DnfiViPK.js} +1 -1
- package/server/public/assets/{highlighted-body-OFNGDK62-eZC03dGh.js → highlighted-body-OFNGDK62-B8Wrmj9H.js} +1 -1
- package/server/public/assets/index-CUr1xv8w.css +1 -0
- package/server/public/assets/{index-SLYGA8AQ.js → index-CsSuZQBI.js} +148 -145
- package/server/public/assets/{linear-6Fi3qnGg.js → linear-C9zFQpkX.js} +1 -1
- package/server/public/assets/mermaid-GHXKKRXX-BUAB8hqt.js +1 -0
- package/server/public/assets/{pieDiagram-4H26LBE5-Dpmc6xsv.js → pieDiagram-4H26LBE5-lR8H7Yjd.js} +1 -1
- package/server/public/assets/{prod-ojHllFvN.js → prod-B1jCQihw.js} +4 -4
- package/server/public/assets/{quadrantDiagram-W4KKPZXB-Ulr9gON5.js → quadrantDiagram-W4KKPZXB-CVQ2guem.js} +1 -1
- package/server/public/assets/{sankeyDiagram-5OEKKPKP-CwdHGXfL.js → sankeyDiagram-5OEKKPKP-eD1RB4gm.js} +1 -1
- package/server/public/assets/{xychartDiagram-2RQKCTM6-r-bEDzJh.js → xychartDiagram-2RQKCTM6-ChEC6dQn.js} +1 -1
- package/server/public/index.html +54 -10
- package/server/{pull-requests-D3N6HQzI.js → pull-requests--Ib2jTgy.js} +1 -1
- package/server/{pull-requests-CjjPj7v6.js → pull-requests-CXIhdCYD.js} +13 -11
- package/server/{queries-B5hl7lMQ.js → queries-6d7Cdtm7.js} +723 -110
- package/server/{rally-Dp0Gb1DN.js → rally-B708-nZn.js} +3 -3
- package/server/{rally-api-DGaFz5L5.js → rally-api-nY0ZANw3.js} +2 -2
- package/server/{rally-api-CKr0O4DJ.js → rally-api-yjQ0TfHd.js} +1 -1
- package/server/{rally-client-SVbjGvqj.js → rally-client-B1EJhfV0.js} +4 -4
- package/server/{rally-client-Cqf6EX_r.js → rally-client-CULK2XAY.js} +1 -1
- package/server/rally-njs_mJrt.js +3 -0
- package/server/reap-terminal-sessions-MWnqdLCJ.js +4 -0
- package/server/{reap-terminal-sessions-CjqRAGw7.js → reap-terminal-sessions-N3BTkmX_.js} +11 -28
- package/server/{rebuild-stack-DHqCLvLX.js → rebuild-stack-Dp4eLkt4.js} +6 -6
- package/server/{rebuild-stack-DjdpALr1.js → rebuild-stack-kA7XngID.js} +1 -1
- package/server/{reconstruct-cache-BqrCQt0o.js → reconstruct-cache-uWbZfjms.js} +6 -6
- package/server/record-t6V-3Dcj.js +3 -0
- package/server/{record-update-BlB8mpKO.js → record-update-DACtKh6_.js} +1 -1
- package/server/record-update-Dq0t2uBG.js +310 -0
- package/server/{recovery-trip-l1Hsi37x.js → recovery-trip-BJtIQuag.js} +2 -2
- package/server/{release-engine-CSI4K6Oj.js → release-engine-DZpmGGzb.js} +5 -5
- package/server/{release-set-BywwggrE.js → release-set-hnXd_kga.js} +3 -3
- package/server/{remote-DYziAkiZ.js → remote-4tiENDaI.js} +3 -3
- package/server/{remote-cnoeuDWn.js → remote-Br-ZWVIP.js} +3 -3
- package/server/{remote-agents-BNORDWAX.js → remote-agents-CRCg1L4H.js} +1 -1
- package/server/{remote-agents-CZ2rc8I0.js → remote-agents-nmty1mLu.js} +6 -6
- package/server/{remote-completion-W67FNQ-A.js → remote-completion-BbWNd10K.js} +13 -13
- package/server/resume-CcKqnTvE.js +3 -0
- package/server/{review-agent-CSswH985.js → review-agent-DJRO8EG8.js} +1 -1
- package/server/{review-agent-CqSqSHkU.js → review-agent-sKkE1FEL.js} +23 -23
- package/server/{review-artifacts-BBgnd5df.js → review-artifacts-BLbSC4ke.js} +5 -5
- package/server/{review-context-Ctp9BdNJ.js → review-context-BgX3lcCx.js} +9 -9
- package/server/{review-status-CCgPVK1h.js → review-status-A7quS5KJ.js} +56 -39
- package/server/review-status-C6n6-9f_.js +3 -0
- package/server/{review-status-enrichment-DtDRGpst.js → review-status-enrichment-tbOn_A_u.js} +3 -3
- package/server/review-status-source-CxuEjLGg.js +39 -0
- package/server/{review-status-sync-jnLgd04F.js → review-status-sync-BhSQ0d0l.js} +2 -2
- package/server/{review-status-sync-C792ksoJ.js → review-status-sync-To3-iS-N.js} +1 -1
- package/server/{review-verdict-feedback-D5lW0o3k.js → review-verdict-feedback-C1Kg8n7t.js} +1 -1
- package/server/{review-verdict-feedback-CMsIpTpy.js → review-verdict-feedback-CTRNtzXO.js} +7 -7
- package/server/{rollup-B3kQmNpl.js → rollup-B53Y81xK.js} +1 -1
- package/server/{rollup-CLj_AK9f.js → rollup-WA0VD-Rr.js} +8 -8
- package/server/{scanner-C4NeC4FE.js → scanner-D2743cp8.js} +11 -7
- package/server/{sequence-io-Ce-6grIY.js → sequence-io-Cg0zYj_E.js} +4 -4
- package/server/{sequencer-agent-Bpz0yGmG.js → sequencer-agent-BGY8gjg-.js} +5 -5
- package/server/server.js +1348 -963
- package/server/{service-CqAY8Kmk.js → service-DCpB_SGd.js} +154 -51
- package/server/{session-fork-uNo4rMRA.js → session-fork-BQ8_6H32.js} +2 -2
- package/server/{session-history-DUehL3KN.js → session-history-CVZDpS3c.js} +4 -4
- package/server/{settings-DP2OYLXL.js → settings-BZ5m1UCl.js} +3 -3
- package/server/settings-D0OSwos5.js +2 -0
- package/server/{settings-D9grjmaP.js → settings-ylxwqwQG.js} +2 -2
- package/server/{shadow-engineering-Bi_oIMtF.js → shadow-engineering-BlxG6Xye.js} +3 -3
- package/server/{shadow-state-CDxEuPlE.js → shadow-state-C2_epgx2.js} +1 -1
- package/server/{shadow-state-a_ztFBJe.js → shadow-state-Dh-HzF2J.js} +2 -2
- package/server/{shadow-utils-CyOg6_Xq.js → shadow-utils-4bvjn9b3.js} +2 -2
- package/server/{ship-log-DDcueaIR.js → ship-log-ClSMIzZX.js} +1 -1
- package/server/{smart-compaction-C1_VVLEd.js → smart-compaction-CHIxLr_d.js} +1 -1
- package/server/{smart-compaction--Oj65Uov.js → smart-compaction-r4pHQBIr.js} +7 -7
- package/server/{spawn-planning-session-AiUSsBnH.js → spawn-planning-session-DWAorh2B.js} +25 -20
- package/server/{spawn-planning-session-LFtK2QCE.js → spawn-planning-session-KC_UduxD.js} +1 -1
- package/server/{specialist-completion-qOgqdqXH.js → specialist-completion-BXhav38U.js} +1 -1
- package/server/{specialist-context-gjj8Z4Ii.js → specialist-context-DtrYvGJ-.js} +5 -5
- package/server/{specialist-handoff-logger-BsBNvVZv.js → specialist-handoff-logger-C45ouoZ6.js} +2 -2
- package/server/{specialist-logs-CSLtvPx6.js → specialist-logs-DJ3RzKxW.js} +3 -3
- package/server/{specialists-D0VBf8g_.js → specialists-D5fRZXmN.js} +1 -1
- package/server/specialists-DVj0hvaL.js +3 -0
- package/server/{specialists-CYRwELzc.js → specialists-DyFeedjn.js} +66 -76
- package/server/{specialists-DAegTvRt.js → specialists-JVO00bs7.js} +374 -220
- package/server/specs-nN45DG2X.js +3 -0
- package/server/{src-OLoJhUiJ.js → src-CG9mCkP6.js} +6 -6
- package/server/{src-BqTcrfO_.js → src-CMTQGyCK.js} +3 -3
- package/server/{src-Dpq1yFIl.js → src-U7_kTPEE.js} +338 -4
- package/server/{stack-health-I713ELld.js → stack-health-Df0YEZKa.js} +1 -1
- package/server/{stack-health-DV_f-lK0.js → stack-health-puygdaMd.js} +2 -2
- package/server/{stale-task-claims-CQSKZVq0.js → stale-task-claims-BbFwCTb0.js} +4 -4
- package/server/{staleness-BbsGxmF2.js → staleness-Bpy41ngS.js} +15 -3
- package/server/{staleness-zGp4P1hd.js → staleness-Cbl_w4Bw.js} +1 -1
- package/server/{state-home-DixkE-up.js → state-home-CIGjwNfJ.js} +119 -54
- package/server/state-migrate-Dkzaxvny.js +487 -0
- package/server/{stuck-remediation-BWkK_O7A.js → stuck-remediation-CzEov_fq.js} +27 -21
- package/server/{stuck-remediation-CTPRC2S5.js → stuck-remediation-sY_MHHgQ.js} +1 -1
- package/server/{substrate-bug-weights-service-DXd0ID83.js → substrate-bug-weights-service-BH66lhm7.js} +3 -3
- package/server/{summary-fork-CdLn8Chr.js → summary-fork-D8bXjCr7.js} +2 -2
- package/server/{summary-fork-f3DpgjXh.js → summary-fork-DHhJIsAL.js} +8 -8
- package/server/{supervisor-Ch8CDuoF.js → supervisor-BO-Zk_h-.js} +3 -3
- package/server/supervisor-BPy-o1A8.js +2 -0
- package/server/{swarm-readiness-C9P2iPap.js → swarm-readiness-CQ_fwUWF.js} +4 -4
- package/server/{system-prerequisites-DkoQBn1q.js → system-prerequisites-Bza0ffAh.js} +24 -44
- package/server/{teardown-workspace-D-5yMyit.js → teardown-workspace-CEgauF4U.js} +15 -15
- package/server/{test-agent-queue-BwpUpu-o.js → test-agent-queue-DXDt0Xa-.js} +7 -7
- package/server/{test-verdict-BRiSu7eW.js → test-verdict-CmUBK5cT.js} +1 -1
- package/server/{test-verdict-BQ1yx7d4.js → test-verdict-DFjjIHR5.js} +1 -1
- package/server/{tldr-daemon-DjxP5g6Y.js → tldr-daemon-BDtLOIlO.js} +2 -2
- package/server/{tldr-daemon-BJA7TkqS.js → tldr-daemon-DL566HbH.js} +1 -1
- package/server/tmux-DoThH6aj.js +3 -0
- package/server/{tmux-y1blSxks.js → tmux-ftABRAmc.js} +76 -44
- package/server/{token-LUrbM9sU.js → token-CsOhvw42.js} +2 -2
- package/server/{token-util-BZaDAQ8S.js → token-util-CTmczIfW.js} +1 -1
- package/server/token-util-DrHg8abn.js +3 -0
- package/server/{tracker-config-DSFZBdXP.js → tracker-config-B4itFzDo.js} +2 -2
- package/server/{tracker-utils-WtP_V-yn.js → tracker-utils-BePq_oj-.js} +1 -1
- package/server/{tracker-utils-DiceZN3a.js → tracker-utils-tnxxqROg.js} +2 -2
- package/server/{traefik-connect-BXqfOP4-.js → traefik-connect-m73vGebA.js} +1 -1
- package/server/{tunnel-DTng1rfQ.js → tunnel-B2vxjx_b.js} +3 -3
- package/server/{tunnel-WcJImbAC.js → tunnel-Cgj-IGIl.js} +1 -1
- package/server/{types-BjaZ1oqH.js → types-BBNjPcqU.js} +1 -1
- package/server/{types-DqeBMmJN.js → types-hraoaQIp.js} +1 -1
- package/server/{uat-train-BpLnp7Cx.js → uat-train-CuEn0t9M.js} +28 -28
- package/server/{uat-train-Wismge7h.js → uat-train-cKfM-_WW.js} +1 -1
- package/server/{validation-BA4e5EGm.js → validation-B5JxoPUS.js} +259 -9
- package/server/{validation-CUWamZ4X.js → validation-CIi6pnI2.js} +1 -1
- package/server/{verification-artifact-Dr_0g9nb.js → verification-artifact-BcnIbigL.js} +1 -1
- package/server/{verification-artifact-CrbI4tJE.js → verification-artifact-C-lIHfUa.js} +1 -1
- package/server/{verification-runner-gAzh3cVD.js → verification-runner-Br0S_Ous.js} +103 -37
- package/server/{verification-runner-Dcksl_P-.js → verification-runner-CDj4lD4t.js} +1 -1
- package/server/{vtt-parser-3VZKsmSm.js → vtt-parser-DKpNNW5i.js} +1 -1
- package/server/{work-agent-prompt-ULdcANl5.js → work-agent-prompt-Yb2bd3Fq.js} +16 -15
- package/server/{workflows-B8ROFlfw.js → workflows-C9WmILql.js} +39 -77
- package/server/workflows-D90rMOya.js +2 -0
- package/server/{workspace-DhTDA8nB.js → workspace-BVl4rihN.js} +3 -3
- package/server/{workspace-DSjUJaJN.js → workspace-DuUdndHe.js} +1 -1
- package/server/{workspace-config-BAAsAv-o.js → workspace-config-cEGcO6UT.js} +1 -1
- package/server/{workspace-manager-CcujONCR.js → workspace-manager-ZTdJAy9M.js} +1 -1
- package/server/{workspace-manager-DsN52IMG.js → workspace-manager-hLUv3ADC.js} +23 -16
- package/server/{workspace-metadata-DIL5_U4c.js → workspace-metadata-CskwzzhL.js} +2 -2
- package/server/{workspace-metadata-CftOpNLs.js → workspace-metadata-DNpMixRq.js} +1 -1
- package/server/{workspaces-Dmlh1YXm.js → workspaces-hWvy9eKs.js} +276 -110
- package/sync-sources/agents/pan-inspect-agent.md +1 -1
- package/sync-sources/agents/pan-merge-agent.md +1 -1
- package/sync-sources/agents/pan-planning-agent.md +4 -4
- package/sync-sources/agents/pan-work-agent.md +1 -1
- package/sync-sources/dev-skills/pan-commit/SKILL.md +1 -1
- package/sync-sources/dev-skills/test-specialist-workflow/SKILL.md +1 -1
- package/sync-sources/hooks/record-cost-event.js +363 -71
- package/sync-sources/hooks/session-start-hook +7 -0
- package/sync-sources/hooks/work-agent-stop-hook +1 -1
- package/sync-sources/rules/per-bead-durability.md +1 -1
- package/sync-sources/rules/prd-authoring.md +1 -1
- package/sync-sources/skills/feature-work/SKILL.md +1 -1
- package/sync-sources/skills/pan/SKILL.md +2 -2
- package/sync-sources/skills/pan-admin-config/SKILL.md +1 -0
- package/sync-sources/skills/pan-approve/SKILL.md +1 -1
- package/sync-sources/skills/pan-close/SKILL.md +1 -1
- package/sync-sources/skills/pan-doctor/SKILL.md +1 -1
- package/sync-sources/skills/pan-new-project/SKILL.md +9 -11
- package/sync-sources/skills/pan-oversee/SKILL.md +5 -5
- package/sync-sources/skills/pan-plan/SKILL.md +6 -6
- package/sync-sources/skills/pan-quickstart/SKILL.md +1 -1
- package/sync-sources/skills/pan-recap/SKILL.md +2 -2
- package/sync-sources/skills/pan-review/SKILL.md +1 -1
- package/sync-sources/skills/pan-start/SKILL.md +26 -3
- package/sync-sources/skills/pan-swarm/SKILL.md +1 -1
- package/sync-sources/skills/pan-sync/SKILL.md +1 -1
- package/sync-sources/skills/pan-task/SKILL.md +2 -2
- package/sync-sources/skills/pan-wipe/SKILL.md +2 -2
- package/sync-sources/skills/pipeline-list/SKILL.md +1 -1
- package/sync-sources/skills/pipeline-status/SKILL.md +2 -2
- package/sync-sources/skills/plan/SKILL.md +11 -11
- package/sync-sources/skills/write-vbrief/SKILL.md +7 -282
- package/sync-sources/skills/write-xbrief/SKILL.md +295 -0
- package/sync-sources/templates/claude-md/sections/warnings.md +1 -1
- package/server/agent-state-BV_6RHnO.js +0 -3
- package/server/agents-Czz6R57Z.js +0 -3
- package/server/cli-ChErG518.js +0 -3
- package/server/codex-BBeZ8c3s.js +0 -3
- package/server/deacon-swarm-uudlSCLM.js +0 -2
- package/server/dist-BEDL2alY.js +0 -3
- package/server/forge-DbhJyH6u.js +0 -2
- package/server/git-utils-Bkxzr1Xf.js +0 -129
- package/server/hume-BrA1tUuk.js +0 -3
- package/server/inspect-agent-CyXNo9fM.js +0 -2
- package/server/lifecycle-io-CUpsxG0p.js +0 -3
- package/server/merge-ops-BpTtuO8x.js +0 -2
- package/server/projects-IRHJIPYC.js +0 -3
- package/server/providers-BqCdTryq.js +0 -3
- package/server/public/assets/index-C6NLz_1S.css +0 -1
- package/server/public/assets/mermaid-GHXKKRXX-BNwFoQsf.js +0 -1
- package/server/rally-DGimSRBQ.js +0 -3
- package/server/reap-terminal-sessions-C1mfzoZo.js +0 -3
- package/server/record-update-RviRDSNs.js +0 -168
- package/server/record-us0YECMO.js +0 -3
- package/server/resume-OyN3dEXE.js +0 -3
- package/server/review-status-DXeqFpk5.js +0 -3
- package/server/settings-BaPXXJsT.js +0 -2
- package/server/specialists-C6WkeKFK.js +0 -3
- package/server/specs-BsNcum0h.js +0 -3
- package/server/state-migrate-_zJJ6XKE.js +0 -362
- package/server/supervisor-Qy1QecAs.js +0 -2
- package/server/tmux-HQLgwo_C.js +0 -3
- package/server/token-util-Cg-QnowA.js +0 -3
- package/server/workflows-C5c-RPsY.js +0 -2
package/server/server.js
CHANGED
|
@@ -1,107 +1,110 @@
|
|
|
1
1
|
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM, r as __exportAll, t as __commonJSMin } from "./rolldown-runtime-DNCzzKnI.js";
|
|
2
|
-
import {
|
|
3
|
-
import { a as shouldRefuseHostDashboardPort, i as readHostDashboardApiPort, n as getDashboardIdentity, r as isNonPrimaryCheckoutRoot } from "./deacon-nudge-log-
|
|
4
|
-
import { $ as runInBatches, A as handleConversationDelete, B as stopConversationRuntime, C as isPiControlChannelHarness, D as conversationNeedsRunningRepair, E as validateConversationControlAckOrigin, F as isInsideGitWorkTree, G as cleanupOrphanedConversationAttachments, H as waitForPiTuiReady, I as resolveAllowedHarness, J as extractConversationAttachmentPaths, K as cleanupUnreferencedConversationAttachments, L as shouldReportUnresolvedLiveSession, M as handleConversationResume, N as handleConversationStop, O as conversationSessionAliveFromState, P as handleConversationSwitchModel, Q as removeConversationAttachment, R as spawnConversationSession, S as handleConversationThinkingLevel, T as resolveConversationDeliveryMethod, U as waitForTmuxSession$1, V as tmuxSessionExists, W as cleanupConversationAttachments, X as hasConversationAttachment, Y as getConversationAttachmentsRoot, Z as isManagedConversationAttachmentPath, _ as handleConversationCodexApproval, _t as validateOrigin$1, a as agentsRouteLayer, at as panCliInvocation, b as handleConversationDeliveryMethod, bt as getDefaultCwd, c as hasDashboardInternalToken, ct as resolveAgentHarness, d as rejectUnsafeDashboardMutationRequest, dt as resolveJsonlPath, et as evaluateSpawnGuardrails, f as saveAgentStateAndEmitEvent, ft as resolvePiSessionPath, g as handleConversationAbort, gt as isTrustedOriginForHost, h as deliverConversationViaControlChannel, ht as getHeaderFromMap, j as handleConversationRestartAll, k as handleConversationCreate, l as rejectUnauthorizedDashboardRequest, lt as resolveClaudeSessionId, m as codexConversationPendingInput, mt as waitForSessionRespawn, nt as resolveAgentGitInfo, o as dashboardCsrfToken, p as saveAgentStateAndEmitEventProgram, pt as isRespawnPending, q as ensureConversationAttachmentDir, rt as resolveConversationGitInfo, s as dashboardSessionCookieHeader, st as readLauncherPinnedSessionId, t as specialistsRouteLayer, tt as invalidateAgentsCache, u as rejectUnauthorizedDashboardSessionMintRequest, ut as resolveCodexRolloutPath, v as handleConversationCompact, vt as validateOriginHeaders, w as pickDeliverAs, x as handleConversationPlanAction, xt as jsonResponse, y as handleConversationControlAck, yt as httpHandler, z as startConversationModelBackfill } from "./specialists-
|
|
2
|
+
import { A as canUseHarnessSync, Br as getOverdeckHome, Cr as LOGS_DIR, D as resolveTieredExecutionEnabled, E as resolveTieredExecutionBlock, Et as getIssueWorkspacePath, Fn as renameProject, Fr as getDocsDisableStatePath, Gr as sessionFilePath, H as init_providers, Hr as isDevMode, Ht as flushAutoCommits, I as UnknownModelError, Ir as getDocsIndexPath, J as defaultBackgroundAiFeatures, Jn as extractPrefixSync, Ln as resolveInfraRepo, Lr as getDocsTelemetryPath, M as init_harness_policy, Nr as encodeClaudeProjectDir, Nt as readIssueRecordSync, On as listProjects, Ot as init_record, Pn as registerProjectSync, Pr as getDocsBudgetStatePath, Q as computeModelOrigin, R as getBuiltInDefaultHarness, Rn as resolveProjectFromIssue, T as init_tier_table, Tn as init_projects, Un as setProjectAutoMergeDefaultSync, Ur as packageRoot, Ut as init_auto_commit, V as getProviderForModelSync, Vr as init_paths, Vt as flushAllPendingAutoCommits, Wn as setProjectSwarmPolicySync, X as DEFAULT_ROLES, Y as init_registry, Yn as init_issue_id, Z as DEFAULT_WORKHORSES, Zn as parseIssueIdSync, _ as getDefaultDocsConfig, at as getModelEffortLevelsSync, br as CLAUDE_DIR, cn as ProjectRenameError, ct as modelSupportsImagesSync, d as loadConfigNoMigration, er as require_dist$1, f as loadConfigSync, fn as findProjectByPathSync, fr as TrackerError, g as mergeConfigs, gn as getIssuePrefix, h as jsYaml, hr as AGENTS_DIR, ht as ROLE_EFFORTS, i as getConversationsConfig, ir as FsError, jr as SYNC_SOURCES, k as validateTieredExecutionConfig, kn as listProjectsSync, lt as resolveModelIdSync, m as init_js_yaml, mn as findProjectByTeamSync, mr as init_errors, mt as PARENT_MODEL_REF, n as clearConfigCache, nt as MODEL_CAPABILITIES, o as getGlobalConfigPath, or as GitHubApiError, ot as hasModelCapabilitySync, p as updateConversationsConfig, pt as COMPLIANCE_MODES, r as getConversationSearchConfigSync, rt as MODEL_DEPRECATIONS, s as init_load, st as init_model_capabilities, t as init_config_yaml, tt as resolveModel, u as isTldrEnabledSync, un as extractTeamPrefix, ur as ProcessSpawnError, v as getDefaultTtsDaemonConfig, w as TieredExecutionConfigError, wr as OVERDECK_HOME, y as mergeTtsDaemonConfigs, yn as getProjectSync, z as getKimiAnthropicBaseUrl, zn as resolveProjectFromIssueSync, zr as getLegacyHome } from "./config-yaml-DvyMuOle.js";
|
|
3
|
+
import { a as shouldRefuseHostDashboardPort, i as readHostDashboardApiPort, n as getDashboardIdentity, r as isNonPrimaryCheckoutRoot } from "./deacon-nudge-log-Bjg8U4Y9.js";
|
|
4
|
+
import { $ as runInBatches, A as handleConversationDelete, B as stopConversationRuntime, C as isPiControlChannelHarness, D as conversationNeedsRunningRepair, E as validateConversationControlAckOrigin, F as isInsideGitWorkTree, G as cleanupOrphanedConversationAttachments, H as waitForPiTuiReady, I as resolveAllowedHarness, J as extractConversationAttachmentPaths, K as cleanupUnreferencedConversationAttachments, L as shouldReportUnresolvedLiveSession, M as handleConversationResume, N as handleConversationStop, O as conversationSessionAliveFromState, P as handleConversationSwitchModel, Q as removeConversationAttachment, R as spawnConversationSession, S as handleConversationThinkingLevel, St as jsonStringResponse, T as resolveConversationDeliveryMethod, U as waitForTmuxSession$1, V as tmuxSessionExists, W as cleanupConversationAttachments, X as hasConversationAttachment, Y as getConversationAttachmentsRoot, Z as isManagedConversationAttachmentPath, _ as handleConversationCodexApproval, _t as validateOrigin$1, a as agentsRouteLayer, at as panCliInvocation, b as handleConversationDeliveryMethod, bt as getDefaultCwd, c as hasDashboardInternalToken, ct as resolveAgentHarness, d as rejectUnsafeDashboardMutationRequest, dt as resolveJsonlPath, et as evaluateSpawnGuardrails, f as saveAgentStateAndEmitEvent, ft as resolvePiSessionPath, g as handleConversationAbort, gt as isTrustedOriginForHost, h as deliverConversationViaControlChannel, ht as getHeaderFromMap, j as handleConversationRestartAll, k as handleConversationCreate, l as rejectUnauthorizedDashboardRequest, lt as resolveClaudeSessionId, m as codexConversationPendingInput, mt as waitForSessionRespawn, nt as resolveAgentGitInfo, o as dashboardCsrfToken, p as saveAgentStateAndEmitEventProgram, pt as isRespawnPending, q as ensureConversationAttachmentDir, rt as resolveConversationGitInfo, s as dashboardSessionCookieHeader, st as readLauncherPinnedSessionId, t as specialistsRouteLayer, tt as invalidateAgentsCache, u as rejectUnauthorizedDashboardSessionMintRequest, ut as resolveCodexRolloutPath, v as handleConversationCompact, vt as validateOriginHeaders, w as pickDeliverAs, x as handleConversationPlanAction, xt as jsonResponse, y as handleConversationControlAck, yt as httpHandler, z as startConversationModelBackfill } from "./specialists-JVO00bs7.js";
|
|
5
5
|
import { a as init_activity_logger, i as emitDashboardLifecycleSync, n as emitActivityEntrySync, r as emitActivityTtsSync } from "./activity-logger-DDlOIAML.js";
|
|
6
|
-
import { A as init_paths$1, O as OVERDECK_MIGRATION_PATH, f as init_infra, i as DbLive, k as getOverdeckDatabasePath, u as TmuxLive } from "./infra-
|
|
6
|
+
import { A as init_paths$1, O as OVERDECK_MIGRATION_PATH, f as init_infra, i as DbLive, k as getOverdeckDatabasePath, u as TmuxLive } from "./infra-CzaSOgul.js";
|
|
7
7
|
import { n as openDatabase, t as init_driver } from "./driver-CKVGi51s.js";
|
|
8
|
-
import { n as updateIssueRecord, t as init_record_update } from "./record-update-
|
|
9
|
-
import {
|
|
10
|
-
import { a as init_event_store, i as initEventStore, n as getEventStore } from "./event-store-
|
|
11
|
-
import {
|
|
12
|
-
import { a as
|
|
13
|
-
import { a as EventStoreService, c as ReadModelService, d as init_read_model, f as toAgentResolution, i as init_issue_lifecycle, l as ReadModelServiceLive, m as toRole, n as IssueLifecycleLive, o as EventStoreServiceLive, p as toAgentStatus, s as init_domain_services, t as IssueLifecycle } from "./issue-lifecycle-
|
|
14
|
-
import { c as listAllAgentsSync, n as AgentsResolverLive, o as init_agents } from "./agents-
|
|
15
|
-
import { i as init_paths$2, l as resolveObservationsFile, r as ensureParentDir, s as resolveIssueMemoryRoot, t as assertMemorySafeSegment } from "./paths-
|
|
16
|
-
import { i as recordBriefingSessionStart, n as ensureSessionContextBriefingFile, r as init_briefing_freshness, t as appendFreshBriefingUpdate } from "./briefing-freshness-
|
|
17
|
-
import { n as listFeatureRegistryEntries, t as init_feature_registry_storage } from "./feature-registry-storage-
|
|
18
|
-
import { a as diffAgainstMain, c as diffCheckpoints, d as diffPatchSinceCommit, f as findCommitAtTime, h as listCheckpoints, l as diffFilesAgainstHead, m as init_checkpoint_manager, o as diffAgainstMainFiles, s as diffCheckpointFiles, t as captureCheckpoint, u as diffPatchFilesAgainstHead } from "./checkpoint-manager-
|
|
19
|
-
import {
|
|
20
|
-
import { a as getCostForIssueAggregateSync, c as getDailyTrendsSync, d as init_cost_sync, l as getModelRollupSync, n as getBackgroundCostBySourceSync, p as queryCostEventsSync, r as getCavemanExperimentDataSync, s as getCostsByIssueSync, u as getTodayCostSync } from "./cost-sync-
|
|
21
|
-
import { c as getAgentsNeedingAttention, d as CostResolverLive, f as CostWriter, l as CostDoorLive, n as readCloisterStateFile, o as generateHealthSummary, s as getAgentHealth, t as getCloisterService, u as CostResolver } from "./service-
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
8
|
+
import { n as updateIssueRecord, t as init_record_update } from "./record-update-Dq0t2uBG.js";
|
|
9
|
+
import { $ as init_child_env, B as sendKeysAsync, C as getWindowDimensions, D as killSession, H as sessionExists, J as init_ui_theme, L as resizeWindow, M as listSessionNames, Q as buildChildEnvWithoutTmuxSync, T as isHarnessProcessAlive, Y as setUiTheme, Z as buildChildEnvSync, d as ensureManagedTmuxContextOnce, i as capturePane, l as deliveryVerifyLine, n as buildTmuxArgs, o as capturePaneText, s as createSession, w as init_tmux, z as sendKeys } from "./tmux-ftABRAmc.js";
|
|
10
|
+
import { a as init_event_store, i as initEventStore, n as getEventStore } from "./event-store-tdiY5eDZ.js";
|
|
11
|
+
import { D as AgentSnapshot, E as AgentRuntimeSnapshot, O as ReviewStatusSnapshot, S as SystemHealthSnapshot, _ as WS_METHODS, b as EDITORS, c as ContextPreviewRequest, g as PanRpcGroup, h as PanRpcError, l as FlywheelStats, n as compareIssueIds, o as getHarnessBehavior, s as ContextLayerSaveRequest, t as init_src, v as FlywheelRunId, w as MemoryObservation, x as DomainEvent, y as FlywheelStatus } from "./src-U7_kTPEE.js";
|
|
12
|
+
import { a as fixStuckCommentedReviews, b as setReviewStatusSync, c as getReviewStatusSync, d as loadReviewStatuses, l as init_review_status, n as clearReviewStatus, o as fixStuckReadyForMerge, p as markWorkspaceStuck, r as clearStuckMergeStatuses, s as getReviewStatus, u as loadReadyForMergeFlags, y as setReviewStatus } from "./review-status-A7quS5KJ.js";
|
|
13
|
+
import { a as EventStoreService, c as ReadModelService, d as init_read_model, f as toAgentResolution, i as init_issue_lifecycle, l as ReadModelServiceLive, m as toRole, n as IssueLifecycleLive, o as EventStoreServiceLive, p as toAgentStatus, s as init_domain_services, t as IssueLifecycle } from "./issue-lifecycle-CreaCkjW.js";
|
|
14
|
+
import { c as listAllAgentsSync, n as AgentsResolverLive, o as init_agents } from "./agents-B4Bjbkfv.js";
|
|
15
|
+
import { i as init_paths$2, l as resolveObservationsFile, r as ensureParentDir, s as resolveIssueMemoryRoot, t as assertMemorySafeSegment } from "./paths-_zEts6wc.js";
|
|
16
|
+
import { i as recordBriefingSessionStart, n as ensureSessionContextBriefingFile, r as init_briefing_freshness, t as appendFreshBriefingUpdate } from "./briefing-freshness-DWdW7vUm.js";
|
|
17
|
+
import { n as listFeatureRegistryEntries, t as init_feature_registry_storage } from "./feature-registry-storage-_wUBRD3J.js";
|
|
18
|
+
import { a as diffAgainstMain, c as diffCheckpoints, d as diffPatchSinceCommit, f as findCommitAtTime, h as listCheckpoints, l as diffFilesAgainstHead, m as init_checkpoint_manager, o as diffAgainstMainFiles, s as diffCheckpointFiles, t as captureCheckpoint, u as diffPatchFilesAgainstHead } from "./checkpoint-manager-DDqcGyu8.js";
|
|
19
|
+
import { Ar as init_codex_auth, Bn as getAgentDir, Cr as getAgentRuntimeStateSync, D as init_tier_supervisor, E as deliverCommitForReview, Ft as init_transcript_landing, Hn as getAgentState, It as probeTranscriptSince, Pt as captureTranscriptUserRecordSnapshot, Q as operatorInterventionEvent, Sr as getAgentRuntimeState, Tn as init_openai_auth, Wn as getAgentStateSync, X as messageAgent, Yt as resolveImplicitStaffing, Z as init_operator_interventions, _t as emergencyBrake, a as listRunningAgentsSync, b as init_agents$1, c as getRuntimeCensus, d as panePidsForSession, dr as readAgentHarnessModelRecordSync, f as refreshRuntimeCensus, hn as init_claude_auth, i as listRunningAgents, in as getProviderAuthMode, ir as saveAgentStateSync, j as supervisorAgentId, kr as checkCodexAuthStatus, kt as deliverAgentMessage, l as getRuntimeCensusSnapshot, mn as getClaudeAuthStatus, n as init_queries, p as runtimeCensusHasHarnessProcess, qt as init_staffing, r as listAgentStates, sn as injectPiConversationMemory, u as init_runtime_census, ur as init_agent_record_sync, vr as normalizeAgentId, wn as getOpenAIAuthStatus, xr as waitForReadySignal, yn as getProviderEnvForModel, yt as init_concurrency } from "./queries-6d7Cdtm7.js";
|
|
20
|
+
import { a as getCostForIssueAggregateSync, c as getDailyTrendsSync, d as init_cost_sync, l as getModelRollupSync, n as getBackgroundCostBySourceSync, p as queryCostEventsSync, r as getCavemanExperimentDataSync, s as getCostsByIssueSync, u as getTodayCostSync } from "./cost-sync-C0VdGme1.js";
|
|
21
|
+
import { c as getAgentsNeedingAttention, d as CostResolverLive, f as CostWriter, l as CostDoorLive, n as readCloisterStateFile, o as generateHealthSummary, s as getAgentHealth, t as getCloisterService, u as CostResolver } from "./service-DCpB_SGd.js";
|
|
22
|
+
import { u as init_agent_runtime_mirror } from "./session-history-CVZDpS3c.js";
|
|
23
|
+
import { t as init_behavior } from "./behavior-B_-4EKF3.js";
|
|
24
|
+
import { n as AgentStateServiceLive } from "./agent-state-service-HoK8U4jW.js";
|
|
25
|
+
import { a as init_tracker_config, i as initTrackerConfigCache, n as getLinearApiKey, r as getRallyConfig, t as getGitHubConfig } from "./tracker-config-B4itFzDo.js";
|
|
25
26
|
import { d as init_typed_errors, i as PlanEmpty, l as WorkspaceCreateError, n as AgentStartError, s as TrackerApiError, t as AgentAlreadyRunning, u as WorkspaceNotFound } from "./typed-errors-2BTMxkZq.js";
|
|
26
|
-
import { i as init_linear_client, r as LinearClientOptionalLive, t as LinearClient } from "./linear-client-
|
|
27
|
-
import { i as init_github_client, r as GitHubClientOptionalLive, t as GitHubClient } from "./github-client
|
|
28
|
-
import { i as init_rally_client, r as RallyClientOptionalLive, t as RallyClient } from "./rally-client-
|
|
29
|
-
import { a as resolveTrackerTypeSync, i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils-
|
|
30
|
-
import { a as CacheService, i as startSharedIssueService, n as init_issue_service_singleton, o as init_cache_service, r as issue_service_singleton_exports, s as parseIntegerHeader, t as getSharedIssueService } from "./issue-service-singleton-
|
|
31
|
-
import { i as ensureInternalTokenSync, s as init_internal_token } from "./internal-token-
|
|
32
|
-
import { a as setPipelineHandlerSync, t as init_pipeline_notifier } from "./pipeline-notifier-
|
|
33
|
-
import { c as init_review_status_sync, i as getMergeBlockerReconcileCandidates } from "./review-status-sync-
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import { C as
|
|
37
|
-
import { C as
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import { i as
|
|
42
|
-
import { i as
|
|
43
|
-
import {
|
|
44
|
-
import { a as
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
58
|
-
import {
|
|
59
|
-
import { n as
|
|
60
|
-
import {
|
|
61
|
-
import {
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
64
|
-
import {
|
|
65
|
-
import { l as
|
|
66
|
-
import {
|
|
67
|
-
import {
|
|
68
|
-
import {
|
|
69
|
-
import {
|
|
70
|
-
import {
|
|
71
|
-
import {
|
|
72
|
-
import {
|
|
73
|
-
import {
|
|
74
|
-
import {
|
|
75
|
-
import {
|
|
76
|
-
import { a as
|
|
77
|
-
import {
|
|
78
|
-
import { a as
|
|
79
|
-
import {
|
|
80
|
-
import { i as
|
|
81
|
-
import {
|
|
82
|
-
import {
|
|
83
|
-
import {
|
|
84
|
-
import {
|
|
85
|
-
import { t as
|
|
86
|
-
import {
|
|
87
|
-
import {
|
|
88
|
-
import {
|
|
89
|
-
import { n as
|
|
90
|
-
import {
|
|
91
|
-
import {
|
|
92
|
-
import {
|
|
93
|
-
import {
|
|
94
|
-
import {
|
|
95
|
-
import { n as
|
|
96
|
-
import {
|
|
97
|
-
import {
|
|
98
|
-
import { a as
|
|
99
|
-
import { a as
|
|
100
|
-
import {
|
|
101
|
-
import { t as
|
|
102
|
-
import {
|
|
103
|
-
import "./
|
|
104
|
-
import { i as
|
|
27
|
+
import { i as init_linear_client, r as LinearClientOptionalLive, t as LinearClient } from "./linear-client-D4zqMnX7.js";
|
|
28
|
+
import { i as init_github_client, r as GitHubClientOptionalLive, t as GitHubClient } from "./github-client--XVlDpwM.js";
|
|
29
|
+
import { i as init_rally_client, r as RallyClientOptionalLive, t as RallyClient } from "./rally-client-B1EJhfV0.js";
|
|
30
|
+
import { a as resolveTrackerTypeSync, i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils-tnxxqROg.js";
|
|
31
|
+
import { a as CacheService, i as startSharedIssueService, n as init_issue_service_singleton, o as init_cache_service, r as issue_service_singleton_exports, s as parseIntegerHeader, t as getSharedIssueService } from "./issue-service-singleton-B5ushCvE.js";
|
|
32
|
+
import { i as ensureInternalTokenSync, o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-Bb4XeV2x.js";
|
|
33
|
+
import { a as setPipelineHandlerSync, t as init_pipeline_notifier } from "./pipeline-notifier-D0ykk59O.js";
|
|
34
|
+
import { c as init_review_status_sync, i as getMergeBlockerReconcileCandidates } from "./review-status-sync-BhSQ0d0l.js";
|
|
35
|
+
import { n as init_review_status_source, t as classifyAdvancingSessionLifecycle } from "./review-status-source-CxuEjLGg.js";
|
|
36
|
+
import { a as PAN_DIRNAME, d as WORKSPACE_RUNTIME_DIRNAME, f as asPanSpecDocument, i as PAN_CONTINUE_FILENAME, p as init_types } from "./types-hraoaQIp.js";
|
|
37
|
+
import { C as transitionToMerging, _ as markFailed, c as isFlywheelGloballyPaused, d as listDuePendingAutoMerges, f as listProblemAutoMerges, g as markBlocked, n as getActionableAutoMerge, o as init_merge_sync, t as cancelPending, u as listActiveAutoMerges, v as markMerged, x as scheduleAutoMergeWithResult, y as requeueToPending } from "./merge-sync-DZ9dojJn.js";
|
|
38
|
+
import { C as init_specs, D as writeSpecDocument, O as writeSpecForIssue, a as findWorkspaceDraftPlan, m as readWorkspacePlanSync, o as init_io, p as readWorkspacePlan, r as findPlan, s as isPlanningComplete, u as readPlan, v as init_types$1, x as findSpecByIssue, y as subItemsOf } from "./io-B3_AHDfr.js";
|
|
39
|
+
import { C as restartCliproxy, S as readPidFile, T as stopCliproxy, b as isCliproxyInstalled, d as getCliproxyAuthDir, o as bridgeCodexAuthToCliproxy, v as init_cliproxy, w as startCliproxy, x as isCliproxyRunning, y as installCliproxy } from "./cliproxy-Bgb2XCqi.js";
|
|
40
|
+
import { $ as updateConversationForkFallbackReason, A as isAgentConversationName, B as removeFavorite, C as getConversationByTmuxSession, D as importLegacyConversation, F as markConversationEnded, H as setClearedToConvId, I as markConversationRunning, J as setForkRequest, M as listConversations, N as listFavoritedIds, O as incrementForkRetryCount, P as markConversationActive, S as getConversationByName, T as getStuckForks, U as setConversationClaudeSessionId, X as unarchiveConversation, Y as setImportedConversationLinks, Z as updateConversationCost, _ as canRefineTitle, b as getConversationByClaudeSessionId, et as updateConversationTitle, gt as getDiscoveredSessionBySessionId, h as archiveConversation, j as listArchivedConversationsWithEnrichment, k as init_conversations, q as setFavorite, tt as updateForkStatus, v as canReplaceTitle, w as getConversationLedgerCosts, x as getConversationById, y as createConversation, yt as init_discovered_sessions, z as recordConversationHandoff } from "./conversations-DbOs1e9Q.js";
|
|
41
|
+
import { n as isBackgroundFeatureEnabled, t as init_features } from "./features-Dhxz-wLc.js";
|
|
42
|
+
import { i as init_settings, r as getMemoryWorkerConcurrency, t as areMemoryObservationsEnabled } from "./settings-BZ5m1UCl.js";
|
|
43
|
+
import { i as updateMemoryHealth, n as extractWithProviderPolicy, r as init_health, t as init_providers$1 } from "./providers-DV7ec8l7.js";
|
|
44
|
+
import { i as normalizeModelOverrideSync, n as init_launcher_generator, r as init_model_validation, t as generateLauncherScriptSync } from "./launcher-generator-CHVm7bGT.js";
|
|
45
|
+
import { a as init_claude_permissions, r as getClaudePermissionFlagsStringSync } from "./claude-permissions-H_5wHQZQ.js";
|
|
46
|
+
import { a as globalContextFile$1, f as resolveProjectContextFile, h as workspaceContextFile, n as codexGlobalContextFile, o as init_layers, p as resolveWorkspaceContextFile, r as ensureProjectLayer } from "./layers-DzxSTGNA.js";
|
|
47
|
+
import { l as init_codex, s as findRolloutPath } from "./codex-TmSi-yTv.js";
|
|
48
|
+
import { n as init_harness_binary, r as prepareHarnessLaunch } from "./harness-binary-CVio2m-u.js";
|
|
49
|
+
import { f as init_config, m as loadConfigSync$1, s as getDashboardApiUrlSync } from "./config-CCvjQf27.js";
|
|
50
|
+
import { C as setMergeTrainEnabled, S as setFlywheelRequireUatBeforeMerge, b as setFlywheelAutoPickupBacklog, c as isCloisterSpawnsPausedSync, d as isFlywheelAutoPickupBacklog, f as isFlywheelGloballyPaused$1, g as setCloisterSpawnsPausedSync, h as setBootReconciliationDecision, m as isMergeTrainEnabled, o as getSetting, p as isFlywheelRequireUatBeforeMerge, r as getBootReconciliationState, s as init_control_settings, u as isDeaconGloballyPausedSync, v as setDeaconGloballyPausedSync, w as setSetting } from "./control-settings-aP1ANIlI.js";
|
|
51
|
+
import { l as init_dag, r as compileGlob } from "./dag-CdOjJVDT.js";
|
|
52
|
+
import { a as loadCloisterConfigSync, o as saveCloisterConfigSync, r as init_config$1, s as shouldAutoStart } from "./config-DjLOdbgT.js";
|
|
53
|
+
import { c as isStateMigrated, i as ensureStateWorktree, o as init_state_home, r as clearStateMigrationCache, s as inspectStateMigration } from "./state-home-CIGjwNfJ.js";
|
|
54
|
+
import { i as checkPrdGateSync, s as promoteWorkspacePrdDraft, t as init_pan_dir } from "./pan-dir-DeVUgwA7.js";
|
|
55
|
+
import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-D8iNBcux.js";
|
|
56
|
+
import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-CQ_fwUWF.js";
|
|
57
|
+
import { n as require_auth_errors, r as require_token_error, t as require_token_util } from "./token-util-CTmczIfW.js";
|
|
58
|
+
import { A as withConcurrencyLimit, D as createPromiseConcurrencyLimiter, E as verifyAppCanMerge, O as createSettledTtlPromiseCache, d as getPullRequestState, f as init_github_app, k as init_concurrency$1, l as getMergeBackendStatus, p as isGitHubAppConfigured } from "./github-app-CMBdIFBQ.js";
|
|
59
|
+
import { C as getWorkspacePathForIssue, E as stopAgentOutputService, S as resolveIssueHeadlineCost, T as startAgentOutputService, _ as getCostsForIssueSync, b as processPendingFeedbackDeliveries, d as resumeQueuedMerges, f as syncWalFromAllProjects, g as migrateAllSessionsSync, h as reclassifyUnknownCostEventsSync, l as internalEventsRouteLayer, m as reconcilePiTranscripts, p as reconcile$1, t as workspacesRouteLayer, u as eventsRouteLayer, v as rebuildCacheSync, w as retainAgentOutputInterest, x as getCachedRunningAgents, y as syncCacheSync } from "./workspaces-hWvy9eKs.js";
|
|
60
|
+
import { _ as init_codex_conversation_parser, a as contextUsageFromParseResult, c as parseEntireConversation, d as init_pi_conversation_parser, f as isPiSessionFile, g as parseOhmypiConversationMessages, h as isOhmypiSessionFile, i as computeContextUsage, l as parseFromLastCompactBoundary, m as init_ohmypi_conversation_parser, n as gateSnapshotEmission, o as summarizeConversationActivity, p as parsePiConversationMessages, r as watchConversation, s as parseConversationMessages, t as init_conversation_service, v as parseCodexConversationMessages } from "./conversation-service-Du-MTNpJ.js";
|
|
61
|
+
import { c as countPendingAskUserQuestionsForAgent, h as detectAwaitingInputFromPaneSync, l as getAgentJsonlMtime, m as detectAwaitingInputForAgent, o as getRuntimeForAgent, p as scanPendingInputsPromise, s as computeAgentEnrichment } from "./stuck-remediation-CzEov_fq.js";
|
|
62
|
+
import { i as CostThresholdError, l as embed, s as parseRelativeTime } from "./scanner-D2743cp8.js";
|
|
63
|
+
import { c as tailEventsSync, n as deduplicateEventsSync, o as readEventsSync } from "./events-CC1dgUpx.js";
|
|
64
|
+
import { n as recordBackgroundAiCost, t as init_cost } from "./cost-CW4WSe72.js";
|
|
65
|
+
import { a as getByIssueId, i as parseFlywheelStatsWindow, n as derivePipelineRunStatsInputs, o as markFixed, r as computeFlywheelStats, s as upsert } from "./substrate-bug-weights-service-BH66lhm7.js";
|
|
66
|
+
import { c as startUatTrainReconciler, d as openFlywheelRunReportForDashboard, f as pauseFlywheelRunForDashboard, g as runDashboardDbJob, h as startFlywheelRunForDashboard, l as stopUatTrainReconciler, m as resumeFlywheelRunForDashboard, p as readCurrentFlywheelStatusForDashboard, u as abortFlywheelRunForDashboard } from "./uat-train-CuEn0t9M.js";
|
|
67
|
+
import { C as writeLatestFlywheelStatus, b as resolveLiveFlywheelRunId, g as listFlywheelRuns, h as isFlywheelRunId, p as getFlywheelRunDetail, u as buildClassifyLookups, v as readCurrentLatestFlywheelStatus, x as subscribeLatestFlywheelStatus } from "./flywheel-DSSpWmqF.js";
|
|
68
|
+
import { At as getContainerHistory, Ct as paneShowsClaudeBootBlockingScreen, F as setAgentStatusChangedNotifier, Ft as getSystemHealthEvidenceSnapshot, I as setAgentStoppedNotifier, J as startBootReconciliation, K as isBootReconciliationCandidate, L as setMergeReadyNotifier, Lt as isSmeeConfiguredSync, Mt as getAcceptedSystemHealthSnapshot, Nt as getDeployStaleness, O as loadConfig, Ot as getResourceStacks, Rt as startSmeeProcessSync, jt as getCurrentDockerStats, k as loadState, kt as formatUptime, n as assessDeaconPatrolFreshness, q as listBootReconciliationCandidates, t as applyBootReconciliationDecision, x as getDeaconLogs, zt as classifyAgentHealth } from "./deacon-pRnyD5w9.js";
|
|
69
|
+
import { l as detectPlatform, u as init_platform } from "./workspace-manager-hLUv3ADC.js";
|
|
70
|
+
import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-C9b6ccN1.js";
|
|
71
|
+
import { r as init_in_flight_guard, t as createInFlightGuard } from "./in-flight-guard-aQ1IxeI3.js";
|
|
72
|
+
import { V as getReviewerSessionName, t as init_specialists } from "./specialists-DyFeedjn.js";
|
|
73
|
+
import { c as findPrdAnywhereSync, l as init_prd_locations } from "./archive-planning-DYrYojxl.js";
|
|
74
|
+
import { a as getShadowState, s as init_shadow_state } from "./shadow-state-Dh-HzF2J.js";
|
|
75
|
+
import { n as init_issue_closed, t as clearIssueClosedCache } from "./issue-closed-zhdvQicO.js";
|
|
76
|
+
import { b as resolveSwarmPolicy } from "./deacon-swarm-DftYRDo8.js";
|
|
77
|
+
import { a as init_boot_gates, i as formatBootGateState, o as resolveBootGates } from "./no-resume-mode-Cx3K0hHi.js";
|
|
78
|
+
import { _ as selectNeedsPlanning, c as classifyIssue, d as computeLanes, f as computeStats, g as normalizeGate, l as computeCohort, m as init_pickup, p as computeWaves, u as computeEpicGroups } from "./pickup-Dd0Znxxy.js";
|
|
79
|
+
import { a as applyIssueObjectionLabel, c as applyIssueReleasedLabel, d as removeIssueBlocksMainLabel, f as removeIssueObjectionLabel, g as removeIssueVetoedLabel, h as removeIssueReleasedLabel, i as applyIssueBlocksMainLabel, l as applyIssueVetoedLabel, m as removeIssueReadyLabel, o as applyIssueParkedLabel, p as removeIssueParkedLabel, s as applyIssueReadyLabel, u as init_label_ops } from "./label-reconciler-DdWbHEBu.js";
|
|
80
|
+
import { n as parseSequenceMd, r as writeSequenceMd, t as init_sequence_io } from "./sequence-io-Cg0zYj_E.js";
|
|
81
|
+
import { c as init_resource_utils, i as gatherProjectLensSignals, l as parseIssueIdFromTextSync, n as init_pipeline_membership, o as init_pipeline_membership_gather, r as resolvePipelineMembership, s as listOpenPullRequestsSnapshot } from "./pipeline-membership-0HaEGDlH.js";
|
|
82
|
+
import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-CskwzzhL.js";
|
|
83
|
+
import { i as resolveAutoSpawnOnFinalize, o as spawnPlanningSession } from "./spawn-planning-session-DWAorh2B.js";
|
|
84
|
+
import { d as killRemoteAgent, m as loadRemoteAgentState, o as getRemoteAgentOutput, r as checkRemoteSpendCap, s as init_remote_agents, v as sendToRemoteAgent, y as spawnRemoteAgent } from "./remote-agents-nmty1mLu.js";
|
|
85
|
+
import { r as spawnInspectAgent } from "./inspect-agent-DJKLWcVT.js";
|
|
86
|
+
import { n as init_github_pr_lookup, r as lookupPullRequestNumberForBranch, t as githubPrLookupSource } from "./github-pr-lookup-BRbDW-qk.js";
|
|
87
|
+
import { a as fetchIssuePullRequestDiff, c as getCachedIssuePrTabResponse, d as setCachedIssuePrTabResponse, i as fetchIssuePullRequestDetails, l as getIssuePrTabCacheGeneration, n as fetchIssueCheckRuns, o as init_pull_requests, r as fetchIssuePullRequest, s as bumpIssuePrTabCacheGeneration, u as init_pr_tab_cache } from "./pull-requests-CXIhdCYD.js";
|
|
88
|
+
import { t as DOD_ROWS } from "./dod-BrSfUHm0.js";
|
|
89
|
+
import { t as enrichReviewStatus } from "./review-status-enrichment-tbOn_A_u.js";
|
|
90
|
+
import { i as runMemoryFtsTransaction, n as init_fts_db, r as runMemoryFtsStatement, t as closeMemoryFtsDatabases } from "./fts-db-CKgg0VKg.js";
|
|
91
|
+
import { c as init_pending, l as maybeTriggerStatusRollup, o as readRecentObservations, r as init_rollup, u as writePendingTurn } from "./rollup-WA0VD-Rr.js";
|
|
92
|
+
import { n as getTldrDaemonServiceSync, r as init_tldr_daemon } from "./tldr-daemon-BDtLOIlO.js";
|
|
93
|
+
import { T as listGitOperationsSync, w as init_git_activity } from "./merge-agent-XrB80vfT.js";
|
|
94
|
+
import { t as readVerificationArtifact } from "./verification-artifact-BcnIbigL.js";
|
|
95
|
+
import { t as getAgentCommandSync } from "./settings-ylxwqwQG.js";
|
|
96
|
+
import { n as init_review_agent, r as isExtendedReviewEnabled } from "./review-agent-sKkE1FEL.js";
|
|
97
|
+
import { r as isRemoteAvailable, t as createFlyProviderFromConfig } from "./remote-Br-ZWVIP.js";
|
|
98
|
+
import { n as init_claude_settings_overlay, t as detectProviderEnvConflicts } from "./claude-settings-overlay-CbSz0Dvb.js";
|
|
99
|
+
import { a as init_query_expansion, i as clearQueryExpansionCache, n as init_injection, o as buildMatchQuery, r as injectPromptTimeMemory, s as init_search } from "./injection-DZ0PfYa4.js";
|
|
100
|
+
import { _ as init_transcript_adapter, a as generateFallbackSummary, c as handoffPreconditionFallbackReason, d as prependFallbackFocus, f as requestHandoffFromAgent, g as getTranscriptAdapter, i as copySessionFromCompactBoundary, l as init_summary_fork, o as generateSummaryForFork, p as reserveSummaryForkSession, r as authorHandoffExternal, s as handoffFailureReason, u as logHandoffFallback } from "./summary-fork-DHhJIsAL.js";
|
|
101
|
+
import { a as init_conversation_compaction, c as shouldInterceptManualCompact, n as compactConversationNative, o as isCompacting } from "./conversation-compaction-CNbTLB86.js";
|
|
102
|
+
import { a as init_render, d as validateTemplate, i as hasManagedRegion, l as init_harness, o as userContentOutsideRegion, t as init_context_layers, u as renderForHarness } from "./context-layers-ZYFcWiyc.js";
|
|
103
|
+
import { r as parseArtifactRef } from "./forge-Ch9gCFod.js";
|
|
104
|
+
import { t as getMergeBlockersPayload } from "./merge-blockers-BsFjGrQ8.js";
|
|
105
|
+
import { a as spawnSequencerAgent, i as init_sequencer_agent, n as clearFinishedSequencerRun, r as getSequencerRunStatus, t as SEQUENCER_AGENT_ID } from "./sequencer-agent-BGY8gjg-.js";
|
|
106
|
+
import "./supervisor-BO-Zk_h-.js";
|
|
107
|
+
import { i as listTranscriptCheckpoints, r as getTranscriptCheckpoint$1 } from "./checkpoints-C-AXLfYT.js";
|
|
105
108
|
import { createRequire } from "node:module";
|
|
106
109
|
import * as sp from "node:path";
|
|
107
110
|
import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
@@ -109,7 +112,7 @@ import { Cause, Context, Data, Duration, Effect, Exit, Fiber, FileSystem, Layer,
|
|
|
109
112
|
import { createReadStream, createWriteStream, existsSync, fstatSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
110
113
|
import { basename as basename$1, dirname as dirname$1, join as join$1, resolve as resolve$1 } from "path";
|
|
111
114
|
import { homedir } from "os";
|
|
112
|
-
import {
|
|
115
|
+
import { homedir as homedir$1, type } from "node:os";
|
|
113
116
|
import { constants, createReadStream as createReadStream$1, existsSync as existsSync$1, mkdirSync as mkdirSync$1, promises as promises$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, readlinkSync, renameSync as renameSync$1, rmSync as rmSync$1, stat, statSync as statSync$1, symlinkSync as symlinkSync$1, unwatchFile, watch, watchFile } from "node:fs";
|
|
114
117
|
import { FetchHttpClient, HttpRouter, HttpServer, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
|
|
115
118
|
import { EventEmitter } from "node:events";
|
|
@@ -355,6 +358,24 @@ const ServerConfigLayer = Layer.effect(ServerConfig, Effect.sync(() => {
|
|
|
355
358
|
};
|
|
356
359
|
}));
|
|
357
360
|
//#endregion
|
|
361
|
+
//#region dashboard-listening.ts
|
|
362
|
+
let resolveListening;
|
|
363
|
+
let listening = false;
|
|
364
|
+
let listeningPromise = createListeningPromise();
|
|
365
|
+
function createListeningPromise() {
|
|
366
|
+
return new Promise((resolve) => {
|
|
367
|
+
resolveListening = resolve;
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function markDashboardListening() {
|
|
371
|
+
if (listening) return;
|
|
372
|
+
listening = true;
|
|
373
|
+
resolveListening();
|
|
374
|
+
}
|
|
375
|
+
function whenDashboardListening() {
|
|
376
|
+
return listeningPromise;
|
|
377
|
+
}
|
|
378
|
+
//#endregion
|
|
358
379
|
//#region services/terminal-service.ts
|
|
359
380
|
init_activity_logger();
|
|
360
381
|
init_paths$1();
|
|
@@ -688,7 +709,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
688
709
|
if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
|
|
689
710
|
const plan = readWorkspacePlanSync(workspacePath);
|
|
690
711
|
if (!plan || plan.plan.items.length === 0) throw new PlanEmpty({ id: issueId });
|
|
691
|
-
const { getAgentState, spawnAgent, normalizeAgentId } = await import("./agents-
|
|
712
|
+
const { getAgentState, spawnAgent, normalizeAgentId } = await import("./agents-FlIgQ3ql.js");
|
|
692
713
|
const normalizedId = normalizeAgentId(issueId);
|
|
693
714
|
if ((await Effect.runPromise(getAgentState(normalizedId)))?.status === "running") throw new AgentAlreadyRunning({ id: issueId });
|
|
694
715
|
return {
|
|
@@ -719,7 +740,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
719
740
|
const { workspacePath, projectPath, issue } = opts;
|
|
720
741
|
if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
|
|
721
742
|
const sessionName = opts.sessionName ?? `planning-${issueId.toLowerCase()}`;
|
|
722
|
-
const { spawnPlanningSession } = await import("./spawn-planning-session-
|
|
743
|
+
const { spawnPlanningSession } = await import("./spawn-planning-session-KC_UduxD.js");
|
|
723
744
|
const result = await spawnPlanningSession({
|
|
724
745
|
issue: {
|
|
725
746
|
id: issue.id,
|
|
@@ -752,14 +773,14 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
752
773
|
}),
|
|
753
774
|
kill: (agentId) => Effect.tryPromise({
|
|
754
775
|
try: async () => {
|
|
755
|
-
const { stopAgent } = await import("./agents-
|
|
776
|
+
const { stopAgent } = await import("./agents-FlIgQ3ql.js");
|
|
756
777
|
await Effect.runPromise(stopAgent(agentId));
|
|
757
778
|
},
|
|
758
779
|
catch: () => void 0
|
|
759
780
|
}).pipe(Effect.ignore),
|
|
760
781
|
message: (agentId, msg) => Effect.tryPromise({
|
|
761
782
|
try: async () => {
|
|
762
|
-
const { messageAgent } = await import("./agents-
|
|
783
|
+
const { messageAgent } = await import("./agents-FlIgQ3ql.js");
|
|
763
784
|
await messageAgent(agentId, msg);
|
|
764
785
|
},
|
|
765
786
|
catch: (err) => new AgentStartError({
|
|
@@ -770,8 +791,8 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
770
791
|
}),
|
|
771
792
|
deepWipe: (issueId, opts) => Effect.tryPromise({
|
|
772
793
|
try: async () => {
|
|
773
|
-
const { deepWipe } = await import("./workflows-
|
|
774
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
794
|
+
const { deepWipe } = await import("./workflows-D90rMOya.js");
|
|
795
|
+
const { resolveProjectFromIssueSync } = await import("./projects-9SkRpES9.js");
|
|
775
796
|
const project = resolveProjectFromIssueSync(issueId);
|
|
776
797
|
const projectPath = project?.projectPath ?? process.cwd();
|
|
777
798
|
await Effect.runPromise(deepWipe({
|
|
@@ -830,8 +851,8 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
830
851
|
const { workspacePath, branch } = getWorkspacePath(issueId);
|
|
831
852
|
const issueLower = issueId.toLowerCase();
|
|
832
853
|
if (existsSync$1(workspacePath)) return workspacePath;
|
|
833
|
-
const { createWorkspace } = await import("./workspace-manager-
|
|
834
|
-
const { loadProjectsConfigSync } = await import("./projects-
|
|
854
|
+
const { createWorkspace } = await import("./workspace-manager-ZTdJAy9M.js");
|
|
855
|
+
const { loadProjectsConfigSync } = await import("./projects-9SkRpES9.js");
|
|
835
856
|
const { projects } = loadProjectsConfigSync();
|
|
836
857
|
const project = resolveProjectFromIssueSync(issueId);
|
|
837
858
|
if (!project) throw new WorkspaceCreateError({
|
|
@@ -866,7 +887,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
866
887
|
const { workspacePath } = getWorkspacePath(issueId);
|
|
867
888
|
const issueLower = issueId.toLowerCase();
|
|
868
889
|
if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
|
|
869
|
-
const { removeWorkspace } = await import("./workspace-manager-
|
|
890
|
+
const { removeWorkspace } = await import("./workspace-manager-ZTdJAy9M.js");
|
|
870
891
|
const project = resolveProjectFromIssueSync(issueId);
|
|
871
892
|
if (!project) throw new WorkspaceCreateError({
|
|
872
893
|
id: issueId,
|
|
@@ -897,7 +918,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
897
918
|
try: async () => {
|
|
898
919
|
const { workspacePath } = getWorkspacePath(issueId);
|
|
899
920
|
const issueLower = issueId.toLowerCase();
|
|
900
|
-
const { stopWorkspaceDocker } = await import("./workspace-manager-
|
|
921
|
+
const { stopWorkspaceDocker } = await import("./workspace-manager-ZTdJAy9M.js");
|
|
901
922
|
await Effect.runPromise(stopWorkspaceDocker(workspacePath, issueLower));
|
|
902
923
|
},
|
|
903
924
|
catch: () => void 0
|
|
@@ -966,7 +987,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
966
987
|
join(workspacePath, ".devcontainer", "docker-compose.devcontainer.yml")
|
|
967
988
|
];
|
|
968
989
|
if (!composePaths.find((p) => existsSync$1(p))) {
|
|
969
|
-
const { ensureDevcontainerSync } = await import("./ensure-devcontainer-
|
|
990
|
+
const { ensureDevcontainerSync } = await import("./ensure-devcontainer-DRqaAkBR.js");
|
|
970
991
|
const ensure = ensureDevcontainerSync({
|
|
971
992
|
workspacePath,
|
|
972
993
|
issueId
|
|
@@ -5451,6 +5472,7 @@ function setupTerminalWebSocket(server) {
|
|
|
5451
5472
|
//#endregion
|
|
5452
5473
|
//#region ../../../node_modules/.bun/@ai-sdk+provider@3.0.10/node_modules/@ai-sdk/provider/dist/index.mjs
|
|
5453
5474
|
init_briefing_freshness();
|
|
5475
|
+
init_agent_runtime_mirror();
|
|
5454
5476
|
init_behavior();
|
|
5455
5477
|
init_discovered_sessions();
|
|
5456
5478
|
init_conversations();
|
|
@@ -5460,11 +5482,13 @@ init_openai_auth();
|
|
|
5460
5482
|
init_claude_permissions();
|
|
5461
5483
|
init_claude_auth();
|
|
5462
5484
|
init_layers();
|
|
5485
|
+
init_harness_binary();
|
|
5463
5486
|
init_codex();
|
|
5464
5487
|
init_launcher_generator();
|
|
5465
5488
|
init_transcript_landing();
|
|
5466
5489
|
init_operator_interventions();
|
|
5467
5490
|
init_agents$1();
|
|
5491
|
+
init_runtime_census();
|
|
5468
5492
|
var marker$2 = "vercel.ai.error";
|
|
5469
5493
|
var symbol$3 = Symbol.for(marker$2);
|
|
5470
5494
|
var _a$5, _b$2;
|
|
@@ -15944,7 +15968,7 @@ var require_get_vercel_oidc_token = /* @__PURE__ */ __commonJSMin(((exports, mod
|
|
|
15944
15968
|
err = error;
|
|
15945
15969
|
}
|
|
15946
15970
|
try {
|
|
15947
|
-
const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await import("./token-util-
|
|
15971
|
+
const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await import("./token-util-DrHg8abn.js").then((m) => /* @__PURE__ */ __toESM(m.default)), await import("./token-CsOhvw42.js").then((m) => /* @__PURE__ */ __toESM(m.default))]);
|
|
15948
15972
|
if (!token || isExpired(getTokenPayload(token), options?.expirationBufferMs)) {
|
|
15949
15973
|
await refreshToken(options);
|
|
15950
15974
|
token = getVercelOidcTokenSync();
|
|
@@ -27778,7 +27802,7 @@ function randomId() {
|
|
|
27778
27802
|
function randomNonce() {
|
|
27779
27803
|
return Math.floor(Math.random() * 2147483647);
|
|
27780
27804
|
}
|
|
27781
|
-
function finiteNumber(value, fallback) {
|
|
27805
|
+
function finiteNumber$1(value, fallback) {
|
|
27782
27806
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
27783
27807
|
}
|
|
27784
27808
|
function normalizeExcalidrawElement(element) {
|
|
@@ -27786,12 +27810,12 @@ function normalizeExcalidrawElement(element) {
|
|
|
27786
27810
|
...element,
|
|
27787
27811
|
id: typeof element.id === "string" && element.id ? element.id : randomId(),
|
|
27788
27812
|
type: typeof element.type === "string" && element.type ? element.type : "rectangle",
|
|
27789
|
-
x: finiteNumber(element.x, 0),
|
|
27790
|
-
y: finiteNumber(element.y, 0),
|
|
27791
|
-
width: Math.max(1, finiteNumber(element.width, 100)),
|
|
27792
|
-
height: Math.max(1, finiteNumber(element.height, 100)),
|
|
27793
|
-
version: Math.max(1, Math.trunc(finiteNumber(element.version, 1))),
|
|
27794
|
-
versionNonce: Math.trunc(finiteNumber(element.versionNonce, randomNonce())),
|
|
27813
|
+
x: finiteNumber$1(element.x, 0),
|
|
27814
|
+
y: finiteNumber$1(element.y, 0),
|
|
27815
|
+
width: Math.max(1, finiteNumber$1(element.width, 100)),
|
|
27816
|
+
height: Math.max(1, finiteNumber$1(element.height, 100)),
|
|
27817
|
+
version: Math.max(1, Math.trunc(finiteNumber$1(element.version, 1))),
|
|
27818
|
+
versionNonce: Math.trunc(finiteNumber$1(element.versionNonce, randomNonce())),
|
|
27795
27819
|
isDeleted: element.isDeleted === true
|
|
27796
27820
|
};
|
|
27797
27821
|
if (Math.abs(normalized.x) > VISIBLE_CANVAS_LIMIT || Math.abs(normalized.y) > VISIBLE_CANVAS_LIMIT) console.warn(`Excalidraw element ${normalized.id} has coordinates outside visible canvas range`);
|
|
@@ -28261,7 +28285,7 @@ var GoogleCloudTranscription = class {
|
|
|
28261
28285
|
}
|
|
28262
28286
|
async start(apiKey, model) {
|
|
28263
28287
|
try {
|
|
28264
|
-
const { SpeechClient } = await import("./src-
|
|
28288
|
+
const { SpeechClient } = await import("./src-CG9mCkP6.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1)).then((module) => module.v1p1beta1 ?? module.v1);
|
|
28265
28289
|
if (this.closed) return;
|
|
28266
28290
|
const stream = new SpeechClient({ apiKey }).streamingRecognize({
|
|
28267
28291
|
config: {
|
|
@@ -28926,6 +28950,21 @@ function setupAutoPresoWebSocket(server) {
|
|
|
28926
28950
|
});
|
|
28927
28951
|
}
|
|
28928
28952
|
//#endregion
|
|
28953
|
+
//#region services/agent-output-stream.ts
|
|
28954
|
+
function shouldBroadcastDashboardEvent(event) {
|
|
28955
|
+
return event.type !== "agent.output_received";
|
|
28956
|
+
}
|
|
28957
|
+
/** Dedicated, scoped stream for one agent's ephemeral output. */
|
|
28958
|
+
function streamAgentOutput(eventStore, agentId) {
|
|
28959
|
+
return Stream.unwrap(Effect.acquireRelease(Effect.sync(() => retainAgentOutputInterest(agentId)), (release) => Effect.sync(release)).pipe(Effect.map(() => eventStore.streamEvents.pipe(Stream.filter((event) => event.type === "agent.output_received" && event.payload["agentId"] === agentId), Stream.flatMap((event) => {
|
|
28960
|
+
const payload = event.payload;
|
|
28961
|
+
return Stream.fromIterable(payload.lines.map((line) => ({
|
|
28962
|
+
agentId: payload.agentId,
|
|
28963
|
+
line
|
|
28964
|
+
})));
|
|
28965
|
+
})))));
|
|
28966
|
+
}
|
|
28967
|
+
//#endregion
|
|
28929
28968
|
//#region services/read-workspace-file.ts
|
|
28930
28969
|
init_codex_conversation_parser();
|
|
28931
28970
|
init_ohmypi_conversation_parser();
|
|
@@ -28972,7 +29011,7 @@ const LANGUAGE_BY_EXTENSION = {
|
|
|
28972
29011
|
function isInsidePath(parent, child) {
|
|
28973
29012
|
return child === parent || child.startsWith(`${parent}${sep}`);
|
|
28974
29013
|
}
|
|
28975
|
-
function splitLines
|
|
29014
|
+
function splitLines(text) {
|
|
28976
29015
|
if (text.length === 0) return [];
|
|
28977
29016
|
const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
28978
29017
|
return normalized.endsWith("\n") ? normalized.slice(0, -1).split("\n") : normalized.split("\n");
|
|
@@ -28986,7 +29025,7 @@ function validateIntegerAtLeast(value, name, min) {
|
|
|
28986
29025
|
return value;
|
|
28987
29026
|
}
|
|
28988
29027
|
function selectRequestedLines(text, line, contextLines) {
|
|
28989
|
-
const lines = splitLines
|
|
29028
|
+
const lines = splitLines(text);
|
|
28990
29029
|
const totalLines = lines.length;
|
|
28991
29030
|
if (!line) return {
|
|
28992
29031
|
text: contextLines === void 0 ? text : lines.slice(0, contextLines).join("\n"),
|
|
@@ -29273,7 +29312,6 @@ function normalizeSessionsFeedFilter(input) {
|
|
|
29273
29312
|
*/
|
|
29274
29313
|
init_src();
|
|
29275
29314
|
init_paths();
|
|
29276
|
-
init_tmux();
|
|
29277
29315
|
init_projects();
|
|
29278
29316
|
function storedToDomainEvent(stored) {
|
|
29279
29317
|
return {
|
|
@@ -29286,7 +29324,8 @@ function storedToDomainEvent(stored) {
|
|
|
29286
29324
|
const isKnownDomainEvent = Schema.is(DomainEvent);
|
|
29287
29325
|
function passesDomainEventSchema(event) {
|
|
29288
29326
|
if (isKnownDomainEvent(event)) return true;
|
|
29289
|
-
|
|
29327
|
+
const candidate = event;
|
|
29328
|
+
console.error(`[ws-rpc] dropping domain event that fails DomainEvent schema validation — add it to the contracts union: type=${String(candidate.type)} seq=${String(candidate.sequence)}`);
|
|
29290
29329
|
return false;
|
|
29291
29330
|
}
|
|
29292
29331
|
function createSystemHeartbeatEvent() {
|
|
@@ -29657,8 +29696,9 @@ function startSharedPresencePoller() {
|
|
|
29657
29696
|
if (sharedPresencePoller.interval) return;
|
|
29658
29697
|
const tick = async () => {
|
|
29659
29698
|
try {
|
|
29660
|
-
const
|
|
29661
|
-
|
|
29699
|
+
const census = await getRuntimeCensus();
|
|
29700
|
+
if (!census.available) return;
|
|
29701
|
+
const current = new Set(census.sessionNames);
|
|
29662
29702
|
for (const s of sharedPresencePoller.knownSessions) if (!current.has(s)) {
|
|
29663
29703
|
const issueId = extractIssueIdFromSession(s);
|
|
29664
29704
|
if (issueId) {
|
|
@@ -29722,7 +29762,7 @@ const PanRpcLayer = PanRpcGroup.toLayer(Effect.gen(function* () {
|
|
|
29722
29762
|
[WS_METHODS.subscribeDomainEvents]: (_input) => {
|
|
29723
29763
|
console.log("[ws-rpc] subscribeDomainEvents invoked");
|
|
29724
29764
|
const heartbeats = Stream.tick("15 seconds").pipe(Stream.map(createSystemHeartbeatEvent));
|
|
29725
|
-
return eventStore.streamEvents.pipe(Stream.map(storedToDomainEvent), Stream.filter(passesDomainEventSchema), Stream.merge(heartbeats));
|
|
29765
|
+
return eventStore.streamEvents.pipe(Stream.filter(shouldBroadcastDashboardEvent), Stream.map(storedToDomainEvent), Stream.filter(passesDomainEventSchema), Stream.merge(heartbeats));
|
|
29726
29766
|
},
|
|
29727
29767
|
[WS_METHODS.subscribeFlywheelStatus]: (_input) => Stream.callback((queue) => Effect.acquireRelease(Effect.promise(async () => {
|
|
29728
29768
|
const latest = await readCurrentLatestFlywheelStatus({ activeRunId: await runDashboardDbJob("getSetting", "flywheel.active_run_id") });
|
|
@@ -29733,16 +29773,10 @@ const PanRpcLayer = PanRpcGroup.toLayer(Effect.gen(function* () {
|
|
|
29733
29773
|
}), (unsubscribe) => Effect.sync(() => unsubscribe()))),
|
|
29734
29774
|
[WS_METHODS.subscribeIssueEvents]: (input) => {
|
|
29735
29775
|
console.log(`[ws-rpc] subscribeIssueEvents invoked issueId=${input.issueId}`);
|
|
29736
|
-
return eventStore.streamEvents.pipe(Stream.map(storedToDomainEvent), Stream.filter(passesDomainEventSchema), Stream.mapEffect((event) => getCachedAgentIssueLookup(readModel).pipe(Effect.map((lookup) => filterDomainEventForIssue(event, input.issueId, lookup)))), Stream.filter((event) => event !== null));
|
|
29776
|
+
return eventStore.streamEvents.pipe(Stream.filter(shouldBroadcastDashboardEvent), Stream.map(storedToDomainEvent), Stream.filter(passesDomainEventSchema), Stream.mapEffect((event) => getCachedAgentIssueLookup(readModel).pipe(Effect.map((lookup) => filterDomainEventForIssue(event, input.issueId, lookup)))), Stream.filter((event) => event !== null));
|
|
29737
29777
|
},
|
|
29738
29778
|
[WS_METHODS.subscribeTerminal]: (input) => terminalService.streamSession(input.sessionName, input.cols, input.rows),
|
|
29739
|
-
[WS_METHODS.subscribeAgentOutput]: (input) => eventStore
|
|
29740
|
-
const payload = e.payload;
|
|
29741
|
-
return Stream.fromIterable(payload.lines.map((line) => ({
|
|
29742
|
-
agentId: payload.agentId,
|
|
29743
|
-
line
|
|
29744
|
-
})));
|
|
29745
|
-
})),
|
|
29779
|
+
[WS_METHODS.subscribeAgentOutput]: (input) => streamAgentOutput(eventStore, input.agentId),
|
|
29746
29780
|
[WS_METHODS.getSnapshot]: (_input) => Effect.gen(function* () {
|
|
29747
29781
|
const t0 = Date.now();
|
|
29748
29782
|
console.log("[ws-rpc] getSnapshot invoked");
|
|
@@ -30039,7 +30073,11 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
30039
30073
|
}));
|
|
30040
30074
|
}));
|
|
30041
30075
|
//#endregion
|
|
30042
|
-
//#region ../../lib/
|
|
30076
|
+
//#region ../../lib/xbrief/quality-lint.ts
|
|
30077
|
+
init_internal_token();
|
|
30078
|
+
init_pipeline_notifier();
|
|
30079
|
+
init_review_status_sync();
|
|
30080
|
+
init_review_status();
|
|
30043
30081
|
init_state_home();
|
|
30044
30082
|
init_pan_dir();
|
|
30045
30083
|
init_in_flight_guard();
|
|
@@ -30048,7 +30086,7 @@ init_dag();
|
|
|
30048
30086
|
init_swarm_readiness();
|
|
30049
30087
|
var PlanQualityLintError = class extends Error {
|
|
30050
30088
|
constructor(issues) {
|
|
30051
|
-
super(`
|
|
30089
|
+
super(`xBRIEF quality lint failed with ${issues.length} issue${issues.length === 1 ? "" : "s"}`);
|
|
30052
30090
|
this.issues = issues;
|
|
30053
30091
|
this.name = "PlanQualityLintError";
|
|
30054
30092
|
}
|
|
@@ -30411,28 +30449,80 @@ function assertPlanQuality(doc, options = {}) {
|
|
|
30411
30449
|
return issues;
|
|
30412
30450
|
}
|
|
30413
30451
|
//#endregion
|
|
30452
|
+
//#region services/resource-discovery-shared.ts
|
|
30453
|
+
init_conversations();
|
|
30454
|
+
init_runtime_census();
|
|
30455
|
+
const execFileAsync$18 = promisify(execFile);
|
|
30456
|
+
async function loadTrackerIssues() {
|
|
30457
|
+
const map = /* @__PURE__ */ new Map();
|
|
30458
|
+
try {
|
|
30459
|
+
const { getSharedIssueService } = await import("./issue-service-singleton-DabvBWUp.js");
|
|
30460
|
+
const issues = (await getSharedIssueService()).getIssues();
|
|
30461
|
+
for (const issue of issues) if (issue.identifier) map.set(issue.identifier.toUpperCase(), issue);
|
|
30462
|
+
} catch {}
|
|
30463
|
+
return map;
|
|
30464
|
+
}
|
|
30465
|
+
async function loadDockerContainers() {
|
|
30466
|
+
try {
|
|
30467
|
+
const { stdout } = await execFileAsync$18("docker", [
|
|
30468
|
+
"ps",
|
|
30469
|
+
"--format",
|
|
30470
|
+
"{{.Names}}"
|
|
30471
|
+
], {
|
|
30472
|
+
encoding: "utf-8",
|
|
30473
|
+
timeout: 5e3
|
|
30474
|
+
});
|
|
30475
|
+
return stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
30476
|
+
} catch {
|
|
30477
|
+
return [];
|
|
30478
|
+
}
|
|
30479
|
+
}
|
|
30480
|
+
async function loadActiveRemoteAgentStates() {
|
|
30481
|
+
try {
|
|
30482
|
+
const { listActiveRemoteAgentStates } = await import("./remote-agents-CRCg1L4H.js");
|
|
30483
|
+
return listActiveRemoteAgentStates();
|
|
30484
|
+
} catch {
|
|
30485
|
+
return [];
|
|
30486
|
+
}
|
|
30487
|
+
}
|
|
30488
|
+
async function captureSharedResourceSignals() {
|
|
30489
|
+
const [trackerIssues, runtimeCensus, dockerContainers, remoteAgentStates] = await Promise.all([
|
|
30490
|
+
loadTrackerIssues(),
|
|
30491
|
+
getRuntimeCensus(),
|
|
30492
|
+
loadDockerContainers(),
|
|
30493
|
+
loadActiveRemoteAgentStates()
|
|
30494
|
+
]);
|
|
30495
|
+
const tmuxSessions = [...runtimeCensus.sessionNames];
|
|
30496
|
+
let conversations = [];
|
|
30497
|
+
try {
|
|
30498
|
+
conversations = listConversations();
|
|
30499
|
+
} catch {}
|
|
30500
|
+
return {
|
|
30501
|
+
trackerIssues,
|
|
30502
|
+
tmuxSessions,
|
|
30503
|
+
dockerContainers,
|
|
30504
|
+
conversations,
|
|
30505
|
+
remoteAgentStates
|
|
30506
|
+
};
|
|
30507
|
+
}
|
|
30508
|
+
//#endregion
|
|
30414
30509
|
//#region review-status.ts
|
|
30415
30510
|
init_concurrency$1();
|
|
30416
30511
|
init_github_app();
|
|
30417
30512
|
init_resource_utils();
|
|
30418
30513
|
init_pipeline_membership_gather();
|
|
30419
|
-
|
|
30514
|
+
init_pipeline_membership();
|
|
30420
30515
|
//#endregion
|
|
30421
30516
|
//#region services/pipeline-membership.ts
|
|
30422
|
-
init_internal_token();
|
|
30423
|
-
init_pipeline_notifier();
|
|
30424
|
-
init_review_status_sync();
|
|
30425
|
-
init_pipeline_membership();
|
|
30426
30517
|
const PIPELINE_MEMBERSHIP_TTL_MS = 3e4;
|
|
30427
30518
|
function createPipelineMembershipService(deps = {
|
|
30428
30519
|
gather: gatherProjectLensSignals,
|
|
30429
30520
|
now: Date.now
|
|
30430
30521
|
}) {
|
|
30431
30522
|
const cachedGather = createSettledTtlPromiseCache(PIPELINE_MEMBERSHIP_TTL_MS, deps.now);
|
|
30432
|
-
|
|
30433
|
-
|
|
30434
|
-
|
|
30435
|
-
};
|
|
30523
|
+
const service = async (project) => cachedGather(project.path, () => deps.gather(project).then((signals) => signals.map(resolvePipelineMembership)));
|
|
30524
|
+
service.invalidate = (projectPath) => cachedGather.invalidate(projectPath);
|
|
30525
|
+
return service;
|
|
30436
30526
|
}
|
|
30437
30527
|
const getProjectPipelineMembership = createPipelineMembershipService();
|
|
30438
30528
|
const membershipSnapshots = /* @__PURE__ */ new Map();
|
|
@@ -30447,22 +30537,10 @@ function refreshMembershipSnapshot(project, snapshot, getMembership, now) {
|
|
|
30447
30537
|
});
|
|
30448
30538
|
return snapshot.refresh;
|
|
30449
30539
|
}
|
|
30450
|
-
/**
|
|
30451
|
-
function
|
|
30540
|
+
/** Read the latest successful snapshots without scheduling tracker or git work. */
|
|
30541
|
+
function readPipelineMembershipSnapshotsForProjects(projects) {
|
|
30452
30542
|
return projects.map((project) => {
|
|
30453
|
-
if (!project.github_repo) return {
|
|
30454
|
-
project,
|
|
30455
|
-
error: /* @__PURE__ */ new Error("Pipeline membership unavailable: missing github_repo")
|
|
30456
|
-
};
|
|
30457
30543
|
const snapshot = membershipSnapshots.get(project.path);
|
|
30458
|
-
if (!snapshot?.refresh && (!snapshot || now() - snapshot.refreshedAt >= 3e5)) {
|
|
30459
|
-
const current = snapshot ?? {
|
|
30460
|
-
value: [],
|
|
30461
|
-
refreshedAt: 0
|
|
30462
|
-
};
|
|
30463
|
-
membershipSnapshots.set(project.path, current);
|
|
30464
|
-
refreshMembershipSnapshot(project, current, getMembership, now);
|
|
30465
|
-
}
|
|
30466
30544
|
return snapshot?.refreshedAt ? {
|
|
30467
30545
|
project,
|
|
30468
30546
|
memberships: snapshot.value
|
|
@@ -30472,34 +30550,26 @@ function getPipelineMembershipSnapshotsForProjects(projects, getMembership = get
|
|
|
30472
30550
|
};
|
|
30473
30551
|
});
|
|
30474
30552
|
}
|
|
30475
|
-
/**
|
|
30476
|
-
|
|
30477
|
-
|
|
30478
|
-
|
|
30479
|
-
|
|
30480
|
-
|
|
30481
|
-
|
|
30482
|
-
|
|
30483
|
-
|
|
30484
|
-
|
|
30485
|
-
return {
|
|
30486
|
-
project,
|
|
30487
|
-
memberships: existing.value
|
|
30488
|
-
};
|
|
30489
|
-
}
|
|
30490
|
-
const snapshot = existing ?? {
|
|
30553
|
+
/**
|
|
30554
|
+
* PAN-2893 — event-driven refresh. Invalidate the per-project TTL cache and
|
|
30555
|
+
* force a snapshot re-gather NOW for the given projects, so agent lifecycle
|
|
30556
|
+
* changes reach membership consumers without waiting out the 5-minute TTL.
|
|
30557
|
+
* Refresh failures keep the last good snapshot (same policy as TTL refreshes).
|
|
30558
|
+
*/
|
|
30559
|
+
async function refreshMembershipSnapshotsForProjects(projects, getMembership = getProjectPipelineMembership, now = Date.now) {
|
|
30560
|
+
await Promise.all(projects.map(async (project) => {
|
|
30561
|
+
getMembership.invalidate(project.path);
|
|
30562
|
+
const snapshot = membershipSnapshots.get(project.path) ?? {
|
|
30491
30563
|
value: [],
|
|
30492
30564
|
refreshedAt: 0
|
|
30493
30565
|
};
|
|
30494
30566
|
membershipSnapshots.set(project.path, snapshot);
|
|
30567
|
+
const inFlight = snapshot.refresh;
|
|
30568
|
+
if (inFlight) {
|
|
30569
|
+
await inFlight;
|
|
30570
|
+
getMembership.invalidate(project.path);
|
|
30571
|
+
}
|
|
30495
30572
|
await refreshMembershipSnapshot(project, snapshot, getMembership, now);
|
|
30496
|
-
return snapshot.refreshedAt ? {
|
|
30497
|
-
project,
|
|
30498
|
-
memberships: snapshot.value
|
|
30499
|
-
} : {
|
|
30500
|
-
project,
|
|
30501
|
-
error: /* @__PURE__ */ new Error("Pipeline membership snapshot failed to load")
|
|
30502
|
-
};
|
|
30503
30573
|
}));
|
|
30504
30574
|
}
|
|
30505
30575
|
function summarizePipelineMembership(membership) {
|
|
@@ -30520,16 +30590,15 @@ function unavailablePipelineMembership() {
|
|
|
30520
30590
|
}
|
|
30521
30591
|
//#endregion
|
|
30522
30592
|
//#region services/resource-discovery.ts
|
|
30523
|
-
|
|
30593
|
+
init_src();
|
|
30524
30594
|
init_projects();
|
|
30595
|
+
init_pipeline_membership();
|
|
30525
30596
|
init_pipeline_membership_gather();
|
|
30526
|
-
|
|
30527
|
-
const execFileAsync$18 = promisify(execFile);
|
|
30528
|
-
const RESOURCE_DISCOVERY_TTL_MS = 3e4;
|
|
30597
|
+
const execFileAsync$17 = promisify(execFile);
|
|
30529
30598
|
const RECENT_ACTIVITY_WINDOW_MS = 5e3;
|
|
30599
|
+
const projectResourceSnapshots = /* @__PURE__ */ new Map();
|
|
30530
30600
|
let cachedResourceIssues = null;
|
|
30531
30601
|
let cachedDetailedResourceIssues = null;
|
|
30532
|
-
let resourceIssuesRefreshPromise = null;
|
|
30533
30602
|
function projectPrefixes(project) {
|
|
30534
30603
|
const prefixes = /* @__PURE__ */ new Set();
|
|
30535
30604
|
if (project.config.issue_prefix) prefixes.add(project.config.issue_prefix.toUpperCase());
|
|
@@ -30569,7 +30638,7 @@ function summarizeResourceDetails(details) {
|
|
|
30569
30638
|
state: pr.state,
|
|
30570
30639
|
isDraft: pr.isDraft
|
|
30571
30640
|
})),
|
|
30572
|
-
|
|
30641
|
+
hasXbrief: details.xbriefPath !== null,
|
|
30573
30642
|
hasTasks: details.tasksPath !== null,
|
|
30574
30643
|
dockerContainerCount: details.dockerContainers.length,
|
|
30575
30644
|
actualBranch: details.actualBranch,
|
|
@@ -30636,46 +30705,6 @@ const DISCOVERABLE_SESSION_PREFIXES = [
|
|
|
30636
30705
|
function isDiscoverableAgentSession(sessionName) {
|
|
30637
30706
|
return DISCOVERABLE_SESSION_PREFIXES.some((prefix) => sessionName.startsWith(prefix));
|
|
30638
30707
|
}
|
|
30639
|
-
async function loadTrackerIssues() {
|
|
30640
|
-
const map = /* @__PURE__ */ new Map();
|
|
30641
|
-
try {
|
|
30642
|
-
const { getSharedIssueService } = await import("./issue-service-singleton-D5EB5eYr.js");
|
|
30643
|
-
const issues = (await getSharedIssueService()).getIssues();
|
|
30644
|
-
for (const issue of issues) if (issue.identifier) map.set(issue.identifier.toUpperCase(), issue);
|
|
30645
|
-
} catch {
|
|
30646
|
-
return map;
|
|
30647
|
-
}
|
|
30648
|
-
return map;
|
|
30649
|
-
}
|
|
30650
|
-
async function loadTmuxSessions() {
|
|
30651
|
-
try {
|
|
30652
|
-
return (await Effect.runPromise(listSessionNames())).map((name) => name.trim()).filter(Boolean);
|
|
30653
|
-
} catch {
|
|
30654
|
-
return [];
|
|
30655
|
-
}
|
|
30656
|
-
}
|
|
30657
|
-
function loadConversations() {
|
|
30658
|
-
try {
|
|
30659
|
-
return listConversations();
|
|
30660
|
-
} catch {
|
|
30661
|
-
return [];
|
|
30662
|
-
}
|
|
30663
|
-
}
|
|
30664
|
-
async function loadDockerContainers() {
|
|
30665
|
-
try {
|
|
30666
|
-
const { stdout } = await execFileAsync$18("docker", [
|
|
30667
|
-
"ps",
|
|
30668
|
-
"--format",
|
|
30669
|
-
"{{.Names}}"
|
|
30670
|
-
], {
|
|
30671
|
-
encoding: "utf-8",
|
|
30672
|
-
timeout: 5e3
|
|
30673
|
-
});
|
|
30674
|
-
return stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
30675
|
-
} catch {
|
|
30676
|
-
return [];
|
|
30677
|
-
}
|
|
30678
|
-
}
|
|
30679
30708
|
async function loadOpenPullRequests(projects) {
|
|
30680
30709
|
const pullRequests = /* @__PURE__ */ new Map();
|
|
30681
30710
|
await Promise.all(projects.map(async (project) => {
|
|
@@ -30706,80 +30735,31 @@ async function loadOpenPullRequests(projects) {
|
|
|
30706
30735
|
for (const [issueId, prs] of pullRequests) pullRequests.set(issueId, sortPullRequests(prs));
|
|
30707
30736
|
return pullRequests;
|
|
30708
30737
|
}
|
|
30709
|
-
|
|
30710
|
-
|
|
30711
|
-
|
|
30712
|
-
|
|
30713
|
-
|
|
30714
|
-
|
|
30715
|
-
|
|
30716
|
-
|
|
30717
|
-
|
|
30718
|
-
|
|
30719
|
-
|
|
30720
|
-
|
|
30721
|
-
|
|
30722
|
-
|
|
30723
|
-
|
|
30724
|
-
|
|
30725
|
-
|
|
30726
|
-
|
|
30727
|
-
|
|
30728
|
-
|
|
30729
|
-
|
|
30730
|
-
|
|
30731
|
-
|
|
30732
|
-
|
|
30733
|
-
"--format=%(refname:short)"
|
|
30734
|
-
], {
|
|
30735
|
-
cwd: projectPath,
|
|
30736
|
-
encoding: "utf-8",
|
|
30737
|
-
timeout: 1e4
|
|
30738
|
-
}).catch(() => ({ stdout: "" })),
|
|
30739
|
-
execFileAsync$18("git", [
|
|
30740
|
-
"for-each-ref",
|
|
30741
|
-
"refs/remotes/origin/bypass/*",
|
|
30742
|
-
"--format=%(refname:short)"
|
|
30743
|
-
], {
|
|
30744
|
-
cwd: projectPath,
|
|
30745
|
-
encoding: "utf-8",
|
|
30746
|
-
timeout: 1e4
|
|
30747
|
-
}).catch(() => ({ stdout: "" }))
|
|
30748
|
-
]);
|
|
30749
|
-
return {
|
|
30750
|
-
local: [...localFeature.stdout.split("\n").map((line) => line.trim()).filter(Boolean), ...localBypass.stdout.split("\n").map((line) => line.trim()).filter(Boolean)],
|
|
30751
|
-
remote: [...remoteFeature.stdout.split("\n").map((line) => line.trim()).filter(Boolean), ...remoteBypass.stdout.split("\n").map((line) => line.trim()).filter(Boolean)]
|
|
30752
|
-
};
|
|
30753
|
-
} catch {
|
|
30754
|
-
return {
|
|
30755
|
-
local: [],
|
|
30756
|
-
remote: []
|
|
30757
|
-
};
|
|
30758
|
-
}
|
|
30759
|
-
}
|
|
30760
|
-
async function loadBranchesAheadOfMain(projectPath) {
|
|
30761
|
-
const ahead = /* @__PURE__ */ new Set();
|
|
30762
|
-
const run = async (patterns) => {
|
|
30763
|
-
if (patterns.length === 0) return;
|
|
30764
|
-
try {
|
|
30765
|
-
const { stdout } = await execFileAsync$18("git", [
|
|
30766
|
-
"for-each-ref",
|
|
30767
|
-
"--format=%(refname:short)",
|
|
30768
|
-
...patterns,
|
|
30769
|
-
"--no-merged=main"
|
|
30770
|
-
], {
|
|
30771
|
-
cwd: projectPath,
|
|
30772
|
-
encoding: "utf-8",
|
|
30773
|
-
timeout: 1e4
|
|
30774
|
-
});
|
|
30775
|
-
for (const line of stdout.split("\n")) {
|
|
30776
|
-
const branch = line.trim();
|
|
30777
|
-
if (branch) ahead.add(branch);
|
|
30778
|
-
}
|
|
30779
|
-
} catch {}
|
|
30738
|
+
const PROJECT_BRANCH_PATTERNS = [
|
|
30739
|
+
"refs/heads/feature/*",
|
|
30740
|
+
"refs/remotes/origin/feature/*",
|
|
30741
|
+
"refs/heads/bypass/*",
|
|
30742
|
+
"refs/remotes/origin/bypass/*"
|
|
30743
|
+
];
|
|
30744
|
+
async function loadProjectBranchSnapshot(projectPath) {
|
|
30745
|
+
const run = (extraArgs = []) => execFileAsync$17("git", [
|
|
30746
|
+
"for-each-ref",
|
|
30747
|
+
"--format=%(refname:short)",
|
|
30748
|
+
...extraArgs,
|
|
30749
|
+
...PROJECT_BRANCH_PATTERNS
|
|
30750
|
+
], {
|
|
30751
|
+
cwd: projectPath,
|
|
30752
|
+
encoding: "utf-8",
|
|
30753
|
+
timeout: 1e4
|
|
30754
|
+
}).catch(() => ({ stdout: "" }));
|
|
30755
|
+
const [allRefs, unmergedRefs] = await Promise.all([run(), run(["--no-merged=main"])]);
|
|
30756
|
+
const branches = allRefs.stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
30757
|
+
const ahead = new Set(unmergedRefs.stdout.split("\n").map((line) => line.trim()).filter(Boolean));
|
|
30758
|
+
return {
|
|
30759
|
+
local: branches.filter((branch) => !branch.startsWith("origin/")),
|
|
30760
|
+
remote: branches.filter((branch) => branch.startsWith("origin/")),
|
|
30761
|
+
ahead
|
|
30780
30762
|
};
|
|
30781
|
-
await Promise.all([run(["refs/heads/feature/*", "refs/heads/bypass/*"]), run(["refs/remotes/origin/feature/*", "refs/remotes/origin/bypass/*"])]);
|
|
30782
|
-
return ahead;
|
|
30783
30763
|
}
|
|
30784
30764
|
async function scanWorkspace(workspacesDir, workspaceName) {
|
|
30785
30765
|
const workspacePath = join(workspacesDir, workspaceName);
|
|
@@ -30789,46 +30769,43 @@ async function scanWorkspace(workspacesDir, workspaceName) {
|
|
|
30789
30769
|
const issueMatch = workspaceName.match(/^feature-([a-z]+-\d+)$/i);
|
|
30790
30770
|
const issueId = issueMatch ? issueMatch[1].toUpperCase() : null;
|
|
30791
30771
|
const specEntry = issueId ? await Effect.runPromise(findSpecByIssue(projectRoot, issueId)).catch(() => null) : null;
|
|
30792
|
-
const
|
|
30793
|
-
let
|
|
30794
|
-
if (
|
|
30795
|
-
|
|
30772
|
+
const xbriefPath = specEntry ? specEntry.path : null;
|
|
30773
|
+
let xbriefMtime = null;
|
|
30774
|
+
if (xbriefPath) try {
|
|
30775
|
+
xbriefMtime = (await stat$1(xbriefPath)).mtimeMs;
|
|
30796
30776
|
} catch {
|
|
30797
|
-
|
|
30777
|
+
xbriefMtime = null;
|
|
30798
30778
|
}
|
|
30799
30779
|
return {
|
|
30800
30780
|
workspacePath,
|
|
30801
30781
|
hasPlanning: workspaceEntries.has(PAN_DIRNAME),
|
|
30802
30782
|
hasPrd: panEntries.has("prd.md"),
|
|
30803
30783
|
hasState: panEntries.has(PAN_CONTINUE_FILENAME),
|
|
30804
|
-
|
|
30805
|
-
|
|
30806
|
-
|
|
30807
|
-
hasTasks:
|
|
30784
|
+
hasXbrief: xbriefPath !== null,
|
|
30785
|
+
xbriefPath,
|
|
30786
|
+
xbriefMtime,
|
|
30787
|
+
hasTasks: xbriefPath !== null
|
|
30808
30788
|
};
|
|
30809
30789
|
}
|
|
30810
|
-
async function computeResourceAllocatedIssues() {
|
|
30811
|
-
const
|
|
30812
|
-
const
|
|
30813
|
-
|
|
30814
|
-
|
|
30815
|
-
|
|
30816
|
-
|
|
30817
|
-
|
|
30790
|
+
async function computeResourceAllocatedIssues(projectConfigs, sharedSignals) {
|
|
30791
|
+
const registeredProjects = listProjectsSync();
|
|
30792
|
+
const projects = projectConfigs.map((config) => registeredProjects.find((entry) => entry.config.path === config.path) ?? {
|
|
30793
|
+
key: config.name ?? config.path,
|
|
30794
|
+
config
|
|
30795
|
+
});
|
|
30796
|
+
const { trackerIssues, tmuxSessions, dockerContainers, conversations, remoteAgentStates } = sharedSignals ?? await captureSharedResourceSignals();
|
|
30797
|
+
const pullRequests = await loadOpenPullRequests(projects);
|
|
30818
30798
|
const issueMap = /* @__PURE__ */ new Map();
|
|
30819
30799
|
const projectByPrefix = /* @__PURE__ */ new Map();
|
|
30820
30800
|
for (const project of projects) for (const prefix of projectPrefixes(project)) projectByPrefix.set(prefix, project);
|
|
30821
|
-
const projectRefFromResolved = (resolvedProject) => (
|
|
30822
|
-
key: resolvedProject.projectKey,
|
|
30823
|
-
config: {
|
|
30824
|
-
name: resolvedProject.projectName,
|
|
30825
|
-
path: resolvedProject.projectPath
|
|
30826
|
-
}
|
|
30827
|
-
});
|
|
30801
|
+
const projectRefFromResolved = (resolvedProject) => projects.find((project) => project.key === resolvedProject.projectKey || project.config.path === resolvedProject.projectPath) ?? null;
|
|
30828
30802
|
const resolveProjectRef = (issueId, preferredProject) => {
|
|
30829
30803
|
if (preferredProject) return preferredProject;
|
|
30830
30804
|
const resolvedProject = resolveProjectFromIssueSync(issueId);
|
|
30831
|
-
if (resolvedProject)
|
|
30805
|
+
if (resolvedProject) {
|
|
30806
|
+
const project = projectRefFromResolved(resolvedProject);
|
|
30807
|
+
if (project) return project;
|
|
30808
|
+
}
|
|
30832
30809
|
const prefix = issueId.toUpperCase().match(/^([A-Z]+)-\d+$/)?.[1] ?? "";
|
|
30833
30810
|
return projectByPrefix.get(prefix) ?? null;
|
|
30834
30811
|
};
|
|
@@ -30861,8 +30838,8 @@ async function computeResourceAllocatedIssues() {
|
|
|
30861
30838
|
localBranches: [],
|
|
30862
30839
|
remoteBranches: [],
|
|
30863
30840
|
prs: [],
|
|
30864
|
-
|
|
30865
|
-
|
|
30841
|
+
xbriefPath: null,
|
|
30842
|
+
xbriefMtime: null,
|
|
30866
30843
|
tasksPath: null,
|
|
30867
30844
|
dockerContainers: [],
|
|
30868
30845
|
actualBranch: null,
|
|
@@ -30895,7 +30872,6 @@ async function computeResourceAllocatedIssues() {
|
|
|
30895
30872
|
issue.resourceSources.add("tmux");
|
|
30896
30873
|
if (!issue.resourceDetails.tmuxSessions.includes(sessionName)) issue.resourceDetails.tmuxSessions.push(sessionName);
|
|
30897
30874
|
}
|
|
30898
|
-
const conversations = loadConversations();
|
|
30899
30875
|
for (const conv of conversations) {
|
|
30900
30876
|
if (!conv.issueId || conv.archivedAt) continue;
|
|
30901
30877
|
const issue = ensureIssue(conv.issueId);
|
|
@@ -30909,21 +30885,18 @@ async function computeResourceAllocatedIssues() {
|
|
|
30909
30885
|
tmuxSession: conv.tmuxSession
|
|
30910
30886
|
});
|
|
30911
30887
|
}
|
|
30912
|
-
|
|
30913
|
-
const
|
|
30914
|
-
|
|
30915
|
-
|
|
30916
|
-
|
|
30917
|
-
|
|
30918
|
-
|
|
30919
|
-
|
|
30920
|
-
|
|
30921
|
-
|
|
30922
|
-
|
|
30923
|
-
|
|
30924
|
-
if (!issue.agentStatus) issue.agentStatus = "active";
|
|
30925
|
-
}
|
|
30926
|
-
} catch {}
|
|
30888
|
+
for (const remoteState of remoteAgentStates) {
|
|
30889
|
+
const issue = ensureIssue(remoteState.issueId);
|
|
30890
|
+
if (!issue) continue;
|
|
30891
|
+
issue.resourceSources.add("remote-agent");
|
|
30892
|
+
issue.resourceDetails.remoteAgent = {
|
|
30893
|
+
vmName: remoteState.vmName,
|
|
30894
|
+
status: remoteState.status,
|
|
30895
|
+
model: remoteState.model,
|
|
30896
|
+
startedAt: remoteState.startedAt
|
|
30897
|
+
};
|
|
30898
|
+
if (!issue.agentStatus) issue.agentStatus = "active";
|
|
30899
|
+
}
|
|
30927
30900
|
for (const containerName of dockerContainers) {
|
|
30928
30901
|
const issueId = parseIssueIdFromTextSync(containerName.replace(/feature\//g, "feature-"));
|
|
30929
30902
|
if (!issueId) continue;
|
|
@@ -30935,8 +30908,7 @@ async function computeResourceAllocatedIssues() {
|
|
|
30935
30908
|
await Promise.all(projects.map(async (project) => {
|
|
30936
30909
|
const projectPath = project.config.path;
|
|
30937
30910
|
const workspacesDir = join(projectPath, "workspaces");
|
|
30938
|
-
const [workspaceEntries, branches] = await Promise.all([readdir(workspacesDir, { withFileTypes: true }).catch(() => []),
|
|
30939
|
-
const aheadBranches = await loadBranchesAheadOfMain(projectPath);
|
|
30911
|
+
const [workspaceEntries, branches] = await Promise.all([readdir(workspacesDir, { withFileTypes: true }).catch(() => []), loadProjectBranchSnapshot(projectPath)]);
|
|
30940
30912
|
await Promise.all(workspaceEntries.map(async (entry) => {
|
|
30941
30913
|
if (!entry.isDirectory() || !entry.name.startsWith("feature-")) return;
|
|
30942
30914
|
const issue = ensureIssue(entry.name.replace(/^feature-/, "").toUpperCase(), project);
|
|
@@ -30947,10 +30919,10 @@ async function computeResourceAllocatedIssues() {
|
|
|
30947
30919
|
issue.hasPlanning = workspace.hasPlanning;
|
|
30948
30920
|
issue.hasPrd = workspace.hasPrd;
|
|
30949
30921
|
issue.hasState = workspace.hasState;
|
|
30950
|
-
if (workspace.
|
|
30922
|
+
if (workspace.xbriefPath) {
|
|
30951
30923
|
issue.resourceSources.add("vbrief");
|
|
30952
|
-
issue.resourceDetails.
|
|
30953
|
-
issue.resourceDetails.
|
|
30924
|
+
issue.resourceDetails.xbriefPath = workspace.xbriefPath;
|
|
30925
|
+
issue.resourceDetails.xbriefMtime = workspace.xbriefMtime;
|
|
30954
30926
|
}
|
|
30955
30927
|
if (workspace.hasTasks) {
|
|
30956
30928
|
issue.resourceSources.add("tasks");
|
|
@@ -30968,7 +30940,7 @@ async function computeResourceAllocatedIssues() {
|
|
|
30968
30940
|
if (!issue) continue;
|
|
30969
30941
|
issue.resourceSources.add("branch");
|
|
30970
30942
|
if (!issue.resourceDetails[key].includes(branch)) issue.resourceDetails[key].push(branch);
|
|
30971
|
-
if (
|
|
30943
|
+
if (branches.ahead.has(branch)) issue.resourceDetails.branchAheadOfMain = true;
|
|
30972
30944
|
}
|
|
30973
30945
|
}));
|
|
30974
30946
|
for (const [issueId, prs] of pullRequests) {
|
|
@@ -30993,14 +30965,18 @@ async function computeResourceAllocatedIssues() {
|
|
|
30993
30965
|
for (const issue of issueMap.values()) issue.readyForMerge = readyForMergeFlags.get(issue.issueId) ?? false;
|
|
30994
30966
|
}
|
|
30995
30967
|
const memberships = /* @__PURE__ */ new Map();
|
|
30996
|
-
const
|
|
30997
|
-
|
|
30998
|
-
|
|
30999
|
-
|
|
30968
|
+
const unavailableProjects = /* @__PURE__ */ new Set();
|
|
30969
|
+
const projectMemberships = readPipelineMembershipSnapshotsForProjects(projects.map((project) => project.config));
|
|
30970
|
+
for (const result of projectMemberships) {
|
|
30971
|
+
if (result.error) unavailableProjects.add(result.project.name);
|
|
30972
|
+
for (const membership of result.memberships ?? []) {
|
|
30973
|
+
ensureIssue(membership.issueId);
|
|
30974
|
+
memberships.set(membership.issueId, membership);
|
|
30975
|
+
}
|
|
31000
30976
|
}
|
|
31001
30977
|
return [...issueMap.values()].filter((issue) => issue.resourceSources.size > 0).filter((issue) => {
|
|
31002
30978
|
const membership = memberships.get(issue.issueId);
|
|
31003
|
-
return membership?.inPipeline === true || membership?.bucket === "clean_terminal" && isLiveResource(issue);
|
|
30979
|
+
return membership?.inPipeline === true || membership?.bucket === "clean_terminal" && isLiveResource(issue) || !membership && unavailableProjects.has(issue.projectName) && isLiveResource(issue);
|
|
31004
30980
|
}).map((issue) => {
|
|
31005
30981
|
const membership = memberships.get(issue.issueId);
|
|
31006
30982
|
const hasTmux = issue.resourceDetails.tmuxSessions.length > 0;
|
|
@@ -31029,10 +31005,11 @@ async function computeResourceAllocatedIssues() {
|
|
|
31029
31005
|
resourceSources: new Set([...issue.resourceSources].sort()),
|
|
31030
31006
|
resourceDetails: issue.resourceDetails,
|
|
31031
31007
|
taskTotals: issue.taskTotals,
|
|
31032
|
-
pipelineBucket: membership
|
|
31033
|
-
|
|
31008
|
+
pipelineBucket: membership?.bucket,
|
|
31009
|
+
specOnlyPlanned: membership ? membership.bucket === "planned_backlog" && membership.reasons.includes("open issue with an xBRIEF spec but no branch/PR — planned work whose plan encodes code paths that age; needs starting or re-planning") : void 0,
|
|
31010
|
+
resourceDrift: membership ? !membership.inPipeline : void 0
|
|
31034
31011
|
};
|
|
31035
|
-
}).sort((a, b) => a.issueId
|
|
31012
|
+
}).sort((a, b) => compareIssueIds(a.issueId, b.issueId));
|
|
31036
31013
|
}
|
|
31037
31014
|
function toPublicResourceIssue(issue) {
|
|
31038
31015
|
return {
|
|
@@ -31041,28 +31018,42 @@ function toPublicResourceIssue(issue) {
|
|
|
31041
31018
|
resourceDetails: summarizeResourceDetails(issue.resourceDetails)
|
|
31042
31019
|
};
|
|
31043
31020
|
}
|
|
31044
|
-
function
|
|
31045
|
-
|
|
31046
|
-
|
|
31047
|
-
|
|
31048
|
-
|
|
31049
|
-
|
|
31050
|
-
|
|
31051
|
-
|
|
31052
|
-
|
|
31053
|
-
|
|
31054
|
-
|
|
31055
|
-
|
|
31021
|
+
function rebuildCombinedResourceSnapshot() {
|
|
31022
|
+
const detailed = [...projectResourceSnapshots.values()].flatMap((snapshot) => snapshot.detailed).sort((a, b) => compareIssueIds(a.issueId, b.issueId));
|
|
31023
|
+
const publicIssues = detailed.map(toPublicResourceIssue);
|
|
31024
|
+
cachedDetailedResourceIssues = detailed;
|
|
31025
|
+
cachedResourceIssues = {
|
|
31026
|
+
value: publicIssues,
|
|
31027
|
+
computedAt: Math.max(0, ...[...projectResourceSnapshots.values()].map((snapshot) => snapshot.computedAt))
|
|
31028
|
+
};
|
|
31029
|
+
return publicIssues;
|
|
31030
|
+
}
|
|
31031
|
+
function publishProjectResourceSnapshot(project, issues) {
|
|
31032
|
+
projectResourceSnapshots.set(project.path, {
|
|
31033
|
+
detailed: issues,
|
|
31034
|
+
public: issues.map(toPublicResourceIssue),
|
|
31035
|
+
computedAt: Date.now()
|
|
31056
31036
|
});
|
|
31057
|
-
|
|
31037
|
+
rebuildCombinedResourceSnapshot();
|
|
31058
31038
|
}
|
|
31059
|
-
|
|
31060
|
-
|
|
31061
|
-
if (
|
|
31062
|
-
|
|
31063
|
-
|
|
31039
|
+
/** Refresh only the requested projects, capturing fleet-wide signals once for the batch. */
|
|
31040
|
+
async function refreshResourceAllocatedProjects(projects, options = {}) {
|
|
31041
|
+
if (projects.length === 0) return cachedResourceIssues?.value ?? [];
|
|
31042
|
+
const sharedSignals = await captureSharedResourceSignals();
|
|
31043
|
+
const failures = [];
|
|
31044
|
+
for (const project of projects) try {
|
|
31045
|
+
if (options.refreshMembership !== false) await refreshMembershipSnapshotsForProjects([project]);
|
|
31046
|
+
publishProjectResourceSnapshot(project, await computeResourceAllocatedIssues([project], sharedSignals));
|
|
31047
|
+
} catch (error) {
|
|
31048
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
31049
|
+
failures.push(failure);
|
|
31050
|
+
console.warn(`[resource-discovery] refresh failed for ${project.name ?? project.path}; keeping last-good snapshot:`, failure.message);
|
|
31064
31051
|
}
|
|
31065
|
-
|
|
31052
|
+
if (failures.length > 0) throw new AggregateError(failures, `${failures.length} project resource refresh(es) failed`);
|
|
31053
|
+
return cachedResourceIssues?.value ?? [];
|
|
31054
|
+
}
|
|
31055
|
+
async function getCachedResourceAllocatedIssues() {
|
|
31056
|
+
return cachedResourceIssues?.value ?? [];
|
|
31066
31057
|
}
|
|
31067
31058
|
function sanitizeResourceAllocatedIssues(issues) {
|
|
31068
31059
|
return issues.map((issue) => ({
|
|
@@ -31078,7 +31069,7 @@ function sanitizeResourceAllocatedIssues(issues) {
|
|
|
31078
31069
|
state: pr.state,
|
|
31079
31070
|
isDraft: pr.isDraft
|
|
31080
31071
|
})),
|
|
31081
|
-
|
|
31072
|
+
hasXbrief: issue.resourceDetails.hasXbrief,
|
|
31082
31073
|
hasTasks: issue.resourceDetails.hasTasks,
|
|
31083
31074
|
dockerContainerCount: issue.resourceDetails.dockerContainerCount,
|
|
31084
31075
|
actualBranch: issue.resourceDetails.actualBranch,
|
|
@@ -31101,10 +31092,7 @@ function toPublicResourceDetailIdentifiers(details) {
|
|
|
31101
31092
|
async function getResourceDetailIdentifiers(issueId) {
|
|
31102
31093
|
const normalizedIssueId = issueId.toUpperCase();
|
|
31103
31094
|
const cachedMatch = cachedDetailedResourceIssues?.find((entry) => entry.issueId === normalizedIssueId);
|
|
31104
|
-
|
|
31105
|
-
await refreshResourceAllocatedIssues();
|
|
31106
|
-
const refreshedMatch = cachedDetailedResourceIssues?.find((entry) => entry.issueId === normalizedIssueId);
|
|
31107
|
-
return refreshedMatch ? toPublicResourceDetailIdentifiers(refreshedMatch.resourceDetails) : null;
|
|
31095
|
+
return cachedMatch ? toPublicResourceDetailIdentifiers(cachedMatch.resourceDetails) : null;
|
|
31108
31096
|
}
|
|
31109
31097
|
function groupResourceAllocatedIssuesByProject(issues) {
|
|
31110
31098
|
const projectTree = /* @__PURE__ */ new Map();
|
|
@@ -31122,7 +31110,7 @@ function groupResourceAllocatedIssuesByProject(issues) {
|
|
|
31122
31110
|
}
|
|
31123
31111
|
return [...projectTree.values()].map((project) => ({
|
|
31124
31112
|
...project,
|
|
31125
|
-
features: project.features.sort((a, b) => a.issueId
|
|
31113
|
+
features: project.features.sort((a, b) => compareIssueIds(a.issueId, b.issueId))
|
|
31126
31114
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
31127
31115
|
}
|
|
31128
31116
|
//#endregion
|
|
@@ -31308,7 +31296,7 @@ function getIssueTasks(id) {
|
|
|
31308
31296
|
};
|
|
31309
31297
|
});
|
|
31310
31298
|
const doc = workspacePath ? readWorkspacePlanSync(workspacePath) : null;
|
|
31311
|
-
if (!doc) return jsonResponse({ error: `The
|
|
31299
|
+
if (!doc) return jsonResponse({ error: `The xBRIEF for ${id} is missing or unreadable.` }, { status: 404 });
|
|
31312
31300
|
const record = projectPath ? readIssueRecordSync({
|
|
31313
31301
|
name: resolvedProject?.projectName ?? id,
|
|
31314
31302
|
path: projectPath
|
|
@@ -31401,11 +31389,12 @@ init_tracker_config();
|
|
|
31401
31389
|
init_agents$1();
|
|
31402
31390
|
init_pan_dir();
|
|
31403
31391
|
init_projects();
|
|
31392
|
+
init_review_status();
|
|
31404
31393
|
init_remote_agents();
|
|
31405
31394
|
init_tracker_utils();
|
|
31406
31395
|
init_tmux();
|
|
31407
31396
|
init_io();
|
|
31408
|
-
const execFileAsync$
|
|
31397
|
+
const execFileAsync$16 = promisify(execFile);
|
|
31409
31398
|
function getIssueDataService$9() {
|
|
31410
31399
|
return getSharedIssueService();
|
|
31411
31400
|
}
|
|
@@ -31462,12 +31451,12 @@ async function completePlanningArtifacts(options) {
|
|
|
31462
31451
|
const workspacePlanPath = await Effect.runPromise(Effect.gen(function* () {
|
|
31463
31452
|
return (yield* findWorkspaceDraftPlan(workspacePath)) ?? (yield* findPlan(workspacePath));
|
|
31464
31453
|
}));
|
|
31465
|
-
if (!workspacePlanPath) throw new Error(`No workspace
|
|
31454
|
+
if (!workspacePlanPath) throw new Error(`No workspace xBRIEF found for ${upperIssueId} at ${workspacePath}/.overdeck/spec.vbrief.json`);
|
|
31466
31455
|
const workspaceDoc = await Effect.runPromise(readPlan(workspacePlanPath));
|
|
31467
31456
|
const workspaceIssueId = workspaceDoc.plan?.id;
|
|
31468
|
-
if (workspaceIssueId && workspaceIssueId.toLowerCase() !== issueLower) throw new Error(`Workspace
|
|
31457
|
+
if (workspaceIssueId && workspaceIssueId.toLowerCase() !== issueLower) throw new Error(`Workspace xBRIEF is for ${workspaceIssueId.toUpperCase()}, not ${upperIssueId}`);
|
|
31469
31458
|
assertPlanQuality(workspaceDoc);
|
|
31470
|
-
emitCompletePlanningPhase(upperIssueId, "specWrite", "start", "writing proposed
|
|
31459
|
+
emitCompletePlanningPhase(upperIssueId, "specWrite", "start", "writing proposed xBRIEF spec", { projectPath });
|
|
31471
31460
|
const existingSpec = await Effect.runPromise(findSpecByIssue(projectPath, upperIssueId));
|
|
31472
31461
|
let proposed;
|
|
31473
31462
|
try {
|
|
@@ -31482,7 +31471,7 @@ async function completePlanningArtifacts(options) {
|
|
|
31482
31471
|
path: e.path,
|
|
31483
31472
|
filename: e.filename
|
|
31484
31473
|
}));
|
|
31485
|
-
emitCompletePlanningPhase(upperIssueId, "specWrite", "success", "proposed
|
|
31474
|
+
emitCompletePlanningPhase(upperIssueId, "specWrite", "success", "proposed xBRIEF spec written", {
|
|
31486
31475
|
path: proposed.path,
|
|
31487
31476
|
filename: proposed.filename
|
|
31488
31477
|
});
|
|
@@ -31491,7 +31480,7 @@ async function completePlanningArtifacts(options) {
|
|
|
31491
31480
|
throw error;
|
|
31492
31481
|
}
|
|
31493
31482
|
const planItemCount = workspaceDoc.plan.items?.length ?? 0;
|
|
31494
|
-
if (planItemCount === 0) throw new Error(`The
|
|
31483
|
+
if (planItemCount === 0) throw new Error(`The xBRIEF for ${upperIssueId} contains no implementation items.`);
|
|
31495
31484
|
return {
|
|
31496
31485
|
proposed,
|
|
31497
31486
|
taskCount: planItemCount,
|
|
@@ -31531,7 +31520,7 @@ async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
|
|
|
31531
31520
|
} catch {}
|
|
31532
31521
|
const recordPath = join(".pan", "records", `${issueLower}.json`);
|
|
31533
31522
|
try {
|
|
31534
|
-
const { stdout: statusOut } = await execFileAsync$
|
|
31523
|
+
const { stdout: statusOut } = await execFileAsync$16("git", [
|
|
31535
31524
|
"status",
|
|
31536
31525
|
"--porcelain",
|
|
31537
31526
|
"--",
|
|
@@ -31541,7 +31530,7 @@ async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
|
|
|
31541
31530
|
encoding: "utf-8"
|
|
31542
31531
|
});
|
|
31543
31532
|
if (!statusOut.trim()) return;
|
|
31544
|
-
await execFileAsync$
|
|
31533
|
+
await execFileAsync$16("git", [
|
|
31545
31534
|
"add",
|
|
31546
31535
|
"--",
|
|
31547
31536
|
recordPath
|
|
@@ -31550,7 +31539,7 @@ async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
|
|
|
31550
31539
|
encoding: "utf-8"
|
|
31551
31540
|
});
|
|
31552
31541
|
try {
|
|
31553
|
-
await execFileAsync$
|
|
31542
|
+
await execFileAsync$16("git", [
|
|
31554
31543
|
"diff",
|
|
31555
31544
|
"--cached",
|
|
31556
31545
|
"--quiet",
|
|
@@ -31562,7 +31551,7 @@ async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
|
|
|
31562
31551
|
});
|
|
31563
31552
|
return;
|
|
31564
31553
|
} catch {}
|
|
31565
|
-
await execFileAsync$
|
|
31554
|
+
await execFileAsync$16("git", [
|
|
31566
31555
|
"commit",
|
|
31567
31556
|
"-m",
|
|
31568
31557
|
`chore(records): update ${issueId.toUpperCase()} per-issue record before auto-start`,
|
|
@@ -31584,25 +31573,59 @@ function getInternalDashboardOrigin() {
|
|
|
31584
31573
|
}
|
|
31585
31574
|
function classifyAutoSpawnSkip(status, body) {
|
|
31586
31575
|
const error = typeof body["error"] === "string" ? body["error"] : "";
|
|
31576
|
+
if (status === 401 || status === 403) return "unauthorized";
|
|
31587
31577
|
if (body["stackHealth"] || /workspace docker stack/i.test(error)) return "stack-unhealthy";
|
|
31588
31578
|
if (body["paused"] === true) return "paused";
|
|
31589
31579
|
if (body["troubled"] === true) return "troubled";
|
|
31590
31580
|
if (body["guardrails"] || body["requiresAcknowledgement"] === true || status === 409) return "guardrails";
|
|
31591
31581
|
return "spawn-failed";
|
|
31592
31582
|
}
|
|
31583
|
+
function resolveCompletePlanningTerminalStatus(autoSpawnRequested, autoSpawnResult) {
|
|
31584
|
+
return autoSpawnRequested && autoSpawnResult?.workAgentSpawned !== true ? "failure" : "success";
|
|
31585
|
+
}
|
|
31586
|
+
async function recordPlanningAutoHandoffFailure(options) {
|
|
31587
|
+
const skipReason = options.result.workAgentSkipReason ?? "spawn-failed";
|
|
31588
|
+
const error = options.result.workAgentError ?? `Work agent startup failed: ${skipReason}`;
|
|
31589
|
+
const details = {
|
|
31590
|
+
workAgentSkipReason: skipReason,
|
|
31591
|
+
workAgentError: error
|
|
31592
|
+
};
|
|
31593
|
+
await Effect.runPromise(options.eventStore.append({
|
|
31594
|
+
type: "planning.failed",
|
|
31595
|
+
timestamp: (options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))(),
|
|
31596
|
+
payload: {
|
|
31597
|
+
issueId: options.issueId,
|
|
31598
|
+
error,
|
|
31599
|
+
stage: "auto-handoff",
|
|
31600
|
+
...details
|
|
31601
|
+
}
|
|
31602
|
+
}));
|
|
31603
|
+
(options.markStuck ?? markWorkspaceStuck)(options.issueId, "planning_auto_handoff_failed", details);
|
|
31604
|
+
(options.emitActivity ?? emitActivityEntrySync)({
|
|
31605
|
+
source: "plan",
|
|
31606
|
+
level: "error",
|
|
31607
|
+
message: `${options.issueId} planning complete, but work-agent startup failed: ${error}`,
|
|
31608
|
+
issueId: options.issueId,
|
|
31609
|
+
details: JSON.stringify(details)
|
|
31610
|
+
});
|
|
31611
|
+
return error;
|
|
31612
|
+
}
|
|
31593
31613
|
async function completePlanningAutoSpawn(options) {
|
|
31594
31614
|
if (options.autoSpawn !== true) {
|
|
31595
31615
|
emitCompletePlanningPhase(options.issueId, "autoSpawn", "skipped", "autoSpawn not requested");
|
|
31596
31616
|
return null;
|
|
31597
31617
|
}
|
|
31598
31618
|
const dashboardOrigin = options.dashboardOrigin ?? getInternalDashboardOrigin();
|
|
31619
|
+
const internalToken = getInternalTokenSync();
|
|
31620
|
+
const internalTokenHeaders = internalToken ? { [INTERNAL_TOKEN_HEADER]: internalToken } : {};
|
|
31599
31621
|
emitCompletePlanningPhase(options.issueId, "autoSpawn", "start", "posting work-agent spawn request", { dashboardOrigin });
|
|
31600
31622
|
try {
|
|
31601
31623
|
const response = await (options.fetchImpl ?? fetch)(new URL("/api/agents", dashboardOrigin), {
|
|
31602
31624
|
method: "POST",
|
|
31603
31625
|
headers: {
|
|
31604
31626
|
"content-type": "application/json",
|
|
31605
|
-
origin: dashboardOrigin
|
|
31627
|
+
origin: dashboardOrigin,
|
|
31628
|
+
...internalTokenHeaders
|
|
31606
31629
|
},
|
|
31607
31630
|
body: JSON.stringify({
|
|
31608
31631
|
issueId: options.issueId,
|
|
@@ -31623,7 +31646,10 @@ async function completePlanningAutoSpawn(options) {
|
|
|
31623
31646
|
if (skipReason === "stack-unhealthy") {
|
|
31624
31647
|
const recovery = await (options.fetchImpl ?? fetch)(new URL(`/api/workspaces/${encodeURIComponent(options.issueId)}/rebuild-and-start`, dashboardOrigin), {
|
|
31625
31648
|
method: "POST",
|
|
31626
|
-
headers: {
|
|
31649
|
+
headers: {
|
|
31650
|
+
origin: dashboardOrigin,
|
|
31651
|
+
...internalTokenHeaders
|
|
31652
|
+
}
|
|
31627
31653
|
});
|
|
31628
31654
|
const recoveryBody = await recovery.json().catch(() => ({}));
|
|
31629
31655
|
if (recovery.ok && recoveryBody["success"] !== false) {
|
|
@@ -31766,6 +31792,19 @@ async function completePlanningForIssue(options) {
|
|
|
31766
31792
|
}
|
|
31767
31793
|
emitCompletePlanningPhase(id, "prdGate", "success", `found ${prdGate.path} (${prdGate.lineCount} lines)`);
|
|
31768
31794
|
}
|
|
31795
|
+
try {
|
|
31796
|
+
const draftPromotion = await Effect.runPromise(promoteWorkspacePrdDraft({
|
|
31797
|
+
projectRoot: projectPath,
|
|
31798
|
+
workspacePath,
|
|
31799
|
+
issueId: id
|
|
31800
|
+
}));
|
|
31801
|
+
if (draftPromotion.promoted) emitCompletePlanningPhase(id, "prdPromote", "success", `promoted ${draftPromotion.source} -> ${draftPromotion.path}`);
|
|
31802
|
+
else emitCompletePlanningPhase(id, "prdPromote", "skipped", draftPromotion.reason);
|
|
31803
|
+
} catch (error) {
|
|
31804
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
31805
|
+
emitCompletePlanningPhase(id, "prdPromote", "failure", reason);
|
|
31806
|
+
return jsonResponse({ error: `PRD draft promotion failed for ${id.toUpperCase()}: ${reason}` }, { status: 500 });
|
|
31807
|
+
}
|
|
31769
31808
|
const workspacePlanPath = await (async () => await Effect.runPromise(findWorkspaceDraftPlan(workspacePath)) ?? await Effect.runPromise(findPlan(workspacePath)))();
|
|
31770
31809
|
if (workspacePlanPath) {
|
|
31771
31810
|
const workspaceDoc = await Effect.runPromise(readPlan(workspacePlanPath));
|
|
@@ -31773,7 +31812,7 @@ async function completePlanningForIssue(options) {
|
|
|
31773
31812
|
assertPlanQuality(workspaceDoc);
|
|
31774
31813
|
} catch (error) {
|
|
31775
31814
|
if (error instanceof PlanQualityLintError) return jsonResponse({
|
|
31776
|
-
error: "
|
|
31815
|
+
error: "xBRIEF quality lint failed",
|
|
31777
31816
|
qualityIssues: error.issues
|
|
31778
31817
|
}, { status: 422 });
|
|
31779
31818
|
throw error;
|
|
@@ -31790,7 +31829,7 @@ async function completePlanningForIssue(options) {
|
|
|
31790
31829
|
issueId: id
|
|
31791
31830
|
});
|
|
31792
31831
|
console.log(`[complete-planning] Wrote pan spec to ${proposed.path}`);
|
|
31793
|
-
console.log(`[complete-planning] Finalized ${taskCount}
|
|
31832
|
+
console.log(`[complete-planning] Finalized ${taskCount} xBRIEF tasks for ${upperIssueId}`);
|
|
31794
31833
|
const project = findProjectByPathSync(projectPath);
|
|
31795
31834
|
const migrated = project ? await isStateMigrated(project) : false;
|
|
31796
31835
|
const filesToStage = completePlanningFilesToStage(projectPath, proposed.filename, migrated);
|
|
@@ -31798,7 +31837,7 @@ async function completePlanningForIssue(options) {
|
|
|
31798
31837
|
if (migrated) await Effect.runPromise(flushAutoCommits(projectPath));
|
|
31799
31838
|
else if (!projectIsGitRepo) console.log(`[complete-planning] Project root ${projectPath} is not a git repository (polyrepo) — pan spec updated on disk but not committed`);
|
|
31800
31839
|
else {
|
|
31801
|
-
const { stdout: branchStdout } = await execFileAsync$
|
|
31840
|
+
const { stdout: branchStdout } = await execFileAsync$16("git", [
|
|
31802
31841
|
"rev-parse",
|
|
31803
31842
|
"--abbrev-ref",
|
|
31804
31843
|
"HEAD"
|
|
@@ -31808,7 +31847,7 @@ async function completePlanningForIssue(options) {
|
|
|
31808
31847
|
});
|
|
31809
31848
|
const currentBranch = branchStdout.trim();
|
|
31810
31849
|
if (currentBranch === "main") {
|
|
31811
|
-
await execFileAsync$
|
|
31850
|
+
await execFileAsync$16("git", [
|
|
31812
31851
|
"add",
|
|
31813
31852
|
"--",
|
|
31814
31853
|
...filesToStage
|
|
@@ -31817,7 +31856,7 @@ async function completePlanningForIssue(options) {
|
|
|
31817
31856
|
encoding: "utf-8"
|
|
31818
31857
|
});
|
|
31819
31858
|
try {
|
|
31820
|
-
await execFileAsync$
|
|
31859
|
+
await execFileAsync$16("git", [
|
|
31821
31860
|
"diff",
|
|
31822
31861
|
"--cached",
|
|
31823
31862
|
"--quiet",
|
|
@@ -31828,10 +31867,10 @@ async function completePlanningForIssue(options) {
|
|
|
31828
31867
|
encoding: "utf-8"
|
|
31829
31868
|
});
|
|
31830
31869
|
} catch {
|
|
31831
|
-
await execFileAsync$
|
|
31870
|
+
await execFileAsync$16("git", [
|
|
31832
31871
|
"commit",
|
|
31833
31872
|
"-m",
|
|
31834
|
-
`chore(scope): propose ${upperIssueId}
|
|
31873
|
+
`chore(scope): propose ${upperIssueId} xBRIEF`,
|
|
31835
31874
|
"--no-verify",
|
|
31836
31875
|
"--",
|
|
31837
31876
|
...filesToStage
|
|
@@ -31841,7 +31880,7 @@ async function completePlanningForIssue(options) {
|
|
|
31841
31880
|
});
|
|
31842
31881
|
console.log(`[complete-planning] Committed pan spec on main for ${upperIssueId}`);
|
|
31843
31882
|
try {
|
|
31844
|
-
const { stdout: remotes } = await execFileAsync$
|
|
31883
|
+
const { stdout: remotes } = await execFileAsync$16("git", ["remote"], {
|
|
31845
31884
|
cwd: projectPath,
|
|
31846
31885
|
encoding: "utf-8"
|
|
31847
31886
|
});
|
|
@@ -31854,16 +31893,16 @@ async function completePlanningForIssue(options) {
|
|
|
31854
31893
|
}
|
|
31855
31894
|
} else console.log(`[complete-planning] Project root not on main (${currentBranch}) — pan spec updated on disk but not committed on main`);
|
|
31856
31895
|
}
|
|
31857
|
-
if (!existsSync$1(join(gitRoot, ".git"))) await execFileAsync$
|
|
31896
|
+
if (!existsSync$1(join(gitRoot, ".git"))) await execFileAsync$16("git", ["init"], {
|
|
31858
31897
|
cwd: gitRoot,
|
|
31859
31898
|
encoding: "utf-8"
|
|
31860
31899
|
});
|
|
31861
|
-
for (const args of completePlanningWorkspaceGitAddCommands(gitRoot, migrated)) await execFileAsync$
|
|
31900
|
+
for (const args of completePlanningWorkspaceGitAddCommands(gitRoot, migrated)) await execFileAsync$16("git", args, {
|
|
31862
31901
|
cwd: gitRoot,
|
|
31863
31902
|
encoding: "utf-8"
|
|
31864
31903
|
});
|
|
31865
31904
|
try {
|
|
31866
|
-
await execFileAsync$
|
|
31905
|
+
await execFileAsync$16("git", [
|
|
31867
31906
|
"diff",
|
|
31868
31907
|
"--cached",
|
|
31869
31908
|
"--quiet"
|
|
@@ -31872,7 +31911,7 @@ async function completePlanningForIssue(options) {
|
|
|
31872
31911
|
encoding: "utf-8"
|
|
31873
31912
|
});
|
|
31874
31913
|
} catch {
|
|
31875
|
-
await execFileAsync$
|
|
31914
|
+
await execFileAsync$16("git", [
|
|
31876
31915
|
"commit",
|
|
31877
31916
|
"-m",
|
|
31878
31917
|
`chore(plan): complete planning for ${id}`,
|
|
@@ -31883,7 +31922,7 @@ async function completePlanningForIssue(options) {
|
|
|
31883
31922
|
});
|
|
31884
31923
|
}
|
|
31885
31924
|
try {
|
|
31886
|
-
const { stdout: remotes } = await execFileAsync$
|
|
31925
|
+
const { stdout: remotes } = await execFileAsync$16("git", ["remote"], {
|
|
31887
31926
|
cwd: gitRoot,
|
|
31888
31927
|
encoding: "utf-8"
|
|
31889
31928
|
});
|
|
@@ -31948,19 +31987,6 @@ async function completePlanningForIssue(options) {
|
|
|
31948
31987
|
});
|
|
31949
31988
|
} catch {}
|
|
31950
31989
|
invalidateAgentsCache();
|
|
31951
|
-
emitActivityEntrySync({
|
|
31952
|
-
source: "plan",
|
|
31953
|
-
level: "info",
|
|
31954
|
-
message: `${id} planning complete — ready for work`,
|
|
31955
|
-
issueId: id
|
|
31956
|
-
});
|
|
31957
|
-
emitActivityTtsSync({
|
|
31958
|
-
utterance: `${id} planning complete, ready for work`,
|
|
31959
|
-
priority: 2,
|
|
31960
|
-
issueId: id,
|
|
31961
|
-
source: "planning-agent",
|
|
31962
|
-
eventType: "planning.complete"
|
|
31963
|
-
});
|
|
31964
31990
|
const effectiveAutoSpawn = autoSpawn || completePlanningLease.autoSpawnRequested();
|
|
31965
31991
|
if (effectiveAutoSpawn && workspacePath) await commitWorkspaceRecordBeforeAutoSpawn(workspacePath, id);
|
|
31966
31992
|
const autoSpawnResult = await completePlanningAutoSpawnAndKill({
|
|
@@ -31969,7 +31995,29 @@ async function completePlanningForIssue(options) {
|
|
|
31969
31995
|
skipKill,
|
|
31970
31996
|
sessionName
|
|
31971
31997
|
});
|
|
31972
|
-
|
|
31998
|
+
const autoHandoffFailed = effectiveAutoSpawn && autoSpawnResult?.workAgentSpawned !== true;
|
|
31999
|
+
let autoHandoffError;
|
|
32000
|
+
if (autoHandoffFailed && autoSpawnResult) autoHandoffError = await recordPlanningAutoHandoffFailure({
|
|
32001
|
+
issueId: id,
|
|
32002
|
+
result: autoSpawnResult,
|
|
32003
|
+
eventStore
|
|
32004
|
+
});
|
|
32005
|
+
else {
|
|
32006
|
+
emitActivityEntrySync({
|
|
32007
|
+
source: "plan",
|
|
32008
|
+
level: "info",
|
|
32009
|
+
message: autoSpawnResult?.workAgentSpawned ? `${id} planning complete — work-agent startup accepted` : `${id} planning complete — ready for work`,
|
|
32010
|
+
issueId: id
|
|
32011
|
+
});
|
|
32012
|
+
emitActivityTtsSync({
|
|
32013
|
+
utterance: autoSpawnResult?.workAgentSpawned ? `${id} planning complete, work agent starting` : `${id} planning complete, ready for work`,
|
|
32014
|
+
priority: 2,
|
|
32015
|
+
issueId: id,
|
|
32016
|
+
source: "planning-agent",
|
|
32017
|
+
eventType: "planning.complete"
|
|
32018
|
+
});
|
|
32019
|
+
}
|
|
32020
|
+
emitCompletePlanningPhase(id, "terminal", resolveCompletePlanningTerminalStatus(effectiveAutoSpawn, autoSpawnResult), autoSpawnResult?.workAgentSpawned ? "planning complete and work agent spawn requested" : autoSpawnResult?.workAgentSkipReason ?? "planning complete", {
|
|
31973
32021
|
autoSpawn: effectiveAutoSpawn,
|
|
31974
32022
|
workAgentSpawned: autoSpawnResult?.workAgentSpawned ?? false,
|
|
31975
32023
|
workAgentSkipReason: autoSpawnResult?.workAgentSkipReason
|
|
@@ -31981,7 +32029,7 @@ async function completePlanningForIssue(options) {
|
|
|
31981
32029
|
gitPushed,
|
|
31982
32030
|
...taskWarning ? { taskWarning } : {},
|
|
31983
32031
|
...autoSpawnResult ?? {},
|
|
31984
|
-
message: autoSpawnResult?.workAgentSpawned ? "Planning complete and work agent spawn requested" : gitPushed ? "Planning complete and pushed to git - ready for execution" : "Planning complete - ready for execution"
|
|
32032
|
+
message: autoHandoffFailed ? `Planning complete, but work-agent startup failed (${autoSpawnResult?.workAgentSkipReason ?? "spawn-failed"}): ${autoHandoffError}` : autoSpawnResult?.workAgentSpawned ? "Planning complete and work agent spawn requested" : gitPushed ? "Planning complete and pushed to git - ready for execution" : "Planning complete - ready for execution"
|
|
31985
32033
|
});
|
|
31986
32034
|
} finally {
|
|
31987
32035
|
completePlanningLease.release();
|
|
@@ -32063,7 +32111,7 @@ init_tracker_utils();
|
|
|
32063
32111
|
init_agents$1();
|
|
32064
32112
|
init_issue_id();
|
|
32065
32113
|
const execAsync$8 = promisify(exec);
|
|
32066
|
-
const execFileAsync$
|
|
32114
|
+
const execFileAsync$15 = promisify(execFile);
|
|
32067
32115
|
function isGitHubIssue$4(issueId) {
|
|
32068
32116
|
const resolved = resolveGitHubIssueSync(issueId);
|
|
32069
32117
|
if (resolved.isGitHub) return {
|
|
@@ -32102,7 +32150,7 @@ async function closeIssuePullRequest(issueId, reason = "Canceled via Overdeck")
|
|
|
32102
32150
|
if (!githubCheck.isGitHub || !githubCheck.owner || !githubCheck.repo) return ["No GitHub PR to close"];
|
|
32103
32151
|
const branchName = `feature/${issueId.toLowerCase()}`;
|
|
32104
32152
|
try {
|
|
32105
|
-
const { stdout: prListRaw } = await execFileAsync$
|
|
32153
|
+
const { stdout: prListRaw } = await execFileAsync$15("gh", [
|
|
32106
32154
|
"pr",
|
|
32107
32155
|
"list",
|
|
32108
32156
|
"--repo",
|
|
@@ -32121,7 +32169,7 @@ async function closeIssuePullRequest(issueId, reason = "Canceled via Overdeck")
|
|
|
32121
32169
|
});
|
|
32122
32170
|
const prNumber = prListRaw.trim();
|
|
32123
32171
|
if (!prNumber) return ["No open PR found for branch"];
|
|
32124
|
-
await execFileAsync$
|
|
32172
|
+
await execFileAsync$15("gh", [
|
|
32125
32173
|
"pr",
|
|
32126
32174
|
"close",
|
|
32127
32175
|
prNumber,
|
|
@@ -32134,7 +32182,7 @@ async function closeIssuePullRequest(issueId, reason = "Canceled via Overdeck")
|
|
|
32134
32182
|
timeout: 15e3
|
|
32135
32183
|
});
|
|
32136
32184
|
try {
|
|
32137
|
-
const { setReviewStatusSync } = await import("./review-status-
|
|
32185
|
+
const { setReviewStatusSync } = await import("./review-status-C6n6-9f_.js");
|
|
32138
32186
|
setReviewStatusSync(issueId.toUpperCase(), { prUrl: void 0 });
|
|
32139
32187
|
} catch {}
|
|
32140
32188
|
return [`Closed PR #${prNumber} on ${githubCheck.owner}/${githubCheck.repo}`];
|
|
@@ -32188,7 +32236,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
|
|
|
32188
32236
|
const { ctx, projectConfig } = buildLifecycleContext(id, getIssueDataService$8().getIssueSource(id) ?? void 0);
|
|
32189
32237
|
const deleteWorkspace = opts.deleteWorkspace ?? true;
|
|
32190
32238
|
cleanupLog.push(...await closeIssuePullRequest(id, mode === "cancel" ? "Canceled via Overdeck" : "Reset to Todo via Overdeck"));
|
|
32191
|
-
const { resetToTodo, cancelIssueWorkflow } = await import("./lifecycle-
|
|
32239
|
+
const { resetToTodo, cancelIssueWorkflow } = await import("./lifecycle-sycO16hj.js");
|
|
32192
32240
|
const workflow = mode === "cancel" ? cancelIssueWorkflow : resetToTodo;
|
|
32193
32241
|
const result = await Effect.runPromise(workflow(ctx, {
|
|
32194
32242
|
deleteWorkspace,
|
|
@@ -32203,16 +32251,16 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
|
|
|
32203
32251
|
}));
|
|
32204
32252
|
cleanupLog.push(...result.steps.flatMap((step) => step.details || [step.error].filter(Boolean)));
|
|
32205
32253
|
if (mode === "cancel") try {
|
|
32206
|
-
const {
|
|
32207
|
-
const tx = await Effect.runPromise(
|
|
32208
|
-
if (tx.moved) cleanupLog.push(`
|
|
32209
|
-
if (tx.committed) cleanupLog.push(`Committed
|
|
32254
|
+
const { transitionXBriefOnMain } = await import("./lifecycle-io-Bsnr2K4F.js");
|
|
32255
|
+
const tx = await Effect.runPromise(transitionXBriefOnMain(ctx.projectPath, id, "cancelled", "cancelled", `scope: cancel ${id.toUpperCase()} xBRIEF`));
|
|
32256
|
+
if (tx.moved) cleanupLog.push(`xBRIEF moved ${tx.fromDir} → cancelled`);
|
|
32257
|
+
if (tx.committed) cleanupLog.push(`Committed xBRIEF cancellation on main`);
|
|
32210
32258
|
} catch (err) {
|
|
32211
|
-
cleanupLog.push(`
|
|
32259
|
+
cleanupLog.push(`xBRIEF cancel transition failed (non-fatal): ${err?.message ?? err}`);
|
|
32212
32260
|
}
|
|
32213
32261
|
try {
|
|
32214
|
-
const { killAllReviewerSessions } = await import("./review-agent-
|
|
32215
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
32262
|
+
const { killAllReviewerSessions } = await import("./review-agent-DJRO8EG8.js");
|
|
32263
|
+
const { resolveProjectFromIssueSync } = await import("./projects-9SkRpES9.js");
|
|
32216
32264
|
const projectKey = resolveProjectFromIssueSync(id)?.projectKey;
|
|
32217
32265
|
if (projectKey) {
|
|
32218
32266
|
const { killed } = await Effect.runPromise(killAllReviewerSessions(projectKey, id.toUpperCase()));
|
|
@@ -32226,7 +32274,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
|
|
|
32226
32274
|
cleanupLog.push("Cleared review status");
|
|
32227
32275
|
} catch {}
|
|
32228
32276
|
try {
|
|
32229
|
-
const { resetPostMergeState } = await import("./merge-agent-
|
|
32277
|
+
const { resetPostMergeState } = await import("./merge-agent-BQM3a8z5.js");
|
|
32230
32278
|
resetPostMergeState(id);
|
|
32231
32279
|
resetPostMergeState(id.toUpperCase());
|
|
32232
32280
|
cleanupLog.push("Cleared merge state");
|
|
@@ -32246,7 +32294,7 @@ function closeIssueTransition(options) {
|
|
|
32246
32294
|
const { issueId, body, eventStore } = options;
|
|
32247
32295
|
const { reason } = body;
|
|
32248
32296
|
const projectPath = getProjectPath$3(void 0, extractPrefixSync(issueId) ?? issueId.split("-")[0]);
|
|
32249
|
-
const { close: closeWorkflow } = yield* Effect.promise(() => import("./lifecycle-
|
|
32297
|
+
const { close: closeWorkflow } = yield* Effect.promise(() => import("./lifecycle-sycO16hj.js"));
|
|
32250
32298
|
const githubCheck = isGitHubIssue$4(issueId);
|
|
32251
32299
|
const issueDataService = getIssueDataService$8();
|
|
32252
32300
|
const issueSource = issueDataService.getIssueSource(issueId);
|
|
@@ -32513,7 +32561,7 @@ function reopenIssueTransition(options) {
|
|
|
32513
32561
|
else clearReviewStatus(id.toUpperCase());
|
|
32514
32562
|
} catch {}
|
|
32515
32563
|
try {
|
|
32516
|
-
const { resetPostMergeState } = await import("./merge-agent-
|
|
32564
|
+
const { resetPostMergeState } = await import("./merge-agent-BQM3a8z5.js");
|
|
32517
32565
|
resetPostMergeState(id);
|
|
32518
32566
|
resetPostMergeState(id.toUpperCase());
|
|
32519
32567
|
} catch {}
|
|
@@ -32577,7 +32625,7 @@ function moveIssueStatus(options) {
|
|
|
32577
32625
|
"done"
|
|
32578
32626
|
];
|
|
32579
32627
|
if (!targetStatus || !validStatuses.includes(targetStatus)) return jsonResponse({ error: `Invalid targetStatus. Must be one of: ${validStatuses.join(", ")}` }, { status: 400 });
|
|
32580
|
-
const { updateShadowState } = yield* Effect.promise(() => import("./shadow-state-
|
|
32628
|
+
const { updateShadowState } = yield* Effect.promise(() => import("./shadow-state-C2_epgx2.js"));
|
|
32581
32629
|
const issueState = {
|
|
32582
32630
|
backlog: "open",
|
|
32583
32631
|
todo: "open",
|
|
@@ -32804,7 +32852,7 @@ async function copySettingsToWorkspace(id) {
|
|
|
32804
32852
|
success: false,
|
|
32805
32853
|
error: "Workspace not found"
|
|
32806
32854
|
}, { status: 404 });
|
|
32807
|
-
const { copyOverdeckSettingsToWorkspaceSync } = await import("./workspace-manager-
|
|
32855
|
+
const { copyOverdeckSettingsToWorkspaceSync } = await import("./workspace-manager-ZTdJAy9M.js");
|
|
32808
32856
|
const result = copyOverdeckSettingsToWorkspaceSync(workspacePath);
|
|
32809
32857
|
return jsonResponse({
|
|
32810
32858
|
success: result.errors.length === 0 || result.copied.length > 0,
|
|
@@ -32835,7 +32883,7 @@ function generateTasksForIssue(id) {
|
|
|
32835
32883
|
const plan = readWorkspacePlanSync(join(projectPath, "workspaces", `feature-${issueLower}`));
|
|
32836
32884
|
if (!plan) return jsonResponse({
|
|
32837
32885
|
success: false,
|
|
32838
|
-
error: `No
|
|
32886
|
+
error: `No xBRIEF spec found on main for ${id} — run planning first.`
|
|
32839
32887
|
}, { status: 409 });
|
|
32840
32888
|
return jsonResponse({
|
|
32841
32889
|
success: true,
|
|
@@ -32858,7 +32906,7 @@ init_tracker_utils();
|
|
|
32858
32906
|
init_tmux();
|
|
32859
32907
|
init_typed_errors();
|
|
32860
32908
|
const execAsync$6 = promisify(exec);
|
|
32861
|
-
const execFileAsync$
|
|
32909
|
+
const execFileAsync$14 = promisify(execFile);
|
|
32862
32910
|
function getIssueDataService$6() {
|
|
32863
32911
|
return getSharedIssueService();
|
|
32864
32912
|
}
|
|
@@ -33158,7 +33206,7 @@ function abortPlanningForIssue(options) {
|
|
|
33158
33206
|
const featureWorkspacePath = join(projectPath, "workspaces", `feature-${issueIdentifier.toLowerCase()}`);
|
|
33159
33207
|
const plainWorkspacePath = join(projectPath, "workspaces", issueIdentifier.toLowerCase());
|
|
33160
33208
|
if (existsSync$1(existsSync$1(featureWorkspacePath) ? featureWorkspacePath : plainWorkspacePath)) {
|
|
33161
|
-
await execFileAsync$
|
|
33209
|
+
await execFileAsync$14("pan", [
|
|
33162
33210
|
"workspace",
|
|
33163
33211
|
"destroy",
|
|
33164
33212
|
issueIdentifier.toLowerCase(),
|
|
@@ -33267,7 +33315,7 @@ function restartFromPlan(options) {
|
|
|
33267
33315
|
});
|
|
33268
33316
|
const resetResult = yield* Effect.promise(async () => {
|
|
33269
33317
|
try {
|
|
33270
|
-
const { runGitResetHard } = await import("./dangerous-git-ops-
|
|
33318
|
+
const { runGitResetHard } = await import("./dangerous-git-ops-CT-IypG3.js");
|
|
33271
33319
|
async function findPlanningCommit(grep, label) {
|
|
33272
33320
|
try {
|
|
33273
33321
|
const { stdout } = await execAsync$6(`git log --grep="${grep.replace(/"/g, "\\\"")}" --format=%H -1`, {
|
|
@@ -33720,7 +33768,7 @@ function closeOutIssue(id, opts = {}) {
|
|
|
33720
33768
|
}
|
|
33721
33769
|
const closeOutResult = yield* Effect.promise(async () => {
|
|
33722
33770
|
try {
|
|
33723
|
-
const { closeOut } = await import("./lifecycle-
|
|
33771
|
+
const { closeOut } = await import("./lifecycle-sycO16hj.js");
|
|
33724
33772
|
return {
|
|
33725
33773
|
ok: true,
|
|
33726
33774
|
result: await Effect.runPromise(closeOut(ctx, {
|
|
@@ -33809,7 +33857,7 @@ function bulkCloseOut(body) {
|
|
|
33809
33857
|
const invalidIds = issueIds.filter((id) => !isValidIssueId(id));
|
|
33810
33858
|
if (invalidIds.length > 0) return jsonResponse({ error: `Invalid issue ID format: ${invalidIds.join(", ")}` }, { status: 400 });
|
|
33811
33859
|
const eventStore = yield* EventStoreService;
|
|
33812
|
-
const { closeOut } = yield* Effect.promise(() => import("./lifecycle-
|
|
33860
|
+
const { closeOut } = yield* Effect.promise(() => import("./lifecycle-sycO16hj.js"));
|
|
33813
33861
|
const issueDataService = getIssueDataService$5();
|
|
33814
33862
|
const tasks = [];
|
|
33815
33863
|
const agentChecks = yield* withConcurrencyLimit(issueIds.map((id) => Effect.promise(async () => {
|
|
@@ -33973,7 +34021,7 @@ init_issue_service_singleton();
|
|
|
33973
34021
|
init_domain_services();
|
|
33974
34022
|
init_linear_client();
|
|
33975
34023
|
promisify(exec);
|
|
33976
|
-
const execFileAsync$
|
|
34024
|
+
const execFileAsync$13 = promisify(execFile);
|
|
33977
34025
|
function getIssueDataService$4() {
|
|
33978
34026
|
return getSharedIssueService();
|
|
33979
34027
|
}
|
|
@@ -34008,7 +34056,7 @@ const getIssuesRoute = HttpRouter.add("GET", "/api/issues", httpHandler(Effect.g
|
|
|
34008
34056
|
}
|
|
34009
34057
|
}
|
|
34010
34058
|
const membershipByIssue = /* @__PURE__ */ new Map();
|
|
34011
|
-
const results =
|
|
34059
|
+
const results = readPipelineMembershipSnapshotsForProjects([...projects.values()]);
|
|
34012
34060
|
const successfulPaths = /* @__PURE__ */ new Set();
|
|
34013
34061
|
const failedPaths = /* @__PURE__ */ new Set();
|
|
34014
34062
|
for (const result of results) {
|
|
@@ -34035,8 +34083,8 @@ const getIssueShipLogRoute = HttpRouter.add("GET", "/api/issues/:id/ship-log", h
|
|
|
34035
34083
|
const id = (yield* HttpRouter.params)["id"] ?? "";
|
|
34036
34084
|
if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
|
|
34037
34085
|
return yield* Effect.promise(async () => {
|
|
34038
|
-
const { getShipLog } = await import("./ship-log-
|
|
34039
|
-
const { getReviewStatusSync } = await import("./review-status-
|
|
34086
|
+
const { getShipLog } = await import("./ship-log-ClSMIzZX.js");
|
|
34087
|
+
const { getReviewStatusSync } = await import("./review-status-C6n6-9f_.js");
|
|
34040
34088
|
const log = getShipLog(id);
|
|
34041
34089
|
const rs = getReviewStatusSync(id);
|
|
34042
34090
|
return jsonResponse({
|
|
@@ -34051,8 +34099,8 @@ const getIssueVerificationRoute = HttpRouter.add("GET", "/api/issues/:id/verific
|
|
|
34051
34099
|
const id = (yield* HttpRouter.params)["id"] ?? "";
|
|
34052
34100
|
if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
|
|
34053
34101
|
return yield* Effect.promise(async () => {
|
|
34054
|
-
const { readVerificationArtifact } = await import("./verification-artifact-
|
|
34055
|
-
const { getReviewStatusSync } = await import("./review-status-
|
|
34102
|
+
const { readVerificationArtifact } = await import("./verification-artifact-C-lIHfUa.js");
|
|
34103
|
+
const { getReviewStatusSync } = await import("./review-status-C6n6-9f_.js");
|
|
34056
34104
|
const { join } = await import("node:path");
|
|
34057
34105
|
const resolved = resolveProjectFromIssueSync(id);
|
|
34058
34106
|
const workspacePath = resolved ? join(resolved.projectPath, "workspaces", `feature-${id.toLowerCase()}`) : null;
|
|
@@ -34137,7 +34185,7 @@ const postIssueResetToPlannedRoute = HttpRouter.add("POST", "/api/issues/:id/res
|
|
|
34137
34185
|
if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
|
|
34138
34186
|
try {
|
|
34139
34187
|
const invocation = panCliInvocation(["reset-to-planned", id]);
|
|
34140
|
-
const { stdout } = yield* Effect.promise(() => execFileAsync$
|
|
34188
|
+
const { stdout } = yield* Effect.promise(() => execFileAsync$13(invocation.command, invocation.args, { encoding: "utf8" }));
|
|
34141
34189
|
invalidateAgentsCache();
|
|
34142
34190
|
return jsonResponse({
|
|
34143
34191
|
success: true,
|
|
@@ -34376,7 +34424,9 @@ const getPipelineMembershipRoute = HttpRouter.add("GET", "/api/pipeline/membersh
|
|
|
34376
34424
|
if (!projectKey) return jsonResponse({ error: "project query parameter is required" }, { status: 400 });
|
|
34377
34425
|
const project = getProjectSync(projectKey);
|
|
34378
34426
|
if (!project) return jsonResponse({ error: `Project not found: ${projectKey}` }, { status: 404 });
|
|
34379
|
-
|
|
34427
|
+
const snapshot = readPipelineMembershipSnapshotsForProjects([project])[0];
|
|
34428
|
+
if (snapshot?.memberships) return jsonResponse(snapshot.memberships);
|
|
34429
|
+
return jsonResponse({ error: "Pipeline membership snapshot is loading" }, { status: 503 });
|
|
34380
34430
|
})));
|
|
34381
34431
|
const getIssueResourceDetailsRoute = HttpRouter.add("GET", "/api/issues/:id/resource-details", httpHandler(Effect.gen(function* () {
|
|
34382
34432
|
return yield* getIssueResourceDetails((yield* HttpRouter.params)["id"] ?? "");
|
|
@@ -35048,8 +35098,7 @@ const cloisterRouteLayer = Layer.mergeAll(getCloisterStatusRoute, postCloisterSt
|
|
|
35048
35098
|
//#region routes/resources/agents-stats.ts
|
|
35049
35099
|
init_agents$1();
|
|
35050
35100
|
init_cost_sync();
|
|
35051
|
-
|
|
35052
|
-
const execFileAsync$13 = promisify(execFile);
|
|
35101
|
+
init_runtime_census();
|
|
35053
35102
|
const BURN_WINDOW_MS = 1800 * 1e3;
|
|
35054
35103
|
function buildAgentStatsSnapshot(options) {
|
|
35055
35104
|
const nowMs = options.nowMs ?? Date.now();
|
|
@@ -35116,27 +35165,19 @@ function getAgentStatsSnapshotEffect(deps = {}) {
|
|
|
35116
35165
|
});
|
|
35117
35166
|
});
|
|
35118
35167
|
}
|
|
35119
|
-
function parseProcessTable(psTable) {
|
|
35120
|
-
return psTable.split("\n").map((line) => line.trim()).filter(Boolean).flatMap((line) => {
|
|
35121
|
-
const match = line.match(/^(\d+)\s+(\d+)\s+([0-9.]+)\s+(\d+)$/);
|
|
35122
|
-
if (!match) return [];
|
|
35123
|
-
return [{
|
|
35124
|
-
pid: Number(match[1]),
|
|
35125
|
-
ppid: Number(match[2]),
|
|
35126
|
-
cpuPercent: Number(match[3]),
|
|
35127
|
-
rssBytes: Number(match[4]) * 1024
|
|
35128
|
-
}];
|
|
35129
|
-
});
|
|
35130
|
-
}
|
|
35131
35168
|
async function readBatchedProcessTable() {
|
|
35132
|
-
|
|
35133
|
-
|
|
35169
|
+
return [...(await getRuntimeCensus()).processesByPid.values()].map((process) => ({
|
|
35170
|
+
pid: process.pid,
|
|
35171
|
+
ppid: process.ppid,
|
|
35172
|
+
cpuPercent: process.cpuPercent,
|
|
35173
|
+
rssBytes: process.rssBytes
|
|
35174
|
+
}));
|
|
35134
35175
|
}
|
|
35135
35176
|
function defaultListSessionNames() {
|
|
35136
|
-
return
|
|
35177
|
+
return Effect.promise(async () => [...(await getRuntimeCensus()).sessionNames]);
|
|
35137
35178
|
}
|
|
35138
35179
|
function defaultListPanePids(sessionName) {
|
|
35139
|
-
return
|
|
35180
|
+
return Effect.promise(async () => panePidsForSession(await getRuntimeCensus(), sessionName));
|
|
35140
35181
|
}
|
|
35141
35182
|
function buildProcessTotalsByRoot(roots, processes) {
|
|
35142
35183
|
const processByPid = new Map(processes.map((process) => [process.pid, process]));
|
|
@@ -35165,7 +35206,7 @@ function buildProcessTotalsByRoot(roots, processes) {
|
|
|
35165
35206
|
}
|
|
35166
35207
|
totals.set(root.rootPid, {
|
|
35167
35208
|
processCount: seen.size,
|
|
35168
|
-
cpuPercent: roundOneDecimal$
|
|
35209
|
+
cpuPercent: roundOneDecimal$2(cpuPercent),
|
|
35169
35210
|
memoryBytes
|
|
35170
35211
|
});
|
|
35171
35212
|
}
|
|
@@ -35199,7 +35240,7 @@ function getIdleMinutes(lastActivity, nowMs) {
|
|
|
35199
35240
|
if (!Number.isFinite(lastActivityMs)) return 0;
|
|
35200
35241
|
return Math.max(0, Math.floor((nowMs - lastActivityMs) / 6e4));
|
|
35201
35242
|
}
|
|
35202
|
-
function roundOneDecimal$
|
|
35243
|
+
function roundOneDecimal$2(value) {
|
|
35203
35244
|
return Math.round(value * 10) / 10;
|
|
35204
35245
|
}
|
|
35205
35246
|
function roundCurrency(value) {
|
|
@@ -35207,7 +35248,6 @@ function roundCurrency(value) {
|
|
|
35207
35248
|
}
|
|
35208
35249
|
//#endregion
|
|
35209
35250
|
//#region services/event-loop-monitor.ts
|
|
35210
|
-
init_activity_logger();
|
|
35211
35251
|
const EVENT_LOOP_MONITOR_WINDOW_MS = 6e4;
|
|
35212
35252
|
let lastSample = {
|
|
35213
35253
|
p50: 0,
|
|
@@ -35227,7 +35267,6 @@ function sampleEventLoopDelay(histogram, deps = {}) {
|
|
|
35227
35267
|
const warnThresholdMs = deps.warnThresholdMs ?? 100;
|
|
35228
35268
|
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
35229
35269
|
const warn = deps.warn ?? ((message) => console.warn(message));
|
|
35230
|
-
const emit = deps.emit ?? emitActivityEntrySync;
|
|
35231
35270
|
const sample = {
|
|
35232
35271
|
p50: nsToRoundedMs(histogram.percentile(50)),
|
|
35233
35272
|
p99: nsToRoundedMs(histogram.percentile(99)),
|
|
@@ -35237,16 +35276,7 @@ function sampleEventLoopDelay(histogram, deps = {}) {
|
|
|
35237
35276
|
windowMs: EVENT_LOOP_MONITOR_WINDOW_MS
|
|
35238
35277
|
};
|
|
35239
35278
|
lastSample = sample;
|
|
35240
|
-
if (sample.p99 > warnThresholdMs) {
|
|
35241
|
-
const message = `Dashboard event loop p99 delay ${sample.p99}ms exceeded ${warnThresholdMs}ms`;
|
|
35242
|
-
warn(`[event-loop-monitor] ${message}`);
|
|
35243
|
-
emit({
|
|
35244
|
-
source: "dashboard",
|
|
35245
|
-
level: "warn",
|
|
35246
|
-
message,
|
|
35247
|
-
details: `p50=${sample.p50}ms p99=${sample.p99}ms max=${sample.max}ms over ${sample.windowMs}ms`
|
|
35248
|
-
});
|
|
35249
|
-
}
|
|
35279
|
+
if (sample.p99 > warnThresholdMs) warn(`[event-loop-monitor] Dashboard event loop p99 delay ${sample.p99}ms exceeded ${warnThresholdMs}ms`);
|
|
35250
35280
|
histogram.reset();
|
|
35251
35281
|
return sample;
|
|
35252
35282
|
}
|
|
@@ -35357,7 +35387,7 @@ function aggregateSupportFleet(processes) {
|
|
|
35357
35387
|
const supportProcesses = processes.filter(isSupportFleetProcess);
|
|
35358
35388
|
const members = supportProcesses.map((process) => process.command);
|
|
35359
35389
|
return {
|
|
35360
|
-
cpuPercent: roundOneDecimal$
|
|
35390
|
+
cpuPercent: roundOneDecimal$1(supportProcesses.reduce((sum, process) => sum + process.cpuPercent, 0)),
|
|
35361
35391
|
memoryBytes: supportProcesses.reduce((sum, process) => sum + process.memoryBytes, 0),
|
|
35362
35392
|
memberCount: supportProcesses.length,
|
|
35363
35393
|
members
|
|
@@ -35384,7 +35414,7 @@ function formatDuration(totalSeconds) {
|
|
|
35384
35414
|
if (minutes > 0) return `${minutes}m ${seconds}s`;
|
|
35385
35415
|
return `${seconds}s`;
|
|
35386
35416
|
}
|
|
35387
|
-
function roundOneDecimal$
|
|
35417
|
+
function roundOneDecimal$1(value) {
|
|
35388
35418
|
return Math.round(value * 10) / 10;
|
|
35389
35419
|
}
|
|
35390
35420
|
//#endregion
|
|
@@ -35410,7 +35440,7 @@ function buildCapacityForecast(stacks, options) {
|
|
|
35410
35440
|
}),
|
|
35411
35441
|
headroom: {
|
|
35412
35442
|
freeRamBytes: options.hostVitals.mem.availableBytes,
|
|
35413
|
-
loadHeadroom: Math.max(0, 100 - options.hostVitals.cpu.percent)
|
|
35443
|
+
loadHeadroom: options.hostVitals.cpu.percent === null ? null : Math.max(0, 100 - options.hostVitals.cpu.percent)
|
|
35414
35444
|
}
|
|
35415
35445
|
};
|
|
35416
35446
|
}
|
|
@@ -35481,8 +35511,8 @@ function buildHostProcesses(processes, options = {}) {
|
|
|
35481
35511
|
const row = {
|
|
35482
35512
|
...group,
|
|
35483
35513
|
pids: group.pids.sort((a, b) => a - b),
|
|
35484
|
-
cpuPercent: roundOneDecimal
|
|
35485
|
-
peakCpuPercent: roundOneDecimal
|
|
35514
|
+
cpuPercent: roundOneDecimal(group.cpuPercent),
|
|
35515
|
+
peakCpuPercent: roundOneDecimal(peakCpuPercent),
|
|
35486
35516
|
peakMemoryBytes
|
|
35487
35517
|
};
|
|
35488
35518
|
if (peakCpuPercent >= burstCpuThreshold) retainedBursts.set(group.id, {
|
|
@@ -35557,7 +35587,7 @@ function selectTopRows(rows, limit) {
|
|
|
35557
35587
|
for (const row of [...topByCpu, ...topByMemory]) merged.set(row.id, row);
|
|
35558
35588
|
return [...merged.values()].sort((a, b) => b.cpuPercent - a.cpuPercent || b.peakCpuPercent - a.peakCpuPercent).slice(0, limit);
|
|
35559
35589
|
}
|
|
35560
|
-
function roundOneDecimal
|
|
35590
|
+
function roundOneDecimal(value) {
|
|
35561
35591
|
return Math.round(value * 10) / 10;
|
|
35562
35592
|
}
|
|
35563
35593
|
//#endregion
|
|
@@ -35575,12 +35605,20 @@ let cachedDockerCounts = {
|
|
|
35575
35605
|
}
|
|
35576
35606
|
};
|
|
35577
35607
|
function buildHostVitalsSnapshot(options = {}) {
|
|
35578
|
-
const
|
|
35579
|
-
|
|
35580
|
-
|
|
35608
|
+
const metrics = options.hostMetrics;
|
|
35609
|
+
const cpuPercent = metrics?.cpuPercent ?? null;
|
|
35610
|
+
if (cpuPercent !== null) {
|
|
35611
|
+
cpuSpark.push(cpuPercent);
|
|
35612
|
+
cpuSpark = cpuSpark.slice(-CPU_SPARK_MAX);
|
|
35613
|
+
}
|
|
35581
35614
|
const dockerCounts = options.dockerStale ? cachedDockerCounts : computeDockerCounts(options.containers ?? [], options.networkCount ?? 0, options.networkPoolTotal ?? 31);
|
|
35582
35615
|
if (!options.dockerStale) cachedDockerCounts = dockerCounts;
|
|
35583
|
-
const memory =
|
|
35616
|
+
const memory = {
|
|
35617
|
+
usedBytes: metrics?.usedMemoryBytes ?? null,
|
|
35618
|
+
availableBytes: metrics?.availableMemoryBytes ?? null,
|
|
35619
|
+
swapUsedBytes: metrics?.swapUsedBytes ?? null,
|
|
35620
|
+
swapTotalBytes: metrics?.swapTotalBytes ?? null
|
|
35621
|
+
};
|
|
35584
35622
|
const disk = options.disk ?? {
|
|
35585
35623
|
usedBytes: 0,
|
|
35586
35624
|
freeBytes: 0,
|
|
@@ -35591,7 +35629,11 @@ function buildHostVitalsSnapshot(options = {}) {
|
|
|
35591
35629
|
stale: options.dockerStale === true,
|
|
35592
35630
|
cpu: {
|
|
35593
35631
|
percent: cpuPercent,
|
|
35594
|
-
load:
|
|
35632
|
+
load: [
|
|
35633
|
+
metrics?.loadAverage1m ?? null,
|
|
35634
|
+
null,
|
|
35635
|
+
null
|
|
35636
|
+
],
|
|
35595
35637
|
spark: [...cpuSpark]
|
|
35596
35638
|
},
|
|
35597
35639
|
mem: memory,
|
|
@@ -35637,26 +35679,6 @@ function computeAgentCounts(agents, fleet, nowMs) {
|
|
|
35637
35679
|
totalUsd: fleet.totalUsd ?? 0
|
|
35638
35680
|
};
|
|
35639
35681
|
}
|
|
35640
|
-
function getDefaultMemoryVitals() {
|
|
35641
|
-
const total = totalmem$1();
|
|
35642
|
-
const available = freemem$1();
|
|
35643
|
-
return {
|
|
35644
|
-
usedBytes: Math.max(0, total - available),
|
|
35645
|
-
availableBytes: available,
|
|
35646
|
-
swapUsedBytes: 0,
|
|
35647
|
-
swapTotalBytes: 0
|
|
35648
|
-
};
|
|
35649
|
-
}
|
|
35650
|
-
function normalizeLoad(load) {
|
|
35651
|
-
return [
|
|
35652
|
-
roundOneDecimal(load[0] ?? 0),
|
|
35653
|
-
roundOneDecimal(load[1] ?? 0),
|
|
35654
|
-
roundOneDecimal(load[2] ?? 0)
|
|
35655
|
-
];
|
|
35656
|
-
}
|
|
35657
|
-
function roundOneDecimal(value) {
|
|
35658
|
-
return Math.round(value * 10) / 10;
|
|
35659
|
-
}
|
|
35660
35682
|
//#endregion
|
|
35661
35683
|
//#region routes/resources/limits.ts
|
|
35662
35684
|
const OOM_WINDOW_MS = 1440 * 60 * 1e3;
|
|
@@ -35767,52 +35789,122 @@ function isClosedReviewStatus(issueId) {
|
|
|
35767
35789
|
}
|
|
35768
35790
|
//#endregion
|
|
35769
35791
|
//#region routes/resources/spawn-gate.ts
|
|
35770
|
-
let
|
|
35771
|
-
function mapSpawnGateDecision(decision) {
|
|
35772
|
-
|
|
35792
|
+
let readSystemHealthEvidenceSnapshot = () => getSystemHealthEvidenceSnapshot();
|
|
35793
|
+
function mapSpawnGateDecision(decision, accepted) {
|
|
35794
|
+
if (decision.health.freshness.status !== "fresh") {
|
|
35795
|
+
const reason = decision.health.freshness.status === "stale" ? {
|
|
35796
|
+
code: "admission.snapshot.stale",
|
|
35797
|
+
domain: "admission",
|
|
35798
|
+
severity: "critical",
|
|
35799
|
+
message: decision.error ?? `Spawn gate health is stale: ${decision.health.freshness.reason.message}`
|
|
35800
|
+
} : {
|
|
35801
|
+
code: "admission.snapshot.measuring",
|
|
35802
|
+
domain: "admission",
|
|
35803
|
+
severity: "info",
|
|
35804
|
+
message: decision.error ?? "Spawn gate health is still measuring."
|
|
35805
|
+
};
|
|
35806
|
+
return unavailableSpawnGate(accepted ?? null, reason, decision.warnings);
|
|
35807
|
+
}
|
|
35808
|
+
const admission = accepted?.admission;
|
|
35809
|
+
const state = admission ? strongestAdmissionState(admission.state, decision.blocked ? "blocked" : decision.requiresAcknowledgement ? "soft" : "open") : decision.blocked ? "blocked" : decision.requiresAcknowledgement ? "soft" : "open";
|
|
35810
|
+
const reasons = mergeAdmissionReasons(admission?.reasons ?? [], decision.warnings.map((warning) => ({
|
|
35811
|
+
code: warning.code,
|
|
35812
|
+
domain: "admission",
|
|
35813
|
+
severity: warning.severity,
|
|
35814
|
+
message: warning.message
|
|
35815
|
+
})));
|
|
35773
35816
|
return {
|
|
35774
|
-
state
|
|
35775
|
-
reason,
|
|
35817
|
+
state,
|
|
35818
|
+
reason: decision.error ?? decision.warnings[0]?.message ?? reasons[0]?.message ?? "",
|
|
35819
|
+
reasons,
|
|
35820
|
+
admittedWorkAgentCount: admission?.admittedWorkAgentCount ?? decision.health.summary.workAgentCount,
|
|
35776
35821
|
warnings: decision.warnings,
|
|
35777
|
-
pressure: spawnGatePressure(
|
|
35822
|
+
pressure: spawnGatePressure(state)
|
|
35778
35823
|
};
|
|
35779
35824
|
}
|
|
35780
|
-
function
|
|
35825
|
+
function getResourcesHealthEvidenceEffect() {
|
|
35781
35826
|
return Effect.tryPromise({
|
|
35782
|
-
try: () =>
|
|
35827
|
+
try: () => readSystemHealthEvidenceSnapshot(),
|
|
35783
35828
|
catch: (error) => error
|
|
35784
|
-
}).pipe(Effect.map((
|
|
35785
|
-
|
|
35786
|
-
|
|
35787
|
-
|
|
35829
|
+
}).pipe(Effect.map(({ accepted, compatibility }) => ({
|
|
35830
|
+
accepted,
|
|
35831
|
+
decision: evaluateSpawnGuardrails(compatibility)
|
|
35832
|
+
})), Effect.catch(() => Effect.succeed({
|
|
35833
|
+
accepted: null,
|
|
35834
|
+
decision: null
|
|
35835
|
+
})));
|
|
35836
|
+
}
|
|
35837
|
+
function getSpawnGatePayloadEffect(evidence) {
|
|
35838
|
+
return (evidence ? Effect.succeed(evidence) : getResourcesHealthEvidenceEffect()).pipe(Effect.map(({ accepted, decision }) => {
|
|
35839
|
+
if (!accepted || !decision) return unavailableSpawnGate(accepted);
|
|
35840
|
+
return mapSpawnGateDecision(decision, accepted);
|
|
35841
|
+
}));
|
|
35842
|
+
}
|
|
35843
|
+
function unavailableSpawnGate(accepted, unavailableReason, warnings = []) {
|
|
35844
|
+
const reasons = unavailableReason ? [unavailableReason] : accepted?.admission.reasons.length ? [...accepted.admission.reasons] : [{
|
|
35845
|
+
code: "admission.snapshot.unavailable",
|
|
35846
|
+
domain: "admission",
|
|
35847
|
+
severity: "critical",
|
|
35848
|
+
message: "Spawn gate health is unavailable."
|
|
35849
|
+
}];
|
|
35850
|
+
return {
|
|
35851
|
+
state: "unavailable",
|
|
35852
|
+
reason: reasons[0]?.message ?? "Spawn gate health is unavailable.",
|
|
35853
|
+
reasons,
|
|
35854
|
+
admittedWorkAgentCount: accepted?.admission.admittedWorkAgentCount ?? null,
|
|
35855
|
+
warnings,
|
|
35788
35856
|
pressure: 0,
|
|
35789
35857
|
stale: true
|
|
35790
|
-
}
|
|
35858
|
+
};
|
|
35791
35859
|
}
|
|
35792
|
-
function
|
|
35793
|
-
|
|
35794
|
-
|
|
35795
|
-
|
|
35860
|
+
function mergeAdmissionReasons(...reasonGroups) {
|
|
35861
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35862
|
+
return reasonGroups.flatMap((reasons) => reasons).filter((reason) => {
|
|
35863
|
+
const key = `${reason.code}::${reason.message}`;
|
|
35864
|
+
if (seen.has(key)) return false;
|
|
35865
|
+
seen.add(key);
|
|
35866
|
+
return true;
|
|
35867
|
+
});
|
|
35868
|
+
}
|
|
35869
|
+
function strongestAdmissionState(accepted, enforced) {
|
|
35870
|
+
if (accepted === "unavailable") return accepted;
|
|
35871
|
+
const rank = {
|
|
35872
|
+
open: 0,
|
|
35873
|
+
soft: 1,
|
|
35874
|
+
blocked: 2
|
|
35875
|
+
};
|
|
35876
|
+
return rank[accepted] >= rank[enforced] ? accepted : enforced;
|
|
35877
|
+
}
|
|
35878
|
+
function spawnGatePressure(state) {
|
|
35879
|
+
if (state === "blocked") return 100;
|
|
35880
|
+
if (state === "soft") return 67;
|
|
35881
|
+
if (state === "open") return 12;
|
|
35882
|
+
return 0;
|
|
35796
35883
|
}
|
|
35797
35884
|
//#endregion
|
|
35798
35885
|
//#region routes/resources/snapshot.ts
|
|
35799
35886
|
init_agents$1();
|
|
35800
|
-
|
|
35801
|
-
|
|
35802
|
-
|
|
35887
|
+
init_runtime_census();
|
|
35888
|
+
const RESOURCES_SNAPSHOT_INTERVAL_MS = 3e3;
|
|
35889
|
+
let resourcesSnapshotJson = null;
|
|
35890
|
+
let resourcesSnapshotRefresh = null;
|
|
35891
|
+
let resourcesSnapshotTimer = null;
|
|
35892
|
+
/** Build the resources payload from cached collectors and the SQLite agents table. */
|
|
35893
|
+
function buildResourcesPayloadEffect() {
|
|
35803
35894
|
return Effect.gen(function* () {
|
|
35804
35895
|
const containers = enrichContainersWithLimits(getCurrentDockerStats());
|
|
35805
35896
|
const agentStats = yield* getAgentStatsSnapshotEffect();
|
|
35806
|
-
const
|
|
35897
|
+
const healthEvidence = yield* getResourcesHealthEvidenceEffect();
|
|
35898
|
+
const spawnGate = yield* getSpawnGatePayloadEffect(healthEvidence);
|
|
35807
35899
|
const stoppedContainers = [];
|
|
35808
|
-
const
|
|
35809
|
-
const tmuxSessionNames = new Set(sessions.map((s) => s.name));
|
|
35900
|
+
const tmuxSessionNames = (yield* Effect.promise(() => getRuntimeCensus()).pipe(Effect.catch(() => Effect.succeed(null))))?.sessionNames ?? /* @__PURE__ */ new Set();
|
|
35810
35901
|
const agents = listAgentStates().filter((state) => state.status !== "stopped").map((state) => ({
|
|
35811
35902
|
...state,
|
|
35812
35903
|
hasLiveTmuxSession: tmuxSessionNames.has(state.id)
|
|
35813
35904
|
}));
|
|
35814
35905
|
const agentStatsById = new Map(agentStats.agents.map((agent) => [agent.id, agent]));
|
|
35815
35906
|
const baseHostVitals = buildHostVitalsSnapshot({
|
|
35907
|
+
hostMetrics: healthEvidence.accepted?.host.metrics,
|
|
35816
35908
|
containers,
|
|
35817
35909
|
agents: agents.map((agent) => ({
|
|
35818
35910
|
id: String(agent.id),
|
|
@@ -35830,7 +35922,7 @@ function getResourcesEffect() {
|
|
|
35830
35922
|
reclaimableBytes: reclaim.reclaimTotals.diskBytes
|
|
35831
35923
|
}
|
|
35832
35924
|
};
|
|
35833
|
-
return
|
|
35925
|
+
return {
|
|
35834
35926
|
agents: agents.map((agent) => ({
|
|
35835
35927
|
...agent,
|
|
35836
35928
|
resourceStats: agentStatsById.get(String(agent.id)) ?? null
|
|
@@ -35849,10 +35941,39 @@ function getResourcesEffect() {
|
|
|
35849
35941
|
stacks,
|
|
35850
35942
|
volumes: [],
|
|
35851
35943
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
35852
|
-
}
|
|
35944
|
+
};
|
|
35945
|
+
});
|
|
35946
|
+
}
|
|
35947
|
+
function refreshResourcesSnapshot() {
|
|
35948
|
+
if (resourcesSnapshotRefresh) return resourcesSnapshotRefresh;
|
|
35949
|
+
resourcesSnapshotRefresh = Effect.runPromise(buildResourcesPayloadEffect()).then((payload) => {
|
|
35950
|
+
resourcesSnapshotJson = JSON.stringify(payload);
|
|
35951
|
+
}).finally(() => {
|
|
35952
|
+
resourcesSnapshotRefresh = null;
|
|
35853
35953
|
});
|
|
35954
|
+
return resourcesSnapshotRefresh;
|
|
35955
|
+
}
|
|
35956
|
+
function getResourcesSnapshotEffect() {
|
|
35957
|
+
return Effect.sync(() => resourcesSnapshotJson ? jsonStringResponse(resourcesSnapshotJson) : jsonResponse({ error: "Resources snapshot is warming" }, 503));
|
|
35854
35958
|
}
|
|
35855
|
-
|
|
35959
|
+
function startResourcesSnapshotService() {
|
|
35960
|
+
if (resourcesSnapshotTimer) return stopResourcesSnapshotService;
|
|
35961
|
+
refreshResourcesSnapshot().catch((error) => {
|
|
35962
|
+
console.warn("[resources-snapshot] initial refresh failed:", error instanceof Error ? error.message : error);
|
|
35963
|
+
});
|
|
35964
|
+
resourcesSnapshotTimer = setInterval(() => {
|
|
35965
|
+
refreshResourcesSnapshot().catch((error) => {
|
|
35966
|
+
console.warn("[resources-snapshot] refresh failed; keeping last-good snapshot:", error instanceof Error ? error.message : error);
|
|
35967
|
+
});
|
|
35968
|
+
}, RESOURCES_SNAPSHOT_INTERVAL_MS);
|
|
35969
|
+
resourcesSnapshotTimer.unref?.();
|
|
35970
|
+
return stopResourcesSnapshotService;
|
|
35971
|
+
}
|
|
35972
|
+
function stopResourcesSnapshotService() {
|
|
35973
|
+
if (resourcesSnapshotTimer) clearInterval(resourcesSnapshotTimer);
|
|
35974
|
+
resourcesSnapshotTimer = null;
|
|
35975
|
+
}
|
|
35976
|
+
const getResourcesRoute = HttpRouter.add("GET", "/api/resources", httpHandler(getResourcesSnapshotEffect()));
|
|
35856
35977
|
//#endregion
|
|
35857
35978
|
//#region routes/resources/containers.ts
|
|
35858
35979
|
init_domain_services();
|
|
@@ -38292,7 +38413,7 @@ async function fetchPlanningData(issueId, options = {}) {
|
|
|
38292
38413
|
}
|
|
38293
38414
|
} catch {}
|
|
38294
38415
|
if (!hasPlanningDir && !hasPanContinue) {
|
|
38295
|
-
const prd = await readPrdContent(
|
|
38416
|
+
const prd = await readPrdContent(findPrdAnywhereSync(projectPath, issueId));
|
|
38296
38417
|
if (prd) {
|
|
38297
38418
|
result.prd = prd;
|
|
38298
38419
|
result.hasPrd = true;
|
|
@@ -38320,16 +38441,11 @@ async function fetchPlanningData(issueId, options = {}) {
|
|
|
38320
38441
|
const fileStat = await stat$1(statusReviewPath).catch(() => null);
|
|
38321
38442
|
if (fileStat) result.statusReviewedAt = fileStat.mtime.toISOString();
|
|
38322
38443
|
}
|
|
38323
|
-
if (!result.prd)
|
|
38324
|
-
|
|
38325
|
-
"planned",
|
|
38326
|
-
"completed"
|
|
38327
|
-
]) {
|
|
38328
|
-
const content = await readPrdContent(findPrdAtStatusSync(projectPath, issueId, status));
|
|
38444
|
+
if (!result.prd) {
|
|
38445
|
+
const content = await readPrdContent(findPrdAnywhereSync(projectPath, issueId));
|
|
38329
38446
|
if (content) {
|
|
38330
38447
|
result.prd = content;
|
|
38331
38448
|
result.hasPrd = true;
|
|
38332
|
-
break;
|
|
38333
38449
|
}
|
|
38334
38450
|
}
|
|
38335
38451
|
if (!result.prd && result.state) result.prd = result.state;
|
|
@@ -38532,7 +38648,7 @@ ${issueContext ? `\n${issueContext}\n` : ""}
|
|
|
38532
38648
|
- Review: ${reviewStatus}
|
|
38533
38649
|
- Tests: ${testStatus}
|
|
38534
38650
|
|
|
38535
|
-
## Planning Context (continue.
|
|
38651
|
+
## Planning Context (.overdeck/continue.json)
|
|
38536
38652
|
${state ? state.slice(0, 4e3) : "(No planning state available)"}
|
|
38537
38653
|
|
|
38538
38654
|
## Files Changed
|
|
@@ -38574,7 +38690,7 @@ Be specific: reference actual file names, function names, requirement text, disc
|
|
|
38574
38690
|
const { command: cliCmd, args: cliArgs } = getAgentCommandSync(statusModelId);
|
|
38575
38691
|
const modelFlag = cliArgs.length > 0 ? ` ${cliArgs.join(" ")}` : "";
|
|
38576
38692
|
const promptFile = join(planningDir, ".status-review-prompt.tmp");
|
|
38577
|
-
const { getProviderForModelSync, getProviderEnvSync } = await import("./providers-
|
|
38693
|
+
const { getProviderForModelSync, getProviderEnvSync } = await import("./providers-DKkBXhxU.js");
|
|
38578
38694
|
let providerEnvStr = "";
|
|
38579
38695
|
let providerEnv = {};
|
|
38580
38696
|
const statusProvider = getProviderForModelSync(statusModelId);
|
|
@@ -38657,7 +38773,7 @@ const postMissionControlUploadRoute = HttpRouter.add("POST", "/api/command-deck/
|
|
|
38657
38773
|
let safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
38658
38774
|
let processedContent = content;
|
|
38659
38775
|
if (safeName.endsWith(".vtt")) {
|
|
38660
|
-
const { vttToMarkdown } = yield* Effect.promise(() => import("./vtt-parser-
|
|
38776
|
+
const { vttToMarkdown } = yield* Effect.promise(() => import("./vtt-parser-DKpNNW5i.js"));
|
|
38661
38777
|
processedContent = vttToMarkdown(content);
|
|
38662
38778
|
safeName = safeName.replace(/\.vtt$/, ".md");
|
|
38663
38779
|
}
|
|
@@ -44484,7 +44600,7 @@ const postRallyValidateRoute = HttpRouter.add("POST", "/api/rally/validate", Eff
|
|
|
44484
44600
|
}, { status: 400 });
|
|
44485
44601
|
return yield* Effect.promise(async () => {
|
|
44486
44602
|
try {
|
|
44487
|
-
const { RallyRestApi } = await import("./rally-api-
|
|
44603
|
+
const { RallyRestApi } = await import("./rally-api-yjQ0TfHd.js");
|
|
44488
44604
|
const api = new RallyRestApi({
|
|
44489
44605
|
apiKey,
|
|
44490
44606
|
server: server || "https://rally1.rallydev.com"
|
|
@@ -44516,15 +44632,9 @@ const postRallyValidateRoute = HttpRouter.add("POST", "/api/rally/validate", Eff
|
|
|
44516
44632
|
const trackersRouteLayer = Layer.mergeAll(postTrackersRefreshRoute, getTrackerStatusRoute, postRallyValidateRoute);
|
|
44517
44633
|
//#endregion
|
|
44518
44634
|
//#region ../lib/health-filtering.ts
|
|
44519
|
-
/**
|
|
44520
|
-
* Health filtering logic for dashboard health API
|
|
44521
|
-
* Determines which agents should be visible in health checks
|
|
44522
|
-
*/
|
|
44523
|
-
init_config$1();
|
|
44524
44635
|
init_tmux();
|
|
44525
|
-
const KICKOFF_STALL_GRACE_MS = 300 * 1e3;
|
|
44526
44636
|
/**
|
|
44527
|
-
* Check if agent tmux session is alive
|
|
44637
|
+
* Check if agent tmux session is alive.
|
|
44528
44638
|
*/
|
|
44529
44639
|
const checkAgentHealth = (agentId) => Effect.gen(function* () {
|
|
44530
44640
|
if (!(yield* sessionExists(agentId))) return { alive: false };
|
|
@@ -44533,133 +44643,196 @@ const checkAgentHealth = (agentId) => Effect.gen(function* () {
|
|
|
44533
44643
|
lastOutput: (yield* capturePane(agentId, 5)).trim()
|
|
44534
44644
|
};
|
|
44535
44645
|
}).pipe(Effect.catch(() => Effect.succeed({ alive: false })));
|
|
44536
|
-
/**
|
|
44537
|
-
* Determine health status based on activity
|
|
44538
|
-
* Returns null if agent should be hidden (completed/stopped/no state.json)
|
|
44539
|
-
*
|
|
44540
|
-
* `liveSessions` is REQUIRED — pass the session list fetched once per request.
|
|
44541
|
-
* Iterating ~150 agent dirs and spawning a tmux subprocess per agent was pinning
|
|
44542
|
-
* the dashboard process at 100% CPU on every 5s `/api/health/agents` poll.
|
|
44543
|
-
* State is also read before the tmux check so stopped/completed/missing
|
|
44544
|
-
* agents short-circuit without any extra work.
|
|
44545
|
-
*/
|
|
44546
|
-
const determineHealthStatus = (agentId, stateFile, liveSessions) => Effect.gen(function* () {
|
|
44547
|
-
let agentStatus;
|
|
44548
|
-
let lastActivity = null;
|
|
44549
|
-
let contextSaturatedAt;
|
|
44550
|
-
if (!existsSync(stateFile)) return null;
|
|
44551
|
-
const state = yield* Effect.tryPromise({
|
|
44552
|
-
try: () => readFile$1(stateFile, "utf-8").then((content) => JSON.parse(content)),
|
|
44553
|
-
catch: () => null
|
|
44554
|
-
}).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
44555
|
-
if (state === null) return null;
|
|
44556
|
-
agentStatus = state.status;
|
|
44557
|
-
lastActivity = state.lastActivity ? new Date(state.lastActivity) : null;
|
|
44558
|
-
if (!agentStatus) return null;
|
|
44559
|
-
if (agentStatus === "stopped" || agentStatus === "completed") return null;
|
|
44560
|
-
const runtimeFile = stateFile.replace("state.json", "runtime.json");
|
|
44561
|
-
if (existsSync(runtimeFile)) {
|
|
44562
|
-
const runtime = yield* Effect.tryPromise({
|
|
44563
|
-
try: () => readFile$1(runtimeFile, "utf-8").then((content) => JSON.parse(content)),
|
|
44564
|
-
catch: () => null
|
|
44565
|
-
}).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
44566
|
-
if (runtime?.lastActivity) {
|
|
44567
|
-
const runtimeDate = new Date(runtime.lastActivity);
|
|
44568
|
-
if (!lastActivity || runtimeDate > lastActivity) lastActivity = runtimeDate;
|
|
44569
|
-
}
|
|
44570
|
-
if (runtime?.contextSaturatedAt) contextSaturatedAt = runtime.contextSaturatedAt;
|
|
44571
|
-
}
|
|
44572
|
-
if (!liveSessions.has(agentId)) {
|
|
44573
|
-
const STALE_THRESHOLD_MS = ((yield* loadCloisterConfig()).retention?.health_staleness_hours ?? 24) * 60 * 60 * 1e3;
|
|
44574
|
-
if (lastActivity) {
|
|
44575
|
-
if (Date.now() - lastActivity.getTime() > STALE_THRESHOLD_MS) return null;
|
|
44576
|
-
} else return null;
|
|
44577
|
-
return {
|
|
44578
|
-
status: "dead",
|
|
44579
|
-
reason: "Agent crashed unexpectedly"
|
|
44580
|
-
};
|
|
44581
|
-
}
|
|
44582
|
-
if (contextSaturatedAt) return {
|
|
44583
|
-
status: "wedged",
|
|
44584
|
-
reason: "Context window exhausted (400) — recovery in progress"
|
|
44585
|
-
};
|
|
44586
|
-
const startedAtMs = typeof state.startedAt === "string" ? Date.parse(state.startedAt) : NaN;
|
|
44587
|
-
if (state.role === "work" && agentStatus === "running" && state.kickoffDelivered === false && Number.isFinite(startedAtMs) && Date.now() - startedAtMs > KICKOFF_STALL_GRACE_MS) return {
|
|
44588
|
-
status: "stalled",
|
|
44589
|
-
reason: "Work agent running with no kickoff delivered since spawn"
|
|
44590
|
-
};
|
|
44591
|
-
if (lastActivity) {
|
|
44592
|
-
const ageMinutes = (Date.now() - lastActivity.getTime()) / (1e3 * 60);
|
|
44593
|
-
if (ageMinutes > 30) return {
|
|
44594
|
-
status: "stuck",
|
|
44595
|
-
reason: `No activity for ${Math.round(ageMinutes)} minutes`
|
|
44596
|
-
};
|
|
44597
|
-
else if (ageMinutes > 15) return {
|
|
44598
|
-
status: "warning",
|
|
44599
|
-
reason: `Low activity (${Math.round(ageMinutes)} minutes)`
|
|
44600
|
-
};
|
|
44601
|
-
}
|
|
44602
|
-
return { status: "healthy" };
|
|
44603
|
-
});
|
|
44604
44646
|
//#endregion
|
|
44605
44647
|
//#region routes/misc/health.ts
|
|
44606
|
-
|
|
44607
|
-
|
|
44648
|
+
init_src();
|
|
44649
|
+
init_review_status_source();
|
|
44650
|
+
init_paths();
|
|
44651
|
+
init_runtime_census();
|
|
44608
44652
|
init_read_model();
|
|
44609
|
-
|
|
44610
|
-
|
|
44611
|
-
|
|
44612
|
-
|
|
44613
|
-
|
|
44653
|
+
function readHealthSessionNames(readSnapshot = getRuntimeCensusSnapshot) {
|
|
44654
|
+
const census = readSnapshot();
|
|
44655
|
+
if (!census) throw new Error("Runtime census snapshot is warming");
|
|
44656
|
+
return [...census.sessionNames];
|
|
44657
|
+
}
|
|
44658
|
+
function unavailableSystemHealthResponse() {
|
|
44614
44659
|
return jsonResponse({
|
|
44615
|
-
|
|
44616
|
-
|
|
44617
|
-
|
|
44618
|
-
|
|
44619
|
-
|
|
44660
|
+
status: "unavailable",
|
|
44661
|
+
reasons: [{
|
|
44662
|
+
code: "system.health_snapshot.unavailable",
|
|
44663
|
+
domain: "host",
|
|
44664
|
+
severity: "critical",
|
|
44665
|
+
message: "The accepted system health snapshot could not be produced or decoded."
|
|
44666
|
+
}]
|
|
44667
|
+
}, { status: 503 });
|
|
44668
|
+
}
|
|
44669
|
+
function decodeAcceptedSystemHealth(value) {
|
|
44670
|
+
const decoded = Schema.decodeUnknownResult(SystemHealthSnapshot)(value);
|
|
44671
|
+
if (decoded._tag === "Failure") throw new Error("The accepted system health snapshot failed shared-contract decoding.");
|
|
44672
|
+
return decoded.success;
|
|
44673
|
+
}
|
|
44674
|
+
function buildSystemHealthResponse(dependencies) {
|
|
44675
|
+
return dependencies.snapshot.pipe(Effect.map((snapshot) => jsonResponse(decodeAcceptedSystemHealth(snapshot))), Effect.catchCause(() => Effect.succeed(unavailableSystemHealthResponse())));
|
|
44676
|
+
}
|
|
44677
|
+
function buildGodviewSystemHealthResponse(dependencies) {
|
|
44678
|
+
return dependencies.snapshot.pipe(Effect.map((snapshot) => {
|
|
44679
|
+
const health = decodeAcceptedSystemHealth(snapshot);
|
|
44680
|
+
return jsonResponse({
|
|
44681
|
+
...health,
|
|
44682
|
+
cpu: health.summary.cpuPercent,
|
|
44683
|
+
memPercent: health.summary.memoryUsedPercent,
|
|
44684
|
+
memUsed: health.summary.usedMemoryBytes,
|
|
44685
|
+
memTotal: health.summary.totalMemoryBytes,
|
|
44686
|
+
updatedAt: health.updatedAt
|
|
44687
|
+
});
|
|
44688
|
+
}), Effect.catchCause(() => Effect.succeed(unavailableSystemHealthResponse())));
|
|
44689
|
+
}
|
|
44690
|
+
const getSystemHealthRoute = HttpRouter.add("GET", "/api/system/health", httpHandler(buildSystemHealthResponse({ snapshot: Effect.promise(() => getAcceptedSystemHealthSnapshot()) })));
|
|
44691
|
+
const getGodviewSystemHealthRoute = HttpRouter.add("GET", "/api/godview/system-health", httpHandler(buildGodviewSystemHealthResponse({ snapshot: Effect.promise(() => getAcceptedSystemHealthSnapshot()) })));
|
|
44692
|
+
const getDeployStalenessRoute = HttpRouter.add("GET", "/api/deploy/staleness", Effect.promise(async () => jsonResponse(await getDeployStaleness())));
|
|
44693
|
+
function finiteNumber(value) {
|
|
44694
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
44695
|
+
}
|
|
44696
|
+
async function readAgentHealthObservations(agentId) {
|
|
44697
|
+
if (!/^[A-Za-z0-9._-]+$/.test(agentId) || agentId.includes("..")) return {};
|
|
44698
|
+
const agentDir = join(getOverdeckHome(), "agents", agentId);
|
|
44699
|
+
const observations = {};
|
|
44700
|
+
try {
|
|
44701
|
+
const stored = JSON.parse(await readFile(join(agentDir, "health.json"), "utf-8"));
|
|
44702
|
+
if (stored && typeof stored === "object" && !Array.isArray(stored)) {
|
|
44703
|
+
const record = stored;
|
|
44704
|
+
const consecutiveFailures = finiteNumber(record["consecutiveFailures"]);
|
|
44705
|
+
const killCount = finiteNumber(record["killCount"]);
|
|
44706
|
+
if (consecutiveFailures !== void 0) observations.consecutiveFailures = consecutiveFailures;
|
|
44707
|
+
if (killCount !== void 0) observations.killCount = killCount;
|
|
44708
|
+
}
|
|
44709
|
+
} catch {}
|
|
44710
|
+
try {
|
|
44711
|
+
const raw = (await readFile(join(agentDir, "context-pct"), "utf-8")).trim();
|
|
44712
|
+
const contextPercent = raw === "" ? NaN : Number(raw);
|
|
44713
|
+
if (Number.isFinite(contextPercent)) observations.contextPercent = contextPercent;
|
|
44714
|
+
} catch {}
|
|
44715
|
+
return observations;
|
|
44716
|
+
}
|
|
44717
|
+
function runtimeHealthState(runtime) {
|
|
44718
|
+
if (!runtime) return null;
|
|
44719
|
+
switch (runtime.activity) {
|
|
44720
|
+
case "working":
|
|
44721
|
+
case "thinking": return {
|
|
44722
|
+
state: "active",
|
|
44723
|
+
lastActivity: runtime.lastActivity,
|
|
44724
|
+
contextSaturatedAt: runtime.contextSaturatedAt
|
|
44725
|
+
};
|
|
44726
|
+
case "waiting": return {
|
|
44727
|
+
state: "waiting-on-human",
|
|
44728
|
+
lastActivity: runtime.lastActivity,
|
|
44729
|
+
contextSaturatedAt: runtime.contextSaturatedAt
|
|
44730
|
+
};
|
|
44731
|
+
case "idle": return {
|
|
44732
|
+
state: "idle",
|
|
44733
|
+
lastActivity: runtime.lastActivity,
|
|
44734
|
+
contextSaturatedAt: runtime.contextSaturatedAt
|
|
44735
|
+
};
|
|
44736
|
+
case "stopped": return {
|
|
44737
|
+
state: "stopped",
|
|
44738
|
+
lastActivity: runtime.lastActivity,
|
|
44739
|
+
contextSaturatedAt: runtime.contextSaturatedAt
|
|
44740
|
+
};
|
|
44741
|
+
}
|
|
44742
|
+
}
|
|
44743
|
+
function decodeReviewStatuses(value) {
|
|
44744
|
+
const statuses = /* @__PURE__ */ new Map();
|
|
44745
|
+
for (const candidate of value ?? []) {
|
|
44746
|
+
const decoded = Schema.decodeUnknownResult(ReviewStatusSnapshot)(candidate);
|
|
44747
|
+
if (decoded._tag === "Success") statuses.set(decoded.success.issueId.toUpperCase(), decoded.success);
|
|
44748
|
+
}
|
|
44749
|
+
return statuses;
|
|
44750
|
+
}
|
|
44751
|
+
function reviewLifecycle(agent, statuses, tmuxActive) {
|
|
44752
|
+
if (agent.role !== "review" && agent.role !== "test" && agent.role !== "ship") return "unknown";
|
|
44753
|
+
return classifyAdvancingSessionLifecycle(agent.role, statuses.get(agent.issueId.toUpperCase()), tmuxActive);
|
|
44754
|
+
}
|
|
44755
|
+
function snapshotSource(value) {
|
|
44756
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("The canonical read model did not return an object.");
|
|
44757
|
+
const candidate = value;
|
|
44758
|
+
if (!Array.isArray(candidate["agents"])) throw new Error("The canonical read model did not return an agent array.");
|
|
44759
|
+
return {
|
|
44760
|
+
agents: candidate["agents"],
|
|
44761
|
+
agentRuntimeById: candidate["agentRuntimeById"],
|
|
44762
|
+
reviewStatuses: Array.isArray(candidate["reviewStatuses"]) ? candidate["reviewStatuses"] : void 0
|
|
44763
|
+
};
|
|
44764
|
+
}
|
|
44765
|
+
function runtimeRecord(value) {
|
|
44766
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
44767
|
+
}
|
|
44768
|
+
async function projectAgentHealth(snapshotValue, sessionNames, readObservations, nowMs) {
|
|
44769
|
+
const snapshot = snapshotSource(snapshotValue);
|
|
44770
|
+
const liveSessions = new Set(sessionNames);
|
|
44771
|
+
const runtimes = runtimeRecord(snapshot.agentRuntimeById);
|
|
44772
|
+
const reviewStatuses = decodeReviewStatuses(snapshot.reviewStatuses);
|
|
44773
|
+
return Promise.all(snapshot.agents.map(async (candidate, index) => {
|
|
44774
|
+
const decoded = Schema.decodeUnknownResult(AgentSnapshot)(candidate);
|
|
44775
|
+
if (decoded._tag === "Failure") {
|
|
44776
|
+
const candidateId = candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate["id"] : void 0;
|
|
44777
|
+
return classifyAgentHealth({
|
|
44778
|
+
agentId: typeof candidateId === "string" ? candidateId : `unavailable-agent-${index + 1}`,
|
|
44779
|
+
persisted: {
|
|
44780
|
+
status: "unavailable",
|
|
44781
|
+
reason: "The canonical agent snapshot could not be decoded."
|
|
44782
|
+
},
|
|
44783
|
+
runtime: null,
|
|
44784
|
+
liveSessions,
|
|
44785
|
+
reviewLifecycle: "unknown",
|
|
44786
|
+
nowMs
|
|
44787
|
+
});
|
|
44788
|
+
}
|
|
44789
|
+
const agent = decoded.success;
|
|
44790
|
+
const runtimeCandidate = Schema.decodeUnknownResult(AgentRuntimeSnapshot)(runtimes[agent.id]);
|
|
44791
|
+
const runtime = runtimeCandidate._tag === "Success" ? runtimeCandidate.success : null;
|
|
44792
|
+
const observations = await readObservations(agent.id).catch(() => ({}));
|
|
44793
|
+
return classifyAgentHealth({
|
|
44794
|
+
agentId: agent.id,
|
|
44795
|
+
persisted: {
|
|
44796
|
+
status: "available",
|
|
44797
|
+
value: {
|
|
44798
|
+
id: agent.id,
|
|
44799
|
+
issueId: agent.issueId,
|
|
44800
|
+
role: agent.role,
|
|
44801
|
+
status: agent.status,
|
|
44802
|
+
startedAt: agent.startedAt,
|
|
44803
|
+
lastActivity: agent.lastActivity,
|
|
44804
|
+
paused: agent.paused,
|
|
44805
|
+
stoppedByUser: agent.stoppedByUser,
|
|
44806
|
+
consecutiveFailures: agent.consecutiveFailures
|
|
44807
|
+
}
|
|
44808
|
+
},
|
|
44809
|
+
runtime: runtimeHealthState(runtime),
|
|
44810
|
+
liveSessions,
|
|
44811
|
+
reviewLifecycle: reviewLifecycle(agent, reviewStatuses, liveSessions.has(agent.id)),
|
|
44812
|
+
observations,
|
|
44813
|
+
nowMs
|
|
44814
|
+
});
|
|
44815
|
+
}));
|
|
44816
|
+
}
|
|
44817
|
+
function buildHealthAgentsResponse(dependencies) {
|
|
44818
|
+
return Effect.all({
|
|
44819
|
+
snapshot: dependencies.snapshot,
|
|
44820
|
+
sessionNames: dependencies.sessionNames
|
|
44821
|
+
}).pipe(Effect.flatMap(({ snapshot, sessionNames }) => Effect.promise(async () => jsonResponse(await projectAgentHealth(snapshot, sessionNames, dependencies.readObservations ?? readAgentHealthObservations, dependencies.nowMs ?? Date.now())))), Effect.catchCause(() => Effect.succeed(jsonResponse({
|
|
44822
|
+
status: "unavailable",
|
|
44823
|
+
reasons: [{
|
|
44824
|
+
code: "agent.health_snapshot.unavailable",
|
|
44825
|
+
domain: "agent",
|
|
44826
|
+
severity: "critical",
|
|
44827
|
+
message: "The canonical agent health snapshot could not be loaded."
|
|
44828
|
+
}]
|
|
44829
|
+
}, { status: 503 }))));
|
|
44830
|
+
}
|
|
44831
|
+
const getHealthAgentsRoute = HttpRouter.add("GET", "/api/health/agents", Effect.gen(function* () {
|
|
44832
|
+
return yield* buildHealthAgentsResponse({
|
|
44833
|
+
snapshot: (yield* ReadModelService).getSnapshot,
|
|
44834
|
+
sessionNames: Effect.sync(() => readHealthSessionNames())
|
|
44620
44835
|
});
|
|
44621
|
-
})));
|
|
44622
|
-
const getHealthAgentsRoute = HttpRouter.add("GET", "/api/health/agents", Effect.promise(async () => {
|
|
44623
|
-
try {
|
|
44624
|
-
const agentsDir = join(homedir$1(), ".overdeck", "agents");
|
|
44625
|
-
if (!existsSync$1(agentsDir)) return jsonResponse([]);
|
|
44626
|
-
const agentNames = (await readdir(agentsDir)).filter((name) => name.startsWith("agent-") || name.startsWith("planning-") || name.startsWith("specialist-"));
|
|
44627
|
-
const liveSessions = new Set(await Effect.runPromise(listSessionNames()));
|
|
44628
|
-
return jsonResponse((await Promise.all(agentNames.map(async (name) => {
|
|
44629
|
-
const stateFile = getAgentStateFilePath(name);
|
|
44630
|
-
const healthFile = join(agentsDir, name, "health.json");
|
|
44631
|
-
const healthStatus = await Effect.runPromise(determineHealthStatus(name, stateFile, liveSessions));
|
|
44632
|
-
if (!healthStatus) return null;
|
|
44633
|
-
let storedHealth = {
|
|
44634
|
-
consecutiveFailures: 0,
|
|
44635
|
-
killCount: 0
|
|
44636
|
-
};
|
|
44637
|
-
try {
|
|
44638
|
-
const healthContent = await readFile(healthFile, "utf-8");
|
|
44639
|
-
storedHealth = {
|
|
44640
|
-
...storedHealth,
|
|
44641
|
-
...JSON.parse(healthContent)
|
|
44642
|
-
};
|
|
44643
|
-
} catch {}
|
|
44644
|
-
let contextPercent = null;
|
|
44645
|
-
try {
|
|
44646
|
-
const ctxContent = await readFile(join(agentsDir, name, "context-pct"), "utf-8");
|
|
44647
|
-
contextPercent = parseInt(ctxContent.trim(), 10) || null;
|
|
44648
|
-
} catch {}
|
|
44649
|
-
return {
|
|
44650
|
-
agentId: name,
|
|
44651
|
-
status: healthStatus.status,
|
|
44652
|
-
reason: healthStatus.reason,
|
|
44653
|
-
lastPing: (/* @__PURE__ */ new Date()).toISOString(),
|
|
44654
|
-
consecutiveFailures: storedHealth.consecutiveFailures,
|
|
44655
|
-
killCount: storedHealth.killCount,
|
|
44656
|
-
contextPercent
|
|
44657
|
-
};
|
|
44658
|
-
}))).filter((agent) => agent !== null));
|
|
44659
|
-
} catch (error) {
|
|
44660
|
-
console.error("Error fetching health:", error);
|
|
44661
|
-
return jsonResponse([]);
|
|
44662
|
-
}
|
|
44663
44836
|
}));
|
|
44664
44837
|
const postHealthAgentPingRoute = HttpRouter.add("POST", "/api/health/agents/:id/ping", Effect.gen(function* () {
|
|
44665
44838
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
@@ -44681,7 +44854,7 @@ const postHealthAgentPingRoute = HttpRouter.add("POST", "/api/health/agents/:id/
|
|
|
44681
44854
|
}
|
|
44682
44855
|
});
|
|
44683
44856
|
}));
|
|
44684
|
-
const healthRouteLayer$1 = Layer.mergeAll(getSystemHealthRoute, getGodviewSystemHealthRoute, getHealthAgentsRoute, postHealthAgentPingRoute);
|
|
44857
|
+
const healthRouteLayer$1 = Layer.mergeAll(getSystemHealthRoute, getGodviewSystemHealthRoute, getDeployStalenessRoute, getHealthAgentsRoute, postHealthAgentPingRoute);
|
|
44685
44858
|
//#endregion
|
|
44686
44859
|
//#region routes/misc/deacon.ts
|
|
44687
44860
|
init_control_settings();
|
|
@@ -44812,7 +44985,7 @@ const getPlanningStatusRoute = HttpRouter.add("GET", "/api/planning/:issueId/sta
|
|
|
44812
44985
|
const remoteState = loadRemoteAgentState(sessionName);
|
|
44813
44986
|
const isRemote = !!remoteState;
|
|
44814
44987
|
const vmName = remoteState?.vmName ?? "";
|
|
44815
|
-
const { getAgentStateSync } = await import("./agents-
|
|
44988
|
+
const { getAgentStateSync } = await import("./agents-FlIgQ3ql.js");
|
|
44816
44989
|
const agentStarting = getAgentStateSync(sessionName)?.status === "starting";
|
|
44817
44990
|
let tmuxSessionAlive = false;
|
|
44818
44991
|
if (!isRemote) try {
|
|
@@ -44932,7 +45105,7 @@ const postPlanningMessageRoute = HttpRouter.add("POST", "/api/planning/:issueId/
|
|
|
44932
45105
|
**YOU SHOULD ONLY:**
|
|
44933
45106
|
- Ask clarifying questions
|
|
44934
45107
|
- Explore the codebase to understand context
|
|
44935
|
-
- Generate planning artifacts (\`.
|
|
45108
|
+
- Generate planning artifacts (\`.overdeck/continue.json\`, \`.overdeck/spec.vbrief.json\`)
|
|
44936
45109
|
- Present options and tradeoffs
|
|
44937
45110
|
|
|
44938
45111
|
---
|
|
@@ -44954,8 +45127,9 @@ ${message}
|
|
|
44954
45127
|
Continue the PLANNING session. Do NOT implement anything.
|
|
44955
45128
|
`);
|
|
44956
45129
|
const agentCwd = workspacePath;
|
|
45130
|
+
const harnessLaunch = await prepareHarnessLaunch("claude-code");
|
|
44957
45131
|
if (existsSync$1(outputFile)) await rename(outputFile, join(planningDir, `output-${Date.now()}.jsonl`));
|
|
44958
|
-
const { getAgentCommandSync } = await import("./settings-
|
|
45132
|
+
const { getAgentCommandSync } = await import("./settings-D0OSwos5.js");
|
|
44959
45133
|
let msgPlanningModel = "claude-sonnet-5";
|
|
44960
45134
|
try {
|
|
44961
45135
|
msgPlanningModel = resolveModel("plan", void 0, loadConfigSync().config);
|
|
@@ -44969,6 +45143,7 @@ Continue the PLANNING session. Do NOT implement anything.
|
|
|
44969
45143
|
role: "plan",
|
|
44970
45144
|
workingDir: agentCwd,
|
|
44971
45145
|
baseCommand: msgCmdWithArgs,
|
|
45146
|
+
extraEnvExports: [harnessLaunch.pathExport],
|
|
44972
45147
|
appendSystemPromptFiles: await claudePlanningSystemPromptFiles(agentCwd),
|
|
44973
45148
|
promptInline: `Please read the continuation prompt at ${continuationPromptPath} and continue the planning session.`
|
|
44974
45149
|
}), { mode: 493 });
|
|
@@ -45076,7 +45251,7 @@ async function getIndexStats(rootPath, isMain) {
|
|
|
45076
45251
|
}
|
|
45077
45252
|
const getTldrStatusRoute = HttpRouter.add("GET", "/api/services/tldr/status", Effect.promise(async () => {
|
|
45078
45253
|
try {
|
|
45079
|
-
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-
|
|
45254
|
+
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DL566HbH.js");
|
|
45080
45255
|
const projectRoot = process.cwd();
|
|
45081
45256
|
const venvPath = join(projectRoot, ".venv");
|
|
45082
45257
|
const results = [];
|
|
@@ -45121,7 +45296,7 @@ const getTldrStatusRoute = HttpRouter.add("GET", "/api/services/tldr/status", Ef
|
|
|
45121
45296
|
}));
|
|
45122
45297
|
const postTldrStartRoute = HttpRouter.add("POST", "/api/services/tldr/start", Effect.promise(async () => {
|
|
45123
45298
|
try {
|
|
45124
|
-
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-
|
|
45299
|
+
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DL566HbH.js");
|
|
45125
45300
|
const projectRoot = process.cwd();
|
|
45126
45301
|
const venvPath = join(projectRoot, ".venv");
|
|
45127
45302
|
if (!existsSync$1(venvPath)) return jsonResponse({ error: "No .venv found in project root" }, { status: 404 });
|
|
@@ -45138,7 +45313,7 @@ const postTldrStartRoute = HttpRouter.add("POST", "/api/services/tldr/start", Ef
|
|
|
45138
45313
|
}));
|
|
45139
45314
|
const postTldrStopRoute = HttpRouter.add("POST", "/api/services/tldr/stop", Effect.promise(async () => {
|
|
45140
45315
|
try {
|
|
45141
|
-
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-
|
|
45316
|
+
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DL566HbH.js");
|
|
45142
45317
|
const projectRoot = process.cwd();
|
|
45143
45318
|
const venvPath = join(projectRoot, ".venv");
|
|
45144
45319
|
if (!existsSync$1(venvPath)) return jsonResponse({ error: "No .venv found in project root" }, { status: 404 });
|
|
@@ -45155,7 +45330,7 @@ const postTldrStopRoute = HttpRouter.add("POST", "/api/services/tldr/stop", Effe
|
|
|
45155
45330
|
}));
|
|
45156
45331
|
const postTldrReloadRoute = HttpRouter.add("POST", "/api/services/tldr/reload", Effect.promise(async () => {
|
|
45157
45332
|
try {
|
|
45158
|
-
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-
|
|
45333
|
+
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DL566HbH.js");
|
|
45159
45334
|
const enabled = isTldrEnabledSync();
|
|
45160
45335
|
const projectRoot = process.cwd();
|
|
45161
45336
|
const targets = [];
|
|
@@ -45343,7 +45518,7 @@ const getVersionRoute = HttpRouter.add("GET", "/api/version", Effect.promise(asy
|
|
|
45343
45518
|
const version = await getOverdeckVersion();
|
|
45344
45519
|
let supervisorUrl = null;
|
|
45345
45520
|
try {
|
|
45346
|
-
const { getSupervisorUrlSync } = await import("./supervisor-
|
|
45521
|
+
const { getSupervisorUrlSync } = await import("./supervisor-BPy-o1A8.js");
|
|
45347
45522
|
supervisorUrl = getSupervisorUrlSync();
|
|
45348
45523
|
} catch {}
|
|
45349
45524
|
return jsonResponse({
|
|
@@ -45353,11 +45528,11 @@ const getVersionRoute = HttpRouter.add("GET", "/api/version", Effect.promise(asy
|
|
|
45353
45528
|
});
|
|
45354
45529
|
}));
|
|
45355
45530
|
const getPrerequisitesRoute = HttpRouter.add("GET", "/api/prerequisites", Effect.promise(async () => {
|
|
45356
|
-
const { checkSystemPrerequisites } = await import("./system-prerequisites-
|
|
45531
|
+
const { checkSystemPrerequisites } = await import("./system-prerequisites-Bza0ffAh.js");
|
|
45357
45532
|
return jsonResponse(await checkSystemPrerequisites());
|
|
45358
45533
|
}));
|
|
45359
45534
|
const getSetupDiagnosticsRoute = HttpRouter.add("GET", "/api/diagnostics/setup", Effect.promise(async () => {
|
|
45360
|
-
const { collectSetupDiagnostics } = await import("./system-prerequisites-
|
|
45535
|
+
const { collectSetupDiagnostics } = await import("./system-prerequisites-Bza0ffAh.js");
|
|
45361
45536
|
return jsonResponse(await collectSetupDiagnostics(await getOverdeckVersion()));
|
|
45362
45537
|
}));
|
|
45363
45538
|
const getSyncStatusRoute = HttpRouter.add("GET", "/api/sync-status", Effect.sync(() => {
|
|
@@ -45537,7 +45712,7 @@ const postShadowMonitorRoute = HttpRouter.add("POST", "/api/shadow/:issueId/moni
|
|
|
45537
45712
|
const projectPath = await getProjectPath(issuePrefix);
|
|
45538
45713
|
const workspacePath = join(projectPath, "workspaces", `feature-${issueLower}`);
|
|
45539
45714
|
if (!existsSync$1(workspacePath)) return jsonResponse({ error: "Workspace not found" }, { status: 404 });
|
|
45540
|
-
const { gatherArtifacts, generateBasicInference, updateInferenceDocumentSync } = await import("./shadow-engineering-
|
|
45715
|
+
const { gatherArtifacts, generateBasicInference, updateInferenceDocumentSync } = await import("./shadow-engineering-BlxG6Xye.js");
|
|
45541
45716
|
const config = {
|
|
45542
45717
|
issueId,
|
|
45543
45718
|
workspacePath,
|
|
@@ -45567,7 +45742,7 @@ const postShadowObserveRoute = HttpRouter.add("POST", "/api/shadow/:issueId/obse
|
|
|
45567
45742
|
if (!existsSync$1(workspacePath)) return jsonResponse({ error: "Workspace not found" }, { status: 404 });
|
|
45568
45743
|
const ghConfig = getGitHubConfig();
|
|
45569
45744
|
if (!ghConfig) return jsonResponse({ error: "GitHub not configured - Observer requires GitHub" }, { status: 400 });
|
|
45570
|
-
const { runObserverCycle } = await import("./shadow-engineering-
|
|
45745
|
+
const { runObserverCycle } = await import("./shadow-engineering-BlxG6Xye.js");
|
|
45571
45746
|
const firstRepo = ghConfig.repos[0];
|
|
45572
45747
|
const config = {
|
|
45573
45748
|
issueId,
|
|
@@ -46103,9 +46278,9 @@ const PAN_COMMANDS = [
|
|
|
46103
46278
|
},
|
|
46104
46279
|
{
|
|
46105
46280
|
name: "pan plan <id>",
|
|
46106
|
-
description: "Plan an issue (interactive
|
|
46281
|
+
description: "Plan an issue (interactive xBRIEF + tasks)",
|
|
46107
46282
|
group: "Issues",
|
|
46108
|
-
keywords: ["planning", "
|
|
46283
|
+
keywords: ["planning", "xbrief"]
|
|
46109
46284
|
},
|
|
46110
46285
|
{
|
|
46111
46286
|
name: "pan plan <id> --auto",
|
|
@@ -46807,6 +46982,17 @@ async function diffFilesSinceBase(repoRoot, baseCommit, filePaths) {
|
|
|
46807
46982
|
}
|
|
46808
46983
|
return diffs;
|
|
46809
46984
|
}
|
|
46985
|
+
async function diffPatchForFiles(repoRoot, createdAt, filePaths) {
|
|
46986
|
+
const baseCommit = await Effect.runPromise(findCommitAtTime(repoRoot, createdAt));
|
|
46987
|
+
if (!baseCommit) return Effect.runPromise(diffPatchFilesAgainstHead(repoRoot, filePaths));
|
|
46988
|
+
const quotedPaths = filePaths.map((p) => JSON.stringify(p)).join(" ");
|
|
46989
|
+
const { stdout } = await promisify(exec)(`git diff --patch --minimal --no-color ${baseCommit} -- ${quotedPaths}`, {
|
|
46990
|
+
cwd: repoRoot,
|
|
46991
|
+
encoding: "utf-8",
|
|
46992
|
+
maxBuffer: 50 * 1024 * 1024
|
|
46993
|
+
});
|
|
46994
|
+
return stdout;
|
|
46995
|
+
}
|
|
46810
46996
|
async function getConversationDiffs(name, deps) {
|
|
46811
46997
|
try {
|
|
46812
46998
|
const conv = lookupConversation(name);
|
|
@@ -46852,22 +47038,28 @@ async function getConversationDiffFull(name, deps) {
|
|
|
46852
47038
|
const conv = getConversationByName(name);
|
|
46853
47039
|
if (!conv) return result$1({ error: "Conversation not found" }, 404);
|
|
46854
47040
|
const cwd = conv.cwd;
|
|
46855
|
-
|
|
46856
|
-
|
|
46857
|
-
|
|
46858
|
-
|
|
47041
|
+
const cwdRepoRoot = existsSync$1(join(cwd, ".git")) ? cwd : null;
|
|
47042
|
+
const patches = [];
|
|
47043
|
+
if (cwdRepoRoot) {
|
|
47044
|
+
const baseCommit = await Effect.runPromise(findCommitAtTime(cwdRepoRoot, conv.createdAt));
|
|
47045
|
+
if (baseCommit) {
|
|
47046
|
+
const patch = await Effect.runPromise(diffPatchSinceCommit(cwdRepoRoot, baseCommit));
|
|
47047
|
+
if (patch) patches.push(patch);
|
|
47048
|
+
}
|
|
46859
47049
|
}
|
|
46860
47050
|
const sessionFile = await deps.resolveSessionFile(conv);
|
|
46861
|
-
if (!sessionFile || !existsSync$1(sessionFile)) return result$1({ diff: "" });
|
|
47051
|
+
if (!sessionFile || !existsSync$1(sessionFile)) return result$1({ diff: patches.join("\n") });
|
|
46862
47052
|
const { fileEditsByAssistantId } = await deps.getCachedMessages(sessionFile, false);
|
|
46863
|
-
if (!fileEditsByAssistantId || fileEditsByAssistantId.size === 0) return result$1({ diff: "" });
|
|
47053
|
+
if (!fileEditsByAssistantId || fileEditsByAssistantId.size === 0) return result$1({ diff: patches.join("\n") });
|
|
46864
47054
|
const repoRootCache = /* @__PURE__ */ new Map();
|
|
46865
47055
|
const filesByRepo = await groupFilesByRepo([...fileEditsByAssistantId.values()].flat(), repoRootCache);
|
|
46866
|
-
const
|
|
46867
|
-
|
|
46868
|
-
|
|
46869
|
-
|
|
46870
|
-
|
|
47056
|
+
for (const [repoRoot, filePaths] of filesByRepo) {
|
|
47057
|
+
if (repoRoot === cwdRepoRoot) continue;
|
|
47058
|
+
try {
|
|
47059
|
+
const patch = await diffPatchForFiles(repoRoot, conv.createdAt, filePaths);
|
|
47060
|
+
if (patch) patches.push(patch);
|
|
47061
|
+
} catch {}
|
|
47062
|
+
}
|
|
46871
47063
|
return result$1({ diff: patches.join("\n") });
|
|
46872
47064
|
} catch (error) {
|
|
46873
47065
|
const msg = error instanceof Error ? error.message : String(error);
|
|
@@ -46880,35 +47072,34 @@ async function getConversationDiffTurn(name, turnId, fileFilter, deps) {
|
|
|
46880
47072
|
const conv = lookupConversation(name);
|
|
46881
47073
|
if (!conv) return result$1({ error: "Conversation not found" }, 404);
|
|
46882
47074
|
const cwd = conv.cwd;
|
|
46883
|
-
|
|
46884
|
-
|
|
46885
|
-
|
|
46886
|
-
|
|
46887
|
-
|
|
46888
|
-
|
|
47075
|
+
const cwdRepoRoot = existsSync$1(join(cwd, ".git")) ? cwd : null;
|
|
47076
|
+
const patches = [];
|
|
47077
|
+
if (cwdRepoRoot) {
|
|
47078
|
+
const baseCommit = await Effect.runPromise(findCommitAtTime(cwdRepoRoot, conv.createdAt));
|
|
47079
|
+
if (baseCommit) {
|
|
47080
|
+
const patch = await Effect.runPromise(diffPatchSinceCommit(cwdRepoRoot, baseCommit, fileFilter));
|
|
47081
|
+
if (patch) patches.push(patch);
|
|
47082
|
+
}
|
|
46889
47083
|
}
|
|
46890
47084
|
const assistantId = turnId.startsWith("conv-turn-") ? turnId.slice(10) : turnId;
|
|
46891
47085
|
const sessionFile = await deps.resolveSessionFile(conv);
|
|
46892
|
-
if (!sessionFile || !existsSync$1(sessionFile)) return result$1({
|
|
47086
|
+
if (!sessionFile || !existsSync$1(sessionFile)) return result$1({
|
|
47087
|
+
turnId,
|
|
47088
|
+
diff: patches.join("\n")
|
|
47089
|
+
});
|
|
46893
47090
|
const edits = (await deps.getCachedMessages(sessionFile, false)).fileEditsByAssistantId?.get(assistantId);
|
|
46894
|
-
if (!edits || edits.length === 0) return result$1({
|
|
47091
|
+
if (!edits || edits.length === 0) return result$1({
|
|
47092
|
+
turnId,
|
|
47093
|
+
diff: patches.join("\n")
|
|
47094
|
+
});
|
|
46895
47095
|
const filesByRepo = await groupFilesByRepo(edits, /* @__PURE__ */ new Map(), fileFilter);
|
|
46896
|
-
const
|
|
46897
|
-
|
|
46898
|
-
|
|
46899
|
-
|
|
46900
|
-
|
|
46901
|
-
|
|
46902
|
-
|
|
46903
|
-
const { stdout } = await promisify(exec)(`git diff --patch --minimal --no-color ${baseCommit} -- ${filePaths.map((p) => JSON.stringify(p)).join(" ")}`, {
|
|
46904
|
-
cwd: repoRoot,
|
|
46905
|
-
encoding: "utf-8",
|
|
46906
|
-
maxBuffer: 50 * 1024 * 1024
|
|
46907
|
-
});
|
|
46908
|
-
patch = stdout;
|
|
46909
|
-
} else patch = await Effect.runPromise(diffPatchFilesAgainstHead(repoRoot, filePaths));
|
|
46910
|
-
if (patch) patches.push(patch);
|
|
46911
|
-
} catch {}
|
|
47096
|
+
for (const [repoRoot, filePaths] of filesByRepo) {
|
|
47097
|
+
if (repoRoot === cwdRepoRoot) continue;
|
|
47098
|
+
try {
|
|
47099
|
+
const patch = await diffPatchForFiles(repoRoot, conv.createdAt, filePaths);
|
|
47100
|
+
if (patch) patches.push(patch);
|
|
47101
|
+
} catch {}
|
|
47102
|
+
}
|
|
46912
47103
|
return result$1({
|
|
46913
47104
|
turnId,
|
|
46914
47105
|
diff: patches.join("\n")
|
|
@@ -48735,7 +48926,7 @@ async function refreshMergeStateFromGitHub(issueId, repo, prNumber) {
|
|
|
48735
48926
|
let mergeState;
|
|
48736
48927
|
let isDraft;
|
|
48737
48928
|
let checksFailed;
|
|
48738
|
-
const { isGitHubAppConfigured, getPullRequestState } = await import("./github-app-
|
|
48929
|
+
const { isGitHubAppConfigured, getPullRequestState } = await import("./github-app-CPfoFAdV.js");
|
|
48739
48930
|
if (isGitHubAppConfigured()) {
|
|
48740
48931
|
const prState = await Effect.runPromise(getPullRequestState(owner, repoName, prNumber));
|
|
48741
48932
|
mergeable = prState.mergeable === null ? "UNKNOWN" : prState.mergeable ? "MERGEABLE" : "CONFLICTING";
|
|
@@ -48884,8 +49075,8 @@ async function handlePullRequestPromise(payload) {
|
|
|
48884
49075
|
bumpIssuePrTabCacheGeneration(issueId);
|
|
48885
49076
|
const repo = payload.repository.full_name;
|
|
48886
49077
|
if (payload.action === "closed" && pr.merged === true) try {
|
|
48887
|
-
const { postMergeLifecycle } = await import("./merge-agent-
|
|
48888
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
49078
|
+
const { postMergeLifecycle } = await import("./merge-agent-BQM3a8z5.js");
|
|
49079
|
+
const { resolveProjectFromIssueSync } = await import("./projects-9SkRpES9.js");
|
|
48889
49080
|
const project = resolveProjectFromIssueSync(issueId);
|
|
48890
49081
|
if (project) {
|
|
48891
49082
|
const branchName = pr.head.ref;
|
|
@@ -50281,7 +50472,7 @@ async function registerProjectFromPath(opts) {
|
|
|
50281
50472
|
registerProjectSync(key, projectConfig);
|
|
50282
50473
|
const seededContextLayer = ensureProjectLayer(fullPath);
|
|
50283
50474
|
try {
|
|
50284
|
-
const { preTrustDirectorySync } = await import("./workspace-manager-
|
|
50475
|
+
const { preTrustDirectorySync } = await import("./workspace-manager-ZTdJAy9M.js");
|
|
50285
50476
|
preTrustDirectorySync(fullPath);
|
|
50286
50477
|
} catch {}
|
|
50287
50478
|
let hooksInstalled = 0;
|
|
@@ -50311,6 +50502,7 @@ init_issue_id();
|
|
|
50311
50502
|
init_tmux();
|
|
50312
50503
|
init_concurrency$1();
|
|
50313
50504
|
init_read_model();
|
|
50505
|
+
init_src();
|
|
50314
50506
|
init_agents$1();
|
|
50315
50507
|
init_pan_dir();
|
|
50316
50508
|
init_io();
|
|
@@ -50318,7 +50510,7 @@ init_specs();
|
|
|
50318
50510
|
init_paths();
|
|
50319
50511
|
const execAsync$2 = promisify(exec);
|
|
50320
50512
|
async function getIssueDataService() {
|
|
50321
|
-
const { getSharedIssueService } = await import("./issue-service-singleton-
|
|
50513
|
+
const { getSharedIssueService } = await import("./issue-service-singleton-DabvBWUp.js");
|
|
50322
50514
|
return getSharedIssueService();
|
|
50323
50515
|
}
|
|
50324
50516
|
/** Returns true if the path exists (any type). */
|
|
@@ -50373,9 +50565,9 @@ function getSlotWorkSessionNumber(sessionId, issueLower) {
|
|
|
50373
50565
|
return Number.parseInt(match[1], 10);
|
|
50374
50566
|
}
|
|
50375
50567
|
function getSessionTreeWorkspacePath(issueLower, baseWorkspacePath, projectPath, sessionId) {
|
|
50568
|
+
if (sessionId.toLowerCase() === `strike-${issueLower.toLowerCase()}`) return join(projectPath, "workspaces", `feature-${issueLower}-strike`);
|
|
50376
50569
|
const slotNumber = getSlotWorkSessionNumber(sessionId, issueLower);
|
|
50377
|
-
|
|
50378
|
-
return join(projectPath, "workspaces", `feature-${issueLower}-slot-${slotNumber}`);
|
|
50570
|
+
return slotNumber === null ? baseWorkspacePath : join(projectPath, "workspaces", `feature-${issueLower}-slot-${slotNumber}`);
|
|
50379
50571
|
}
|
|
50380
50572
|
function compareSessionTreeSessionIds(a, b, issueLower) {
|
|
50381
50573
|
const planningAgentId = `planning-${issueLower}`;
|
|
@@ -50733,7 +50925,7 @@ async function fetchProjectSessionTree(projectKey, sharedContext) {
|
|
|
50733
50925
|
})), 15));
|
|
50734
50926
|
features.push(...results.filter((f) => f !== null));
|
|
50735
50927
|
}
|
|
50736
|
-
features.sort((a, b) => a.issueId
|
|
50928
|
+
features.sort((a, b) => compareIssueIds(a.issueId, b.issueId));
|
|
50737
50929
|
return {
|
|
50738
50930
|
projectKey,
|
|
50739
50931
|
features
|
|
@@ -50775,7 +50967,7 @@ const getProjectReleaseStatusRoute = HttpRouter.add("GET", "/api/projects/:proje
|
|
|
50775
50967
|
const projectKey = (yield* HttpRouter.params)["projectKey"] ?? "";
|
|
50776
50968
|
return jsonResponse(yield* Effect.tryPromise({
|
|
50777
50969
|
try: async () => {
|
|
50778
|
-
const { fetchProjectReleaseStatus } = await import("./project-pipelines-
|
|
50970
|
+
const { fetchProjectReleaseStatus } = await import("./project-pipelines-2sK1apsO.js");
|
|
50779
50971
|
return fetchProjectReleaseStatus(projectKey);
|
|
50780
50972
|
},
|
|
50781
50973
|
catch: (err) => new Error(err instanceof Error ? err.message : String(err))
|
|
@@ -51290,7 +51482,7 @@ function fullPromptPreview(previews) {
|
|
|
51290
51482
|
"## Runtime-only sections",
|
|
51291
51483
|
"",
|
|
51292
51484
|
"- Memory retrieval: injected at agent spawn when enabled; unavailable in this layer editor preview.",
|
|
51293
|
-
"- Issue briefing and
|
|
51485
|
+
"- Issue briefing and xBRIEF excerpts: injected per agent run; unavailable until a specific issue/session is selected.",
|
|
51294
51486
|
"- Status and tool output: produced during the live session; not part of static context layers."
|
|
51295
51487
|
].join("\n");
|
|
51296
51488
|
}
|
|
@@ -51590,6 +51782,35 @@ async function checkCommand(cmd, args = ["--version"]) {
|
|
|
51590
51782
|
return false;
|
|
51591
51783
|
}
|
|
51592
51784
|
}
|
|
51785
|
+
const LINUX_PACKAGE_MANAGERS = [
|
|
51786
|
+
"pacman",
|
|
51787
|
+
"dnf",
|
|
51788
|
+
"zypper",
|
|
51789
|
+
"apk",
|
|
51790
|
+
"apt-get"
|
|
51791
|
+
];
|
|
51792
|
+
async function detectLinuxPackageManager(commandAvailable = checkCommand) {
|
|
51793
|
+
for (const packageManager of LINUX_PACKAGE_MANAGERS) if (await commandAvailable(packageManager)) return packageManager;
|
|
51794
|
+
return null;
|
|
51795
|
+
}
|
|
51796
|
+
function getLinuxInstallCommand(tool, packageManager) {
|
|
51797
|
+
switch (packageManager) {
|
|
51798
|
+
case "pacman": return `sudo pacman -S --noconfirm ${tool}`;
|
|
51799
|
+
case "dnf": return `sudo dnf install -y ${tool}`;
|
|
51800
|
+
case "zypper": return `sudo zypper install -y ${tool}`;
|
|
51801
|
+
case "apk": return `sudo apk add ${tool}`;
|
|
51802
|
+
case "apt-get": return `sudo apt-get update && sudo apt-get install -y ${tool}`;
|
|
51803
|
+
}
|
|
51804
|
+
}
|
|
51805
|
+
function getLinuxManualInstallHint(tool, packageManager) {
|
|
51806
|
+
if (packageManager) return getLinuxInstallCommand(tool, packageManager);
|
|
51807
|
+
return `${tool} — download from ${tool === "jq" ? "https://jqlang.github.io/jq/download/" : "https://github.com/tmux/tmux/wiki/Installing"}`;
|
|
51808
|
+
}
|
|
51809
|
+
async function installLinuxPackage(tool) {
|
|
51810
|
+
const packageManager = await detectLinuxPackageManager();
|
|
51811
|
+
if (!packageManager) throw new Error(`No supported Linux package manager found. Install ${getLinuxManualInstallHint(tool, null)}`);
|
|
51812
|
+
await execAsync$1(getLinuxInstallCommand(tool, packageManager), { timeout: 12e4 });
|
|
51813
|
+
}
|
|
51593
51814
|
async function isToolInstalled(tool) {
|
|
51594
51815
|
if (tool === "docker") return checkCommand("docker", ["info"]);
|
|
51595
51816
|
if (tool === "traefik") try {
|
|
@@ -51632,7 +51853,7 @@ async function installTool(tool) {
|
|
|
51632
51853
|
}
|
|
51633
51854
|
async function installTmux() {
|
|
51634
51855
|
if (await Effect.runPromise(detectPlatform()) === "darwin") await execAsync$1("brew install tmux", { timeout: 12e4 });
|
|
51635
|
-
else await
|
|
51856
|
+
else await installLinuxPackage("tmux");
|
|
51636
51857
|
return {
|
|
51637
51858
|
tool: "tmux",
|
|
51638
51859
|
success: true,
|
|
@@ -51682,7 +51903,7 @@ async function installMkcert() {
|
|
|
51682
51903
|
}
|
|
51683
51904
|
async function installJq() {
|
|
51684
51905
|
if (await Effect.runPromise(detectPlatform()) === "darwin") await execAsync$1("brew install jq", { timeout: 12e4 });
|
|
51685
|
-
else await
|
|
51906
|
+
else await installLinuxPackage("jq");
|
|
51686
51907
|
return {
|
|
51687
51908
|
tool: "jq",
|
|
51688
51909
|
success: true,
|
|
@@ -52417,7 +52638,7 @@ function getCheckpointWorker() {
|
|
|
52417
52638
|
return worker;
|
|
52418
52639
|
}
|
|
52419
52640
|
async function runInline(operation, payload) {
|
|
52420
|
-
const { claimTranscriptRange, commitTranscriptRange, releaseTranscriptRange, getTranscriptCheckpoint, listTranscriptCheckpoints } = await import("./checkpoints-
|
|
52641
|
+
const { claimTranscriptRange, commitTranscriptRange, releaseTranscriptRange, getTranscriptCheckpoint, listTranscriptCheckpoints } = await import("./checkpoints-CpgCjAlN.js");
|
|
52421
52642
|
switch (operation) {
|
|
52422
52643
|
case "claimTranscriptRange": return claimTranscriptRange(payload);
|
|
52423
52644
|
case "commitTranscriptRange": return commitTranscriptRange(payload);
|
|
@@ -53571,7 +53792,7 @@ function buildPendingTurn(input, fromOffset, toOffset, compressed) {
|
|
|
53571
53792
|
};
|
|
53572
53793
|
}
|
|
53573
53794
|
async function emitMemoryObservationCreated(observation, timestamp) {
|
|
53574
|
-
const { initEventStore } = await import("./event-store-
|
|
53795
|
+
const { initEventStore } = await import("./event-store-Cr5PQwFC.js");
|
|
53575
53796
|
await (await initEventStore()).appendAsync({
|
|
53576
53797
|
type: "memory.observation_created",
|
|
53577
53798
|
timestamp,
|
|
@@ -56583,7 +56804,7 @@ async function getFlywheelConversationPayload() {
|
|
|
56583
56804
|
};
|
|
56584
56805
|
}
|
|
56585
56806
|
async function postFlywheelReportPayload() {
|
|
56586
|
-
const { flywheelReportCommand } = await import("./flywheel-
|
|
56807
|
+
const { flywheelReportCommand } = await import("./flywheel-DcBkQvgE.js");
|
|
56587
56808
|
await flywheelReportCommand({ cwd: process.cwd() });
|
|
56588
56809
|
return {
|
|
56589
56810
|
status: 200,
|
|
@@ -56741,11 +56962,11 @@ const getMergeBlockersRoute = HttpRouter.add("GET", "/api/flywheel/merge-blocker
|
|
|
56741
56962
|
async function defaultGetOrderedIssueIds() {
|
|
56742
56963
|
const status = await readCurrentFlywheelStatusForDashboard();
|
|
56743
56964
|
if (!status) return [];
|
|
56744
|
-
const { computeMergeQueue } = await import("./flywheel-merge-order-
|
|
56965
|
+
const { computeMergeQueue } = await import("./flywheel-merge-order-C-6zRLvM.js");
|
|
56745
56966
|
return (await Effect.runPromise(computeMergeQueue(status.activePipeline, process.cwd()).pipe(Effect.provide(layer)))).map((i) => i.issueId);
|
|
56746
56967
|
}
|
|
56747
56968
|
async function defaultMergeOne(issueId) {
|
|
56748
|
-
const { triggerMerge } = await import("./merge-ops-
|
|
56969
|
+
const { triggerMerge } = await import("./merge-ops-DlB1IM0Y.js");
|
|
56749
56970
|
const r = await triggerMerge(issueId);
|
|
56750
56971
|
return r.success ? { ok: true } : {
|
|
56751
56972
|
ok: false,
|
|
@@ -56765,7 +56986,7 @@ async function postFlywheelMergeNextPayload(payload, deps = {}) {
|
|
|
56765
56986
|
body: { error: "n must be a positive integer" }
|
|
56766
56987
|
};
|
|
56767
56988
|
const issueIds = (await (deps.getOrderedIssueIds ?? defaultGetOrderedIssueIds)()).slice(0, n);
|
|
56768
|
-
const { shipMergeBatch } = await import("./merge-batch-
|
|
56989
|
+
const { shipMergeBatch } = await import("./merge-batch-Bwoyr8Je.js");
|
|
56769
56990
|
return {
|
|
56770
56991
|
status: 200,
|
|
56771
56992
|
body: { outcomes: await shipMergeBatch(issueIds, { merge: deps.merge ?? defaultMergeOne }) }
|
|
@@ -56922,7 +57143,7 @@ const getFlywheelMergeQueueRoute = HttpRouter.add("GET", "/api/flywheel/merge-qu
|
|
|
56922
57143
|
return yield* Effect.promise(async () => {
|
|
56923
57144
|
const status = await readCurrentFlywheelStatusForDashboard();
|
|
56924
57145
|
if (!status) return jsonResponse([]);
|
|
56925
|
-
const { computeMergeQueue, resolveMergeQueuePrUrl } = await import("./flywheel-merge-order-
|
|
57146
|
+
const { computeMergeQueue, resolveMergeQueuePrUrl } = await import("./flywheel-merge-order-C-6zRLvM.js");
|
|
56926
57147
|
return jsonResponse(await Effect.runPromise(computeMergeQueue(status.activePipeline, process.cwd(), { getPrUrl: resolveMergeQueuePrUrl }).pipe(Effect.provide(layer))));
|
|
56927
57148
|
});
|
|
56928
57149
|
})));
|
|
@@ -56936,18 +57157,18 @@ function uatGenerationNameFromParam(param) {
|
|
|
56936
57157
|
return decoded.startsWith("uat/") ? decoded : `uat/${decoded}`;
|
|
56937
57158
|
}
|
|
56938
57159
|
const getUatGenerationsRoute = HttpRouter.add("GET", "/api/flywheel/uat-generations", httpHandler(Effect.gen(function* () {
|
|
56939
|
-
const { getUatGenerationsPayload } = yield* Effect.promise(() => import("./uat-train-
|
|
57160
|
+
const { getUatGenerationsPayload } = yield* Effect.promise(() => import("./uat-train-cKfM-_WW.js"));
|
|
56940
57161
|
return jsonResponse(yield* Effect.promise(() => getUatGenerationsPayload()));
|
|
56941
57162
|
})));
|
|
56942
57163
|
const getUatCandidateRoute = HttpRouter.add("GET", "/api/flywheel/uat-candidate", httpHandler(Effect.gen(function* () {
|
|
56943
|
-
const { getUatCandidatePayload } = yield* Effect.promise(() => import("./uat-train-
|
|
57164
|
+
const { getUatCandidatePayload } = yield* Effect.promise(() => import("./uat-train-cKfM-_WW.js"));
|
|
56944
57165
|
return jsonResponse(yield* Effect.promise(() => getUatCandidatePayload()));
|
|
56945
57166
|
})));
|
|
56946
57167
|
const postUatGenerationStackRoute = HttpRouter.add("POST", "/api/flywheel/uat-generations/:name/stack", httpHandler(Effect.gen(function* () {
|
|
56947
57168
|
const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
|
|
56948
57169
|
if (authError) return authError;
|
|
56949
57170
|
const name = uatGenerationNameFromParam((yield* HttpRouter.params)["name"] ?? "");
|
|
56950
|
-
const { postUatGenerationStackPayload } = yield* Effect.promise(() => import("./uat-train-
|
|
57171
|
+
const { postUatGenerationStackPayload } = yield* Effect.promise(() => import("./uat-train-cKfM-_WW.js"));
|
|
56951
57172
|
const result = yield* Effect.promise(() => postUatGenerationStackPayload(name));
|
|
56952
57173
|
if (!result.ok) return jsonResponse({ error: result.error }, { status: result.status });
|
|
56953
57174
|
return jsonResponse({
|
|
@@ -56959,8 +57180,8 @@ const postUatGenerationPromoteRoute = HttpRouter.add("POST", "/api/flywheel/uat-
|
|
|
56959
57180
|
const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
|
|
56960
57181
|
if (authError) return authError;
|
|
56961
57182
|
const name = uatGenerationNameFromParam((yield* HttpRouter.params)["name"] ?? "");
|
|
56962
|
-
const { postUatGenerationPromotePayload } = yield* Effect.promise(() => import("./uat-train-
|
|
56963
|
-
const { firePostMergeLifecycle } = yield* Effect.promise(() => import("./specialists-
|
|
57183
|
+
const { postUatGenerationPromotePayload } = yield* Effect.promise(() => import("./uat-train-cKfM-_WW.js"));
|
|
57184
|
+
const { firePostMergeLifecycle } = yield* Effect.promise(() => import("./specialists-D5fRZXmN.js"));
|
|
56964
57185
|
const result = yield* Effect.promise(() => postUatGenerationPromotePayload(name, firePostMergeLifecycle));
|
|
56965
57186
|
if (!result.success) return jsonResponse(result, { status: result.reason === "not-found" ? 404 : result.reason === "merge-failed" ? 500 : 409 });
|
|
56966
57187
|
return jsonResponse(result);
|
|
@@ -56973,7 +57194,7 @@ const postUatGenerationPromoteRoute = HttpRouter.add("POST", "/api/flywheel/uat-
|
|
|
56973
57194
|
const postFlywheelAssembleUatRoute = HttpRouter.add("POST", "/api/flywheel/assemble-uat", httpHandler(Effect.gen(function* () {
|
|
56974
57195
|
const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
|
|
56975
57196
|
if (authError) return authError;
|
|
56976
|
-
const { runUatTrainReconcile } = yield* Effect.promise(() => import("./uat-train-
|
|
57197
|
+
const { runUatTrainReconcile } = yield* Effect.promise(() => import("./uat-train-cKfM-_WW.js"));
|
|
56977
57198
|
return jsonResponse(yield* Effect.promise(() => runUatTrainReconcile({ force: true })));
|
|
56978
57199
|
})));
|
|
56979
57200
|
const getFlywheelStateRoute = HttpRouter.add("GET", "/api/flywheel/state", httpHandler(Effect.gen(function* () {
|
|
@@ -59796,6 +60017,27 @@ const postTieredCalloutsRoute = HttpRouter.add("POST", "/api/tiered/callouts", h
|
|
|
59796
60017
|
})));
|
|
59797
60018
|
const tieredCalloutsRouteLayer = Layer.mergeAll(postTieredCalloutsRoute);
|
|
59798
60019
|
//#endregion
|
|
60020
|
+
//#region server-bind.ts
|
|
60021
|
+
function isAddressInUseError(error) {
|
|
60022
|
+
if (!error || typeof error !== "object") return false;
|
|
60023
|
+
if ("code" in error && error.code === "EADDRINUSE") return true;
|
|
60024
|
+
return "cause" in error && isAddressInUseError(error.cause);
|
|
60025
|
+
}
|
|
60026
|
+
const BIND_RETRY_DELAY_MS = 250;
|
|
60027
|
+
const BIND_RETRY_COUNT = 3;
|
|
60028
|
+
function retryDashboardBind(bind, onRetry) {
|
|
60029
|
+
let failures = 0;
|
|
60030
|
+
const observedBind = Effect.tapError(bind, (error) => Effect.sync(() => {
|
|
60031
|
+
failures += 1;
|
|
60032
|
+
if (failures <= BIND_RETRY_COUNT && isAddressInUseError(error)) onRetry?.(failures, BIND_RETRY_DELAY_MS);
|
|
60033
|
+
}));
|
|
60034
|
+
return Effect.retry(observedBind, {
|
|
60035
|
+
times: BIND_RETRY_COUNT,
|
|
60036
|
+
schedule: Schedule.spaced(Duration.millis(BIND_RETRY_DELAY_MS)),
|
|
60037
|
+
while: isAddressInUseError
|
|
60038
|
+
});
|
|
60039
|
+
}
|
|
60040
|
+
//#endregion
|
|
59799
60041
|
//#region server.ts
|
|
59800
60042
|
/**
|
|
59801
60043
|
* Dashboard HTTP server — Effect-based with dual-runtime support (PAN-428 B5)
|
|
@@ -59821,14 +60063,19 @@ init_activity_logger();
|
|
|
59821
60063
|
const HttpServerLive = Layer.unwrap(Effect.gen(function* () {
|
|
59822
60064
|
const config = yield* ServerConfig;
|
|
59823
60065
|
const [NodeHttpServer, NodeHttp] = yield* Effect.all([Effect.promise(() => import("@effect/platform-node/NodeHttpServer")), Effect.promise(() => import("node:http"))]);
|
|
59824
|
-
const
|
|
59825
|
-
|
|
59826
|
-
|
|
59827
|
-
|
|
59828
|
-
|
|
60066
|
+
const bind = retryDashboardBind(NodeHttpServer.make(() => {
|
|
60067
|
+
const nodeServer = NodeHttp.createServer();
|
|
60068
|
+
setupTerminalWebSocket(nodeServer);
|
|
60069
|
+
setupVoiceWebSocket(nodeServer);
|
|
60070
|
+
setupAutoPresoWebSocket(nodeServer);
|
|
60071
|
+
return nodeServer;
|
|
60072
|
+
}, {
|
|
59829
60073
|
host: config.host,
|
|
59830
60074
|
port: config.port
|
|
60075
|
+
}), (attempt, delayMs) => {
|
|
60076
|
+
console.warn(`[overdeck] HTTP bind failed with EADDRINUSE; retry ${attempt}/3 in ${delayMs}ms`);
|
|
59831
60077
|
});
|
|
60078
|
+
return Layer.mergeAll(Layer.effect(HttpServer.HttpServer)(bind), NodeHttpServer.layerHttpServices);
|
|
59832
60079
|
}));
|
|
59833
60080
|
const PlatformServicesLive = Layer.unwrap(Effect.gen(function* () {
|
|
59834
60081
|
const { layer } = yield* Effect.promise(() => import("@effect/platform-node/NodeServices"));
|
|
@@ -59920,6 +60167,7 @@ const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
59920
60167
|
const httpListeningLayer = Layer.effectDiscard(Effect.gen(function* () {
|
|
59921
60168
|
yield* HttpServer.HttpServer;
|
|
59922
60169
|
yield* Effect.sync(() => {
|
|
60170
|
+
markDashboardListening();
|
|
59923
60171
|
console.log(`[boot-timing] HTTP server listening at +${Math.round(performance.now())}ms (since process start)`);
|
|
59924
60172
|
console.log(`[overdeck] Dashboard listening on http://${config.host}:${config.port}`);
|
|
59925
60173
|
const mode = process.env["OVERDECK_MODE"] === "production" ? "production mode" : "development mode";
|
|
@@ -59978,7 +60226,7 @@ function buildAwaitingInputActivityMessage(agentId, issueId, kinds) {
|
|
|
59978
60226
|
const kindList = kinds.length > 0 ? kinds.join(", ") : "input";
|
|
59979
60227
|
return issueId ? `${agentId} on ${issueId} is waiting for ${kindList}` : `${agentId} is waiting for ${kindList}`;
|
|
59980
60228
|
}
|
|
59981
|
-
async function pollOnce
|
|
60229
|
+
async function pollOnce(state) {
|
|
59982
60230
|
let runningAgents;
|
|
59983
60231
|
try {
|
|
59984
60232
|
runningAgents = await Effect.runPromise(listRunningAgents());
|
|
@@ -60108,8 +60356,8 @@ async function pollOnce$1(state) {
|
|
|
60108
60356
|
/** Poll interval: 10 seconds (was 3s). The enrichment data changes slowly —
|
|
60109
60357
|
* pending questions, resolution state, phase — none of these need sub-second
|
|
60110
60358
|
* latency. 10s eliminates ~70% of poller I/O without any user-visible lag. */
|
|
60111
|
-
const POLL_INTERVAL_MS$
|
|
60112
|
-
const serviceState$
|
|
60359
|
+
const POLL_INTERVAL_MS$3 = 1e4;
|
|
60360
|
+
const serviceState$2 = {
|
|
60113
60361
|
timer: null,
|
|
60114
60362
|
lastEnrichment: /* @__PURE__ */ new Map(),
|
|
60115
60363
|
lastScan: /* @__PURE__ */ new Map(),
|
|
@@ -60117,18 +60365,18 @@ const serviceState$3 = {
|
|
|
60117
60365
|
reconciledAgentIds: /* @__PURE__ */ new Set()
|
|
60118
60366
|
};
|
|
60119
60367
|
function startAgentEnrichmentService() {
|
|
60120
|
-
if (serviceState$
|
|
60121
|
-
serviceState$
|
|
60122
|
-
pollOnce
|
|
60123
|
-
}, POLL_INTERVAL_MS$
|
|
60368
|
+
if (serviceState$2.timer !== null) return;
|
|
60369
|
+
serviceState$2.timer = setInterval(() => {
|
|
60370
|
+
pollOnce(serviceState$2).catch(() => {});
|
|
60371
|
+
}, POLL_INTERVAL_MS$3);
|
|
60124
60372
|
}
|
|
60125
60373
|
function stopAgentEnrichmentService() {
|
|
60126
|
-
if (serviceState$
|
|
60127
|
-
clearInterval(serviceState$
|
|
60128
|
-
serviceState$
|
|
60374
|
+
if (serviceState$2.timer !== null) {
|
|
60375
|
+
clearInterval(serviceState$2.timer);
|
|
60376
|
+
serviceState$2.timer = null;
|
|
60129
60377
|
}
|
|
60130
|
-
serviceState$
|
|
60131
|
-
serviceState$
|
|
60378
|
+
serviceState$2.lastEnrichment.clear();
|
|
60379
|
+
serviceState$2.lastScan.clear();
|
|
60132
60380
|
}
|
|
60133
60381
|
//#endregion
|
|
60134
60382
|
//#region services/merge-blocker-reconcile-service.ts
|
|
@@ -60148,7 +60396,7 @@ function stopAgentEnrichmentService() {
|
|
|
60148
60396
|
* Bounded + cheap: each issue has a throttle. Ready/no-blocker rows use the PAN-1620
|
|
60149
60397
|
* 3-minute cadence; already-blocked mergeability rows use a 10-minute cadence.
|
|
60150
60398
|
*/
|
|
60151
|
-
const POLL_INTERVAL_MS$
|
|
60399
|
+
const POLL_INTERVAL_MS$2 = 6e4;
|
|
60152
60400
|
/** Re-check each ready-to-merge PR at most this often, to bound `gh` calls. */
|
|
60153
60401
|
const RECHECK_INTERVAL_MS = 18e4;
|
|
60154
60402
|
/** Re-check already-flagged mergeability blockers less often; they are not mergeable yet. */
|
|
@@ -60159,7 +60407,7 @@ const MERGEABILITY_BLOCKERS = new Set([
|
|
|
60159
60407
|
"failing_checks"
|
|
60160
60408
|
]);
|
|
60161
60409
|
const MAX_REFRESH_CONCURRENCY = 4;
|
|
60162
|
-
const serviceState$
|
|
60410
|
+
const serviceState$1 = {
|
|
60163
60411
|
timer: null,
|
|
60164
60412
|
lastChecked: /* @__PURE__ */ new Map(),
|
|
60165
60413
|
blockerLastChecked: /* @__PURE__ */ new Map(),
|
|
@@ -60214,11 +60462,11 @@ async function reconcileOnce(state) {
|
|
|
60214
60462
|
for (const id of [...state.blockerLastChecked.keys()]) if (!hasMergeabilityBlocker(candidateById.get(id)?.blockerReasons)) state.blockerLastChecked.delete(id);
|
|
60215
60463
|
}
|
|
60216
60464
|
function startMergeBlockerReconcileService() {
|
|
60217
|
-
if (serviceState$
|
|
60218
|
-
serviceState$
|
|
60219
|
-
reconcileOnce(serviceState$
|
|
60220
|
-
}, POLL_INTERVAL_MS$
|
|
60221
|
-
serviceState$
|
|
60465
|
+
if (serviceState$1.timer !== null) return;
|
|
60466
|
+
serviceState$1.timer = setInterval(() => {
|
|
60467
|
+
reconcileOnce(serviceState$1).catch(() => {});
|
|
60468
|
+
}, POLL_INTERVAL_MS$2);
|
|
60469
|
+
serviceState$1.timer.unref?.();
|
|
60222
60470
|
}
|
|
60223
60471
|
function enqueueRefresh(state, task) {
|
|
60224
60472
|
if (state.refreshInFlight.has(task.issueId)) return;
|
|
@@ -60241,6 +60489,174 @@ function drainRefreshQueue(state) {
|
|
|
60241
60489
|
}
|
|
60242
60490
|
}
|
|
60243
60491
|
//#endregion
|
|
60492
|
+
//#region services/project-resource-refresh-queue.ts
|
|
60493
|
+
init_projects();
|
|
60494
|
+
const PROJECT_RESOURCE_CONVERGENCE_INTERVAL_MS = 5 * 6e4;
|
|
60495
|
+
function createProjectResourceRefreshQueue(deps) {
|
|
60496
|
+
const debounceMs = deps.debounceMs ?? 1e3;
|
|
60497
|
+
const now = deps.now ?? Date.now;
|
|
60498
|
+
const pending = /* @__PURE__ */ new Map();
|
|
60499
|
+
const reasons = /* @__PURE__ */ new Map();
|
|
60500
|
+
const idleWaiters = /* @__PURE__ */ new Set();
|
|
60501
|
+
let activeProjectPaths = [];
|
|
60502
|
+
let timer = null;
|
|
60503
|
+
let running = false;
|
|
60504
|
+
let stopped = false;
|
|
60505
|
+
let lastStartedAt = null;
|
|
60506
|
+
let lastCompletedAt = null;
|
|
60507
|
+
let lastError = null;
|
|
60508
|
+
const isIdle = () => !running && timer === null && pending.size === 0;
|
|
60509
|
+
const resolveIdleWaiters = () => {
|
|
60510
|
+
if (!isIdle()) return;
|
|
60511
|
+
for (const resolve of idleWaiters) resolve();
|
|
60512
|
+
idleWaiters.clear();
|
|
60513
|
+
};
|
|
60514
|
+
const drain = async () => {
|
|
60515
|
+
timer = null;
|
|
60516
|
+
if (running || stopped) return;
|
|
60517
|
+
running = true;
|
|
60518
|
+
try {
|
|
60519
|
+
while (!stopped && pending.size > 0) {
|
|
60520
|
+
const projects = [...pending.values()];
|
|
60521
|
+
const reasonsByProjectPath = /* @__PURE__ */ new Map();
|
|
60522
|
+
for (const project of projects) {
|
|
60523
|
+
reasonsByProjectPath.set(project.path, new Set(reasons.get(project.path) ?? []));
|
|
60524
|
+
reasons.delete(project.path);
|
|
60525
|
+
}
|
|
60526
|
+
pending.clear();
|
|
60527
|
+
activeProjectPaths = projects.map((project) => project.path);
|
|
60528
|
+
lastStartedAt = now();
|
|
60529
|
+
try {
|
|
60530
|
+
await deps.refreshProjects(projects, { reasonsByProjectPath });
|
|
60531
|
+
lastError = null;
|
|
60532
|
+
} catch (error) {
|
|
60533
|
+
lastError = error instanceof Error ? error.message : String(error);
|
|
60534
|
+
console.warn("[project-resource-refresh] batch failed:", lastError);
|
|
60535
|
+
} finally {
|
|
60536
|
+
activeProjectPaths = [];
|
|
60537
|
+
lastCompletedAt = now();
|
|
60538
|
+
}
|
|
60539
|
+
}
|
|
60540
|
+
} finally {
|
|
60541
|
+
running = false;
|
|
60542
|
+
resolveIdleWaiters();
|
|
60543
|
+
}
|
|
60544
|
+
};
|
|
60545
|
+
const schedule = () => {
|
|
60546
|
+
if (stopped || running || timer) return;
|
|
60547
|
+
timer = setTimeout(() => void drain(), debounceMs);
|
|
60548
|
+
timer.unref?.();
|
|
60549
|
+
};
|
|
60550
|
+
const enqueueProject = (project, reason) => {
|
|
60551
|
+
if (stopped) return;
|
|
60552
|
+
pending.set(project.path, project);
|
|
60553
|
+
const projectReasons = reasons.get(project.path) ?? /* @__PURE__ */ new Set();
|
|
60554
|
+
projectReasons.add(reason);
|
|
60555
|
+
reasons.set(project.path, projectReasons);
|
|
60556
|
+
schedule();
|
|
60557
|
+
};
|
|
60558
|
+
return {
|
|
60559
|
+
enqueueProject,
|
|
60560
|
+
enqueueProjects(projects, reason) {
|
|
60561
|
+
for (const project of projects) enqueueProject(project, reason);
|
|
60562
|
+
},
|
|
60563
|
+
whenIdle() {
|
|
60564
|
+
if (isIdle()) return Promise.resolve();
|
|
60565
|
+
return new Promise((resolve) => idleWaiters.add(resolve));
|
|
60566
|
+
},
|
|
60567
|
+
getState() {
|
|
60568
|
+
return {
|
|
60569
|
+
running,
|
|
60570
|
+
activeProjectPaths: [...activeProjectPaths],
|
|
60571
|
+
pendingProjectPaths: [...pending.keys()],
|
|
60572
|
+
lastStartedAt,
|
|
60573
|
+
lastCompletedAt,
|
|
60574
|
+
lastError
|
|
60575
|
+
};
|
|
60576
|
+
},
|
|
60577
|
+
stop() {
|
|
60578
|
+
stopped = true;
|
|
60579
|
+
if (timer) clearTimeout(timer);
|
|
60580
|
+
timer = null;
|
|
60581
|
+
pending.clear();
|
|
60582
|
+
reasons.clear();
|
|
60583
|
+
resolveIdleWaiters();
|
|
60584
|
+
}
|
|
60585
|
+
};
|
|
60586
|
+
}
|
|
60587
|
+
const MEMBERSHIP_REFRESH_REASONS = new Set(["boot-warm", "periodic-convergence"]);
|
|
60588
|
+
const projectResourceRefreshQueue = createProjectResourceRefreshQueue({ refreshProjects: (projects, context) => refreshResourceAllocatedProjects(projects, { refreshMembership: [...context.reasonsByProjectPath.values()].some((projectReasons) => [...projectReasons].some((reason) => MEMBERSHIP_REFRESH_REASONS.has(reason))) }) });
|
|
60589
|
+
function enqueueProjectsResourceRefresh(projects, reason) {
|
|
60590
|
+
projectResourceRefreshQueue.enqueueProjects(projects, reason);
|
|
60591
|
+
}
|
|
60592
|
+
function whenProjectResourceRefreshIdle() {
|
|
60593
|
+
return projectResourceRefreshQueue.whenIdle();
|
|
60594
|
+
}
|
|
60595
|
+
function getProjectResourceRefreshQueueState() {
|
|
60596
|
+
return projectResourceRefreshQueue.getState();
|
|
60597
|
+
}
|
|
60598
|
+
function stopProjectResourceRefreshQueue() {
|
|
60599
|
+
projectResourceRefreshQueue.stop();
|
|
60600
|
+
}
|
|
60601
|
+
function startProjectResourceConvergence() {
|
|
60602
|
+
const timer = setInterval(() => {
|
|
60603
|
+
enqueueProjectsResourceRefresh(listProjectsSync().map((entry) => entry.config), "periodic-convergence");
|
|
60604
|
+
}, PROJECT_RESOURCE_CONVERGENCE_INTERVAL_MS);
|
|
60605
|
+
timer.unref?.();
|
|
60606
|
+
return () => clearInterval(timer);
|
|
60607
|
+
}
|
|
60608
|
+
//#endregion
|
|
60609
|
+
//#region services/resource-refresh-triggers.ts
|
|
60610
|
+
init_agents$1();
|
|
60611
|
+
init_projects();
|
|
60612
|
+
init_event_store();
|
|
60613
|
+
const TRIGGER_EVENT_TYPES = new Set([
|
|
60614
|
+
"agent.created",
|
|
60615
|
+
"agent.started",
|
|
60616
|
+
"agent.stopped",
|
|
60617
|
+
"agent.completed",
|
|
60618
|
+
"agent.heartbeat_dead"
|
|
60619
|
+
]);
|
|
60620
|
+
function createResourceRefreshTriggers(deps) {
|
|
60621
|
+
const warn = deps.warn ?? ((message) => console.warn(message));
|
|
60622
|
+
return deps.subscribe((event) => {
|
|
60623
|
+
if (!TRIGGER_EVENT_TYPES.has(event.type)) return;
|
|
60624
|
+
const payload = event.payload;
|
|
60625
|
+
let project = null;
|
|
60626
|
+
if (typeof payload?.projectKey === "string") project = deps.projectForKey(payload.projectKey);
|
|
60627
|
+
if (!project && typeof payload?.issueId === "string") project = deps.projectForIssue(payload.issueId);
|
|
60628
|
+
if (!project && typeof payload?.agentId === "string") {
|
|
60629
|
+
const issueId = deps.issueForAgent(payload.agentId);
|
|
60630
|
+
if (issueId) project = deps.projectForIssue(issueId);
|
|
60631
|
+
}
|
|
60632
|
+
if (!project) {
|
|
60633
|
+
warn(`[resource-refresh] skipped ${event.type}: affected project could not be resolved`);
|
|
60634
|
+
return;
|
|
60635
|
+
}
|
|
60636
|
+
deps.enqueueProjects([project], event.type);
|
|
60637
|
+
});
|
|
60638
|
+
}
|
|
60639
|
+
function startResourceRefreshTriggers() {
|
|
60640
|
+
const entries = () => listProjectsSync();
|
|
60641
|
+
return createResourceRefreshTriggers({
|
|
60642
|
+
subscribe: (fn) => getEventStore().subscribe(fn),
|
|
60643
|
+
projectForIssue: (issueId) => {
|
|
60644
|
+
const resolved = resolveProjectFromIssueSync(issueId);
|
|
60645
|
+
if (!resolved) return null;
|
|
60646
|
+
return entries().find((entry) => entry.key === resolved.projectKey)?.config ?? null;
|
|
60647
|
+
},
|
|
60648
|
+
projectForKey: (projectKey) => entries().find((entry) => entry.key === projectKey)?.config ?? null,
|
|
60649
|
+
issueForAgent: (agentId) => {
|
|
60650
|
+
try {
|
|
60651
|
+
return getAgentStateSync(agentId)?.issueId ?? null;
|
|
60652
|
+
} catch {
|
|
60653
|
+
return null;
|
|
60654
|
+
}
|
|
60655
|
+
},
|
|
60656
|
+
enqueueProjects: enqueueProjectsResourceRefresh
|
|
60657
|
+
});
|
|
60658
|
+
}
|
|
60659
|
+
//#endregion
|
|
60244
60660
|
//#region ../../lib/cloister/stale-check-classifier.ts
|
|
60245
60661
|
/**
|
|
60246
60662
|
* Pure classification for stale PR checks inherited from a red main branch.
|
|
@@ -60426,12 +60842,12 @@ async function rerunFailedRun(repo, runId) {
|
|
|
60426
60842
|
//#endregion
|
|
60427
60843
|
//#region services/stale-check-retrigger-service.ts
|
|
60428
60844
|
init_review_status_sync();
|
|
60429
|
-
const POLL_INTERVAL_MS$
|
|
60845
|
+
const POLL_INTERVAL_MS$1 = 6e4;
|
|
60430
60846
|
const MAIN_PROBE_INTERVAL_MS = 3 * 6e4;
|
|
60431
60847
|
const EVAL_INTERVAL_MS = 10 * 6e4;
|
|
60432
60848
|
const MAX_RERUNS_PER_TICK = 5;
|
|
60433
60849
|
const RUN_STATE_RETENTION_MS = 1440 * 6e4;
|
|
60434
|
-
const serviceState
|
|
60850
|
+
const serviceState = {
|
|
60435
60851
|
timer: null,
|
|
60436
60852
|
repoWindows: /* @__PURE__ */ new Map(),
|
|
60437
60853
|
lastEvaluated: /* @__PURE__ */ new Map(),
|
|
@@ -60577,120 +60993,21 @@ async function runTickIfIdle(state) {
|
|
|
60577
60993
|
}
|
|
60578
60994
|
}
|
|
60579
60995
|
function startStaleCheckRetriggerService() {
|
|
60580
|
-
if (serviceState
|
|
60581
|
-
serviceState
|
|
60582
|
-
serviceState
|
|
60996
|
+
if (serviceState.timer !== null) return;
|
|
60997
|
+
serviceState.timer = setInterval(() => void runTickIfIdle(serviceState), POLL_INTERVAL_MS$1);
|
|
60998
|
+
serviceState.timer.unref?.();
|
|
60583
60999
|
}
|
|
60584
61000
|
function shouldStartStaleCheckRetriggerService(env = process.env) {
|
|
60585
61001
|
return env.OVERDECK_DISABLE_DEACON !== "1";
|
|
60586
61002
|
}
|
|
60587
61003
|
function stopStaleCheckRetriggerService() {
|
|
60588
|
-
if (serviceState
|
|
60589
|
-
serviceState
|
|
60590
|
-
serviceState
|
|
60591
|
-
serviceState
|
|
60592
|
-
serviceState
|
|
60593
|
-
serviceState
|
|
60594
|
-
serviceState
|
|
60595
|
-
}
|
|
60596
|
-
//#endregion
|
|
60597
|
-
//#region services/agent-output-service.ts
|
|
60598
|
-
/**
|
|
60599
|
-
* Agent Output Service (PAN-1221 F3)
|
|
60600
|
-
*
|
|
60601
|
-
* Background poller that captures tmux pane output for each running agent
|
|
60602
|
-
* every ~3 seconds and emits `agent.output_received` domain events when
|
|
60603
|
-
* new lines appear.
|
|
60604
|
-
*
|
|
60605
|
-
* This restores the event-driven output pipeline that DrawerActiveAgent
|
|
60606
|
-
* expects — the reducer and WebSocket subscription already exist, but no
|
|
60607
|
-
* server code was emitting the events.
|
|
60608
|
-
*/
|
|
60609
|
-
init_agents$1();
|
|
60610
|
-
init_tmux();
|
|
60611
|
-
init_concurrency$1();
|
|
60612
|
-
init_event_store();
|
|
60613
|
-
function splitLines(text) {
|
|
60614
|
-
const lines = text.split("\n");
|
|
60615
|
-
if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
60616
|
-
return lines;
|
|
60617
|
-
}
|
|
60618
|
-
/**
|
|
60619
|
-
* Find new lines by looking for the longest suffix of `previous` that matches
|
|
60620
|
-
* a prefix of `current`. The non-overlapping prefix of `current` is returned.
|
|
60621
|
-
* If there is no overlap, all of `current` is new (pane was cleared or scrolled
|
|
60622
|
-
* past the overlap window).
|
|
60623
|
-
*/
|
|
60624
|
-
function diffLines(previous, current) {
|
|
60625
|
-
if (previous.length === 0) return current;
|
|
60626
|
-
for (let start = 0; start < previous.length; start++) {
|
|
60627
|
-
const suffix = previous.slice(start);
|
|
60628
|
-
if (suffix.length > current.length) continue;
|
|
60629
|
-
if (suffix.every((line, i) => line === current[i])) return current.slice(suffix.length);
|
|
60630
|
-
}
|
|
60631
|
-
return current;
|
|
60632
|
-
}
|
|
60633
|
-
async function pollOnce(state) {
|
|
60634
|
-
let runningAgents;
|
|
60635
|
-
try {
|
|
60636
|
-
runningAgents = await Effect.runPromise(listRunningAgents());
|
|
60637
|
-
} catch {
|
|
60638
|
-
return;
|
|
60639
|
-
}
|
|
60640
|
-
const eventStore = getEventStore();
|
|
60641
|
-
const activeAgents = runningAgents.filter((a) => a.tmuxActive);
|
|
60642
|
-
await Effect.runPromise(withConcurrencyLimit(activeAgents.map((agent) => Effect.tryPromise({
|
|
60643
|
-
try: async () => {
|
|
60644
|
-
const { id: agentId } = agent;
|
|
60645
|
-
let stdout;
|
|
60646
|
-
try {
|
|
60647
|
-
const remoteState = await readFile(join(homedir$1(), ".overdeck", "agents", agentId, "remote-state.json"), "utf-8").then((text) => JSON.parse(text)).catch(() => null);
|
|
60648
|
-
if (remoteState?.location === "remote" && remoteState?.vmName) {
|
|
60649
|
-
const { getRemoteAgentOutput } = await import("./remote-agents-BNORDWAX.js");
|
|
60650
|
-
stdout = await getRemoteAgentOutput(agentId, remoteState.vmName, 50);
|
|
60651
|
-
} else stdout = await Effect.runPromise(capturePane(agentId, 50));
|
|
60652
|
-
} catch {
|
|
60653
|
-
stdout = await Effect.runPromise(capturePane(agentId, 50).pipe(Effect.catch(() => Effect.succeed(""))));
|
|
60654
|
-
}
|
|
60655
|
-
if (!stdout || stdout.trim() === "" || stdout.trim() === "Session not found") return;
|
|
60656
|
-
const previousOutput = state.lastOutput.get(agentId) ?? "";
|
|
60657
|
-
if (stdout === previousOutput) return;
|
|
60658
|
-
const newLines = diffLines(splitLines(previousOutput), splitLines(stdout));
|
|
60659
|
-
state.lastOutput.set(agentId, stdout);
|
|
60660
|
-
if (newLines.length === 0) return;
|
|
60661
|
-
const event = {
|
|
60662
|
-
type: "agent.output_received",
|
|
60663
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
60664
|
-
payload: {
|
|
60665
|
-
agentId,
|
|
60666
|
-
lines: newLines
|
|
60667
|
-
}
|
|
60668
|
-
};
|
|
60669
|
-
eventStore.emitOnly(event);
|
|
60670
|
-
},
|
|
60671
|
-
catch: (cause) => cause
|
|
60672
|
-
})), 4));
|
|
60673
|
-
const activeIds = new Set(activeAgents.map((a) => a.id));
|
|
60674
|
-
for (const id of state.lastOutput.keys()) if (!activeIds.has(id)) state.lastOutput.delete(id);
|
|
60675
|
-
}
|
|
60676
|
-
/** Poll interval: 3 seconds. Output is high-frequency and latency-sensitive. */
|
|
60677
|
-
const POLL_INTERVAL_MS$1 = 3e3;
|
|
60678
|
-
const serviceState = {
|
|
60679
|
-
timer: null,
|
|
60680
|
-
lastOutput: /* @__PURE__ */ new Map()
|
|
60681
|
-
};
|
|
60682
|
-
function startAgentOutputService() {
|
|
60683
|
-
if (serviceState.timer !== null) return;
|
|
60684
|
-
serviceState.timer = setInterval(() => {
|
|
60685
|
-
pollOnce(serviceState).catch(() => {});
|
|
60686
|
-
}, POLL_INTERVAL_MS$1);
|
|
60687
|
-
}
|
|
60688
|
-
function stopAgentOutputService() {
|
|
60689
|
-
if (serviceState.timer !== null) {
|
|
60690
|
-
clearInterval(serviceState.timer);
|
|
60691
|
-
serviceState.timer = null;
|
|
60692
|
-
}
|
|
60693
|
-
serviceState.lastOutput.clear();
|
|
61004
|
+
if (serviceState.timer !== null) clearInterval(serviceState.timer);
|
|
61005
|
+
serviceState.timer = null;
|
|
61006
|
+
serviceState.repoWindows.clear();
|
|
61007
|
+
serviceState.lastEvaluated.clear();
|
|
61008
|
+
serviceState.successfulRunIds.clear();
|
|
61009
|
+
serviceState.failedRunsByIssue.clear();
|
|
61010
|
+
serviceState.loggedSkips.clear();
|
|
60694
61011
|
}
|
|
60695
61012
|
//#endregion
|
|
60696
61013
|
//#region services/conversation-lifecycle.ts
|
|
@@ -60710,7 +61027,7 @@ function stopAgentOutputService() {
|
|
|
60710
61027
|
* spawn-only.
|
|
60711
61028
|
*/
|
|
60712
61029
|
init_conversations();
|
|
60713
|
-
|
|
61030
|
+
init_runtime_census();
|
|
60714
61031
|
init_paths();
|
|
60715
61032
|
init_behavior();
|
|
60716
61033
|
const POLL_INTERVAL_MS = 1e4;
|
|
@@ -60754,12 +61071,10 @@ async function tailFile(path, maxBytes) {
|
|
|
60754
61071
|
* a "; "-prefixed suffix for the log line, or "" when nothing is available.
|
|
60755
61072
|
* Every probe is independently guarded so a diagnostics failure never throws.
|
|
60756
61073
|
*/
|
|
60757
|
-
async function captureCorpseDiagnostics(tmuxSession) {
|
|
61074
|
+
async function captureCorpseDiagnostics(tmuxSession, census) {
|
|
60758
61075
|
const parts = [];
|
|
60759
|
-
|
|
60760
|
-
|
|
60761
|
-
if (status) parts.push(`exitStatus=${status}`);
|
|
60762
|
-
} catch {}
|
|
61076
|
+
const status = (census.panesBySession.get(tmuxSession) ?? []).map((pane) => pane.paneDeadStatus).find((value) => value !== null);
|
|
61077
|
+
if (status !== void 0) parts.push(`exitStatus=${status}`);
|
|
60763
61078
|
try {
|
|
60764
61079
|
const logPath = join$1(getOverdeckHome(), "agents", tmuxSession, "output.log");
|
|
60765
61080
|
if (existsSync(logPath)) {
|
|
@@ -60779,7 +61094,10 @@ async function pollConversations() {
|
|
|
60779
61094
|
try {
|
|
60780
61095
|
const conversations = listConversations();
|
|
60781
61096
|
if (conversations.length === 0) return;
|
|
60782
|
-
const
|
|
61097
|
+
const census = await getRuntimeCensus();
|
|
61098
|
+
if (!census.available) return;
|
|
61099
|
+
const aliveSessions = new Set(census.sessionNames);
|
|
61100
|
+
let revalidationCensus = null;
|
|
60783
61101
|
const endedConversations = [];
|
|
60784
61102
|
let sessionGoneCount = 0;
|
|
60785
61103
|
let keepAliveCorpseCount = 0;
|
|
@@ -60787,8 +61105,8 @@ async function pollConversations() {
|
|
|
60787
61105
|
const now = Date.now();
|
|
60788
61106
|
for (const conv of conversations) {
|
|
60789
61107
|
if (now - new Date(conv.createdAt).getTime() < SPAWN_GRACE_PERIOD_MS) continue;
|
|
60790
|
-
|
|
60791
|
-
|
|
61108
|
+
let sessionGone = !aliveSessions.has(conv.tmuxSession);
|
|
61109
|
+
let harnessGone = !sessionGone && !await runtimeCensusHasHarnessProcess(census, conv.tmuxSession);
|
|
60792
61110
|
if (!sessionGone && !harnessGone) {
|
|
60793
61111
|
if (conv.status === "ended") {
|
|
60794
61112
|
console.log(`[conversation-lifecycle] Session ${conv.tmuxSession} alive but row marked ended — resurrecting to active`);
|
|
@@ -60801,9 +61119,14 @@ async function pollConversations() {
|
|
|
60801
61119
|
const fresh = getConversationByName(conv.name) ?? conv;
|
|
60802
61120
|
const lastAliveSignalMs = Math.max(new Date(fresh.createdAt).getTime() || 0, fresh.lastAttachedAt ? new Date(fresh.lastAttachedAt).getTime() || 0 : 0);
|
|
60803
61121
|
if (Date.now() - lastAliveSignalMs < SPAWN_GRACE_PERIOD_MS) continue;
|
|
61122
|
+
revalidationCensus ??= await refreshRuntimeCensus();
|
|
61123
|
+
if (!revalidationCensus.available) continue;
|
|
61124
|
+
sessionGone = !revalidationCensus.sessionNames.has(conv.tmuxSession);
|
|
61125
|
+
harnessGone = !sessionGone && !await runtimeCensusHasHarnessProcess(revalidationCensus, conv.tmuxSession);
|
|
61126
|
+
if (!sessionGone && !harnessGone) continue;
|
|
60804
61127
|
if (process.env.DEBUG?.includes("conversation-lifecycle")) console.log(sessionGone ? `[conversation-lifecycle] Session ${conv.tmuxSession} gone — marking ended` : `[conversation-lifecycle] Session ${conv.tmuxSession} alive but harness exited (keep-alive corpse) — marking ended`);
|
|
60805
61128
|
if (!sessionGone) {
|
|
60806
|
-
const diag = await captureCorpseDiagnostics(conv.tmuxSession);
|
|
61129
|
+
const diag = await captureCorpseDiagnostics(conv.tmuxSession, revalidationCensus);
|
|
60807
61130
|
if (diag) keepAliveCorpseDiagnostics.push(`${conv.tmuxSession}${diag}`);
|
|
60808
61131
|
}
|
|
60809
61132
|
markConversationEnded(conv.name);
|
|
@@ -61458,7 +61781,8 @@ init_event_store();
|
|
|
61458
61781
|
init_tracker_config();
|
|
61459
61782
|
const DEFAULT_INTERVAL_MS = 6e4;
|
|
61460
61783
|
const DEFAULT_LOOKBACK_MS = 5 * 6e4;
|
|
61461
|
-
const
|
|
61784
|
+
const FLYWHEEL_FILED_BY_TRAILER = "\"Flywheel-Filed-By:\" in:body";
|
|
61785
|
+
const LEGACY_BOT_LOGIN = "panopticon-agent[bot]";
|
|
61462
61786
|
var CacheServiceRateLimitStore = class {
|
|
61463
61787
|
cache = null;
|
|
61464
61788
|
getCache() {
|
|
@@ -61564,14 +61888,14 @@ function createSubstrateBugPoller(options = {}) {
|
|
|
61564
61888
|
const since = isoLookback(now(), lookbackMs);
|
|
61565
61889
|
for (const repo of config.repos) try {
|
|
61566
61890
|
const repoQualifier = `repo:${repo.owner}/${repo.repo}`;
|
|
61567
|
-
const
|
|
61891
|
+
const trailerResults = await fetchSearch(config.token, searchQuery([
|
|
61568
61892
|
repoQualifier,
|
|
61569
61893
|
"is:issue",
|
|
61570
61894
|
"-is:pr",
|
|
61571
|
-
|
|
61895
|
+
FLYWHEEL_FILED_BY_TRAILER,
|
|
61572
61896
|
`updated:>=${since}`
|
|
61573
61897
|
]));
|
|
61574
|
-
if (
|
|
61898
|
+
if (trailerResults === null) return;
|
|
61575
61899
|
const substrateResults = await fetchSearch(config.token, searchQuery([
|
|
61576
61900
|
repoQualifier,
|
|
61577
61901
|
"is:issue",
|
|
@@ -61581,12 +61905,12 @@ function createSubstrateBugPoller(options = {}) {
|
|
|
61581
61905
|
]));
|
|
61582
61906
|
if (substrateResults === null) return;
|
|
61583
61907
|
const byNumber = /* @__PURE__ */ new Map();
|
|
61584
|
-
for (const issue of [...
|
|
61908
|
+
for (const issue of [...trailerResults, ...substrateResults]) byNumber.set(issue.number, issue);
|
|
61585
61909
|
for (const issue of byNumber.values()) {
|
|
61586
61910
|
const issueId = issueIdFor(repo.prefix, issue.number);
|
|
61587
61911
|
if (!issueId) continue;
|
|
61588
61912
|
const trailer = parseSubstrateBugTrailer(issue.body);
|
|
61589
|
-
const filedBy = trailer.filedBy ?? (issue.user?.login ===
|
|
61913
|
+
const filedBy = trailer.filedBy ?? (issue.user?.login === LEGACY_BOT_LOGIN ? "agent" : "operator");
|
|
61590
61914
|
const labelNames = (issue.labels ?? []).map((label) => typeof label === "string" ? label : label.name ?? "");
|
|
61591
61915
|
const affectedCriteria = parseAffectedCriteria(issue.body, labelNames);
|
|
61592
61916
|
const existing = repository.getByIssueId(issueId);
|
|
@@ -61852,7 +62176,7 @@ const RESTART_MARKER = join$1(homedir(), ".overdeck", "dashboard-restarting.json
|
|
|
61852
62176
|
* loads new content-hashed chunk filenames (no ERR_MODULE_NOT_FOUND after rebuild).
|
|
61853
62177
|
*/
|
|
61854
62178
|
async function defaultLifecycleRunner(pending) {
|
|
61855
|
-
const { postMergeLifecycle, notifyTldrDaemon } = await import("./merge-agent-
|
|
62179
|
+
const { postMergeLifecycle, notifyTldrDaemon } = await import("./merge-agent-BQM3a8z5.js");
|
|
61856
62180
|
await postMergeLifecycle(pending.issueId, pending.projectPath, pending.sourceBranch, { skipDeploy: true });
|
|
61857
62181
|
if (pending.sourceBranch) await notifyTldrDaemon(pending.projectPath, pending.sourceBranch);
|
|
61858
62182
|
}
|
|
@@ -62173,7 +62497,7 @@ function failureReason(result) {
|
|
|
62173
62497
|
return result.error ?? result.message ?? `merge returned status ${result.statusCode ?? "unknown"}`;
|
|
62174
62498
|
}
|
|
62175
62499
|
async function defaultMergeIssue(issueId) {
|
|
62176
|
-
const { triggerMerge } = await import("./merge-ops-
|
|
62500
|
+
const { triggerMerge } = await import("./merge-ops-DlB1IM0Y.js");
|
|
62177
62501
|
return triggerMerge(issueId);
|
|
62178
62502
|
}
|
|
62179
62503
|
function defaultAnnounceFailure(issueId, reason) {
|
|
@@ -62401,24 +62725,27 @@ init_projects();
|
|
|
62401
62725
|
init_state_home();
|
|
62402
62726
|
const execFileAsync = promisify(execFile);
|
|
62403
62727
|
const inFlight = /* @__PURE__ */ new Map();
|
|
62404
|
-
async function pathIsGitWorkTree(path) {
|
|
62728
|
+
async function pathIsGitWorkTree(path, signal) {
|
|
62405
62729
|
try {
|
|
62730
|
+
signal?.throwIfAborted();
|
|
62406
62731
|
const { stdout } = await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
62407
62732
|
cwd: path,
|
|
62408
62733
|
encoding: "utf8",
|
|
62409
|
-
timeout: 15e3
|
|
62734
|
+
timeout: 15e3,
|
|
62735
|
+
signal
|
|
62410
62736
|
});
|
|
62411
62737
|
return stdout.trim() === "true";
|
|
62412
62738
|
} catch {
|
|
62739
|
+
signal?.throwIfAborted();
|
|
62413
62740
|
return false;
|
|
62414
62741
|
}
|
|
62415
62742
|
}
|
|
62416
62743
|
const defaultDependencies = {
|
|
62417
62744
|
inspect: inspectStateMigration,
|
|
62418
62745
|
ensureWorktree: ensureStateWorktree,
|
|
62419
|
-
migrate: async (projectKey, project) => {
|
|
62420
|
-
const { migrateProjectState } = await import("./state-migrate-
|
|
62421
|
-
await migrateProjectState(projectKey, {}, project);
|
|
62746
|
+
migrate: async (projectKey, project, signal) => {
|
|
62747
|
+
const { migrateProjectState } = await import("./state-migrate-Dkzaxvny.js");
|
|
62748
|
+
await migrateProjectState(projectKey, { signal }, project);
|
|
62422
62749
|
},
|
|
62423
62750
|
clearCache: clearStateMigrationCache,
|
|
62424
62751
|
isGitWorkTree: pathIsGitWorkTree
|
|
@@ -62445,24 +62772,28 @@ function blocked(projectKey, error) {
|
|
|
62445
62772
|
function worktreeBlockReason(status) {
|
|
62446
62773
|
return `The canonical overdeck-state worktree is ${status.status}: ${status.detail}`;
|
|
62447
62774
|
}
|
|
62448
|
-
async function reconcile(projectKey, project, dependencies) {
|
|
62775
|
+
async function reconcile(projectKey, project, dependencies, signal) {
|
|
62449
62776
|
try {
|
|
62450
|
-
if (!(await dependencies.inspect(project)).migrated) {
|
|
62777
|
+
if (!(await dependencies.inspect(project, { signal })).migrated) {
|
|
62451
62778
|
const { repoPath } = resolveInfraRepo(project);
|
|
62452
|
-
if (!await dependencies.isGitWorkTree(repoPath)) return blocked(projectKey, describeUnmigratableProjectPath(projectKey, project, repoPath));
|
|
62453
|
-
await dependencies.migrate(projectKey, project);
|
|
62779
|
+
if (!await dependencies.isGitWorkTree(repoPath, signal)) return blocked(projectKey, describeUnmigratableProjectPath(projectKey, project, repoPath));
|
|
62780
|
+
await dependencies.migrate(projectKey, project, signal);
|
|
62454
62781
|
dependencies.clearCache();
|
|
62455
|
-
if (!(await dependencies.inspect(project)).migrated) return blocked(projectKey, "Migration completed without a valid marker on origin/overdeck-state.");
|
|
62782
|
+
if (!(await dependencies.inspect(project, { signal })).migrated) return blocked(projectKey, "Migration completed without a valid marker on origin/overdeck-state.");
|
|
62456
62783
|
}
|
|
62457
|
-
const worktree = await dependencies.ensureWorktree(project, {
|
|
62784
|
+
const worktree = await dependencies.ensureWorktree(project, {
|
|
62785
|
+
projectKey,
|
|
62786
|
+
signal
|
|
62787
|
+
});
|
|
62458
62788
|
if (worktree.status === "dirty" || worktree.status === "error") return blocked(projectKey, worktreeBlockReason(worktree));
|
|
62459
|
-
if (worktree.status === "legacy") return blocked(projectKey,
|
|
62789
|
+
if (worktree.status === "legacy") return blocked(projectKey, worktree.detail);
|
|
62460
62790
|
return {
|
|
62461
62791
|
status: "ready",
|
|
62462
62792
|
projectKey,
|
|
62463
62793
|
worktree: worktree.status
|
|
62464
62794
|
};
|
|
62465
62795
|
} catch (error) {
|
|
62796
|
+
signal.throwIfAborted();
|
|
62466
62797
|
return blocked(projectKey, error);
|
|
62467
62798
|
}
|
|
62468
62799
|
}
|
|
@@ -62471,12 +62802,39 @@ async function reconcile(projectKey, project, dependencies) {
|
|
|
62471
62802
|
* state. Concurrent dashboard/CLI callers on this process share one attempt;
|
|
62472
62803
|
* the migration command supplies the cross-process lock and no-loss gates.
|
|
62473
62804
|
*/
|
|
62474
|
-
function ensureAutomaticStateMigration(projectKey, project, dependencies = defaultDependencies) {
|
|
62475
|
-
|
|
62476
|
-
|
|
62477
|
-
|
|
62478
|
-
|
|
62479
|
-
|
|
62805
|
+
function ensureAutomaticStateMigration(projectKey, project, dependencies = defaultDependencies, signal) {
|
|
62806
|
+
signal?.throwIfAborted();
|
|
62807
|
+
let entry = inFlight.get(projectKey);
|
|
62808
|
+
if (!entry) {
|
|
62809
|
+
const controller = new AbortController();
|
|
62810
|
+
const task = reconcile(projectKey, project, dependencies, controller.signal).finally(() => inFlight.delete(projectKey));
|
|
62811
|
+
entry = {
|
|
62812
|
+
controller,
|
|
62813
|
+
persistentOwner: signal === void 0,
|
|
62814
|
+
waiters: /* @__PURE__ */ new Map(),
|
|
62815
|
+
task
|
|
62816
|
+
};
|
|
62817
|
+
inFlight.set(projectKey, entry);
|
|
62818
|
+
} else if (!signal) entry.persistentOwner = true;
|
|
62819
|
+
if (!signal) return entry.task;
|
|
62820
|
+
const token = Symbol(projectKey);
|
|
62821
|
+
entry.waiters.set(token, false);
|
|
62822
|
+
const maybeAbortSharedMigration = () => {
|
|
62823
|
+
entry?.waiters.set(token, true);
|
|
62824
|
+
if (!entry?.persistentOwner && [...entry.waiters.values()].every(Boolean)) entry.controller.abort(signal.reason);
|
|
62825
|
+
};
|
|
62826
|
+
signal.addEventListener("abort", maybeAbortSharedMigration, { once: true });
|
|
62827
|
+
if (signal.aborted) maybeAbortSharedMigration();
|
|
62828
|
+
return entry.task.then((result) => {
|
|
62829
|
+
signal.throwIfAborted();
|
|
62830
|
+
return result;
|
|
62831
|
+
}, (error) => {
|
|
62832
|
+
signal.throwIfAborted();
|
|
62833
|
+
throw error;
|
|
62834
|
+
}).finally(() => {
|
|
62835
|
+
signal.removeEventListener("abort", maybeAbortSharedMigration);
|
|
62836
|
+
entry?.waiters.delete(token);
|
|
62837
|
+
});
|
|
62480
62838
|
}
|
|
62481
62839
|
function formatAutomaticStateMigrationBlock(result) {
|
|
62482
62840
|
return `State migration for ${result.projectKey} is blocked: ${result.reason} Overdeck will not start pipeline work because that would write permanent state into the legacy project checkout. Resolve the stated prerequisite, then run "pan sync"; do not commit project-root .pan/ or .beads/ files.`;
|
|
@@ -62514,6 +62872,7 @@ function decideDeaconBootGate(migrations) {
|
|
|
62514
62872
|
//#region main.ts
|
|
62515
62873
|
init_issue_service_singleton();
|
|
62516
62874
|
init_tracker_config();
|
|
62875
|
+
init_internal_token();
|
|
62517
62876
|
init_review_status();
|
|
62518
62877
|
init_event_store();
|
|
62519
62878
|
init_activity_logger();
|
|
@@ -62528,16 +62887,34 @@ init_projects();
|
|
|
62528
62887
|
initDashboardLogFile();
|
|
62529
62888
|
console.log(`[boot-timing] module graph loaded at +${Math.round(performance.now())}ms (since process start)`);
|
|
62530
62889
|
console.log(`[overdeck] Boot gates: ${formatBootGateState(resolveBootGates())}`);
|
|
62531
|
-
startEventLoopMonitor();
|
|
62532
|
-
console.log("[overdeck] Event loop delay monitor started");
|
|
62533
62890
|
await mkdir(getOverdeckHome(), { recursive: true });
|
|
62534
62891
|
ensureInternalTokenSync();
|
|
62535
|
-
warnIfAutonomousMergeBackendUnavailable();
|
|
62536
|
-
warnIfAppCannotMerge();
|
|
62537
62892
|
await ensureManagedTmuxContextOnce();
|
|
62538
62893
|
await initTrackerConfigCache().catch((err) => {
|
|
62539
62894
|
console.log("[tracker-config] Warning: failed to cache .overdeck.env:", err.message);
|
|
62540
62895
|
});
|
|
62896
|
+
try {
|
|
62897
|
+
const overdeckDbPath = getOverdeckDatabasePath();
|
|
62898
|
+
if (!existsSync$1(overdeckDbPath)) {
|
|
62899
|
+
createOverdeckDatabase({ dbPath: overdeckDbPath });
|
|
62900
|
+
console.log(`[overdeck] Created overdeck.db at ${overdeckDbPath}`);
|
|
62901
|
+
}
|
|
62902
|
+
} catch (err) {
|
|
62903
|
+
console.warn("[overdeck] Overdeck db init failed (non-fatal):", err);
|
|
62904
|
+
}
|
|
62905
|
+
const main = runServer.pipe(Effect.provide(ServerConfigLayer));
|
|
62906
|
+
if (typeof Bun !== "undefined") {
|
|
62907
|
+
const { runMain } = await import("@effect/platform-bun/BunRuntime");
|
|
62908
|
+
runMain(main);
|
|
62909
|
+
} else {
|
|
62910
|
+
const { runMain } = await import("@effect/platform-node/NodeRuntime");
|
|
62911
|
+
runMain(main);
|
|
62912
|
+
}
|
|
62913
|
+
await whenDashboardListening();
|
|
62914
|
+
startEventLoopMonitor();
|
|
62915
|
+
console.log("[overdeck] Event loop delay monitor started");
|
|
62916
|
+
warnIfAutonomousMergeBackendUnavailable();
|
|
62917
|
+
warnIfAppCannotMerge();
|
|
62541
62918
|
const isPeerDashboard = process.env.OVERDECK_DISABLE_DEACON === "1";
|
|
62542
62919
|
if (isPeerDashboard) {
|
|
62543
62920
|
startSharedIssueService({ skipPolling: true });
|
|
@@ -62575,7 +62952,7 @@ if (shouldStartStaleCheckRetriggerService()) {
|
|
|
62575
62952
|
}
|
|
62576
62953
|
if (process.env.OVERDECK_MODE === "desktop") (async () => {
|
|
62577
62954
|
try {
|
|
62578
|
-
const { provisionClaudeHooks } = await import("./claude-hooks-provision-
|
|
62955
|
+
const { provisionClaudeHooks } = await import("./claude-hooks-provision-C8wdRnN1.js");
|
|
62579
62956
|
const result = await provisionClaudeHooks();
|
|
62580
62957
|
if (!result.ok) console.warn(`[overdeck] Claude hook provisioning skipped: ${result.reason}`);
|
|
62581
62958
|
else if (result.changed) console.log(`[overdeck] Claude hooks provisioned: ${result.binariesSynced} scripts, registered ${result.registered.length} hook(s)${result.pruned.length ? `, pruned ${result.pruned.length} stale` : ""}`);
|
|
@@ -62802,7 +63179,8 @@ setMergeReadyNotifier((issueId) => {
|
|
|
62802
63179
|
console.log("[overdeck] Merge-ready notifier → domain events wired");
|
|
62803
63180
|
startConversationLifecycleService();
|
|
62804
63181
|
console.log("[overdeck] ConversationLifecycleService started");
|
|
62805
|
-
|
|
63182
|
+
if (isPeerDashboard) console.log("[overdeck] SubstrateBugPoller skipped — peer dashboard does not poll trackers");
|
|
63183
|
+
else startSubstrateBugPoller();
|
|
62806
63184
|
if (startUatTrainReconciler()) console.log("[overdeck] UAT batch-train reconciler started");
|
|
62807
63185
|
else console.log("[overdeck] UAT batch-train reconciler skipped — non-primary dashboard process");
|
|
62808
63186
|
const attachmentCleanupTimer = setInterval(() => {
|
|
@@ -62821,8 +63199,31 @@ startCostReconcileService();
|
|
|
62821
63199
|
console.log("[overdeck] Cost reconciler started");
|
|
62822
63200
|
const conversationSearchWatcher = startConversationSearchWatcher();
|
|
62823
63201
|
console.log(conversationSearchWatcher ? "[overdeck] Conversation search watcher started" : "[overdeck] Conversation search watcher skipped (conversationSearch.enabled=false)");
|
|
63202
|
+
let stopResourceRefreshServices = () => void 0;
|
|
62824
63203
|
(async () => {
|
|
62825
|
-
|
|
63204
|
+
const store = await initEventStore();
|
|
63205
|
+
whenDashboardListening().then(async () => {
|
|
63206
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
63207
|
+
const stopTriggers = startResourceRefreshTriggers();
|
|
63208
|
+
const stopConvergence = startProjectResourceConvergence();
|
|
63209
|
+
const stopResourcesSnapshot = startResourcesSnapshotService();
|
|
63210
|
+
stopResourceRefreshServices = () => {
|
|
63211
|
+
stopTriggers();
|
|
63212
|
+
stopConvergence();
|
|
63213
|
+
stopResourcesSnapshot();
|
|
63214
|
+
stopProjectResourceRefreshQueue();
|
|
63215
|
+
};
|
|
63216
|
+
console.log("[overdeck] Project resource refresh queue and resources snapshot service started");
|
|
63217
|
+
const warmStart = Date.now();
|
|
63218
|
+
enqueueProjectsResourceRefresh(listProjectsSync().map((entry) => entry.config), "boot-warm");
|
|
63219
|
+
await whenProjectResourceRefreshIdle();
|
|
63220
|
+
const queueState = getProjectResourceRefreshQueueState();
|
|
63221
|
+
if (queueState.lastError) console.warn("[overdeck] Boot cache warm completed with errors:", queueState.lastError);
|
|
63222
|
+
else console.log(`[overdeck] Boot cache warm complete in ${Math.round((Date.now() - warmStart) / 1e3)}s`);
|
|
63223
|
+
}).catch((err) => {
|
|
63224
|
+
console.warn("[overdeck] Resource refresh startup failed:", err instanceof Error ? err.message : String(err));
|
|
63225
|
+
});
|
|
63226
|
+
store.subscribe((event) => {
|
|
62826
63227
|
if (event.type === "agent.stopped" || event.type === "agent.heartbeat_dead") {
|
|
62827
63228
|
const agentId = typeof event.payload.agentId === "string" ? event.payload.agentId : null;
|
|
62828
63229
|
if (agentId) reconcileAgentMemory(agentId).catch((err) => console.warn("[memory-reconciliation] agent sweep failed:", err?.message ?? err));
|
|
@@ -62878,6 +63279,7 @@ const handleShutdownSignal = async (signal) => {
|
|
|
62878
63279
|
if (forkGrace.count > 0) if (forkGrace.completed) console.log(`[overdeck] Waited for ${forkGrace.count} in-flight fork pipeline(s) before shutdown`);
|
|
62879
63280
|
else console.warn(`[overdeck] ${forkGrace.count} in-flight fork pipeline(s) still running after shutdown grace window`);
|
|
62880
63281
|
clearInterval(attachmentCleanupTimer);
|
|
63282
|
+
stopResourceRefreshServices();
|
|
62881
63283
|
stopAgentEnrichmentService();
|
|
62882
63284
|
stopAgentOutputService();
|
|
62883
63285
|
stopConversationLifecycleService();
|
|
@@ -62893,7 +63295,7 @@ const handleShutdownSignal = async (signal) => {
|
|
|
62893
63295
|
stopRestartAnnouncer();
|
|
62894
63296
|
await stopDeaconChild().catch((err) => console.warn("[deacon-supervisor] child shutdown failed:", err?.message ?? err));
|
|
62895
63297
|
try {
|
|
62896
|
-
const { killAllGateProcessGroups } = await import("./validation-
|
|
63298
|
+
const { killAllGateProcessGroups } = await import("./validation-CIi6pnI2.js");
|
|
62897
63299
|
const reaped = killAllGateProcessGroups();
|
|
62898
63300
|
if (reaped > 0) console.log(`[overdeck] reaped ${reaped} in-flight gate process group(s)`);
|
|
62899
63301
|
} catch (err) {
|
|
@@ -62948,7 +63350,7 @@ reconcileStaleGitHubBlockers().then((n) => {
|
|
|
62948
63350
|
}
|
|
62949
63351
|
}).catch((err) => console.warn(`[overdeck] Startup blocker reconciliation failed: ${err.message}`));
|
|
62950
63352
|
try {
|
|
62951
|
-
const { resetProcessingToQueued } = await import("./merge-sync-
|
|
63353
|
+
const { resetProcessingToQueued } = await import("./merge-sync-SSv3E-pl.js");
|
|
62952
63354
|
const resetCount = resetProcessingToQueued();
|
|
62953
63355
|
if (resetCount > 0) {
|
|
62954
63356
|
console.log(`[overdeck] Reset ${resetCount} stuck merge queue entries to queued`);
|
|
@@ -62970,7 +63372,7 @@ else {
|
|
|
62970
63372
|
console.log("[overdeck] Auto-merge executor started");
|
|
62971
63373
|
}
|
|
62972
63374
|
try {
|
|
62973
|
-
const { reconcileInterruptedVerifications } = await import("./verification-runner-
|
|
63375
|
+
const { reconcileInterruptedVerifications } = await import("./verification-runner-CDj4lD4t.js");
|
|
62974
63376
|
const interrupted = reconcileInterruptedVerifications();
|
|
62975
63377
|
if (interrupted > 0) console.log(`[overdeck] recovered ${interrupted} orphaned verification worker(s)`);
|
|
62976
63378
|
} catch (err) {
|
|
@@ -63009,7 +63411,9 @@ if (process.env.OVERDECK_DISABLE_DEACON === "1") {
|
|
|
63009
63411
|
message: summary
|
|
63010
63412
|
});
|
|
63011
63413
|
}
|
|
63012
|
-
if (startBootReconciliation({ onGraceExpired:
|
|
63414
|
+
if (startBootReconciliation({ onGraceExpired: async () => {
|
|
63415
|
+
await applyBootReconciliationDecision();
|
|
63416
|
+
} }).decision !== "pending") applyBootReconciliationDecision();
|
|
63013
63417
|
startDeaconChild().catch((err) => {
|
|
63014
63418
|
console.error("[overdeck] Cloister auto-start failed:", err);
|
|
63015
63419
|
emitActivityEntrySync({
|
|
@@ -63059,25 +63463,6 @@ async function pruneClosedIssueReviewStatuses() {
|
|
|
63059
63463
|
} catch {}
|
|
63060
63464
|
if (removed > 0) console.log(`[overdeck] Pruned ${removed} stale review-status entr${removed === 1 ? "y" : "ies"} for closed issues`);
|
|
63061
63465
|
}
|
|
63062
|
-
await (async () => {
|
|
63063
|
-
try {
|
|
63064
|
-
const overdeckDbPath = getOverdeckDatabasePath();
|
|
63065
|
-
if (!existsSync$1(overdeckDbPath)) {
|
|
63066
|
-
createOverdeckDatabase({ dbPath: overdeckDbPath });
|
|
63067
|
-
console.log(`[overdeck] Created overdeck.db at ${overdeckDbPath}`);
|
|
63068
|
-
}
|
|
63069
|
-
} catch (err) {
|
|
63070
|
-
console.warn("[overdeck] Overdeck db init failed (non-fatal):", err);
|
|
63071
|
-
}
|
|
63072
|
-
})();
|
|
63073
|
-
const main = runServer.pipe(Effect.provide(ServerConfigLayer));
|
|
63074
|
-
if (typeof Bun !== "undefined") {
|
|
63075
|
-
const { runMain } = await import("@effect/platform-bun/BunRuntime");
|
|
63076
|
-
runMain(main);
|
|
63077
|
-
} else {
|
|
63078
|
-
const { runMain } = await import("@effect/platform-node/NodeRuntime");
|
|
63079
|
-
runMain(main);
|
|
63080
|
-
}
|
|
63081
63466
|
//#endregion
|
|
63082
63467
|
export {};
|
|
63083
63468
|
|